/* sane - Scanner Access Now Easy.

   Copyright (C) 2005 Gerard Klaver  <gerard at gkall dot hobby dot nl>
   The teco2 and gl646 backend (Frank Zago) are used as a template for 
   this backend.
   At this moment parts of the the usb commands, bayer decoding, add_text, 
   parts of the stv680 kernel module, pencam and libgphoto2 program are 
   used/included.
   
   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.
   
   As a special exception, the authors of SANE give permission for
   additional uses of the libraries contained in this release of SANE.
   
   The exception is that, if you link a SANE library with other files
   to produce an executable, this does not by itself cause the
   resulting executable to be covered by the GNU General Public
   License.  Your use of that executable is in no way restricted on
   account of linking the SANE library code into it.
   
   This exception does not, however, invalidate any other reasons why
   the executable file might be covered by the GNU General Public
   License.
   
   If you submit changes to SANE to the maintainers to be included in
   a subsequent release, you agree by submitting the changes that
   those changes may be distributed with this exception intact.
   
   If you write modifications of your own for SANE, it is your choice
   whether to permit this exception to apply to your modifications.
   If you do not wish that, delete this exception notice. 
*/

/*  $Id: m560x.c,v 1.01 2005/01/20 17:37:22 gekl-guest Exp $

   m560x vidcam  driver Gerard Klaver
*/

/*SANE FLOW DIAGRAM

   - sane_init() : initialize backend, attach vidcams
   . - sane_get_devices() : query list of vidcam devices
   . - sane_open() : open a particular vidcam device
   . . - sane_set_io_mode : set blocking mode
   . . - sane_get_select_fd : get vidcam fd
   . . - sane_get_option_descriptor() : get option information
   . . - sane_control_option() : change option values
   . .
   . . - sane_start() : start image acquisition
   . .   - sane_get_parameters() : returns actual scan parameters
   . .   - sane_read() : read image data (from pipe)
   . .     (sane_read called multiple times; 
   . .      after sane_read returns EOF)
   . .     go back to sane_start() if more frames desired
   . . - sane_cancel() : cancel operation
   . - sane_close() : close opened vidcam device
   - sane_exit() : terminate use of backend
*/
/*--------------------------------------------------------------------------*/

#define BUILD 1			/* 2005/01/20  update 20-01-2005 */
#define BACKEND_NAME m560x
#define M560X_CONFIG_FILE "m560x.conf"

/* --------------------- SANE INTERNATIONALISATION ------------------------ */

/* must be first include */
#include "../include/sane/config.h"

#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include "../include/sane/sane.h"
#include "../include/sane/sanei.h"
#include "../include/sane/saneopts.h"
#include "../include/sane/sanei_usb.h"
#include "../include/sane/sanei_debug.h"
#include "../include/sane/sanei_backend.h"
#include "../include/sane/sanei_config.h"
#include "../include/lassert.h"

/* for add-text routine  */
#include <time.h>
#include "font_6x11.h"
/*-----------------------*/

#include "m560x.h"

#define TIMEOUT 1000

/*--------------------------------------------------------------------------*/
/* Lists of possible scan modes. */
static SANE_String_Const scan_mode_list[] = {
  COLOR_RGB_STR,
  COLOR_RGB_TEXT_STR,
  SANE_VALUE_SCAN_MODE_COLOR,
  COLOR_RAW_STR,

  NULL
};

/*-----------------------------------------minium, maximum, quantization----*/
static const SANE_Range brightness_range = { -128, 128, 1 };

static const SANE_Range red_level_range = { -32, 32, 1 };

static const SANE_Range green_level_range = { -32, 32, 1 };

static const SANE_Range blue_level_range = { -32, 32, 1 };

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

static const struct dpi_color_adjust m560x_dpi_color_adjust[] = {

  /*dpi, y, x, color sequence R G or B */
  {160, 120, 0, 1, 2},		/* QSIF       */
  {176, 144, 0, 1, 2},		/* QCIF       */
  {320, 240, 0, 1, 2},		/* QVGA (SIF) */
  {352, 288, 0, 1, 2},		/* CIF        */
  {640, 480, 0, 1, 2},		/* VGA        */
  /* must be the last entry */
  {0, 0, 0, 0, 0}
};

static const struct vidcam_hardware vidcams[] = {

  {0x0402, 0x5603, USB_CLASS_VENDOR_SPEC,
   "ALI", "M5603C",
   m560x_dpi_color_adjust},

  {0x1183, 0x0001, USB_CLASS_VENDOR_SPEC,
   "DigitalDream", "l'espion XS",
   m560x_dpi_color_adjust}
};

/* List of vidcams attached. */
static M560x_Vidcam *first_dev = NULL;
static int num_devices = 0;
/* used by sane_get_devices */
static const SANE_Device **devlist = NULL;

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

/* Local functions. */

/* Display a buffer in the log. Display by lines of 16 bytes. */
static void
hexdump (int level, const char *comment, unsigned char *buf, const int length)
{
  int i;
  char line[128];
  char *ptr;
  char asc_buf[17];
  char *asc_ptr;

  DBG (level, "  %s\n", comment);

  i = 0;
  goto start;

  do
    {
      if (i < length)
	{
	  ptr += sprintf (ptr, " %2.2x", *buf);

	  if (*buf >= 32 && *buf <= 127)
	    {
	      asc_ptr += sprintf (asc_ptr, "%c", *buf);
	    }
	  else
	    {
	      asc_ptr += sprintf (asc_ptr, ".");
	    }
	}
      else
	{
	  /* After the length; do nothing. */
	  ptr += sprintf (ptr, "   ");
	}

      i++;
      buf++;

      if ((i % 16) == 0)
	{
	  /* It's a new line */
	  DBG (level, "  %s    %s\n", line, asc_buf);

	start:
	  ptr = line;
	  *ptr = '\0';
	  asc_ptr = asc_buf;
	  *asc_ptr = '\0';

	  ptr += sprintf (ptr, "  %3.3d:", i);
	}
    }
  while (i < ((length + 15) & ~15));
}

/* Returns the length of the longest string, including the terminating
 * character. */
static size_t
max_string_size (SANE_String_Const strings[])
{
  size_t size, max_size = 0;
  int i;

  for (i = 0; strings[i]; ++i)
    {
      size = strlen (strings[i]) + 1;
      if (size > max_size)
	{
	  max_size = size;
	}
    }
  return max_size;
}

/* Initialize a vidcam entry. Return an allocated vidcam with some
 *  */
static M560x_Vidcam *
m560x_init (void)
{
  M560x_Vidcam *dev;

  DBG (DBG_proc, "m560x_init: enter\n");

  /* Allocate a new vidcam entry. */
  dev = calloc (1, sizeof (M560x_Vidcam));
  if (dev == NULL)
    {
      return NULL;
    }
  memset (dev, 0, sizeof (M560x_Vidcam));

/* Allocate the windoww buffer*/
  dev->windoww_size = 0x20;
  dev->windoww = malloc (dev->windoww_size);
  if (dev->windoww == NULL)
    {
      free (dev);
      return NULL;
    }

/* Allocate the windowr buffer*/
  dev->windowr_size = 0x20;
  dev->windowr = malloc (dev->windowr_size);
  if (dev->windowr == NULL)
    {
      free (dev);
      return NULL;
    }

  dev->fd = -1;

  DBG (DBG_proc, "m560x_init: exit\n");

  return (dev);
}

static M560x_Vidcam *
m560x_init_2 (void)
{
  M560x_Vidcam *dev;

  DBG (DBG_proc, "m560x_init_2: enter\n");

  /* Allocate the buffer used to transfer the USB data */
  /* Check for max. format image size so buffer size can
   * be adjusted                                        */
  if (dev->CIF)
    dev->buffer_size = 356 * 292 * 3;
  if (dev->VGA)
    dev->buffer_size = 914 * 1024;	/*644 * 484 * 3 VGA + 4 format, 914 * 1024 */

  DBG (DBG_proc, "m560x_init_2: dev->bufffer = 0x%x\n", dev->buffer_size);

  dev->buffer = malloc (dev->buffer_size);

  if (dev->buffer == NULL)
    {
      free (dev);
      return NULL;
    }

  /* Allocate the output buffer used for bayer conversion */
  dev->output_size = dev->buffer_size;

  dev->output = malloc (dev->output_size);
  if (dev->output == NULL)
    {
      free (dev);
      return NULL;
    }

  DBG (DBG_proc, "m560x_init_2: exit\n");

  return (dev);
}

/* Closes an open vidcams. */
static void
m560x_close (M560x_Vidcam * dev)
{
  DBG (DBG_proc, "m560x_close: enter \n");

  if (dev->fd != -1)
    {

      DBG (DBG_proc, "m560x_close: fd !=-1 \n");
      sanei_usb_close (dev->fd);
      dev->fd = -1;
    }

  DBG (DBG_proc, "m560x_close: exit\n");
}

/* Frees the memory used by a vidcam. */
static void
m560x_free (M560x_Vidcam * dev)
{
  int i;

  DBG (DBG_proc, "m560x_free: enter\n");

  if (dev == NULL)
    return;

  m560x_close (dev);
  if (dev->devicename)
    {
      free (dev->devicename);
    }
  if (dev->buffer)
    {
      free (dev->buffer);
    }
  if (dev->output)
    {
      free (dev->output);
    }
  if (dev->windoww)
    {
      free (dev->windoww);
    }
  if (dev->windowr)
    {
      free (dev->windowr);
    }
  for (i = 1; i < OPT_NUM_OPTIONS; i++)
    {
      if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s)
	{
	  free (dev->val[i].s);
	}
    }
  if (dev->resolutions_list)
    free (dev->resolutions_list);

  free (dev);

  DBG (DBG_proc, "m560x_free: exit\n");
}

static SANE_Status
m560x_set_config (M560x_Vidcam * dev, int configuration, int interface,
		   int alternate)
{
  SANE_Status status;
  DBG (DBG_proc, "m560x_set_config: open\n");
  status = sanei_usb_set_configuration (dev->fd, configuration);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (DBG_error,
	   "m560x_vidcam_init: M560X FAILED to set configuration %d\n",
	   configuration);
      return status;
    }

  status = sanei_usb_claim_interface (dev->fd, interface);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (DBG_error,
	   "m560x_vidcam_init: STV0680 FAILED to claim interface\n");
      return status;
    }

  status = sanei_usb_set_altinterface (dev->fd, alternate);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (DBG_error,
	   "m560x_vidcam_init: STV0680 FAILED to set alternate interface %d\n",
	   alternate);
      return status;
    }
  DBG (DBG_proc,
       "m560x_vidcam_init: configuration=%d, interface=%d, alternate=%d\n",
       configuration, interface, alternate);

  DBG (DBG_proc, "m560x_set_config: exit\n");
  return status;
}

/* Reset vidcam */
static SANE_Status
m560x_reset_vidcam (M560x_Vidcam * dev)
{
  SANE_Status status;
  size_t sizew;			/* significant size of window */
  size_t sizer;

  DBG (DBG_proc, "m560x_reset_vidcam: enter\n");

  if (dev->framecount <= 1000)
    {
      sizew = dev->windoww_size;
      sizer = dev->windowr_size;

      memset (dev->windoww, 0, sizew);
      memset (dev->windowr, 0, sizer);

      sizew = 0x00;
      status =
	sanei_usb_control_msg (dev->fd, 0x41, 0x0a, 0x0000, 0, sizew,
			       dev->windoww);
      if (status != SANE_STATUS_GOOD)
	{
	  return status;
	}
      DBG (DBG_proc, "m560x_reset_vidcam: CMDID_STOP_VIDEO end\n");

      /* this is a high priority command; it stops all lower order commands */

      usleep (2000);
      sizew = 0x0;
      status =
	sanei_usb_control_msg (dev->fd, 0x41, 0x04, 0x0000, 0, sizew,
			       dev->windoww);
      if (status != SANE_STATUS_GOOD)
	{
	  return status;
	}
      DBG (DBG_proc, "m560x_reset_vidcam: CMDID_CANCEL_TRANSACTION end\n");
      usleep (2000);
      sizer = 0x02;
      DBG (DBG_proc, "m560x_reset_vidcam: CMDID_GET_LAST_ERROR begin\n");
      status =
	sanei_usb_control_msg (dev->fd, 0xc1, 0x80, 0x0000, 0, sizer,
			       dev->windowr);
      if (status != SANE_STATUS_GOOD)
	{
	  /* Get Last Error; 2 = busy */
	  DBG (DBG_proc,
	       "m560x_reset_vidcam: last error: %i, command = 0x%x\n",
	       dev->windowr[0], dev->windowr[1]);
	  return status;
	}
      else
	{
	  DBG (DBG_proc, "m560x_reset_vidcam: Camera reset to idle mode.\n");
	}
      hexdump (DBG_info2, "m560x_reset_vidcam: CMDID_GET_LAST_ERROR",
	       dev->windowr, sizer);

      /*  configuration = 1, interface = 0, alternate = 0 */
      /*status = m560x_set_config (dev, 1, 0, 0);
         if (status != SANE_STATUS_GOOD)
         {
         DBG (DBG_error,
         "m560x_vidcam_init: M560X FAILED to set configure\n");
         return status;
         }
       */
    }
  status = SANE_STATUS_GOOD;
  DBG (DBG_proc, "m560x_reset_vidcam: exit\n");

  return status;
}

/* Inquiry a device and returns TRUE if is supported. */
static int
m560x_identify_vidcam (M560x_Vidcam * dev)
{
  SANE_Status status;
  SANE_Word vendor;
  SANE_Word product;
  int i;
  size_t sizer;
  size_t sizew;

  DBG (DBG_info, "m560x_identify_vidcam: open\n");

  status = sanei_usb_get_vendor_product (dev->fd, &vendor, &product);

  /* Loop through our list to make sure this scanner is supported. */
  for (i = 0; i < NELEMS (vidcams); i++)
    {
      if (vidcams[i].vendor == vendor && vidcams[i].product == product)
	{

	  DBG (DBG_info, "m560x_identify_vidcam: vidcam 0x%x:0x%x is in list\n",
	       vendor, product);

	  dev->hw = &(vidcams[i]);

	  sizer = dev->windowr_size;
	  sizew = dev->windoww_size;
	  memset (dev->windowr, 0, sizer);
	  memset (dev->windoww, 0, sizew);

	  /*  configuration = 1, interface = 0, alternate = 0 */
	  status = m560x_set_config (dev, 1, 0, 0);
	  if (status != SANE_STATUS_GOOD)
	    {
	      DBG (DBG_error,
		   "m560x_vidcam_init: M560X FAILED to set configure\n");
	      return status;
	    }

	  DBG (DBG_proc,
	       "m560x_identify_vicdam: urb 5 check if M560X is present\n");
	  
/* [62 ms]  URB 5  40 : c0 04 14 00 00 80 01 00 */
	  sizer = 0x01;
	  status =
	    sanei_usb_control_msg (dev->fd, 0xc0, 0x04, 0x0014, 0x8000, sizer,
				   dev->windowr);
	  if (status != SANE_STATUS_GOOD)
	    return SANE_FALSE;
	  hexdump (DBG_info2, "urb5 data read 0x40", dev->windowr, sizer);
/* [66 ms]  >>>  URB 6 going down  >>> 00000000: 40 00000000: 40 04 13 00 00 80 01 00 */
sizew = 0x01;
dev->windoww[0]=0x40;

	  status =
	    sanei_usb_control_msg (dev->fd, 0x40, 0x04, 0x0013, 0x8000, sizew,
				   dev->windoww);
	  if (status != SANE_STATUS_GOOD)
	    return SANE_FALSE;
	  hexdump (DBG_info2, "urb6 data write 0x40", dev->windoww, sizew);

/* [70 ms]  >>>  URB 7 going down  >>> 00000000: c6 00000000: c0 04 14 00 40 81 01 00 */
	 sizer = 0x01;
	  status = sanei_usb_control_msg (dev->fd, 0xc0, 0x04, 0x0014, 0x8140, sizer, dev->windowr);
/* [74 ms]  >>>  URB 8 going down  >>> 00000000: c6 00000000: c0 04 14 00 40 81 01 00 */
	  status = sanei_usb_control_msg (dev->fd, 0xc0, 0x04, 0x0014, 0x8040, sizer, dev->windowr);
/* [79 ms]  >>>  URB 9 going down  >>> 00000000: 00 00000000: c0 04 14 00 70 81 01 00 */
	  status = sanei_usb_control_msg (dev->fd, 0xc0, 0x04, 0x0014, 0x8170, sizer, dev->windowr);
	  
/* [83 ms]  >>>  URB 10 going down  >>>  */
/*    00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00000010: 00 00 00 00 00 00 00 00
    00000000: c0 04 12 00 00 00 18 00 */
sizer = 0x18;
	  status = sanei_usb_control_msg (dev->fd, 0xc0, 0x04, 0x0012, 0x0000, sizer, dev->windowr);
	  hexdump (DBG_info2, "urb10 data read block 0x18 bytes all 00?", dev->windoww, sizew);
	  
/* [96 ms]  >>>  URB 11 going down  >>> 00000000: 11 00000000: c0 04 14 00 73 81 01 00 */
sizer = 0x01;
	  status = sanei_usb_control_msg (dev->fd, 0xc0, 0x04, 0x0014, 0x8173, sizer, dev->windowr);
/* Urb 12 (C) ep= <<<< 00 00000000: 40 04 13 00 73 81 01 00 */
sizew = 0x01;
dev->windoww[0]=0x00;

	  status = sanei_usb_control_msg (dev->fd, 0x40, 0x04, 0x0013, 0x8113, sizew, dev->windoww);

/* Urb 13 (C) ep= <<<< 00000000: ec 00000000: c0 04 14 00 75 81 01 00 */

sizer = 0x01;
	  status = sanei_usb_control_msg (dev->fd, 0xc0, 0x04, 0x0014, 0x8175, sizer, dev->windowr);

	  /* Urb 14 (C) ep= <<<< 00000000: 11 40 04 13 00 73 81 01 00 */

sizew = 0x01;
dev->windoww[0]=0x11;

	  status = sanei_usb_control_msg (dev->fd, 0x40, 0x04, 0x0013, 0x8173, sizew, dev->windoww);

	  /* Urb 15 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 72 81 01 00 */

/*Urb 16 (C) ep= <<<< 00000000: 00 40 04 13 00 72 81 01 00 */

/*Urb 17 (C) ep= <<<< 00000000: bf 00000000: c0 04 14 00 74 81 01 00 */

/*Urb 18 (C) ep= <<<< 00000000: 40 04 13 00 72 81 01 00 */

/*Urb 19 (C) ep= <<<< 00000000: c6 00000000: c0 04 14 00 40 81 01 00 */

/*Urb 20 (C) ep= <<<< 00000000: 40 04 13 00 40 81 01 00 */

/*Urb 21 (C) ep= <<<< 00000000: 40 04 15 00 00 00 e8 03 */

/*Urb 22 (C) ep= <<<< 00000000: 40 04 15 00 e8 03 e8 03 */

/*Urb 23 (C) ep= <<<< 00000000: 40 04 15 00 d0 07 e8 03 */

/*Urb 24 (C) ep= <<<< 00000000: 40 04 15 00 b8 0b 1b 00 */

/*Urb 25 (C) ep= <<<< 00000000: 40 04 10 00 00 00 01 00 */

/*Urb 26 (C) ep= <<<< 00000000: 40 04 13 00 e4 0f 01 00 */

/*Urb 27 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fe 0f 01 00 */

/*Urb 28 (C) ep= <<<< 00000000: 40 04 13 00 fe 0f 01 00 */

/*Urb 29 (C) ep= <<<< 00000000: 04 00000000: c0 04 14 00 ff 0f 01 00 */

/*Urb 30 (C) ep= <<<< 00000000: 40 04 13 00 ff 0f 01 00 */

/*Urb 31 (C) ep= <<<< 00000000: 40 04 13 00 fd 0f 01 00 */

/*Urb 32 (C) ep= <<<< 00000000: 40 04 13 00 72 81 01 00 */

/*Urb 33 (C) ep= <<<< 00000000: 40 04 13 00 74 81 01 00 */

/*Urb 34 (C) ep= <<<< 00000000: 40 00000000: c0 04 14 00 74 81 01 00 */

/*Urb 35 (C) ep= <<<< 00000000: 40 04 13 00 74 81 01 00 */

/*Urb 36 (C) ep= <<<< 00000000: 40 04 13 00 77 81 01 00 */

/*Urb 37 (C) ep= <<<< 00000000: 40 04 13 00 80 81 01 00 */

/*Urb 38 (C) ep= <<<< 00000000: 40 04 13 00 81 81 01 00 */

/*Urb 39 (C) ep= <<<< 00000000: 40 04 13 00 8a 81 01 00 */

/*Urb 40 (C) ep= <<<< 00000000: 40 04 13 00 8b 81 01 00 */

/*Urb 41 (C) ep= <<<< 00000000: 40 04 13 00 82 81 01 00 */

/*Urb 42 (C) ep= <<<< 00000000: 40 04 13 00 83 81 01 00 */

/*Urb 43 (C) ep= <<<< 00000000: 40 04 13 00 86 81 01 00 */

/*Urb 44 (C) ep= <<<< 00000000: 40 04 13 00 87 81 01 00 */

/*Urb 45 (C) ep= <<<< 00000000: 40 04 13 00 88 81 01 00 */

/*Urb 46 (C) ep= <<<< 00000000: 40 04 13 00 89 81 01 00 */

/*Urb 47 (C) ep= <<<< 00000000: 40 04 13 00 84 81 01 00 */

/*Urb 48 (C) ep= <<<< 00000000: 40 04 13 00 85 81 01 00 */

/*Urb 49 (C) ep= <<<< 00000000: 40 04 13 00 00 80 01 00 */

/*Urb 50 (C) ep= <<<< 00000000: 40 04 13 00 01 80 01 00 */

/*Urb 51 (C) ep= <<<< 00000000: 40 04 13 00 02 80 01 00 */

/*Urb 52 (C) ep= <<<< 00000000: 40 04 13 00 03 80 01 00 */

/*Urb 53 (C) ep= <<<< 00000000: 40 04 13 00 04 80 01 00 */

/*Urb 54 (C) ep= <<<< 00000000: 40 04 13 00 05 80 01 00 */

/*Urb 55 (C) ep= <<<< 00000000: 40 04 13 00 06 80 01 00 */

/*Urb 56 (C) ep= <<<< 00000000: 40 04 13 00 07 80 01 00 */

/*Urb 57 (C) ep= <<<< 00000000: 40 04 13 00 08 80 01 00 */

/*Urb 58 (C) ep= <<<< 00000000: 40 04 13 00 09 80 01 00 */

/*Urb 59 (C) ep= <<<< 00000000: 40 04 13 00 0a 80 01 00 */

/*Urb 60 (C) ep= <<<< 00000000: 40 04 13 00 0b 80 01 00 */

/*Urb 61 (C) ep= <<<< 00000000: 40 04 13 00 0c 80 01 00 */

/*Urb 62 (C) ep= <<<< 00000000: 40 04 13 00 0d 80 01 00 */

/*Urb 63 (C) ep= <<<< 00000000: 40 04 13 00 0e 80 01 00 */

/*Urb 64 (C) ep= <<<< 00000000: 40 04 13 00 10 80 01 00 */

/*Urb 65 (C) ep= <<<< 00000000: 40 04 13 00 0f 80 01 00 */

/*Urb 66 (C) ep= <<<< 00000000: 40 04 13 00 2a 80 01 00 */

/*Urb 67 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 68 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 69 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 70 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 71 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 72 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 73 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 74 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 75 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 76 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 77 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 78 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 79 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 80 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 81 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 82 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 83 (C) ep= <<<< 00000000: 40 04 13 00 5b 80 01 00 */

/*Urb 84 (C) ep= <<<< 00000000: 40 04 13 00 69 80 01 00 */

/*Urb 85 (C) ep= <<<< 00000000: 40 04 13 00 17 80 01 00 */

/*Urb 86 (C) ep= <<<< 00000000: 40 04 13 00 18 80 01 00 */

/*Urb 87 (C) ep= <<<< 00000000: 40 04 13 00 19 80 01 00 */

/*Urb 88 (C) ep= <<<< 00000000: 40 04 13 00 1a 80 01 00 */

/*Urb 89 (C) ep= <<<< 00000000: 40 04 13 00 1b 80 01 00 */

/*Urb 90 (C) ep= <<<< 00000000: 40 04 13 00 1c 80 01 00 */

/*Urb 91 (C) ep= <<<< 00000000: 40 04 13 00 1d 80 01 00 */

/*Urb 92 (C) ep= <<<< 00000000: 40 04 13 00 1e 80 01 00 */

/*Urb 93 (C) ep= <<<< 00000000: 40 04 13 00 1f 80 01 00 */

/*Urb 94 (C) ep= <<<< 00000000: 40 04 13 00 20 80 01 00 */

/*Urb 95 (C) ep= <<<< 00000000: 40 04 13 00 21 80 01 00 */

/*Urb 96 (C) ep= <<<< 00000000: 40 04 13 00 22 80 01 00 */

/*Urb 97 (C) ep= <<<< 00000000: 40 04 13 00 23 80 01 00 */

/*Urb 98 (C) ep= <<<< 00000000: 40 04 13 00 24 80 01 00 */

/*Urb 99 (C) ep= <<<< 00000000: 40 04 13 00 25 80 01 00 */

/*Urb 100 (C) ep= <<<< 00000000: 40 04 13 00 26 80 01 00 */

/*Urb 101 (C) ep= <<<< 00000000: 40 04 13 00 27 80 01 00 */

/*Urb 102 (C) ep= <<<< 00000000: 40 04 13 00 28 80 01 00 */

/*Urb 103 (C) ep= <<<< 00000000: 40 04 13 00 29 80 01 00 */

/*Urb 104 (C) ep= <<<< 00000000: 40 04 13 00 2b 80 01 00 */

/*Urb 105 (C) ep= <<<< 00000000: 40 04 13 00 2c 80 01 00 */

/*Urb 106 (C) ep= <<<< 00000000: 40 04 13 00 2d 80 01 00 */

/*Urb 107 (C) ep= <<<< 00000000: 40 04 13 00 2e 80 01 00 */

/*Urb 108 (C) ep= <<<< 00000000: 40 04 13 00 2f 80 01 00 */

/*Urb 109 (C) ep= <<<< 00000000: 40 04 13 00 30 80 01 00

Urb 110 (C) ep= <<<< 00000000: 40 04 13 00 31 80 01 00

Urb 111 (C) ep= <<<< 00000000: 40 04 13 00 32 80 01 00

Urb 112 (C) ep= <<<< 00000000: 40 04 13 00 33 80 01 00

Urb 113 (C) ep= <<<< 00000000: 40 04 13 00 34 80 01 00

Urb 114 (C) ep= <<<< 00000000: 40 04 13 00 35 80 01 00

Urb 115 (C) ep= <<<< 00000000: 40 04 13 00 36 80 01 00

Urb 116 (C) ep= <<<< 00000000: 40 04 13 00 37 80 01 00

Urb 117 (C) ep= <<<< 00000000: 40 04 13 00 38 80 01 00

Urb 118 (C) ep= <<<< 00000000: 40 04 13 00 39 80 01 00

Urb 119 (C) ep= <<<< 00000000: 40 04 13 00 3a 80 01 00

Urb 120 (C) ep= <<<< 00000000: 40 04 13 00 3b 80 01 00

Urb 121 (C) ep= <<<< 00000000: 40 04 13 00 3c 80 01 00

Urb 122 (C) ep= <<<< 00000000: 40 04 13 00 3d 80 01 00

Urb 123 (C) ep= <<<< 00000000: 40 04 13 00 3e 80 01 00

Urb 124 (C) ep= <<<< 00000000: 40 04 13 00 3f 80 01 00

Urb 125 (C) ep= <<<< 00000000: 40 04 13 00 40 80 01 00

Urb 126 (C) ep= <<<< 00000000: 40 04 13 00 41 80 01 00

Urb 127 (C) ep= <<<< 00000000: 40 04 13 00 42 80 01 00

Urb 128 (C) ep= <<<< 00000000: 40 04 13 00 43 80 01 00

Urb 129 (C) ep= <<<< 00000000: 40 04 13 00 69 80 01 00


 
Urb 130 (C) ep= <<<< 00000000: 40 04 13 00 4d 80 01 00

Urb 131 (C) ep= <<<< 00000000: 40 04 13 00 4e 80 01 00

Urb 132 (C) ep= <<<< 00000000: 40 04 13 00 4f 80 01 00

Urb 133 (C) ep= <<<< 00000000: 40 04 13 00 50 80 01 00

Urb 134 (C) ep= <<<< 00000000: 40 04 13 00 51 80 01 00

Urb 135 (C) ep= <<<< 00000000: 40 04 13 00 52 80 01 00

Urb 136 (C) ep= <<<< 00000000: 40 04 13 00 53 80 01 00

Urb 137 (C) ep= <<<< 00000000: 40 04 13 00 54 80 01 00

Urb 138 (C) ep= <<<< 00000000: 40 04 13 00 55 80 01 00

Urb 139 (C) ep= <<<< 00000000: 40 04 13 00 56 80 01 00

Urb 140 (C) ep= <<<< 00000000: 40 04 13 00 57 80 01 00

Urb 141 (C) ep= <<<< 00000000: 40 04 13 00 58 80 01 00

Urb 142 (C) ep= <<<< 00000000: 40 04 13 00 59 80 01 00

Urb 143 (C) ep= <<<< 00000000: 40 04 13 00 5a 80 01 00


 
Urb 144 (C) ep= <<<< 00000000: 40 04 13 00 5c 80 01 00

Urb 145 (C) ep= <<<< 00000000: 40 04 13 00 5d 80 01 00

Urb 146 (C) ep= <<<< 00000000: 40 04 13 00 5e 80 01 00

Urb 147 (C) ep= <<<< 00000000: 40 04 13 00 5f 80 01 00

Urb 148 (C) ep= <<<< 00000000: 40 04 13 00 60 80 01 00

Urb 149 (C) ep= <<<< 00000000: 40 04 13 00 61 80 01 00

Urb 150 (C) ep= <<<< 00000000: 40 04 13 00 62 80 01 00

Urb 151 (C) ep= <<<< 00000000: 40 04 13 00 63 80 01 00

Urb 152 (C) ep= <<<< 00000000: 40 04 13 00 64 80 01 00

Urb 153 (C) ep= <<<< 00000000: 40 04 13 00 65 80 01 00

Urb 154 (C) ep= <<<< 00000000: 40 04 13 00 66 80 01 00

Urb 155 (C) ep= <<<< 00000000: 40 04 13 00 67 80 01 00


 
Urb 156 (C) ep= <<<< 00000000: 40 04 13 00 56 81 01 00

 
Urb 157 (C) ep= <<<< 00000000: 40 04 13 00 60 81 01 00

Urb 158 (C) ep= <<<< 00000000: 40 04 13 00 61 81 01 00

Urb 159 (C) ep= <<<< 00000000: 40 04 13 00 62 81 01 00

Urb 160 (C) ep= <<<< 00000000: 40 04 13 00 63 81 01 00

 
Urb 161 (C) ep= <<<< 00000000: 40 04 13 00 62 81 01 00

 
Urb 162 (C) ep= <<<< 00000000: 40 04 13 00 62 81 01 00

Urb 163 (C) ep= <<<< 00000000: 40 04 13 00 62 81 01 00

 
Urb 164 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 165 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 166 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 167 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 168 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 169 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 170 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 171 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 172 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 173 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 174 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 175 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 176 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 177 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 178 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 179 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 180 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 181 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 182 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 183 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 184 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 185 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 186 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 187 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 188 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 189 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 190 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 191 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 192 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 193 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 194 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 195 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00

Urb 196 (C) ep= <<<< 00000000: 40 04 13 00 11 80 01 00



Urb 197 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 198 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 199 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 200 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 201 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 202 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 203 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 204 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 205 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 206 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 207 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 208 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 209 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 210 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 211 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 212 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 213 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 214 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 215 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 216 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 217 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 218 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 219 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 220 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 221 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 222 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 223 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 224 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 225 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 226 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 227 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 228 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00

Urb 229 (C) ep= <<<< 00000000: 40 04 13 00 12 80 01 00



Urb 230 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 231 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 232 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 233 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 234 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 235 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 236 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 237 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 238 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 239 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 240 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 241 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 242 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 243 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 244 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 245 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 246 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 247 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 248 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 249 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 250 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 251 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 252 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 253 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 254 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 255 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 256 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 257 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 258 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 259 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 260 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 261 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00

Urb 262 (C) ep= <<<< 00000000: 40 04 13 00 13 80 01 00




Urb 263 (C) ep= <<<< 00000000: 40 04 13 00 44 80 01 00

Urb 264 (C) ep= <<<< 00000000: 40 04 13 00 45 80 01 00

Urb 265 (C) ep= <<<< 00000000: 40 04 13 00 46 80 01 00

Urb 266 (C) ep= <<<< 00000000: 40 04 13 00 47 80 01 00

Urb 267 (C) ep= <<<< 00000000: 40 04 13 00 48 80 01 00

Urb 268 (C) ep= <<<< 00000000: 40 04 13 00 49 80 01 00

Urb 269 (C) ep= <<<< 00000000: 40 04 13 00 4a 80 01 00

Urb 270 (C) ep= <<<< 00000000: 40 04 13 00 4b 80 01 00

Urb 271 (C) ep= <<<< 00000000: 40 04 13 00 4c 80 01 00



Urb 272 (C) ep= <<<< 00000000: 40 04 13 00 14 80 01 00

Urb 273 (C) ep= <<<< 00000000: 40 04 13 00 15 80 01 00

Urb 274 (C) ep= <<<< 00000000: 40 04 13 00 16 80 01 00



Urb 275 (C) ep= <<<< 00000000: 40 04 17 00 42 12 01 00

Urb 276 (C) ep= <<<< 00000000: 40 04 17 00 42 00 01 00

Urb 277 (C) ep= <<<< 00000000: 40 04 17 00 42 01 01 00

Urb 278 (C) ep= <<<< 00000000: 40 04 17 00 42 02 01 00

Urb 279 (C) ep= <<<< 00000000: 40 04 17 00 42 05 01 00


 
Urb 280 (C) ep= <<<< 00000000: 40 04 17 00 42 10 01 00

Urb 281 (C) ep= <<<< 00000000: 40 04 17 00 42 11 01 00

Urb 282 (C) ep= <<<< 00000000: 40 04 17 00 42 12 01 00

Urb 283 (C) ep= <<<< 00000000: 40 04 17 00 42 13 01 00

Urb 284 (C) ep= <<<< 00000000: 40 04 17 00 42 14 01 00

Urb 285 (C) ep= <<<< 00000000: 40 04 17 00 42 17 01 00

Urb 286 (C) ep= <<<< 00000000: 40 04 17 00 42 18 01 00

Urb 287 (C) ep= <<<< 00000000: 40 04 17 00 42 19 01 00

Urb 288 (C) ep= <<<< 00000000: 40 04 17 00 42 1a 01 00

Urb 289 (C) ep= <<<< 00000000: 40 04 17 00 42 20 01 00


 
Urb 290 (C) ep= <<<< 00000000: 40 04 17 00 42 26 01 00

Urb 291 (C) ep= <<<< 00000000: 40 04 17 00 42 27 01 00

Urb 292 (C) ep= <<<< 00000000: 40 04 17 00 42 21 01 00

Urb 293 (C) ep= <<<< 00000000: 40 04 17 00 42 22 01 00

Urb 294 (C) ep= <<<< 00000000: 40 04 17 00 42 2e 01 00

Urb 295 (C) ep= <<<< 00000000: 40 04 17 00 42 78 01 00

Urb 296 (C) ep= <<<< 00000000: 40 04 17 00 42 79 01 00

Urb 297 (C) ep= <<<< 00000000: 40 04 17 00 42 7a 01 00

Urb 298 (C) ep= <<<< 00000000: 40 04 17 00 42 28 01 00

Urb 299 (C) ep= <<<< 00000000: 40 04 17 00 42 60 01 00

Urb 300 (C) ep= <<<< 00000000: 40 04 17 00 42 6f 01 00

Urb 301 (C) ep= <<<< 00000000: 40 04 13 00 00 81 01 00

Urb 302 (C) ep= <<<< 00000000: 40 04 13 00 01 81 01 00

Urb 303 (C) ep= <<<< 00000000: 40 00000000: c0 04 14 00 53 81 01 00

Urb 304 (C) ep= <<<< 00000000: 40 04 13 00 53 81 01 00

Urb 305 (C) ep= <<<< 00000000: 40 04 13 00 6a 80 01 00

Urb 306 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fd 0f 01 00

Urb 307 (C) ep= <<<< 00000000: 40 04 13 00 fd 0f 01 00

Urb 308 (C) ep= <<<< 00000000: 40 04 13 00 e2 0f 01 00


 
Urb 309 (C) ep= <<<< 00000000: 40 04 13 00 80 81 01 00

Urb 310 (C) ep= <<<< 00000000: 40 04 13 00 81 81 01 00

Urb 311 (C) ep= <<<< 00000000: 05 00000000: c0 04 14 00 76 81 01 00

Urb 312 (C) ep= <<<< 00000000: 40 04 13 00 76 81 01 00

Urb 313 (C) ep= <<<< 00000000: 04 00000000: c0 04 14 00 77 81 01 00

Urb 314 (C) ep= <<<< 00000000: 40 04 13 00 77 81 01 00

Urb 315 (C) ep= <<<< 00000000: 40 00000000: c0 04 14 00 47 81 01 00

Urb 316 (C) ep= <<<< 00000000: 40 04 13 00 47 81 01 00

Urb 317 (C) ep= <<<< 00000000: 40 04 13 00 00 80 01 00

Urb 318 (C) ep= <<<< 00000000: 0f 00000000: c0 04 14 00 6a 80 01 00

Urb 319 (C) ep= <<<< 00000000: 40 04 13 00 6a 80 01 00

Urb 320 (C) ep= <<<< 00000000: 40 04 13 00 8a 81 01 00

Urb 321 (C) ep= <<<< 00000000: 40 04 13 00 8b 81 01 00

Urb 322 (C) ep= <<<< 00000000: 40 04 13 00 82 81 01 00

Urb 323 (C) ep= <<<< 00000000: 40 04 13 00 83 81 01 00

Urb 324 (C) ep= <<<< 00000000: 40 04 13 00 86 81 01 00

Urb 325 (C) ep= <<<< 00000000: 40 04 13 00 87 81 01 00

Urb 326 (C) ep= <<<< 00000000: 40 04 13 00 88 81 01 00

Urb 327 (C) ep= <<<< 00000000: 40 04 13 00 89 81 01 00

Urb 328 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 329 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 330 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 331 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 332 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 333 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 334 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 335 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 336 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 337 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 338 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 339 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 340 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 341 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 342 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 343 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 344 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 345 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 346 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 347 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 348 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 349 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 350 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 351 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 352 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 353 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 354 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 355 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 356 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 357 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 358 (C) ep= >>>>

Urb 359 (C) ep= >>>>

Urb 360 (C) ep= >>>>

Urb 361 (C) ep= <<<< 00000000: 40 04 13 00 e4 0f 01 00

Urb 362 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fe 0f 01 00

Urb 363 (C) ep= <<<< 00000000: 40 04 13 00 fe 0f 01 00

Urb 364 (C) ep= <<<< 00000000: 04 00000000: c0 04 14 00 ff 0f 01 00

Urb 365 (C) ep= <<<< 00000000: 40 04 13 00 ff 0f 01 00

Urb 366 (C) ep= <<<< 00000000: 40 04 17 00 42 12 01 00

Urb 367 (C) ep= <<<< 00000000: 40 04 13 00 77 81 01 00

Urb 368 (C) ep= <<<< 00000000: 40 04 13 00 80 81 01 00

Urb 369 (C) ep= <<<< 00000000: 40 04 13 00 81 81 01 00

Urb 370 (C) ep= <<<< 00000000: 40 04 13 00 8a 81 01 00

Urb 371 (C) ep= <<<< 00000000: 40 04 13 00 8b 81 01 00

Urb 372 (C) ep= <<<< 00000000: 40 04 13 00 82 81 01 00

Urb 373 (C) ep= <<<< 00000000: 40 04 13 00 83 81 01 00

Urb 374 (C) ep= <<<< 00000000: 40 04 13 00 86 81 01 00

Urb 375 (C) ep= <<<< 00000000: 40 04 13 00 87 81 01 00

Urb 376 (C) ep= <<<< 00000000: 40 04 13 00 88 81 01 00

Urb 377 (C) ep= <<<< 00000000: 40 04 13 00 89 81 01 00

Urb 378 (C) ep= <<<< 00000000: 40 04 13 00 84 81 01 00

Urb 379 (C) ep= <<<< 00000000: 40 04 13 00 85 81 01 00

Urb 380 (C) ep= <<<< 00000000: 40 04 13 00 00 80 01 00

Urb 381 (C) ep= <<<< 00000000: 40 04 13 00 6a 80 01 00

Urb 382 (C) ep= <<<< 00000000: 40 04 17 00 42 00 01 00

Urb 383 (C) ep= <<<< 00000000: 40 04 17 00 42 01 01 00

Urb 384 (C) ep= <<<< 00000000: 40 04 17 00 42 02 01 00

Urb 385 (C) ep= <<<< 00000000: 40 04 17 00 42 05 01 00

Urb 386 (C) ep= <<<< 00000000: 40 04 17 00 42 10 01 00

Urb 387 (C) ep= <<<< 00000000: 40 04 17 00 42 11 01 00

Urb 388 (C) ep= <<<< 00000000: 40 04 17 00 42 12 01 00

Urb 389 (C) ep= <<<< 00000000: 40 04 17 00 42 13 01 00

Urb 390 (C) ep= <<<< 00000000: 40 04 17 00 42 14 01 00

Urb 391 (C) ep= <<<< 00000000: 40 04 17 00 42 17 01 00

Urb 392 (C) ep= <<<< 00000000: 40 04 17 00 42 18 01 00

Urb 393 (C) ep= <<<< 00000000: 40 04 17 00 42 19 01 00

Urb 394 (C) ep= <<<< 00000000: 40 04 17 00 42 1a 01 00

Urb 395 (C) ep= <<<< 00000000: 40 04 17 00 42 20 01 00

Urb 396 (C) ep= <<<< 00000000: 40 04 17 00 42 26 01 00

Urb 397 (C) ep= <<<< 00000000: 40 04 17 00 42 27 01 00

Urb 398 (C) ep= <<<< 00000000: 40 04 17 00 42 21 01 00

Urb 399 (C) ep= <<<< 00000000: 40 04 17 00 42 22 01 00

Urb 400 (C) ep= <<<< 00000000: 40 04 17 00 42 2e 01 00

Urb 401 (C) ep= <<<< 00000000: 40 04 17 00 42 78 01 00

Urb 402 (C) ep= <<<< 00000000: 40 04 17 00 42 79 01 00

Urb 403 (C) ep= <<<< 00000000: 40 04 17 00 42 7a 01 00

Urb 404 (C) ep= <<<< 00000000: 40 04 17 00 42 28 01 00

Urb 405 (C) ep= <<<< 00000000: 40 04 17 00 42 60 01 00

Urb 406 (C) ep= <<<< 00000000: 40 04 17 00 42 6f 01 00

Urb 407 (C) ep= <<<< 00000000: 40 04 13 00 e2 0f 01 00

Urb 408 (C) ep= <<<< 00000000: 40 04 13 00 e4 0f 01 00

Urb 409 (C) ep= <<<< 00000000: 40 04 13 00 35 80 01 00

Urb 410 (C) ep= <<<< 00000000: 40 04 13 00 36 80 01 00

Urb 411 (C) ep= <<<< 00000000: 40 04 13 00 37 80 01 00

Urb 412 (C) ep= <<<< 00000000: 40 04 13 00 38 80 01 00

Urb 413 (C) ep= <<<< 00000000: 40 04 13 00 ab 0f 01 00

Urb 414 (C) ep= <<<< 00000000: 40 04 13 00 ac 0f 01 00

Urb 415 (C) ep= <<<< 00000000: 40 04 13 00 ad 0f 01 00

Urb 416 (C) ep= <<<< 00000000: 40 04 13 00 ae 0f 01 00

Urb 417 (C) ep= <<<< 00000000: 40 04 13 00 af 0f 01 00

Urb 418 (C) ep= <<<< 00000000: 40 04 13 00 a6 0f 01 00

Urb 419 (C) ep= <<<< 00000000: 40 04 13 00 a7 0f 01 00

Urb 420 (C) ep= <<<< 00000000: 40 04 13 00 a8 0f 01 00

Urb 421 (C) ep= <<<< 00000000: 40 04 13 00 a9 0f 01 00

Urb 422 (C) ep= <<<< 00000000: 40 04 13 00 aa 0f 01 00

Urb 423 (C) ep= <<<< 00000000: 40 04 13 00 57 80 01 00

Urb 424 (C) ep= <<<< 00000000: 40 04 13 00 58 80 01 00

Urb 425 (C) ep= <<<< 00000000: 40 04 13 00 59 80 01 00

Urb 426 (C) ep= <<<< 00000000: 40 04 13 00 5a 80 01 00

Urb 427 (C) ep= <<<< 00000000: 54 00000000: c0 04 14 00 53 81 01 00

Urb 428 (C) ep= <<<< 00000000: 40 04 13 00 53 81 01 00

Urb 429 (C) ep= <<<< 00000000: 40 04 13 00 00 80 01 00

Urb 430 (C) ep= <<<< 00000000: 40 04 13 00 47 81 01 00

Urb 431 (C) ep= <<<< 00000000: 40 04 13 00 1b 80 01 00

Urb 432 (C) ep= <<<< 00000000: 40 04 13 00 17 80 01 00

Urb 433 (C) ep= <<<< 00000000: 40 04 13 00 1c 80 01 00

Urb 434 (C) ep= <<<< 00000000: 40 04 13 00 1d 80 01 00

Urb 435 (C) ep= <<<< 00000000: 40 04 13 00 01 80 01 00

Urb 436 (C) ep= <<<< 00000000: 40 04 13 00 02 80 01 00

Urb 437 (C) ep= <<<< 00000000: 40 04 13 00 03 80 01 00

Urb 438 (C) ep= <<<< 00000000: 40 04 13 00 04 80 01 00

Urb 439 (C) ep= <<<< 00000000: 40 04 13 00 05 80 01 00

Urb 440 (C) ep= <<<< 00000000: 40 04 13 00 06 80 01 00

Urb 441 (C) ep= <<<< 00000000: 40 04 13 00 07 80 01 00

Urb 442 (C) ep= <<<< 00000000: 40 04 13 00 08 80 01 00

Urb 443 (C) ep= <<<< 00000000: 40 04 13 00 09 80 01 00

Urb 444 (C) ep= <<<< 00000000: 40 04 13 00 0a 80 01 00

Urb 445 (C) ep= <<<< 00000000: 40 04 13 00 60 81 01 00

Urb 446 (C) ep= <<<< 00000000: 40 04 13 00 61 81 01 00

Urb 447 (C) ep= <<<< 00000000: 40 04 13 00 34 80 01 00

Urb 448 (C) ep= <<<< 00000000: 40 04 13 00 8a 81 01 00

Urb 449 (C) ep= <<<< 00000000: 40 04 13 00 8b 81 01 00

Urb 450 (C) ep= <<<< 00000000: 40 04 13 00 82 81 01 00

Urb 451 (C) ep= <<<< 00000000: 40 04 13 00 83 81 01 00

Urb 452 (C) ep= <<<< 00000000: 40 04 13 00 86 81 01 00

Urb 453 (C) ep= <<<< 00000000: 40 04 13 00 87 81 01 00

Urb 454 (C) ep= <<<< 00000000: 40 04 13 00 88 81 01 00

Urb 455 (C) ep= <<<< 00000000: 40 04 13 00 89 81 01 00

Urb 456 (C) ep= <<<< 00000000: 40 04 13 00 86 81 01 00

Urb 457 (C) ep= <<<< 00000000: 40 04 13 00 87 81 01 00

Urb 458 (C) ep= <<<< 00000000: 40 04 13 00 88 81 01 00

Urb 459 (C) ep= <<<< 00000000: 40 04 13 00 89 81 01 00

Urb 460 (C) ep= <<<< 00000000: 40 04 13 00 62 81 01 00

Urb 461 (C) ep= <<<< 00000000: 40 04 13 00 62 81 01 00

Urb 462 (C) ep= <<<< 00000000: 40 04 13 00 62 81 01 00

Urb 463 (C) ep= <<<< 00000000: 40 04 13 00 00 80 01 00

Urb 464 (C) ep= <<<< 00000000: 40 04 13 00 00 80 01 00

Urb 465 (C) ep= <<<< 00000000: 40 04 13 00 47 81 01 00

Urb 466 (C) ep= <<<< 00000000: 39 00000000: c0 04 14 00 42 81 01 00

Urb 467 (C) ep= <<<< 00000000: 40 04 13 00 42 81 01 00

Urb 468 (C) ep= <<<< 00000000: 40 04 13 00 e4 0f 01 00

Urb 469 (C) ep= <<<< 00000000: 40 04 13 00 54 81 01 00

Urb 470 (C) ep= <<<< 00000000: 40 04 13 00 55 81 01 00

Urb 471 (C) ep= <<<< 00000000: 40 04 13 00 e4 0f 01 00

Urb 472 (C) ep= <<<< 00000000: 40 04 13 00 63 81 01 00

Urb 473 (C) ep= <<<< 00000000: 0c 00000000: c0 04 14 00 fd 0f 01 00

Urb 474 (C) ep= <<<< 00000000: 40 04 13 00 fd 0f 01 00

Urb 475 (C) ep= <<<< 00000000: 40 04 13 00 e4 0f 01 00

Urb 476 (C) ep= <<<< 00000000: 40 04 13 00 e4 0f 01 00

Urb 477 (C) ep= <<<< 00000000: 40 04 13 00 e4 0f 01 00

Urb 478 (C) ep= <<<< 00000000: 40 04 13 00 66 80 01 00

Urb 479 (C) ep= <<<< 00000000: 40 04 13 00 67 80 01 00

Urb 480 (C) ep= <<<< 00000000: 40 04 13 00 e4 0f 01 00

Urb 481 (C) ep= <<<< 00000000: 40 04 13 00 57 80 01 00

Urb 482 (C) ep= <<<< 00000000: 40 04 13 00 58 80 01 00

Urb 483 (C) ep= <<<< 00000000: 40 04 13 00 59 80 01 00

Urb 484 (C) ep= <<<< 00000000: 40 04 13 00 5a 80 01 00

Urb 485 (C) ep= <<<< 00000000: 40 04 13 00 00 81 01 00

Urb 486 (C) ep= <<<< 00000000: 40 04 13 00 6a 80 01 00

Urb 487 (C) ep= <<<< 00000000: 40 04 13 00 e2 0f 01 00

Urb 488 (C) ep= <<<< 00000000: 40 04 13 00 e4 0f 01 00

Urb 489 (C) ep= <<<< 00000000: 40 04 13 00 35 80 01 00

Urb 490 (C) ep= <<<< 00000000: 40 04 13 00 36 80 01 00

Urb 491 (C) ep= <<<< 00000000: 40 04 13 00 37 80 01 00

Urb 492 (C) ep= <<<< 00000000: 40 04 13 00 38 80 01 00

Urb 493 (C) ep= <<<< 00000000: 40 04 13 00 ab 0f 01 00

Urb 494 (C) ep= <<<< 00000000: 40 04 13 00 ac 0f 01 00

Urb 495 (C) ep= <<<< 00000000: 40 04 13 00 ad 0f 01 00

Urb 496 (C) ep= <<<< 00000000: 40 04 13 00 ae 0f 01 00

Urb 497 (C) ep= <<<< 00000000: 40 04 13 00 af 0f 01 00

Urb 498 (C) ep= <<<< 00000000: 40 04 13 00 a6 0f 01 00

Urb 499 (C) ep= <<<< 00000000: 40 04 13 00 a7 0f 01 00

Urb 500 (C) ep= <<<< 00000000: 40 04 13 00 a8 0f 01 00

Urb 501 (C) ep= <<<< 00000000: 40 04 13 00 a9 0f 01 00

Urb 502 (C) ep= <<<< 00000000: 40 04 13 00 aa 0f 01 00

Urb 503 (C) ep= <<<< 00000000: 54 00000000: c0 04 14 00 53 81 01 00

Urb 504 (C) ep= <<<< 00000000: 40 04 13 00 53 81 01 00

Urb 505 (C) ep= <<<< 00000000: 40 04 13 00 00 80 01 00

Urb 506 (C) ep= <<<< 00000000: 40 04 13 00 47 81 01 00

Urb 507 (C) ep= <<<< 00000000: 40 04 13 00 1b 80 01 00

Urb 508 (C) ep= <<<< 00000000: 40 04 13 00 17 80 01 00

Urb 509 (C) ep= <<<< 00000000: 40 04 13 00 1c 80 01 00

Urb 510 (C) ep= <<<< 00000000: 40 04 13 00 1d 80 01 00

Urb 511 (C) ep= <<<< 00000000: 40 04 13 00 08 80 01 00

Urb 512 (C) ep= <<<< 00000000: 40 04 13 00 09 80 01 00

Urb 513 (C) ep= <<<< 00000000: 40 04 13 00 0a 80 01 00

Urb 514 (C) ep= <<<< 00000000: 40 04 13 00 60 81 01 00

Urb 515 (C) ep= <<<< 00000000: 40 04 13 00 61 81 01 00

Urb 516 (C) ep= <<<< 00000000: 40 04 13 00 34 80 01 00

Urb 517 (C) ep= <<<< 00000000: 40 04 13 00 8a 81 01 00

Urb 518 (C) ep= <<<< 00000000: 40 04 13 00 8b 81 01 00

Urb 519 (C) ep= <<<< 00000000: 40 04 13 00 82 81 01 00

Urb 520 (C) ep= <<<< 00000000: 40 04 13 00 83 81 01 00

Urb 521 (C) ep= <<<< 00000000: 40 04 13 00 86 81 01 00

Urb 522 (C) ep= <<<< 00000000: 40 04 13 00 87 81 01 00

Urb 523 (C) ep= <<<< 00000000: 40 04 13 00 88 81 01 00

Urb 524 (C) ep= <<<< 00000000: 40 04 13 00 89 81 01 00

Urb 525 (C) ep= <<<< 00000000: 40 04 13 00 86 81 01 00

Urb 526 (C) ep= <<<< 00000000: 40 04 13 00 87 81 01 00

Urb 527 (C) ep= <<<< 00000000: 40 04 13 00 88 81 01 00

Urb 528 (C) ep= <<<< 00000000: 40 04 13 00 89 81 01 00

Urb 529 (C) ep= <<<< 00000000: 40 04 13 00 62 81 01 00

Urb 530 (C) ep= <<<< 00000000: 40 04 13 00 62 81 01 00

Urb 531 (C) ep= <<<< 00000000: 40 04 13 00 62 81 01 00

Urb 532 (C) ep= <<<< 00000000: 40 04 13 00 00 80 01 00

Urb 533 (C) ep= <<<< 00000000: 40 04 13 00 00 80 01 00

Urb 534 (C) ep= <<<< 00000000: 40 04 13 00 47 81 01 00

Urb 535 (C) ep= <<<< 00000000: 40 04 17 00 42 12 01 00

Urb 536 (C) ep= <<<< 00000000: 40 04 17 00 42 03 01 00

Urb 537 (C) ep= <<<< 00000000: 40 04 17 00 42 04 01 00

Urb 538 (C) ep= <<<< 00000000: 40 04 17 00 42 05 01 00

Urb 539 (C) ep= <<<< 00000000: 40 04 17 00 42 06 01 00

Urb 540 (C) ep= <<<< 00000000: 40 04 17 00 42 11 01 00

Urb 541 (C) ep= <<<< 00000000: 40 04 17 00 42 12 01 00

Urb 542 (C) ep= <<<< 00000000: 40 04 17 00 42 13 01 00

Urb 543 (C) ep= <<<< 00000000: 40 04 17 00 42 14 01 00

Urb 544 (C) ep= <<<< 00000000: 40 04 17 00 42 15 01 00

Urb 545 (C) ep= <<<< 00000000: 40 04 17 00 42 1f 01 00

Urb 546 (C) ep= <<<< 00000000: 40 04 17 00 42 20 01 00

Urb 547 (C) ep= <<<< 00000000: 40 04 17 00 42 23 01 00

Urb 548 (C) ep= <<<< 00000000: 40 04 17 00 42 24 01 00

Urb 549 (C) ep= <<<< 00000000: 40 04 17 00 42 25 01 00

Urb 550 (C) ep= <<<< 00000000: 40 04 17 00 42 26 01 00

Urb 551 (C) ep= <<<< 00000000: 40 04 17 00 42 27 01 00

Urb 552 (C) ep= <<<< 00000000: 40 04 17 00 42 28 01 00

Urb 553 (C) ep= <<<< 00000000: 40 04 17 00 42 2a 01 00

Urb 554 (C) ep= <<<< 00000000: 40 04 17 00 42 2b 01 00

Urb 555 (C) ep= <<<< 00000000: 40 04 17 00 42 2d 01 00

Urb 556 (C) ep= <<<< 00000000: 40 04 17 00 42 2f 01 00

Urb 557 (C) ep= <<<< 00000000: 40 04 17 00 42 30 01 00

Urb 558 (C) ep= <<<< 00000000: 40 04 17 00 42 31 01 00

Urb 559 (C) ep= <<<< 00000000: 40 04 17 00 42 60 01 00

Urb 560 (C) ep= <<<< 00000000: 40 04 17 00 42 61 01 00

Urb 561 (C) ep= <<<< 00000000: 40 04 17 00 42 62 01 00

Urb 562 (C) ep= <<<< 00000000: 40 04 17 00 42 63 01 00

Urb 563 (C) ep= <<<< 00000000: 40 04 17 00 42 64 01 00

Urb 564 (C) ep= <<<< 00000000: 40 04 17 00 42 65 01 00

Urb 565 (C) ep= <<<< 00000000: 40 04 17 00 42 67 01 00

Urb 566 (C) ep= <<<< 00000000: 40 04 17 00 42 68 01 00

Urb 567 (C) ep= <<<< 00000000: 40 04 17 00 42 69 01 00

Urb 568 (C) ep= <<<< 00000000: 40 04 17 00 42 6c 01 00

Urb 569 (C) ep= <<<< 00000000: 40 04 17 00 42 6d 01 00

Urb 570 (C) ep= <<<< 00000000: 40 04 17 00 42 6e 01 00

Urb 571 (C) ep= <<<< 00000000: 40 04 17 00 42 6f 01 00

Urb 572 (C) ep= <<<< 00000000: 40 04 17 00 42 74 01 00

Urb 573 (C) ep= <<<< 00000000: 40 04 17 00 42 75 01 00

Urb 574 (C) ep= <<<< 00000000: 40 04 17 00 42 77 01 00

Urb 575 (C) ep= <<<< 00000000: 40 04 17 00 42 7d 01 00

Urb 576 (C) ep= <<<< 00000000: 40 04 17 00 42 17 01 00

Urb 577 (C) ep= <<<< 00000000: 40 04 17 00 42 18 01 00

Urb 578 (C) ep= <<<< 00000000: 40 04 17 00 42 19 01 00

Urb 579 (C) ep= <<<< 00000000: 40 04 17 00 42 1a 01 00

Urb 580 (C) ep= <<<< 00000000: 40 04 13 00 44 80 01 00

Urb 581 (C) ep= <<<< 00000000: 40 04 13 00 45 80 01 00

Urb 582 (C) ep= <<<< 00000000: 40 04 13 00 46 80 01 00

Urb 583 (C) ep= <<<< 00000000: 40 04 13 00 47 80 01 00

Urb 584 (C) ep= <<<< 00000000: 40 04 13 00 48 80 01 00

Urb 585 (C) ep= <<<< 00000000: 40 04 13 00 49 80 01 00

Urb 586 (C) ep= <<<< 00000000: 40 04 13 00 4a 80 01 00

Urb 587 (C) ep= <<<< 00000000: 40 04 13 00 4b 80 01 00

Urb 588 (C) ep= <<<< 00000000: 40 04 13 00 4c 80 01 00

Urb 589 (C) ep= <<<< 00000000: 40 04 13 00 14 80 01 00

Urb 590 (C) ep= <<<< 00000000: 40 04 13 00 15 80 01 00

Urb 591 (C) ep= <<<< 00000000: 40 04 13 00 16 80 01 00

Urb 592 (C) ep= <<<< 00000000: 40 04 17 00 42 01 01 00

Urb 593 (C) ep= <<<< 00000000: 40 04 17 00 42 02 01 00

Urb 594 (C) ep= <<<< 00000000: 40 04 13 00 80 81 01 00

Urb 595 (C) ep= <<<< 00000000: 40 04 13 00 81 81 01 00

Urb 596 (C) ep= <<<< 00000000: 40 04 17 00 42 10 01 00

Urb 597 (C) ep= <<<< 00000000: 40 04 17 00 42 76 01 00

Urb 598 (C) ep= <<<< 00000000: 40 04 17 00 42 00 01 00

Urb 599 (C) ep= <<<< 00000000: 40 04 13 00 63 81 01 00

Urb 600 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 601 (C) ep= <<<< 00000000: 00 00000000: c0 04 14 00 fc 0f 01 00

Urb 602 (C) ep= <<<< 00000000: 40 04 13 00 fc 0f 01 00

Urb 603 (C) ep=0x00000081 >>>>

Urb 604 (C) ep= >>>>

Urb 605 (C) ep=0x00000081 >>>>

Urb 605 (C) ep=0x00000081 <<<<
 00000000: ff ff ff ff 02 60 fb ec 0e 73 85 c6 23 98 88 9e
 00000010: 23 db 49 dd 6f f7 ce fc f4 e9 9d 2f 1a 5e eb 7f
 00000020: be 77 e7 a4 ee b7 3f be 77 e7 a2 8a 5e eb 7f be
 00000030: 77 e7 a3 75 be b3 fc f4 51 46 eb 7f be 3f cf 46
 00000040: eb 7d 6e fc f4 51 46 eb 7f be 77 e7 a4 f9 c6 ff
 00000050: 7c 7f 9e 8a 2a 25 dd c6 71 dd 99 e7 f5 9d 72 1b
 00000060: c1 fc d3 a7 55 d3 4f 2f ae a3 9f 6f 33 fc f4 b1
 00000070: ff 3c e9 a3 a9 58 8d 2f f3 d2 4f eb 3f cf 45 18
 00000080: 8d 44 77 d6 7f 9e 93 13 fd 69 5c cf f3 d1 46 23
 00000090: 5a 1b 52 b3 58 9e 23 d3 e9 ab 61 5f b4 7f 2d 36
 000000a0: b7 1d 44 68 88 9d 2f 6b e9 fc b4 6d 1f b7 f2 d3
 000000b0: bb c7 4d e3 41 a8 fd 23 f9 69 3b 4e f4 8f e5 a5
 000000c0: ef 1d 18 d2 71 77 a4 7f 2d 24 f7 bf ba 1f cb 46
 000000d0: f5 18 d1 99 ff 74 3f 96 93 bc 7e 9f d3 4b ce 8c
 000000e0: 68 dd 3c fa 47 f2 d1 bb ed 1f cb 46 74 9c 68 f3
 000000f0: 9e d1 fc b4 79 c1 f4 8f e5 a2 97 51 a5 4c 33 6a
 00000100: 84 44 7f 2d 4b 5b 84 44 73 11 fc b4 1d 18 d3 bb
 00000110: a3 e9 1f cb 46 e8 fa 47 f2 d1 ce 8a 37 95 e9 1f
 00000120: cb 4b de 1f 48 fe 5a 4f 3a 28 cd 5e 95 7e 5a 3e
 000001f0: 73 f6 f4 d5 5d d2 4d a9 d1 5b bd 11 6a e3 da 35
 00000200: 11 cd 57 4d 3a 2a 3a f2 e7 88 52 a3 ac 5d b4 ac
 00000210: 54 e3 c7 3c 6b 9e ed 89 f3 ed 3e 74 93 5d 44 31
 00000220: c4 cf 3c f1 ac a2 9d ce b5 42 3c 6a 3c b5 f5 d5
 00000230: 61 89 ef 3a 9d b4 0f fa 5e 2f fb d1 fe 7a fa 8f
 00000240: e1 f9 e7 e1 d6 95 ed fd d7 11 33 ef e2 35 a7 b5
 00000250: 1f 11 fc 75 5f 74 1e 26 7f e7 ae ba e0 f3 1e be
 00000260: 7d e7 4b cf 9f b6 83 c7 bf fc 74 67 8f 7e 35 2e
 00000270: ab e8 ed cf 1a 33 e7 9e 7f 96 8e b1 e2 23 f9 e9
 00000280: 66 7d 34 9f a6 97 41 e2 67 d7 8e 34 67 df 88 e3
 00000290: 41 fd 7c e8 e3 c7 9f e7
 */
 DBG (DBG_proc, "at the moment URB 13 last command \n");
	  /*  configuration = 1, interface = 0, alternate = 2 */
	  status = m560x_set_config (dev, 1, 0, 2);
	  if (status != SANE_STATUS_GOOD)
	    {
	      DBG (DBG_error,
		   "m560x_vidcam_init: M560X FAILED to set configure\n");
	      return status;
	    }

	  DBG (DBG_info, "m560x_identify_vidcam: exit vidcam supported\n");
	  return SANE_TRUE;
	}
    }
  dev->framecount = 0;
  DBG (DBG_error, "m560x_identify_vidcam: exit this is not a M560X exit\n");
  return SANE_FALSE;
}

static SANE_Status
m560x_vidcam_init (M560x_Vidcam * dev)
{
  SANE_Status status;
  SANE_Byte i = 0;
  SANE_Byte val = 0;
  size_t sizer;
  size_t sizew;
  DBG (DBG_proc, "m560x_vidcam_init: open\n");

      sizew = dev->windoww_size;
      sizer = dev->windowr_size;

      memset (dev->windoww, 0, sizew);
      memset (dev->windowr, 0, sizer);

      DBG (DBG_proc, "at the moment URB 13 last command \n");
      sizer = 0x08;
      status =
	sanei_usb_control_msg (dev->fd, 0xc1, 0x8d, 0x0000, 0, sizer,
			       dev->windowr);
      if (status != SANE_STATUS_GOOD)
	goto done;

      DBG (DBG_proc, "m560x_vidcam_init: urb 14 CMDID_GET_USER_INFO\n");
      sizer = 0x08;
      status =
	sanei_usb_control_msg (dev->fd, 0xc1, 0x8d, 0x0000, 0, sizer,
			       dev->windowr);
      if (status != SANE_STATUS_GOOD)
	goto done;
      if (dev->windowr[1] != 0x08)
	{
	  DBG (DBG_proc,
	       "m560x_vidcam_init: urb 14, val = 0x%x (mode: 0x01=start, 0x02=video, 0x04=busy, 0x08=idle)\n",
	       dev->windowr[0]);
	  goto done;
	}

      /*  Switch to Video mode: 0x0000 = CIF (352x288), 0x0200 = QCIF (176x144)  */
      /*  Switch to Video mode: 0x0100 = VGA (640x480), 0x0300 = QVGA (320x240)  */
      sizew = 0x0;
      status =
	sanei_usb_control_msg (dev->fd, 0x41, 0x09, dev->video_mode, 0, sizew,
			       dev->windoww);
      if (status != SANE_STATUS_GOOD)
	{
	  return status;
	}
      DBG (DBG_proc,
	   "m560x_vidcam_init: CMDID_START_VIDEO: video_mode=0x%x\n",
	   dev->video_mode);
  status = SANE_STATUS_GOOD;
done:
  if (status)
    {
      DBG (DBG_error, "m560x_vidcam_init failed : %s\n",
	   sane_strstatus (status));
    }
  DBG (DBG_proc, "m560x_vidcam_init: exit, status=%d\n", status);
  return status;
}

/* Attach a vidcam to this backend. */
static SANE_Status
attach_vidcam (SANE_String_Const devicename, M560x_Vidcam ** devp)
{
  M560x_Vidcam *dev;
  int fd;

  DBG (DBG_proc, "attach_vidcam: %s\n", devicename);

  if (devp)
    *devp = NULL;

  /* Check if we know this device name. */
  for (dev = first_dev; dev; dev = dev->next)
    {
      if (strcmp (dev->sane.name, devicename) == 0)
	{
	  if (devp)
	    {
	      *devp = dev;
	    }
	  DBG (DBG_info, "device is already known\n");
	  return SANE_STATUS_GOOD;
	}
    }

  /* Allocate a new vidcam entry. */
  dev = m560x_init ();
  if (dev == NULL)
    {
      DBG (DBG_error, "m560x_init ERROR: not enough memory\n");
      return SANE_STATUS_NO_MEM;
    }

  DBG (DBG_info, "attach_vidcam: opening USB device %s\n", devicename);

  if (sanei_usb_open (devicename, &fd) != 0)
    {
      DBG (DBG_error, "ERROR: attach_vidcam: open failed\n");
      m560x_free (dev);
      return SANE_STATUS_INVAL;
    }
  /* Fill some scanner specific values. */
  dev->devicename = strdup (devicename);
  dev->fd = fd;

  /* Now, check that it is a vidcam we support. */

  if (m560x_identify_vidcam (dev) == SANE_FALSE)
    {
      DBG (DBG_error, "ERROR: attach_vidcam: vidcam-identification failed\n");
      m560x_free (dev);
      return SANE_STATUS_INVAL;
    }

  /* Allocate a buffer memory. */
  dev = m560x_init_2 ();
  if (dev == NULL)
    {
      DBG (DBG_error, "m560x_initi_2, ERROR: not enough memory\n");
      return SANE_STATUS_NO_MEM;
    }

  m560x_close (dev);

  DBG (DBG_info, "attach_vidcam: opening USB device %s\n", devicename);

  /* Build list of vidcam supported resolutions. */
  DBG (DBG_proc, "attach_vidcam: build resolution list\n");

  if (dev->hw->color_adjust[0].resolution_x != 0)
    {
      int num_entries;
      int i;
      num_entries = 0;

      while (dev->hw->color_adjust[num_entries].resolution_x != 0)
	num_entries++;

      dev->resolutions_list = malloc (sizeof (SANE_Word) * (num_entries + 1));

      if (dev->resolutions_list == NULL)
	{
	  DBG (DBG_error,
	       "ERROR: attach_vidcam: vidcam resolution list failed\n");
	  m560x_free (dev);
	  return SANE_STATUS_NO_MEM;
	}
      /* for CIF or VGA sensor different resolutions  */
      if (dev->CIF)
	num_entries = 2;
      if (dev->VGA)
	num_entries = 3;
      dev->resolutions_list[0] = num_entries;
      DBG (DBG_proc, "attach_vidcam: make color resolution table \n");
      for (i = 0; i < num_entries; i++)
	{
	  dev->resolutions_list[i + 1 + dev->VGA + dev->QVGA] =
	    dev->hw->color_adjust[i].resolution_x;
	}
    }
  else
    {
      dev->resolutions_list = NULL;
    }

  /* Set the default options for that vidcam. */
  dev->sane.name = dev->devicename;
  dev->sane.vendor = dev->hw->vendor_name;
  dev->sane.model = dev->hw->product_name;
  dev->sane.type = SANE_I18N ("vidcam/webcam");

  /* Link the vidcam with the others. */
  dev->next = first_dev;
  first_dev = dev;

  if (devp)
    {
      *devp = dev;
    }

  num_devices++;

  DBG (DBG_proc, "attach_vidcam: exit\n");

  return SANE_STATUS_GOOD;
}

static SANE_Status
attach_one (const char *dev)
{
  DBG (DBG_proc, "attach_one: open \n");
  attach_vidcam (dev, NULL);
  DBG (DBG_proc, "attach_one: exit \n");
  return SANE_STATUS_GOOD;
}

/* Reset the options for that vidcam. */
static void
m560x_init_options (M560x_Vidcam * dev)
{
  int i;

  DBG (DBG_proc, "m560x_init_options: open\n");

  /* Pre-initialize the options. */
  memset (dev->opt, 0, sizeof (dev->opt));
  memset (dev->val, 0, sizeof (dev->val));

  for (i = 0; i < OPT_NUM_OPTIONS; ++i)
    {
      dev->opt[i].size = sizeof (SANE_Word);
      dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
    }
  DBG (DBG_proc, "m560x_init_options: done loop opt_num_options=%d, i=%d \n",
       OPT_NUM_OPTIONS, i);
  /* Number of options. */
  dev->opt[OPT_NUM_OPTS].name = "";
  dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
  dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
  dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
  dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
  dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS;

  /* Mode group */
  dev->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode");
  dev->opt[OPT_MODE_GROUP].desc = "";	/* not valid for a group */
  dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
  dev->opt[OPT_MODE_GROUP].cap = 0;
  dev->opt[OPT_MODE_GROUP].size = 0;
  dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;

  /* Vidcam supported modes */
  dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
  dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
  dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
  dev->opt[OPT_MODE].type = SANE_TYPE_STRING;
  dev->opt[OPT_MODE].size = max_string_size (scan_mode_list);
  dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
  dev->opt[OPT_MODE].constraint.string_list = scan_mode_list;
  dev->val[OPT_MODE].s = (SANE_Char *) strdup ("");	/* will be set later */

  /* X and Y resolution */
  dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
  dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
  dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
  dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
  dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
  dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
  dev->val[OPT_RESOLUTION].w = dev->resolutions_list[dev->CIF + dev->QCIF + dev->VGA + dev->QVGA + dev->QSIF];	/* value will be 2 or 3 */

  /* brightness   */
  dev->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
  dev->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
  dev->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
  dev->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
  dev->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
  dev->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
  dev->opt[OPT_BRIGHTNESS].constraint.range = &brightness_range;
  dev->val[OPT_BRIGHTNESS].w = 0;	/* to get middle value */

  /* Enhancement group */
  dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement");
  dev->opt[OPT_ENHANCEMENT_GROUP].desc = "";	/* not valid for a group */
  dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
  dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED;
  dev->opt[OPT_ENHANCEMENT_GROUP].size = 0;
  dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;

  /* red level calibration manual correction */
  dev->opt[OPT_WHITE_LEVEL_R].name = SANE_NAME_WHITE_LEVEL_R;
  dev->opt[OPT_WHITE_LEVEL_R].title = SANE_TITLE_WHITE_LEVEL_R;
  dev->opt[OPT_WHITE_LEVEL_R].desc = SANE_DESC_WHITE_LEVEL_R;
  dev->opt[OPT_WHITE_LEVEL_R].type = SANE_TYPE_INT;
  dev->opt[OPT_WHITE_LEVEL_R].unit = SANE_UNIT_NONE;
  dev->opt[OPT_WHITE_LEVEL_R].constraint_type = SANE_CONSTRAINT_RANGE;
  dev->opt[OPT_WHITE_LEVEL_R].constraint.range = &red_level_range;
  dev->val[OPT_WHITE_LEVEL_R].w = 00;	/* to get middle value */

  /* green level calibration manual correction */
  dev->opt[OPT_WHITE_LEVEL_G].name = SANE_NAME_WHITE_LEVEL_G;
  dev->opt[OPT_WHITE_LEVEL_G].title = SANE_TITLE_WHITE_LEVEL_G;
  dev->opt[OPT_WHITE_LEVEL_G].desc = SANE_DESC_WHITE_LEVEL_G;
  dev->opt[OPT_WHITE_LEVEL_G].type = SANE_TYPE_INT;
  dev->opt[OPT_WHITE_LEVEL_G].unit = SANE_UNIT_NONE;
  dev->opt[OPT_WHITE_LEVEL_G].constraint_type = SANE_CONSTRAINT_RANGE;
  dev->opt[OPT_WHITE_LEVEL_G].constraint.range = &green_level_range;
  dev->val[OPT_WHITE_LEVEL_G].w = 00;	/* to get middle value */

  /* blue level calibration manual correction */
  dev->opt[OPT_WHITE_LEVEL_B].name = SANE_NAME_WHITE_LEVEL_B;
  dev->opt[OPT_WHITE_LEVEL_B].title = SANE_TITLE_WHITE_LEVEL_B;
  dev->opt[OPT_WHITE_LEVEL_B].desc = SANE_DESC_WHITE_LEVEL_B;
  dev->opt[OPT_WHITE_LEVEL_B].type = SANE_TYPE_INT;
  dev->opt[OPT_WHITE_LEVEL_B].unit = SANE_UNIT_NONE;
  dev->opt[OPT_WHITE_LEVEL_B].constraint_type = SANE_CONSTRAINT_RANGE;
  dev->opt[OPT_WHITE_LEVEL_B].constraint.range = &blue_level_range;
  dev->val[OPT_WHITE_LEVEL_B].w = 00;	/* to get middle value */

  DBG (DBG_proc, "m560x_init_options: after blue level\n");

  /* Lastly, set the default scan mode. This might change some
   * values previously set here. */

  sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE,
		       (SANE_String_Const *) scan_mode_list[0], NULL);
  DBG (DBG_proc, "m560x_init_options: exit\n");
}

/* Read the image from the vidcam and fill the temporary buffer with it. */
static SANE_Status
m560x_fill_image (M560x_Vidcam * dev)
{
  SANE_Status status;
  size_t size;
  size_t bulk_size_read;

  assert (dev->image_begin == dev->image_end);
  assert (dev->real_bytes_left > 0);

  DBG (DBG_proc, "m560x_fill_image: enter\n");

  DBG (DBG_proc, "m560x_fill_image: real dev bytes left=0x%x \n",
       dev->real_bytes_left);
  bulk_size_read = dev->real_bytes_left;

  while (dev->real_bytes_left)
    {
      /* Try to read the maximum number of bytes. */
      DBG (DBG_proc,
	   "m560x_fill_image: real dev bytes left, while loop=0x%x \n",
	   dev->real_bytes_left);

      size = dev->real_bytes_left;
      if (size < bulk_size_read)
	{
	  size = bulk_size_read;	/* it seems size can not be smaller then read by bulk */
	}
      if (size == 0)
	{
	  /* Probably reached the end of the buffer. Check, just in case. */
	  assert (dev->image_end != 0);
	  return (SANE_STATUS_GOOD);
	}

      /* Do the transfer */

      DBG (DBG_proc,
	   "m560x_fill_image: dev->real_bytes_left: 0x%x size: 0x%x\n",
	   dev->real_bytes_left, size);
      usleep (2000);
      /* urb 44 first read bulk */

      status = sanei_usb_read_bulk (dev->fd, dev->buffer, &size);

      if (status != SANE_STATUS_GOOD)
	{
	  return status;
	}

      DBG (DBG_info,
	   "m560x_fill_image: size (read) = 0x%lx bytes (bpl=0x%lx)\n",
	   (long) size, (long) dev->params.bytes_per_line);

      memcpy (dev->image + dev->image_end, dev->buffer, size);

      dev->image_end += size;
      bulk_size_read = size;
      if (dev->real_bytes_left > size)
	dev->real_bytes_left -= size;
      else if (dev->real_bytes_left <= size)	/* last loop */
	dev->real_bytes_left = 0;
      DBG (DBG_info, "m560x_fill_image: real bytes left = 0x%x\n",
	   dev->real_bytes_left);
    }
  dev->origGain = 80;

  DBG (DBG_proc, "m560x_fill_image: exit\n");
  return (SANE_STATUS_GOOD);	/* unreachable */
}

/**********************************************************************
*
* The add_text routine and font_6x11.h file are taken from the (GPLed) 
* webcam.c file, part of xawtv,   (c) 1998-2002 Gerd Knorr.
* add_text was slightly modified for the pencam2 program.
* m560x_add_text was taken from the pencam2 program and changed on
* some points
*
*********************************************************************/

#define MSG_MAXLEN   45 
#define CHAR_HEIGHT  11 
#define CHAR_WIDTH   6 
#define CHAR_START   4 

static SANE_Status
m560x_add_text (SANE_Byte * image, int width, int height, char *txt)
{
  SANE_Status status;
  time_t t;
  struct tm *tm;
  char line[MSG_MAXLEN + 1];
  SANE_Byte *ptr;
  int i, x, y, f, len;
  char fmtstring[25] = " %Y-%m-%d %H:%M:%S";
  char fmttxt[46];

  DBG (DBG_proc, "m560x_add_text: enter\n");
  time (&t);
  tm = localtime (&t);
  if (strlen (txt) > (MSG_MAXLEN - 23))
    strncpy (fmttxt, txt, (MSG_MAXLEN - 23));
  else
    strcpy (fmttxt, txt);
  strcat (fmttxt, fmtstring);

  len = strftime (line, MSG_MAXLEN, fmttxt, tm);

  for (y = 0; y < CHAR_HEIGHT; y++)
    {
      ptr = image + 3 * width * (height - CHAR_HEIGHT - 2 + y) + 12;

      for (x = 0; x < len; x++)
	{
	  f = fontdata[line[x] * CHAR_HEIGHT + y];
	  for (i = CHAR_WIDTH - 1; i >= 0; i--)
	    {
	      if (f & (CHAR_START << i))
		{
		  ptr[0] = 255;
		  ptr[1] = 255;
		  ptr[2] = 255;
		}
	      ptr += 3;
	    }			/* for i */
	}			/* for x */
    }				/* for y */

  DBG (DBG_proc, "m560x_add_text: exit vw=%d, vh=%d\n", width, height);
  status = (SANE_STATUS_GOOD);
  return status;

}				/*  add_text  */

/* **************************  Video Decoding  *********************  */

static SANE_Status
m560x_bayer_unshuffle (M560x_Vidcam * dev, SANE_Byte * buf, size_t * len)
{
  SANE_Status status;
  size_t size;
  int x, y, i = 0;
  int RED, GREEN, BLUE;
  int w = dev->cwidth;
  int vw = dev->cwidth;
  int vh = dev->cheight;
  SANE_Byte p = 0;
  int colour = 0, bayer = 0;
  int bright_red;
  int bright_green;
  int bright_blue;
  int count;

  RED = dev->red;
  GREEN = dev->green;
  BLUE = dev->blue;

  DBG (DBG_proc, "m560x_bayer_unshuffle: enter\n");

  /* copy from image to output buffer */

  size = vw * vh * 3;
  memcpy (dev->output, dev->image, size);

  /* brightness adjustment */

  count = vw * vh * 3;

  bright_red = (dev->val[OPT_BRIGHTNESS].w) + (dev->val[OPT_WHITE_LEVEL_R].w);
  bright_green =
    (dev->val[OPT_BRIGHTNESS].w) + (dev->val[OPT_WHITE_LEVEL_G].w);
  bright_blue =
    (dev->val[OPT_BRIGHTNESS].w) + (dev->val[OPT_WHITE_LEVEL_B].w);

  for (x = 0; x < count; x++)
    {
      y = x + 1;
      i = x + 2;
      if ((*(dev->output + x) + bright_red) >= 255)
	*(dev->output + x) = 255;

      else if ((*(dev->output + x) + bright_red) <= 0)
	*(dev->output + x) = 0;
      else
	*(dev->output + x) += bright_red;

      if ((*(dev->output + y) + bright_green) >= 255)
	*(dev->output + y) = 255;

      else if ((*(dev->output + y) + bright_green) <= 0)
	*(dev->output + y) = 0;
      else
	*(dev->output + y) += bright_green;

      if ((*(dev->output + i) + bright_blue) >= 255)
	*(dev->output + i) = 255;

      else if ((*(dev->output + i) + bright_blue) <= 0)
	*(dev->output + i) = 0;
      else
	*(dev->output + i) += bright_blue;

      x += 2;
    }

  if (dev->scan_mode == M560X_COLOR_RGB_TEXT)
    {
/* insert add text routine                 */
/**********************************************************************
*
* The add_text routine and font_6x11.h file are taken from the (GPLed) 
* webcam.c file, part of xawtv,   (c) 1998-2002 Gerd Knorr.
* add_text was slightly modified for this program.
*
*********************************************************************/
      strcpy (dev->picmsg_ps, "M5603C");

      status = m560x_add_text (dev->output, vw, vh, dev->picmsg_ps);
      if (status != SANE_STATUS_GOOD)
	{
	  DBG (DBG_info, "m560x_bayer_unshuffle status NOK\n");
	  return (status);
	}
    }

/* end of add text routine                 */
  /* copy from output to buf,  */
  size = vw * vh * 3;
  memcpy (buf, dev->output, size);

  DBG (DBG_proc, "m560x_bayer_unshuffle: exit vw=%d, vh=%d\n", vw, vh);
  status = (SANE_STATUS_GOOD);
  return status;
}

/* end routines from the decoding image routine bayer_unshuffle *********/

/* Sane entry points */

SANE_Status
sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
{
  FILE *fp;
  char line[PATH_MAX];
  size_t len;

  DBG_INIT ();

  DBG (DBG_sane_init, "sane_init\n");

  authorize = authorize;	/* silence gcc */

  DBG (DBG_error, "This is sane-m560x version %d.%d-%d\n", V_MAJOR,
       V_MINOR, BUILD);
  DBG (DBG_error, "(C) 2005 by Gerard Klaver\n");

  if (version_code)
    {
      *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD);
    }

  sanei_usb_init ();

  fp = sanei_config_open (M560X_CONFIG_FILE);
  if (!fp)
    {
      /* No default vidcam? */
      DBG (DBG_warning, "configuration file not found (%s)\n",
	   M560X_CONFIG_FILE);

      return SANE_STATUS_GOOD;
    }

  while (sanei_config_read (line, sizeof (line), fp))
    {
      SANE_Word vendor;
      SANE_Word product;

      if (line[0] == '#')	/* ignore line comments */
	continue;
      len = strlen (line);

      if (!len)
	continue;		/* ignore empty lines */
      if (sscanf (line, "usb %i %i", &vendor, &product) == 2)
	{

	  sanei_usb_attach_matching_devices (line, attach_one);
	}
      else
	{
	  /* Garbage. Ignore. */
	  DBG (DBG_warning, "bad configuration line: \"%s\" - ignoring.\n",
	       line);
	}
    }

  fclose (fp);

  DBG (DBG_proc, "sane_init: exit\n");

  return SANE_STATUS_GOOD;
}

SANE_Status
sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
{
  M560x_Vidcam *dev;
  int i;

  DBG (DBG_proc, "sane_get_devices: enter\n");

  local_only = local_only;	/* silence gcc */

  if (devlist)
    free (devlist);

  devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
  if (!devlist)
    return SANE_STATUS_NO_MEM;

  i = 0;
  for (dev = first_dev; i < num_devices; dev = dev->next)
    devlist[i++] = &dev->sane;
  devlist[i++] = 0;

  *device_list = devlist;

  DBG (DBG_proc, "sane_get_devices: exit\n");

  return SANE_STATUS_GOOD;
}

SANE_Status
sane_open (SANE_String_Const devicename, SANE_Handle * handle)
{
  M560x_Vidcam *dev;
  SANE_Status status;

  DBG (DBG_proc, "sane_open: enter\n");

  /* search for devicename */
  if (devicename[0])
    {
      DBG (DBG_info, "sane_open: devicename=%s\n", devicename);

      for (dev = first_dev; dev; dev = dev->next)
	{
	  if (strcmp (dev->sane.name, devicename) == 0)
	    {
	      break;
	    }
	}

      if (!dev)
	{
	  status = attach_vidcam (devicename, &dev);
	  if (status != SANE_STATUS_GOOD)
	    {
	      return status;
	    }
	}
    }
  else
    {
      DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n");
      dev = first_dev;		/* empty devicename -> use first device */
    }

  if (!dev)
    {
      DBG (DBG_error, "No vidcam found\n");

      return SANE_STATUS_INVAL;
    }

  m560x_init_options (dev);

  *handle = dev;

  DBG (DBG_proc, "sane_open: exit\n");

  return SANE_STATUS_GOOD;
}

const SANE_Option_Descriptor *
sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
{
  M560x_Vidcam *dev = handle;

  DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option);

  if ((unsigned) option >= OPT_NUM_OPTIONS)
    {
      return NULL;
    }

  DBG (DBG_proc, "sane_get_option_descriptor: exit\n");

  return dev->opt + option;
}

SANE_Status
sane_control_option (SANE_Handle handle, SANE_Int option,
		     SANE_Action action, void *val, SANE_Int * info)
{
  M560x_Vidcam *dev = handle;
  SANE_Status status;
  SANE_Word cap;

  DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n",
       option, action);

  if (info)
    {
      *info = 0;
    }

  if (dev->scanning)
    {
      return SANE_STATUS_DEVICE_BUSY;
    }

  if (option < 0 || option >= OPT_NUM_OPTIONS)
    {
      return SANE_STATUS_INVAL;
    }

  cap = dev->opt[option].cap;
  if (!SANE_OPTION_IS_ACTIVE (cap))
    {
      return SANE_STATUS_INVAL;
    }

  if (action == SANE_ACTION_GET_VALUE)
    {

      switch (option)
	{
	  /* word options */
	case OPT_NUM_OPTS:
	case OPT_RESOLUTION:
	case OPT_BRIGHTNESS:
	case OPT_WHITE_LEVEL_R:
	case OPT_WHITE_LEVEL_G:
	case OPT_WHITE_LEVEL_B:
	  *(SANE_Word *) val = dev->val[option].w;
	  return SANE_STATUS_GOOD;
	case OPT_MODE:
	  strcpy (val, dev->val[option].s);
	  return SANE_STATUS_GOOD;
	default:
	  return SANE_STATUS_INVAL;
	}
    }
  else if (action == SANE_ACTION_SET_VALUE)
    {

      if (!SANE_OPTION_IS_SETTABLE (cap))
	{
	  DBG (DBG_error, "could not set option, not settable\n");
	  return SANE_STATUS_INVAL;
	}

      status = sanei_constrain_value (dev->opt + option, val, info);
      if (status != SANE_STATUS_GOOD)
	{
	  DBG (DBG_error, "could not set option, invalid value\n");
	  return status;
	}

      switch (option)
	{

	  /* Numeric side-effect options */
	case OPT_RESOLUTION:
	case OPT_BRIGHTNESS:
	case OPT_WHITE_LEVEL_R:
	case OPT_WHITE_LEVEL_G:
	case OPT_WHITE_LEVEL_B:
	  if (info)
	    {
	      *info |= SANE_INFO_RELOAD_PARAMS;
	    }
	  dev->val[option].w = *(SANE_Word *) val;
	  return SANE_STATUS_GOOD;

	  /* String side-effect options */
	case OPT_MODE:
	  if (strcmp (dev->val[option].s, val) == 0)
	    return SANE_STATUS_GOOD;

	  free (dev->val[OPT_MODE].s);
	  dev->val[OPT_MODE].s = (SANE_Char *) strdup (val);

	  dev->opt[OPT_WHITE_LEVEL_R].cap &= ~SANE_CAP_INACTIVE;
	  dev->opt[OPT_WHITE_LEVEL_G].cap &= ~SANE_CAP_INACTIVE;
	  dev->opt[OPT_WHITE_LEVEL_B].cap &= ~SANE_CAP_INACTIVE;

	  if (strcmp (dev->val[OPT_MODE].s, COLOR_RAW_STR) == 0)
	    {
	      dev->scan_mode = M560X_COLOR_RAW;
	    }
	  else if (strcmp (dev->val[OPT_MODE].s, COLOR_RGB_STR) == 0)
	    {
	      dev->scan_mode = M560X_COLOR_RGB;
	    }
	  else if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR)
		   == 0)
	    {
	      dev->scan_mode = M560X_COLOR;

	    }
	  else if (strcmp (dev->val[OPT_MODE].s, COLOR_RGB_TEXT_STR) == 0)
	    {
	      dev->scan_mode = M560X_COLOR_RGB_TEXT;

	    }

	  /* The M560X supports only a handful of resolution. */
	  /* This the default resolution range for the M560X */

	  dev->depth = 8;
	  if (dev->resolutions_list != NULL)
	    {
	      int i;

	      dev->opt[OPT_RESOLUTION].constraint_type =
		SANE_CONSTRAINT_WORD_LIST;
	      dev->opt[OPT_RESOLUTION].constraint.word_list =
		dev->resolutions_list;

	      /* If the resolution isn't in the list, set a default. */
	      for (i = 1; i <= dev->resolutions_list[0]; i++)
		{
		  if (dev->resolutions_list[i] >= dev->val[OPT_RESOLUTION].w)
		    break;
		}
	      if (i > dev->resolutions_list[0])
		{
		  /* Too big. Take lowest. */
		  dev->val[OPT_RESOLUTION].w = dev->resolutions_list[1];
		}
	      else
		{
		  /* Take immediate superioir value. */
		  dev->val[OPT_RESOLUTION].w = dev->resolutions_list[i];
		}
	    }

	  /* String side-effect options */

	  if (info)
	    {
	      *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
	    }
	  return SANE_STATUS_GOOD;
	default:
	  return SANE_STATUS_INVAL;
	}
    }

  DBG (DBG_proc, "sane_control_option: exit, bad\n");

  return SANE_STATUS_UNSUPPORTED;
}

SANE_Status
sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
{
  M560x_Vidcam *dev = handle;
  int i;

  DBG (DBG_proc, "sane_get_parameters: enter\n");

  if (!(dev->scanning))
    {
      dev->x_resolution = dev->val[OPT_RESOLUTION].w;
      /* Prepare the parameters for the caller. */
      memset (&dev->params, 0, sizeof (SANE_Parameters));

      dev->params.last_frame = SANE_TRUE;

      switch (dev->scan_mode)
	{
	case M560X_COLOR_RAW:
	case M560X_COLOR_RGB:
	case M560X_COLOR:
	case M560X_COLOR_RGB_TEXT:
	  dev->bytes_pixel = 3;
	  break;
	}
      dev->params.format = SANE_FRAME_RGB;
      dev->params.pixels_per_line = dev->x_resolution;
      dev->params.bytes_per_line =
	dev->params.pixels_per_line * dev->bytes_pixel;
      dev->params.depth = 8;
      if (dev->resolutions_list != NULL)
	{
	  /* This vidcam has a fixed number of supported
	   * resolutions. Find the color sequence for that
	   * resolution. */

	  for (i = 0;
	       dev->hw->color_adjust[i].resolution_x != dev->x_resolution;
	       i++);

	  dev->red = dev->hw->color_adjust[i].z1_color_0;
	  dev->green = dev->hw->color_adjust[i].z1_color_1;
	  dev->blue = dev->hw->color_adjust[i].z1_color_2;
	  dev->y_resolution = dev->hw->color_adjust[i].resolution_y;
	}
      dev->params.lines = dev->y_resolution;
      switch (dev->val[OPT_RESOLUTION].w)
	{
	case 176:
	  dev->video_mode = 0x0200;
	  dev->cwidth = dev->x_resolution + 2;
	  dev->cheight = dev->y_resolution + 2;
	  break;
	case 160:
	  dev->video_mode = 0x0300;
	  dev->cwidth = dev->x_resolution + 2;
	  dev->cheight = dev->y_resolution + 2;
	  break;
	case 320:
	  dev->video_mode = 0x0300;
	  dev->cwidth = dev->x_resolution + 2;
	  dev->cheight = dev->y_resolution + 2;
	  break;
	case 352:
	  dev->video_mode = 0x0000;
	  dev->cwidth = dev->x_resolution + 4;
	  dev->cheight = dev->y_resolution + 4;
	  break;
	case 640:
	  dev->video_mode = 0x0100;
	  dev->cwidth = dev->x_resolution + 4;
	  dev->cheight = dev->y_resolution + 4;
	  break;
	}
      dev->params.pixels_per_line = dev->x_resolution;
      dev->params.lines = dev->y_resolution;
      dev->vwidth = dev->x_resolution;
      dev->vheight = dev->y_resolution;
      DBG (DBG_info, "sane_get_parameters: x=%d, y=%d\n", dev->x_resolution,
	   dev->y_resolution);
    }

  /* Return the current values. */
  if (params)
    {
      *params = (dev->params);
    }

  DBG (DBG_proc, "sane_get_parameters: exit\n");

  return SANE_STATUS_GOOD;
}

SANE_Status
sane_start (SANE_Handle handle)
{
  M560x_Vidcam *dev = handle;
  SANE_Status status;

  DBG (DBG_proc, "sane_start: enter\n");

  if (!(dev->scanning))
    {
      sane_get_parameters (dev, NULL);

      /* Open again the vidcam  */
      if (sanei_usb_open (dev->devicename, &(dev->fd)) != 0)
	{
	  DBG (DBG_error, "ERROR: sane_start: open failed\n");
	  return SANE_STATUS_INVAL;
	}

      /* Initialize the vidcam. */
      status = m560x_vidcam_init (dev);
      if (status)
	{
	  DBG (DBG_error, "ERROR: failed to init the vidcam\n");
	  m560x_close (dev);
	  return status;
	}

      dev->image_size = dev->buffer_size;
      dev->image = malloc (dev->image_size);
      if (dev->image == NULL)
	{
	  return SANE_STATUS_NO_MEM;
	}
    }

  dev->image_end = 0;
  dev->image_begin = 0;
  /* for jpeg streams this is different, todo for jpeg webcams */
  dev->real_bytes_left = dev->params.bytes_per_line * dev->params.lines;
  dev->bytes_left = dev->params.bytes_per_line * dev->params.lines;

  dev->scanning = SANE_TRUE;

  DBG (DBG_proc, "sane_start: exit\n");

  return SANE_STATUS_GOOD;
}

SANE_Status
sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
	   SANE_Int * len)
{
  SANE_Status status;
  M560x_Vidcam *dev = handle;
  size_t size;

  DBG (DBG_proc, "sane_read: enter\n");

  *len = 0;

  if (!(dev->scanning))
    {
      /* OOPS, not scanning, stop a scan. */
      m560x_reset_vidcam (dev);
      m560x_close (dev);
      dev->scanning = SANE_FALSE;
      return SANE_STATUS_CANCELLED;
    }

  if (dev->bytes_left <= 0)
    {
      return (SANE_STATUS_EOF);
    }

  if (dev->image_begin == dev->image_end)
    {
      /* Fill image */
      status = m560x_fill_image (dev);
      if (status != SANE_STATUS_GOOD)
	{
	  DBG (DBG_info, "sane_read: m560x_fill_image status NOK\n");
	  return (status);
	}
    }

  /* Something must have been read */
  if (dev->image_begin == dev->image_end)
    {
      DBG (DBG_info, "sane_read: nothing read\n");
      return SANE_STATUS_IO_ERROR;
    }

  size = dev->bytes_left;
  if (((unsigned int) max_len) < size)
    {
      DBG (DBG_error, "sane_read: max_len < size\n");
      return (SANE_FALSE);
    }
  if ((dev->image_end - dev->image_begin) > size)
    {
      size = dev->image_end - dev->image_begin;
      DBG (DBG_proc, "sane_read: size < dev->image_end - dev->image_begin\n");
    }
  /* diff between size an dev->bytes_left because of 356/352 and 292/288 */
  DBG (DBG_info, "sane_read: size =0x%x bytes, max_len=0x%x bytes\n",
       size, max_len);

  if (dev->scan_mode != M560X_COLOR_RAW)
    {
      /* dev->bytes_left -= size;  */
      *len = dev->bytes_left;	/* needed */
      dev->bytes_left = 0;	/* needed for frontend or ? */
      /* do bayer unshuffle  after complete frame is read */
      status = m560x_bayer_unshuffle (dev, buf, &size);
      if (status != SANE_STATUS_GOOD)
	{
	  DBG (DBG_info, "sane_read: m560x_bayer_unshuffle status NOK\n");
	  return (status);
	}
    }
  else
    {
      /* Copy the raw data to the frontend buffer. */

      *len = dev->bytes_left;	/* needed */
      size = dev->bytes_left;
      dev->bytes_left = 0;	/* needed for frontend or? */
      memcpy (buf, dev->image, size);
      /* *len = size; */
      DBG (DBG_info, "sane_read: raw mode\n");
    }
  DBG (DBG_info, "sane_read: exit\n");

  return (SANE_STATUS_GOOD);
}

SANE_Status
sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
{

  DBG (DBG_proc, "sane_set_io_mode: enter\n");

  handle = handle;		/* silence gcc */
  non_blocking = non_blocking;	/* silence gcc */


  DBG (DBG_proc, "sane_set_io_mode: exit\n");

  return SANE_STATUS_UNSUPPORTED;
}

SANE_Status
sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
{
  DBG (DBG_proc, "sane_get_select_fd: enter\n");

  handle = handle;		/* silence gcc */
  fd = fd;			/* silence gcc */

  DBG (DBG_proc, "sane_get_select_fd: exit\n");

  return SANE_STATUS_UNSUPPORTED;
}

void
sane_cancel (SANE_Handle handle)
{
  M560x_Vidcam *dev = handle;

  DBG (DBG_proc, "sane_cancel: enter\n");

  /* Stop a scan. */
  if (dev->scanning == SANE_TRUE)
    {
      /* Reset the vidcam */
      m560x_reset_vidcam (dev);
      m560x_close (dev);
    }
  dev->scanning = SANE_FALSE;

  /* return SANE_STATUS_CANCELLED; */
  DBG (DBG_proc, "sane_cancel: exit\n");
}

void
sane_close (SANE_Handle handle)
{
  M560x_Vidcam *dev = handle;
  M560x_Vidcam *dev_tmp;

  DBG (DBG_proc, "sane_close: enter\n");

/* Stop a scan. */

  if (dev->scanning == SANE_TRUE)
    {
      m560x_reset_vidcam (dev);
      m560x_close (dev);
    }
  dev->scanning = SANE_FALSE;

  /* Unlink dev. */
  if (first_dev == dev)
    {
      first_dev = dev->next;
    }
  else
    {
      dev_tmp = first_dev;
      while (dev_tmp->next && dev_tmp->next != dev)
	{
	  dev_tmp = dev_tmp->next;
	}
      if (dev_tmp->next != NULL)
	{
	  dev_tmp->next = dev_tmp->next->next;
	}
    }

  m560x_free (dev);
  num_devices--;

  DBG (DBG_proc, "sane_close: exit\n");
}

void
sane_exit (void)
{
  DBG (DBG_proc, "sane_exit: enter\n");

  while (first_dev)
    {
      sane_close (first_dev);
    }

  if (devlist)
    {
      free (devlist);
      devlist = NULL;
    }

  DBG (DBG_proc, "sane_exit: exit\n");
}
