kopia lustrzana https://gitlab.com/sane-project/backends
1463 wiersze
44 KiB
C
1463 wiersze
44 KiB
C
![]() |
/* sane - Scanner Access Now Easy.
|
||
|
|
||
|
BACKEND canon_lide70
|
||
|
|
||
|
Copyright (C) 2019 Juergen Ernst
|
||
|
|
||
|
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.
|
||
|
|
||
|
This file is a milestone toward a SANE backend for
|
||
|
the Canon CanoScan LiDE 70 and LiDE 600(f).
|
||
|
This version does not actually work. */
|
||
|
|
||
|
#include <errno.h>
|
||
|
#include <fcntl.h> /* open */
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <unistd.h> /* usleep */
|
||
|
#include <time.h>
|
||
|
#include <math.h> /* exp() */
|
||
|
#ifdef HAVE_OS2_H
|
||
|
#include <sys/types.h> /* mode_t */
|
||
|
#endif
|
||
|
#include <sys/stat.h>
|
||
|
|
||
|
#define USB_TYPE_VENDOR (0x02 << 5)
|
||
|
#define USB_RECIP_DEVICE 0x00
|
||
|
#define USB_DIR_OUT 0x00
|
||
|
#define USB_DIR_IN 0x80
|
||
|
|
||
|
#define MSEC 1000 /* 1ms = 1000us */
|
||
|
|
||
|
/* Assign status and verify a good return code */
|
||
|
#define CHK(A) {if ((status = A) != SANE_STATUS_GOOD) {\
|
||
|
DBG (1, "Failure on line of %s: %d\n", \
|
||
|
__FILE__, __LINE__ ); return A; }}
|
||
|
|
||
|
typedef SANE_Byte byte;
|
||
|
|
||
|
/*****************************************************
|
||
|
Canon LiDE calibration and scan
|
||
|
******************************************************/
|
||
|
|
||
|
/* at 600 dpi */
|
||
|
#define CANON_MAX_WIDTH 5100 /* 8.5in */
|
||
|
/* this may not be right */
|
||
|
#define CANON_MAX_HEIGHT 7000 /* 11.66in */
|
||
|
/* Just for my scanner, or is this universal? Calibrate? */
|
||
|
#define LEFT_EDGE 0x01b3
|
||
|
|
||
|
|
||
|
/* data structures and constants */
|
||
|
typedef struct CANON_Handle
|
||
|
{
|
||
|
char *product; /* product name */
|
||
|
int fd; /* scanner fd */
|
||
|
int x1, x2, y1, y2; /* in pixels, 600 dpi */
|
||
|
long width, height; /* at scan resolution */
|
||
|
int resolution; /* dpi */
|
||
|
char *fname; /* output file name */
|
||
|
FILE *fp; /* output file pointer (for reading) */
|
||
|
unsigned char gain; /* static analog gain, 0 - 31 */
|
||
|
double gamma; /* gamma correction */
|
||
|
int flags;
|
||
|
#define FLG_GRAY 0x01 /* grayscale */
|
||
|
#define FLG_FORCE_CAL 0x02 /* force calibration */
|
||
|
#define FLG_PPM_HEADER 0x04 /* include PPM header in scan file */
|
||
|
}
|
||
|
CANON_Handle;
|
||
|
|
||
|
|
||
|
static byte cmd_buffer[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||
|
|
||
|
/*****************************************************
|
||
|
CP2155 communication primitives
|
||
|
Provides I/O routines to Philips CP2155BE chip
|
||
|
******************************************************/
|
||
|
|
||
|
typedef int CP2155_Register;
|
||
|
|
||
|
/* Write single byte to CP2155 register */
|
||
|
static SANE_Status
|
||
|
cp2155_set (int fd, CP2155_Register reg, byte data)
|
||
|
{
|
||
|
SANE_Status status;
|
||
|
size_t count;
|
||
|
|
||
|
cmd_buffer[0] = (reg >> 8) & 0xff;
|
||
|
cmd_buffer[1] = (reg) & 0xff;
|
||
|
cmd_buffer[2] = 0x01;
|
||
|
cmd_buffer[3] = 0x00;
|
||
|
cmd_buffer[4] = data;
|
||
|
|
||
|
count = 5;
|
||
|
status = sanei_usb_write_bulk (fd, cmd_buffer, &count);
|
||
|
|
||
|
if (status != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
DBG (1, "cp2155_set: sanei_usb_write_bulk error\n");
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/* Read single byte from CP2155 register */
|
||
|
static SANE_Status
|
||
|
cp2155_get (int fd, CP2155_Register reg, byte *data)
|
||
|
{
|
||
|
SANE_Status status;
|
||
|
size_t count;
|
||
|
|
||
|
cmd_buffer[0] = 0x01;
|
||
|
cmd_buffer[1] = (reg) & 0xff;
|
||
|
cmd_buffer[2] = 0x01;
|
||
|
cmd_buffer[3] = 0x00;
|
||
|
|
||
|
count = 4;
|
||
|
status = sanei_usb_write_bulk (fd, cmd_buffer, &count);
|
||
|
|
||
|
if (status != SANE_STATUS_GOOD) {
|
||
|
DBG (1, "cp2155_get: sanei_usb_write_bulk error\n");
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
usleep (1*MSEC);
|
||
|
|
||
|
count = 1;
|
||
|
status = sanei_usb_read_bulk (fd, data, &count);
|
||
|
|
||
|
if (status != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
DBG (1, "cp2155_get: sanei_usb_read_bulk error\n");
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/* Write a block of data to CP2155 chip */
|
||
|
static SANE_Status
|
||
|
cp2155_write (int fd, byte *data, size_t size)
|
||
|
{
|
||
|
SANE_Status status;
|
||
|
size_t count = size + 4;
|
||
|
|
||
|
cmd_buffer[0] = 0x04;
|
||
|
cmd_buffer[1] = 0x70;
|
||
|
cmd_buffer[2] = (size) & 0xff;
|
||
|
cmd_buffer[3] = (size >> 8) & 0xff;
|
||
|
memcpy (cmd_buffer+4, data, size);
|
||
|
|
||
|
status = sanei_usb_write_bulk (fd, cmd_buffer, &count);
|
||
|
|
||
|
if (status != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
DBG (1, "cp2155_write: sanei_usb_write_bulk error\n");
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/* Read a block of data from CP2155 chip */
|
||
|
static SANE_Status
|
||
|
cp2155_read (int fd, byte *data, size_t size)
|
||
|
{
|
||
|
SANE_Status status;
|
||
|
size_t count;
|
||
|
|
||
|
cmd_buffer[0] = 0x05;
|
||
|
cmd_buffer[1] = 0x70;
|
||
|
cmd_buffer[2] = (size) & 0xff;
|
||
|
cmd_buffer[3] = (size >> 8) & 0xff;
|
||
|
|
||
|
count = 4;
|
||
|
status = sanei_usb_write_bulk (fd, cmd_buffer, &count);
|
||
|
|
||
|
if (status != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
DBG (1, "cp2155_read: sanei_usb_write_bulk error\n");
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
usleep (1*MSEC);
|
||
|
|
||
|
count = size;
|
||
|
status = sanei_usb_read_bulk (fd, data, &count);
|
||
|
|
||
|
if (status != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
DBG (1, "cp2155_read: sanei_usb_read_bulk error %d\n",count);
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/*****************************************************/
|
||
|
|
||
|
static void
|
||
|
cp2155_block1 (int fd, byte v001, unsigned int addr, byte *data, size_t size)
|
||
|
{
|
||
|
size_t count = size;
|
||
|
|
||
|
while ((count & 0x0f) != 0)
|
||
|
{
|
||
|
count++;
|
||
|
}
|
||
|
|
||
|
byte pgLO = (count) & 0xff;
|
||
|
byte pgHI = (count >> 8) & 0xff;
|
||
|
|
||
|
DBG (1, "cp2155_block1 %06x %02x %04x %04x\n", addr, v001, size, count);
|
||
|
|
||
|
cp2155_set (fd, 0x71, 0x01);
|
||
|
cp2155_set (fd, 0x0230, 0x11);
|
||
|
cp2155_set (fd, 0x71, v001);
|
||
|
cp2155_set (fd, 0x72, pgHI);
|
||
|
cp2155_set (fd, 0x73, pgLO);
|
||
|
cp2155_set (fd, 0x74, (addr >> 16) & 0xff);
|
||
|
cp2155_set (fd, 0x75, (addr >> 8) & 0xff);
|
||
|
cp2155_set (fd, 0x76, (addr) & 0xff);
|
||
|
cp2155_set (fd, 0x0239, 0x40);
|
||
|
cp2155_set (fd, 0x0238, 0x89);
|
||
|
cp2155_set (fd, 0x023c, 0x2f);
|
||
|
cp2155_set (fd, 0x0264, 0x20);
|
||
|
cp2155_write (fd, data, count);
|
||
|
}
|
||
|
|
||
|
/* size=0x0100 */
|
||
|
static byte cp2155_block2_data[] = {\
|
||
|
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,\
|
||
|
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,\
|
||
|
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,\
|
||
|
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,\
|
||
|
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,\
|
||
|
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,\
|
||
|
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,\
|
||
|
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,\
|
||
|
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,\
|
||
|
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,\
|
||
|
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,\
|
||
|
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,\
|
||
|
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,\
|
||
|
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,\
|
||
|
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,\
|
||
|
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff};
|
||
|
|
||
|
/* size=0x0140 */
|
||
|
static byte cp2155_slope01_data[] = {\
|
||
|
0x80,0x25,0x74,0x25,0x68,0x25,0x5c,0x25,0x51,0x25,0x45,0x25,0x3a,0x25,0x2e,0x25,\
|
||
|
0x23,0x25,0x17,0x25,0x0c,0x25,0x00,0x25,0xf5,0x24,0xea,0x24,0xde,0x24,0xd3,0x24,\
|
||
|
0xc8,0x24,0xbc,0x24,0xb1,0x24,0xa6,0x24,0x9b,0x24,0x90,0x24,0x85,0x24,0x79,0x24,\
|
||
|
0x6e,0x24,0x63,0x24,0x58,0x24,0x4d,0x24,0x42,0x24,0x37,0x24,0x2c,0x24,0x22,0x24,\
|
||
|
0x17,0x24,0x0c,0x24,0x01,0x24,0xf6,0x23,0xec,0x23,0xe1,0x23,0xd6,0x23,0xcb,0x23,\
|
||
|
0xc1,0x23,0xb6,0x23,0xab,0x23,0xa1,0x23,0x96,0x23,0x8c,0x23,0x81,0x23,0x77,0x23,\
|
||
|
0x6c,0x23,0x62,0x23,0x57,0x23,0x4d,0x23,0x43,0x23,0x38,0x23,0x2e,0x23,0x24,0x23,\
|
||
|
0x19,0x23,0x0f,0x23,0x05,0x23,0xfb,0x22,0xf1,0x22,0xe6,0x22,0xdc,0x22,0xd2,0x22,\
|
||
|
0xc8,0x22,0xbe,0x22,0xb4,0x22,0xaa,0x22,0xa0,0x22,0x96,0x22,0x8c,0x22,0x82,0x22,\
|
||
|
0x78,0x22,0x6e,0x22,0x64,0x22,0x5b,0x22,0x51,0x22,0x47,0x22,0x3d,0x22,0x33,0x22,\
|
||
|
0x2a,0x22,0x20,0x22,0x16,0x22,0x0d,0x22,0x03,0x22,0xf9,0x21,0xf0,0x21,0xe6,0x21,\
|
||
|
0xdd,0x21,0xd3,0x21,0xc9,0x21,0xc0,0x21,0xb7,0x21,0xad,0x21,0xa4,0x21,0x9a,0x21,\
|
||
|
0x91,0x21,0x87,0x21,0x7e,0x21,0x75,0x21,0x6b,0x21,0x62,0x21,0x59,0x21,0x50,0x21,\
|
||
|
0x46,0x21,0x3d,0x21,0x34,0x21,0x2b,0x21,0x22,0x21,0x18,0x21,0x0f,0x21,0x06,0x21,\
|
||
|
0xfd,0x20,0xf4,0x20,0xeb,0x20,0xe2,0x20,0xd9,0x20,0xd0,0x20,0xc7,0x20,0xbe,0x20,\
|
||
|
0xb5,0x20,0xac,0x20,0xa3,0x20,0x9b,0x20,0x92,0x20,0x89,0x20,0x80,0x20,0x77,0x20,\
|
||
|
0x6f,0x20,0x66,0x20,0x5d,0x20,0x54,0x20,0x4c,0x20,0x43,0x20,0x3a,0x20,0x32,0x20,\
|
||
|
0x29,0x20,0x20,0x20,0x18,0x20,0x0f,0x20,0x07,0x20,0xfe,0x1f,0xf6,0x1f,0xed,0x1f,\
|
||
|
0xe5,0x1f,0xdc,0x1f,0xd4,0x1f,0xcb,0x1f,0xc3,0x1f,0xbb,0x1f,0xb2,0x1f,0xaa,0x1f,\
|
||
|
0xa1,0x1f,0x99,0x1f,0x91,0x1f,0x89,0x1f,0x80,0x1f,0x78,0x1f,0x70,0x1f,0x68,0x1f};
|
||
|
|
||
|
/* size=0x0018 */
|
||
|
static byte cp2155_slope02_data[] = {\
|
||
|
0x80,0x25,0xd9,0x24,0x38,0x24,0x9d,0x23,0x07,0x23,0x75,0x22,0xe9,0x21,0x60,0x21,\
|
||
|
0xdc,0x20,0x5c,0x20,0xe0,0x1f,0x68,0x1f};
|
||
|
|
||
|
/* size=0x0004 */
|
||
|
static byte cp2155_slope03_data[] = {\
|
||
|
0x80,0x25,0x01,0x00};
|
||
|
|
||
|
/* size=0x0018 */
|
||
|
static byte cp2155_slope04_data[] = {\
|
||
|
0x80,0x25,0x0a,0x00,0x05,0x00,0x03,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x01,0x00,\
|
||
|
0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00};
|
||
|
|
||
|
/* size=0x0040 */
|
||
|
static byte cp2155_slope05_data[] = {\
|
||
|
0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,\
|
||
|
0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,\
|
||
|
0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,\
|
||
|
0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25,0x80,0x25};
|
||
|
|
||
|
/* size=0x0018 */
|
||
|
static byte cp2155_slope06_data[] = {\
|
||
|
0x80,0x25,0x93,0x21,0x65,0x1e,0xc3,0x1b,0x8d,0x19,0xab,0x17,0x0a,0x16,0xa0,0x14,\
|
||
|
0x61,0x13,0x46,0x12,0x4a,0x11,0x68,0x10};
|
||
|
|
||
|
/* size=0x0100 */
|
||
|
static byte cp2155_slope07_data[] = {\
|
||
|
0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,\
|
||
|
0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,\
|
||
|
0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,\
|
||
|
0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,\
|
||
|
0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,\
|
||
|
0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,0x00,0x32,\
|
||
|
0x00,0x32,0xbc,0x30,0x89,0x2f,0x64,0x2e,0x4d,0x2d,0x43,0x2c,0x45,0x2b,0x52,0x2a,\
|
||
|
0x69,0x29,0x8a,0x28,0xb5,0x27,0xe8,0x26,0x23,0x26,0x66,0x25,0xaf,0x24,0x00,0x24,\
|
||
|
0x57,0x23,0xb5,0x22,0x17,0x22,0x80,0x21,0xee,0x20,0x60,0x20,0xd7,0x1f,0x53,0x1f,\
|
||
|
0xd3,0x1e,0x57,0x1e,0xde,0x1d,0x6a,0x1d,0xf9,0x1c,0x8b,0x1c,0x20,0x1c,0xb9,0x1b,\
|
||
|
0x54,0x1b,0xf3,0x1a,0x93,0x1a,0x37,0x1a,0xdd,0x19,0x85,0x19,0x30,0x19,0xdd,0x18,\
|
||
|
0x8c,0x18,0x3d,0x18,0xf0,0x17,0xa5,0x17,0x5c,0x17,0x14,0x17,0xce,0x16,0x8a,0x16,\
|
||
|
0x47,0x16,0x06,0x16,0xc7,0x15,0x88,0x15,0x4b,0x15,0x10,0x15,0xd6,0x14,0x9d,0x14,\
|
||
|
0x65,0x14,0x2e,0x14,0xf9,0x13,0xc4,0x13,0x91,0x13,0x5f,0x13,0x2d,0x13,0xfd,0x12,\
|
||
|
0xce,0x12,0x9f,0x12,0x72,0x12,0x45,0x12,0x19,0x12,0xee,0x11,0xc4,0x11,0x9a,0x11,\
|
||
|
0x71,0x11,0x49,0x11,0x22,0x11,0xfb,0x10,0xd5,0x10,0xb0,0x10,0x8c,0x10,0x68,0x10};
|
||
|
|
||
|
/* size=0x0018 */
|
||
|
static byte cp2155_slope08_data[] = {\
|
||
|
0x00,0x32,0x27,0x2a,0x6f,0x24,0x15,0x20,0xa8,0x1c,0xe5,0x19,0x9e,0x17,0xb5,0x15,\
|
||
|
0x16,0x14,0xb0,0x12,0x79,0x11,0x68,0x10};
|
||
|
|
||
|
/* size=0x01f4 */
|
||
|
static byte cp2155_slope09_data[] = {\
|
||
|
0x80,0x25,0x00,0x25,0x84,0x24,0x0b,0x24,0x96,0x23,0x23,0x23,0xb3,0x22,0x46,0x22,\
|
||
|
0xdb,0x21,0x73,0x21,0x0e,0x21,0xab,0x20,0x4a,0x20,0xeb,0x1f,0x8f,0x1f,0x34,0x1f,\
|
||
|
0xdc,0x1e,0x85,0x1e,0x31,0x1e,0xde,0x1d,0x8d,0x1d,0x3e,0x1d,0xf0,0x1c,0xa4,0x1c,\
|
||
|
0x59,0x1c,0x10,0x1c,0xc9,0x1b,0x83,0x1b,0x3e,0x1b,0xfa,0x1a,0xb8,0x1a,0x77,0x1a,\
|
||
|
0x38,0x1a,0xf9,0x19,0xbc,0x19,0x80,0x19,0x44,0x19,0x0a,0x19,0xd1,0x18,0x99,0x18,\
|
||
|
0x62,0x18,0x2c,0x18,0xf7,0x17,0xc3,0x17,0x8f,0x17,0x5d,0x17,0x2b,0x17,0xfa,0x16,\
|
||
|
0xca,0x16,0x9b,0x16,0x6c,0x16,0x3e,0x16,0x11,0x16,0xe5,0x15,0xb9,0x15,0x8e,0x15,\
|
||
|
0x64,0x15,0x3a,0x15,0x11,0x15,0xe9,0x14,0xc1,0x14,0x9a,0x14,0x73,0x14,0x4d,0x14,\
|
||
|
0x27,0x14,0x02,0x14,0xde,0x13,0xba,0x13,0x96,0x13,0x74,0x13,0x51,0x13,0x2f,0x13,\
|
||
|
0x0d,0x13,0xec,0x12,0xcc,0x12,0xab,0x12,0x8c,0x12,0x6c,0x12,0x4d,0x12,0x2f,0x12,\
|
||
|
0x11,0x12,0xf3,0x11,0xd5,0x11,0xb8,0x11,0x9c,0x11,0x80,0x11,0x64,0x11,0x48,0x11,\
|
||
|
0x2d,0x11,0x12,0x11,0xf7,0x10,0xdd,0x10,0xc3,0x10,0xa9,0x10,0x90,0x10,0x77,0x10,\
|
||
|
0x5e,0x10,0x46,0x10,0x2e,0x10,0x16,0x10,0xfe,0x0f,0xe7,0x0f,0xd0,0x0f,0xb9,0x0f,\
|
||
|
0xa2,0x0f,0x8c,0x0f,0x76,0x0f,0x60,0x0f,0x4b,0x0f,0x35,0x0f,0x20,0x0f,0x0b,0x0f,\
|
||
|
0xf7,0x0e,0xe2,0x0e,0xce,0x0e,0xba,0x0e,0xa6,0x0e,0x92,0x0e,0x7f,0x0e,0x6c,0x0e,\
|
||
|
0x59,0x0e,0x46,0x0e,0x33,0x0e,0x21,0x0e,0x0f,0x0e,0xfd,0x0d,0xeb,0x0d,0xd9,0x0d,\
|
||
|
0xc8,0x0d,0xb6,0x0d,0xa5,0x0d,0x94,0x0d,0x83,0x0d,0x73,0x0d,0x62,0x0d,0x52,0x0d,\
|
||
|
0x41,0x0d,0x31,0x0d,0x22,0x0d,0x12,0x0d,0x02,0x0d,0xf3,0x0c,0xe3,0x0c,0xd4,0x0c,\
|
||
|
0xc5,0x0c,0xb6,0x0c,0xa7,0x0c,0x99,0x0c,0x8a,0x0c,0x7c,0x0c,0x6e,0x0c,0x60,0x0c,\
|
||
|
0x52,0x0c,0x44,0x0c,0x36,0x0c,0x28,0x0c,0x1b,0x0c,0x0d,0x0c,0x00,0x0c,0xf3,0x0b,\
|
||
|
0xe6,0x0b,0xd9,0x0b,0xcc,0x0b,0xbf,0x0b,0xb3,0x0b,0xa6,0x0b,0x9a,0x0b,0x8e,0x0b,\
|
||
|
0x81,0x0b,0x75,0x0b,0x69,0x0b,0x5d,0x0b,0x52,0x0b,0x46,0x0b,0x3a,0x0b,0x2f,0x0b,\
|
||
|
0x23,0x0b,0x18,0x0b,0x0d,0x0b,0x02,0x0b,0xf6,0x0a,0xeb,0x0a,0xe1,0x0a,0xd6,0x0a,\
|
||
|
0xcb,0x0a,0xc0,0x0a,0xb6,0x0a,0xab,0x0a,0xa1,0x0a,0x97,0x0a,0x8c,0x0a,0x82,0x0a,\
|
||
|
0x78,0x0a,0x6e,0x0a,0x64,0x0a,0x5a,0x0a,0x50,0x0a,0x47,0x0a,0x3d,0x0a,0x33,0x0a,\
|
||
|
0x2a,0x0a,0x20,0x0a,0x17,0x0a,0x0e,0x0a,0x04,0x0a,0xfb,0x09,0xf2,0x09,0xe9,0x09,\
|
||
|
0xe0,0x09,0xd7,0x09,0xce,0x09,0xc6,0x09,0xbd,0x09,0xb4,0x09,0xab,0x09,0xa3,0x09,\
|
||
|
0x9a,0x09,0x92,0x09,0x8a,0x09,0x81,0x09,0x79,0x09,0x71,0x09,0x69,0x09,0x61,0x09,\
|
||
|
0x59,0x09,0x51,0x09,0x49,0x09,0x41,0x09,0x39,0x09,0x31,0x09,0x29,0x09,0x22,0x09,\
|
||
|
0x1a,0x09,0x12,0x09,0x0b,0x09,0x03,0x09,0xfc,0x08,0xf5,0x08,0xed,0x08,0xe6,0x08,\
|
||
|
0xdf,0x08,0xd8,0x08,0xd0,0x08,0xc9,0x08,0xc2,0x08,0xbb,0x08,0xb4,0x08,0xad,0x08,\
|
||
|
0xa6,0x08,0xa0,0x08};
|
||
|
|
||
|
/* size=0x0018 */
|
||
|
static byte cp2155_slope10_data[] = {\
|
||
|
0x80,0x25,0xc0,0x1c,0x4f,0x17,0x9a,0x13,0xe9,0x10,0xde,0x0e,0x44,0x0d,0xfa,0x0b,\
|
||
|
0xea,0x0a,0x07,0x0a,0x46,0x09,0xa0,0x08};
|
||
|
|
||
|
static void
|
||
|
cp2155_block2 (int fd, unsigned int addr)
|
||
|
{
|
||
|
DBG (1, "cp2155_block2 %06x\n", addr);
|
||
|
cp2155_block1 (fd, 0x16, addr, cp2155_block2_data, 0x0100);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
cp2155_set_slope (int fd, unsigned int addr, byte *data, size_t size)
|
||
|
{
|
||
|
DBG (1, "cp2155_set_slope %06x %04x\n", addr, size);
|
||
|
cp2155_block1 (fd, 0x14, addr, data, size);
|
||
|
}
|
||
|
|
||
|
/* size=0x0075 */
|
||
|
static byte cp2155_set_regs_data1[] = {\
|
||
|
0x00,0x00,0x01,0xe3,0x02,0x22,0x1d,0x00,0x01,0x90,0x00,0x00,0x00,0x29,0xe0,0x00,\
|
||
|
0x00,0xfa,0x07,0xff,0xff,0xff,0xff,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x02,\
|
||
|
0x00,0x03,0x01,0x01,0x01,0x01,0x04,0x07,0x30,0x31,0x10,0x11,0x01,0x05,0x12,0x12,\
|
||
|
0x00,0x00,0x00,0x00,0x04,0x80,0x80,0x80,0x80,0x80,0x82,0x83,0x50,0x50,0x50,0x06,\
|
||
|
0x50,0x06,0x00,0x00,0xd2,0x00,0x00,0x06,0x00,0x00,0x02,0x80,0x79,0x02,0x1c,0x9c,\
|
||
|
0x38,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,\
|
||
|
0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,\
|
||
|
0x05,0x00,0x00,0x00,0x00};
|
||
|
|
||
|
/* size=0x0075 */
|
||
|
static byte cp2155_set_regs_data2[] = {\
|
||
|
0x00,0x00,0x01,0xe3,0x02,0x22,0x1d,0x00,0x01,0x90,0x00,0x00,0x00,0x29,0xe0,0x04,\
|
||
|
0x04,0xfa,0x07,0xff,0xff,0xff,0xff,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x02,\
|
||
|
0x00,0x03,0x01,0x01,0x01,0x01,0x04,0x07,0x31,0x31,0x11,0x11,0x01,0x05,0x12,0x12,\
|
||
|
0x00,0x05,0x0d,0x0d,0x0d,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x50,0x50,0x50,0x06,\
|
||
|
0x50,0x06,0x00,0x00,0xd2,0x00,0x00,0x06,0x00,0x00,0x02,0x80,0x79,0x02,0x1c,0x9c,\
|
||
|
0x38,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,\
|
||
|
0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,\
|
||
|
0x05,0x00,0x00,0x00,0x00};
|
||
|
|
||
|
/* size=0x0075 */
|
||
|
static byte cp2155_set_regs_data3[] = {\
|
||
|
0x00,0x00,0x01,0xb3,0x01,0xd2,0x1d,0x00,0x00,0x10,0x00,0x00,0x00,0x2e,0x00,0x04,\
|
||
|
0x04,0xf8,0x07,0xff,0xff,0xff,0xff,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x02,\
|
||
|
0x00,0x03,0x01,0x01,0x01,0x01,0x04,0x07,0x31,0x31,0x11,0x11,0x01,0x05,0x12,0x12,\
|
||
|
0x00,0x1d,0x15,0x15,0x15,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x01,0x01,0x01,0x06,\
|
||
|
0x01,0x06,0x00,0x00,0x02,0x00,0x00,0x06,0x00,0x00,0x02,0x83,0x7c,0x02,0x1c,0x9c,\
|
||
|
0x38,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,\
|
||
|
0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,\
|
||
|
0x0d,0x00,0x00,0x00,0x00};
|
||
|
|
||
|
/* size=0x0075 */
|
||
|
static byte cp2155_set_regs_data4[] = {\
|
||
|
0x00,0x00,0x01,0xb3,0x01,0xd2,0x1d,0x00,0x00,0x70,0x00,0x00,0x00,0x15,0xe0,0x04,\
|
||
|
0x04,0xf8,0x07,0xff,0xff,0xff,0xff,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x02,\
|
||
|
0x00,0x03,0x01,0x01,0x01,0x01,0x04,0x07,0x31,0x31,0x11,0x11,0x01,0x05,0x12,0x12,\
|
||
|
0x01,0x05,0x05,0x05,0x05,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x10,0x10,0x10,0x06,\
|
||
|
0x10,0x06,0x00,0x03,0xe8,0x00,0x00,0x06,0x00,0x00,0x02,0x83,0x7c,0x02,0x1c,0x9c,\
|
||
|
0x38,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,\
|
||
|
0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,\
|
||
|
0x0d,0x00,0x00,0x00,0x00};
|
||
|
|
||
|
/* size=0x0075 */
|
||
|
static byte cp2155_set_regs_data5[] = {\
|
||
|
0x00,0x00,0x0b,0x3b,0x0c,0x3a,0x1d,0x00,0x03,0x10,0x00,0x00,0x00,0x15,0xe0,0x04,\
|
||
|
0x04,0xf8,0x07,0xff,0xff,0xff,0xff,0x0a,0xf0,0x0a,0xf0,0x0a,0xf0,0x00,0x01,0x02,\
|
||
|
0x00,0x03,0x01,0x01,0x01,0x01,0x04,0x07,0x31,0x31,0x11,0x11,0x01,0x05,0x12,0x12,\
|
||
|
0x01,0x05,0x05,0x05,0x05,0x83,0x83,0xc3,0xc3,0xc3,0xc1,0xc1,0x40,0x00,0x40,0x06,\
|
||
|
0x40,0x06,0x00,0x00,0x04,0x00,0x01,0x80,0x00,0x00,0x02,0x01,0x01,0x01,0x1c,0x9c,\
|
||
|
0x38,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,\
|
||
|
0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,\
|
||
|
0x0a,0x00,0x00,0x00,0x00};
|
||
|
|
||
|
/* size=0x0075 */
|
||
|
static byte cp2155_set_regs_data6[] = {\
|
||
|
0x00,0x00,0x01,0xb3,0x02,0x32,0x1d,0x00,0x00,0x70,0x00,0x00,0x00,0x2e,0x00,0x04,\
|
||
|
0x04,0xf8,0x07,0xff,0xff,0xff,0xff,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x02,\
|
||
|
0x00,0x03,0x01,0x01,0x01,0x01,0x04,0x07,0x31,0x31,0x11,0x11,0x01,0x05,0x12,0x12,\
|
||
|
0x03,0x05,0x05,0x05,0x05,0x41,0x61,0x21,0x21,0x25,0x25,0x25,0x7d,0x7d,0x7d,0x06,\
|
||
|
0x7d,0x06,0x00,0x36,0xd0,0x00,0x00,0x06,0x00,0x00,0x02,0x83,0x7c,0x02,0x1c,0x9c,\
|
||
|
0x38,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,\
|
||
|
0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,\
|
||
|
0x0d,0x00,0x00,0x00,0x00};
|
||
|
|
||
|
/* size=0x0075 */
|
||
|
static byte cp2155_set_regs_nr[] = {\
|
||
|
0x07,0x07,0x08,0x09,0x0a,0x0b,0xa0,0xa1,0xa2,0xa3,0x64,0x65,0x61,0x62,0x63,0x50,\
|
||
|
0x50,0x90,0x51,0x5a,0x5b,0x5c,0x5d,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5e,\
|
||
|
0x5f,0x5f,0x60,0x60,0x60,0x60,0x50,0x51,0x81,0x81,0x82,0x82,0x83,0x84,0x80,0x80,\
|
||
|
0xb0,0x10,0x10,0x10,0x10,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x13,0x16,0x21,\
|
||
|
0x22,0x20,0x1d,0x1e,0x1f,0x66,0x67,0x68,0x1a,0x1b,0x1c,0x15,0x14,0x17,0x43,0x44,\
|
||
|
0x45,0x23,0x33,0x24,0x34,0x25,0x35,0x26,0x36,0x27,0x37,0x28,0x38,0x29,0x39,0x2a,\
|
||
|
0x3a,0x2b,0x3b,0x2c,0x3c,0x2d,0x3d,0x2e,0x3e,0x2f,0x3f,0x30,0x40,0x31,0x41,0x32,\
|
||
|
0x42,0xca,0xca,0xca,0x18};
|
||
|
|
||
|
static void
|
||
|
cp2155_set_regs (int fd, byte *data)
|
||
|
{
|
||
|
DBG (1, "cp2155_set_regs\n");
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < 0x0075; i++)
|
||
|
{
|
||
|
cp2155_set (fd, cp2155_set_regs_nr[i], data[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
cp2155_block4 (int fd, byte v001)
|
||
|
{
|
||
|
DBG (1, "cp2155_block4 %02x\n", v001);
|
||
|
cp2155_set (fd, 0x90, 0xea);
|
||
|
cp2155_set (fd, 0x9b, 0x07);
|
||
|
cp2155_set (fd, 0x9b, 0x05);
|
||
|
cp2155_set (fd, 0x9b, 0x07);
|
||
|
cp2155_set (fd, 0x9b, 0x05);
|
||
|
cp2155_set (fd, 0x90, 0xfa);
|
||
|
cp2155_set (fd, 0xb0, v001);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
cp2155_block5 (int fd, byte v001)
|
||
|
{
|
||
|
DBG (1, "cp2155_block5 %02x\n", v001);
|
||
|
cp2155_set (fd, 0x90, 0xe8);
|
||
|
cp2155_set (fd, 0x9b, 0x06);
|
||
|
cp2155_set (fd, 0x9b, 0x04);
|
||
|
cp2155_set (fd, 0x90, 0xf8);
|
||
|
cp2155_set (fd, 0xb0, v001);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
cp2155_block6 (int fd, byte v001, byte v002)
|
||
|
{
|
||
|
DBG (1, "cp2155_block6 %02x %02x\n", v001, v002);
|
||
|
cp2155_set (fd, 0x80, v001);
|
||
|
cp2155_set (fd, 0x11, v002);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
cp2155_block7 (int fd, byte v001, byte v002, byte v003)
|
||
|
{
|
||
|
DBG (1, "cp2155_block7 %02x %02x %02x\n", v001, v002, v003);
|
||
|
cp2155_block6 (fd, v001, v002);
|
||
|
cp2155_set (fd, 0x9b, v003);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
cp2155_block8 (int fd)
|
||
|
{
|
||
|
DBG (1, "cp2155_block8\n");
|
||
|
cp2155_set (fd, 0x04, 0x0c);
|
||
|
cp2155_set (fd, 0x05, 0x00);
|
||
|
cp2155_set (fd, 0x06, 0x00);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
cp2155_block9 (int fd)
|
||
|
{
|
||
|
DBG (1, "cp2155_block9\n");
|
||
|
cp2155_block2 (fd, 0x000000);
|
||
|
cp2155_block2 (fd, 0x000100);
|
||
|
cp2155_block2 (fd, 0x000200);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
cp2155_motor (int fd, byte v001, byte v002)
|
||
|
{
|
||
|
byte value;
|
||
|
|
||
|
DBG (1, "cp2155_motor %02x %02x\n", v001, v002);
|
||
|
cp2155_set (fd, 0x10, v001);
|
||
|
|
||
|
cp2155_get (fd, 0x4a, &value); /* FIXME do something with this data */
|
||
|
cp2155_get (fd, 0x4b, &value);
|
||
|
cp2155_get (fd, 0x4c, &value);
|
||
|
|
||
|
cp2155_set (fd, 0x11, v002);
|
||
|
cp2155_set (fd, 0x60, 0x01);
|
||
|
cp2155_set (fd, 0x80, 0x12);
|
||
|
cp2155_set (fd, 0x03, 0x01); /* start motor */
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ---------------------------------------- */
|
||
|
|
||
|
/* Wait until data ready */
|
||
|
static long
|
||
|
wait_for_data (int fd)
|
||
|
{
|
||
|
time_t start_time = time (NULL);
|
||
|
long size;
|
||
|
byte value;
|
||
|
|
||
|
DBG (12, "waiting...\n");
|
||
|
|
||
|
while ( 1 )
|
||
|
{
|
||
|
size = 0;
|
||
|
|
||
|
if ( cp2155_get (fd, 0xa5, &value) != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
size += value;
|
||
|
|
||
|
if ( cp2155_get (fd, 0xa6, &value) != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
size <<= 8;
|
||
|
size += value;
|
||
|
|
||
|
if ( cp2155_get (fd, 0xa7, &value) != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
size <<= 8;
|
||
|
size += value;
|
||
|
|
||
|
if (size != 0)
|
||
|
{
|
||
|
return 2*size;
|
||
|
}
|
||
|
|
||
|
/* Give it 5 seconds */
|
||
|
if ((time (NULL) - start_time) > 5)
|
||
|
{
|
||
|
DBG (1, "wait_for_data: timed out (%ld)\n", size);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
usleep (4*MSEC);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static int
|
||
|
go_home (int fd)
|
||
|
{
|
||
|
byte value;
|
||
|
|
||
|
cp2155_set (fd, 0x90, 0xf8);
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
usleep (100*MSEC);
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0xc1);
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
usleep (100*MSEC);
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0xc1);
|
||
|
|
||
|
cp2155_set (fd, 0x90, 0xf8);
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
usleep (100*MSEC);
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0xc1);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
cp2155_block8 (fd);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
|
||
|
cp2155_block9 (fd);
|
||
|
cp2155_block5 (fd, 0x03);
|
||
|
cp2155_set_regs (fd, cp2155_set_regs_data6);
|
||
|
|
||
|
cp2155_set_slope (fd, 0x030000, cp2155_slope09_data, 0x01f4);
|
||
|
cp2155_set_slope (fd, 0x030200, cp2155_slope09_data, 0x01f4);
|
||
|
cp2155_set_slope (fd, 0x030400, cp2155_slope10_data, 0x0018);
|
||
|
cp2155_set_slope (fd, 0x030600, cp2155_slope09_data, 0x01f4);
|
||
|
cp2155_set_slope (fd, 0x030800, cp2155_slope10_data, 0x0018);
|
||
|
|
||
|
cp2155_motor (fd, 0x05, 0x35);
|
||
|
|
||
|
while ( 1 )
|
||
|
{
|
||
|
usleep (200*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
DBG (1, "home sensor: %02x\n", value);
|
||
|
|
||
|
if (value == 0x08)
|
||
|
{
|
||
|
break ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0x25);
|
||
|
cp2155_set (fd, 0x80, 0x12);
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
usleep (100*MSEC);
|
||
|
|
||
|
/*
|
||
|
cp2155_block6 (fd, 0x12, 0x25);
|
||
|
cp2155_get (fd, 0x90, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x90, &value); usleep (100*MSEC);
|
||
|
cp2155_set (fd, 0x9b, 0x00);
|
||
|
cp2155_set (fd, 0x60, 0x00);
|
||
|
cp2155_set (fd, 0x90, 0xb8);
|
||
|
*/
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Scanner init, called at calibration and scan time.
|
||
|
Returns:
|
||
|
1 if this was the first time the scanner was plugged in,
|
||
|
0 afterward, and
|
||
|
-1 on error. */
|
||
|
static int
|
||
|
init (CANON_Handle *scanner)
|
||
|
{
|
||
|
int fd = scanner->fd;
|
||
|
byte value;
|
||
|
|
||
|
cp2155_get (fd, 0xd0, &value);
|
||
|
/* Detect if scanner is plugged in */
|
||
|
if (value != 0x81)
|
||
|
{
|
||
|
DBG (1, "INIT: invalid value\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int result = 0 ;
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
/* Scanner already initialized? */
|
||
|
if (value == 0x00)
|
||
|
{
|
||
|
cp2155_set (fd, 0x02, 0x01);
|
||
|
usleep (13*MSEC);
|
||
|
cp2155_set (fd, 0x02, 0x00);
|
||
|
|
||
|
cp2155_set (fd, 0x01, 0x00);
|
||
|
cp2155_set (fd, 0x01, 0x28);
|
||
|
cp2155_set (fd, 0xa0, 0x04);
|
||
|
usleep (203*MSEC);
|
||
|
cp2155_set (fd, 0xa0, 0x05);
|
||
|
cp2155_set (fd, 0x01, 0x28);
|
||
|
cp2155_set (fd, 0x04, 0x0c);
|
||
|
cp2155_set (fd, 0x05, 0x00);
|
||
|
cp2155_set (fd, 0x06, 0x00);
|
||
|
result = 1;
|
||
|
}
|
||
|
/* Scan without init starts here */
|
||
|
cp2155_set (fd, 0x90, 0x27);
|
||
|
cp2155_set (fd, 0x92, 0xf7);
|
||
|
cp2155_set (fd, 0x94, 0xf7);
|
||
|
usleep (60*MSEC);
|
||
|
cp2155_set (fd, 0x93, 0x00);
|
||
|
cp2155_set (fd, 0x91, 0x1f);
|
||
|
cp2155_set (fd, 0x95, 0x0f);
|
||
|
cp2155_set (fd, 0x97, 0x0f);
|
||
|
cp2155_set (fd, 0x9b, 0x00);
|
||
|
cp2155_set (fd, 0x9c, 0x07);
|
||
|
cp2155_set (fd, 0x90, 0xf0);
|
||
|
usleep (55*MSEC);
|
||
|
cp2155_set (fd, 0x9b, 0x04);
|
||
|
cp2155_set (fd, 0x98, 0x00);
|
||
|
cp2155_set (fd, 0x98, 0x00);
|
||
|
cp2155_set (fd, 0x98, 0x02);
|
||
|
cp2155_set (fd, 0x99, 0x3b);
|
||
|
cp2155_set (fd, 0x9a, 0x03);
|
||
|
cp2155_set (fd, 0x80, 0x10);
|
||
|
cp2155_set (fd, 0x8d, 0x00);
|
||
|
cp2155_set (fd, 0x8d, 0x04);
|
||
|
|
||
|
cp2155_get (fd, 0x8b, &value);
|
||
|
cp2155_get (fd, 0x8b, &value);
|
||
|
cp2155_set (fd, 0x85, 0x00);
|
||
|
cp2155_set (fd, 0x87, 0x00);
|
||
|
cp2155_set (fd, 0x88, 0x70);
|
||
|
|
||
|
cp2155_get (fd, 0x8b, &value);
|
||
|
cp2155_get (fd, 0x8b, &value);
|
||
|
cp2155_set (fd, 0x85, 0x03);
|
||
|
cp2155_set (fd, 0x87, 0x00);
|
||
|
cp2155_set (fd, 0x88, 0x00);
|
||
|
|
||
|
cp2155_get (fd, 0x8b, &value);
|
||
|
cp2155_get (fd, 0x8b, &value);
|
||
|
cp2155_set (fd, 0x85, 0x06);
|
||
|
cp2155_set (fd, 0x87, 0x00);
|
||
|
cp2155_set (fd, 0x88, 0x88);
|
||
|
|
||
|
CP2155_Register reg;
|
||
|
|
||
|
for (reg = 0; reg < 0xff; reg++)
|
||
|
{
|
||
|
cp2155_get (fd, reg, &value);
|
||
|
}
|
||
|
|
||
|
usleep (3*MSEC);
|
||
|
cp2155_set (fd, 0x60, 0x01);
|
||
|
usleep (998*MSEC);
|
||
|
|
||
|
cp2155_set (fd, 0x90, 0xf8);
|
||
|
cp2155_set (fd, 0x60, 0x01);
|
||
|
cp2155_set (fd, 0x9b, 0x04);
|
||
|
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
|
||
|
DBG (1, "INIT state: %0d\n", result);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* This is the calibration routine Canon driver goes through when the
|
||
|
scanner is first plugged in. USB trace made with USBSnoopy
|
||
|
(http://benoit.papillault.free.fr/usbsnoop/)
|
||
|
*/
|
||
|
static int
|
||
|
calibrate (CANON_Handle *scanner)
|
||
|
{
|
||
|
SANE_Status status;
|
||
|
byte value;
|
||
|
status = status;
|
||
|
int fd = scanner->fd;
|
||
|
|
||
|
DBG (6, "Calibrating\n");
|
||
|
|
||
|
/* ---------------------------------------- */
|
||
|
|
||
|
cp2155_block7 (fd, 0x12, 0x00, 0x05);
|
||
|
cp2155_set (fd, 0x90, 0xfa);
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0x00);
|
||
|
cp2155_set (fd, 0x01, 0x28);
|
||
|
cp2155_block8 (fd);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
|
||
|
cp2155_block9 (fd);
|
||
|
cp2155_block4 (fd, 0x00);
|
||
|
cp2155_set_regs (fd, cp2155_set_regs_data1);
|
||
|
|
||
|
cp2155_set_slope (fd, 0x030000, cp2155_slope01_data, 0x0140);
|
||
|
cp2155_set_slope (fd, 0x030200, cp2155_slope01_data, 0x0140);
|
||
|
cp2155_set_slope (fd, 0x030400, cp2155_slope02_data, 0x0018);
|
||
|
cp2155_set_slope (fd, 0x030600, cp2155_slope01_data, 0x0140);
|
||
|
cp2155_set_slope (fd, 0x030800, cp2155_slope02_data, 0x0018);
|
||
|
|
||
|
cp2155_get (fd, 0x46, &value); usleep (2000*MSEC);
|
||
|
cp2155_motor (fd, 0x05, 0x93);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
|
||
|
/* ---------------------------------------- */
|
||
|
|
||
|
cp2155_block7 (fd, 0x12, 0x83, 0x05);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0x83);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
cp2155_block8 (fd);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
|
||
|
cp2155_block9 (fd);
|
||
|
cp2155_block4 (fd, 0x00);
|
||
|
cp2155_set_regs (fd, cp2155_set_regs_data2);
|
||
|
|
||
|
cp2155_set_slope (fd, 0x030000, cp2155_slope01_data, 0x0140);
|
||
|
cp2155_set_slope (fd, 0x030200, cp2155_slope01_data, 0x0140);
|
||
|
cp2155_set_slope (fd, 0x030400, cp2155_slope02_data, 0x0018);
|
||
|
cp2155_set_slope (fd, 0x030600, cp2155_slope01_data, 0x0140);
|
||
|
cp2155_set_slope (fd, 0x030800, cp2155_slope02_data, 0x0018);
|
||
|
|
||
|
cp2155_motor (fd, 0x0d, 0x93);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
|
||
|
/* ---------------------------------------- */
|
||
|
|
||
|
cp2155_block7 (fd, 0x12, 0x81, 0x04);
|
||
|
cp2155_set (fd, 0x90, 0xf8);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0x81);
|
||
|
|
||
|
cp2155_set (fd, 0x90, 0xf8);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0x81);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
cp2155_block8 (fd);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
|
||
|
cp2155_block9 (fd);
|
||
|
cp2155_set_regs (fd, cp2155_set_regs_data3);
|
||
|
|
||
|
cp2155_set_slope (fd, 0x030000, cp2155_slope03_data, 0x0004);
|
||
|
cp2155_set_slope (fd, 0x030200, cp2155_slope03_data, 0x0004);
|
||
|
cp2155_set_slope (fd, 0x030400, cp2155_slope04_data, 0x0018);
|
||
|
cp2155_set_slope (fd, 0x030600, cp2155_slope03_data, 0x0004);
|
||
|
cp2155_set_slope (fd, 0x030800, cp2155_slope04_data, 0x0018);
|
||
|
|
||
|
cp2155_motor (fd, 0x15, 0x93);
|
||
|
|
||
|
cp2155_set (fd, 0x90, 0xf8);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
|
||
|
/* ---------------------------------------- */
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0x83);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
cp2155_block8 (fd);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
|
||
|
cp2155_block9 (fd);
|
||
|
cp2155_block5 (fd, 0x01);
|
||
|
cp2155_set_regs (fd, cp2155_set_regs_data4);
|
||
|
|
||
|
cp2155_set_slope (fd, 0x030000, cp2155_slope05_data, 0x0040);
|
||
|
cp2155_set_slope (fd, 0x030200, cp2155_slope05_data, 0x0040);
|
||
|
cp2155_set_slope (fd, 0x030400, cp2155_slope06_data, 0x0018);
|
||
|
cp2155_set_slope (fd, 0x030600, cp2155_slope05_data, 0x0040);
|
||
|
cp2155_set_slope (fd, 0x030800, cp2155_slope06_data, 0x0018);
|
||
|
|
||
|
cp2155_motor (fd, 0x05, 0x93);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
|
||
|
/* ---------------------------------------- */
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0x83);
|
||
|
cp2155_set (fd, 0x90, 0xf8);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0x83);
|
||
|
cp2155_get (fd, 0x46, &value); usleep (100*MSEC);
|
||
|
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
cp2155_block8 (fd);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
|
||
|
cp2155_block9 (fd);
|
||
|
cp2155_block5 (fd, 0x01);
|
||
|
cp2155_set_regs (fd, cp2155_set_regs_data5);
|
||
|
|
||
|
cp2155_set_slope (fd, 0x030000, cp2155_slope07_data, 0x0100);
|
||
|
cp2155_set_slope (fd, 0x030200, cp2155_slope07_data, 0x0100);
|
||
|
cp2155_set_slope (fd, 0x030400, cp2155_slope08_data, 0x0018);
|
||
|
cp2155_set_slope (fd, 0x030600, cp2155_slope07_data, 0x0100);
|
||
|
cp2155_set_slope (fd, 0x030800, cp2155_slope08_data, 0x0018);
|
||
|
|
||
|
cp2155_set (fd, 0x90, 0xfa);
|
||
|
cp2155_motor (fd, 0x05, 0xd1);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Scan and save the resulting image as r,g,b non-interleaved PPM file */
|
||
|
static SANE_Status
|
||
|
do_scan (CANON_Handle *scanner)
|
||
|
{
|
||
|
SANE_Status status = SANE_STATUS_GOOD;
|
||
|
byte *readbuf, *linebuf;
|
||
|
int fd = scanner->fd;
|
||
|
byte value;
|
||
|
FILE *fp;
|
||
|
|
||
|
linebuf = malloc (0x40000);
|
||
|
|
||
|
if (!linebuf)
|
||
|
{
|
||
|
return SANE_STATUS_NO_MEM;
|
||
|
}
|
||
|
|
||
|
readbuf = malloc (0xf000);
|
||
|
|
||
|
if (!readbuf)
|
||
|
{
|
||
|
free (linebuf);
|
||
|
return SANE_STATUS_NO_MEM;
|
||
|
}
|
||
|
|
||
|
fp = fopen (scanner->fname, "w");
|
||
|
|
||
|
if (!fp)
|
||
|
{
|
||
|
free (readbuf);
|
||
|
free (linebuf);
|
||
|
DBG (1, "err:%s when opening %s\n", strerror (errno), scanner->fname);
|
||
|
return SANE_STATUS_IO_ERROR;
|
||
|
}
|
||
|
|
||
|
if (fp && (scanner->flags & FLG_PPM_HEADER))
|
||
|
{
|
||
|
fprintf (fp, "P6\n%ld %ld\n255\n", scanner->width, scanner->height);
|
||
|
}
|
||
|
|
||
|
long width = scanner->width;
|
||
|
long height = scanner->height;
|
||
|
/* set width to next multiple of 0x10 */
|
||
|
while ((width & 0x0f) != 0)
|
||
|
{
|
||
|
width++;
|
||
|
}
|
||
|
|
||
|
long x_start = LEFT_EDGE;
|
||
|
long x_end = LEFT_EDGE + (width * 600 / scanner->resolution) - 1;
|
||
|
x_start = LEFT_EDGE + scanner->x1;
|
||
|
x_end = x_start + (width * 600 / scanner->resolution) - 1;
|
||
|
long y_len = 3 * height;
|
||
|
DBG (1, "DEBUG 1: %ld %ld - %ld %ld %ld\n", width,height,x_start,x_end,y_len);
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0x83);
|
||
|
cp2155_set (fd, 0x90, 0xf8);
|
||
|
usleep (30*MSEC);
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
|
||
|
cp2155_block6 (fd, 0x12, 0x83);
|
||
|
cp2155_get (fd, 0x46, &value);
|
||
|
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
cp2155_block8 (fd);
|
||
|
cp2155_set (fd, 0x01, 0x29);
|
||
|
|
||
|
cp2155_block9 (fd);
|
||
|
cp2155_block5 (fd, 0x01);
|
||
|
|
||
|
memcpy (readbuf, cp2155_set_regs_data5, 0x75);
|
||
|
readbuf[2] = (x_start >> 8) & 0xff;
|
||
|
readbuf[3] = (x_start) & 0xff;
|
||
|
readbuf[4] = (x_end >> 8) & 0xff;
|
||
|
readbuf[5] = (x_end) & 0xff;
|
||
|
readbuf[69] = (y_len >> 16) & 0xff;
|
||
|
readbuf[70] = (y_len >> 8) & 0xff;
|
||
|
readbuf[71] = (y_len) & 0xff;
|
||
|
DBG (1, "DEBUG 3: %02x %02x - %02x %02x - %02x %02x %02x\n",
|
||
|
readbuf[2], readbuf[3], readbuf[4], readbuf[5], readbuf[69], readbuf[70], readbuf[71]);
|
||
|
cp2155_set_regs (fd, readbuf);
|
||
|
|
||
|
cp2155_set_slope (fd, 0x030000, cp2155_slope07_data, 0x0100);
|
||
|
cp2155_set_slope (fd, 0x030200, cp2155_slope07_data, 0x0100);
|
||
|
cp2155_set_slope (fd, 0x030400, cp2155_slope08_data, 0x0018);
|
||
|
cp2155_set_slope (fd, 0x030600, cp2155_slope07_data, 0x0100);
|
||
|
cp2155_set_slope (fd, 0x030800, cp2155_slope08_data, 0x0018);
|
||
|
|
||
|
cp2155_set (fd, 0x90, 0xfa);
|
||
|
|
||
|
cp2155_motor (fd, 0x05, 0xd1);
|
||
|
|
||
|
cp2155_set (fd, 0x71, 0x01);
|
||
|
cp2155_set (fd, 0x0230, 0x11);
|
||
|
cp2155_set (fd, 0x71, 0x18);
|
||
|
cp2155_set (fd, 0x72, 0x00);
|
||
|
cp2155_set (fd, 0x73, 0x10);
|
||
|
cp2155_set (fd, 0x0239, 0x40);
|
||
|
cp2155_set (fd, 0x0238, 0x89);
|
||
|
cp2155_set (fd, 0x023c, 0x2f);
|
||
|
cp2155_set (fd, 0x0264, 0x20);
|
||
|
|
||
|
byte *srcptr = readbuf;
|
||
|
byte *dstptr = linebuf;
|
||
|
byte *endptr = linebuf + 3 * width; /* Red line + Green line + Blue line */
|
||
|
long datasize = 0;
|
||
|
long line = 0;
|
||
|
byte slot = 0;
|
||
|
|
||
|
/* Data coming back is "width" bytes Red data, width bytes Green,
|
||
|
width bytes Blue, repeat for "height" lines. */
|
||
|
while (line < height)
|
||
|
{
|
||
|
datasize = wait_for_data (fd);
|
||
|
|
||
|
if (datasize < 0)
|
||
|
{
|
||
|
DBG (1, "no data\n");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
DBG (12, "scan line %ld %ld\n", line, datasize);
|
||
|
|
||
|
cp2155_set (fd, 0x72, (datasize >> 8) & 0xff);
|
||
|
cp2155_set (fd, 0x73, (datasize) & 0xff);
|
||
|
|
||
|
status = cp2155_read (fd, readbuf, datasize);
|
||
|
|
||
|
if (status != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
status = SANE_STATUS_INVAL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Contorsions to convert data from line-by-line RGB to byte-by-byte RGB,
|
||
|
without reading in the whole buffer first. One image line is
|
||
|
constructed in buffer linebuf and written to temp file if complete. */
|
||
|
int idx = 0;
|
||
|
srcptr = readbuf;
|
||
|
|
||
|
while (idx < datasize)
|
||
|
{
|
||
|
*dstptr = *srcptr;
|
||
|
idx++;
|
||
|
srcptr += 1;
|
||
|
dstptr += 3;
|
||
|
/* check if line is complete */
|
||
|
if (dstptr >= endptr)
|
||
|
{
|
||
|
slot++;
|
||
|
dstptr = linebuf + slot;
|
||
|
|
||
|
if (slot == 3)
|
||
|
{
|
||
|
slot = 0;
|
||
|
dstptr = linebuf;
|
||
|
line++;
|
||
|
/* use scanner->width instead of width to remove pad bytes */
|
||
|
fwrite (linebuf, 1, 3*scanner->width, fp);
|
||
|
DBG (6, "line %ld written...\n", line);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fclose (fp);
|
||
|
DBG (6, "created scan file %s\n", scanner->fname);
|
||
|
|
||
|
free (readbuf);
|
||
|
free (linebuf);
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Scan sequence */
|
||
|
/* resolution is 75,150,300,600,1200
|
||
|
scan coordinates in 600-dpi pixels */
|
||
|
static SANE_Status
|
||
|
scan (CANON_Handle *scanner)
|
||
|
{
|
||
|
SANE_Status status = SANE_STATUS_GOOD;
|
||
|
byte *buf;
|
||
|
int temp;
|
||
|
|
||
|
/* create gamma table */
|
||
|
buf = malloc (0x400);
|
||
|
|
||
|
for (temp = 0; temp < 0x0400; temp++)
|
||
|
{
|
||
|
/* gamma calculation by M.Reinelt <reinelt@eunet.at> */
|
||
|
buf[temp] = (double) 255.0 * exp(log((temp + 0.5) / 1023.0) / scanner->gamma)
|
||
|
+ 0.5;
|
||
|
}
|
||
|
/* Gamma R, write and verify */
|
||
|
free (buf);
|
||
|
|
||
|
/* Resolution: dpi 75(ie) 100,150(1c) 200,300(1a) 600,1200(18) */
|
||
|
switch (scanner->resolution)
|
||
|
{
|
||
|
case 75:
|
||
|
case 150:
|
||
|
case 300:
|
||
|
case 600:
|
||
|
case 1200:
|
||
|
break;
|
||
|
default:
|
||
|
scanner->resolution = 75;
|
||
|
}
|
||
|
|
||
|
scanner->width = (scanner->x2 - scanner->x1) * scanner->resolution / 600;
|
||
|
scanner->height = (scanner->y2 - scanner->y1) * scanner->resolution / 600;
|
||
|
scanner->flags = 0;
|
||
|
|
||
|
DBG (1, "dpi=%d\n", scanner->resolution);
|
||
|
DBG (1, "x1=%d y1=%d\n", scanner->x1, scanner->y1);
|
||
|
DBG (1, "x2=%d y2=%d\n", scanner->x2, scanner->y2);
|
||
|
DBG (1, "width=%ld height=%ld\n", scanner->width, scanner->height);
|
||
|
|
||
|
CHK ( do_scan (scanner) );
|
||
|
go_home (scanner->fd) ;
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
|
||
|
static SANE_Status
|
||
|
CANON_set_scan_parameters (CANON_Handle *scan,
|
||
|
const int forceCal,
|
||
|
const int gray,
|
||
|
const int left,
|
||
|
const int top,
|
||
|
const int right,
|
||
|
const int bottom,
|
||
|
const int res,
|
||
|
const int gain,
|
||
|
const double gamma)
|
||
|
{
|
||
|
DBG (2, "CANON_set_scan_parameters:\n");
|
||
|
DBG (2, "cal = %d\n", forceCal);
|
||
|
DBG (2, "gray = %d (ignored)\n", gray);
|
||
|
DBG (2, "res = %d\n", res);
|
||
|
DBG (2, "gain = %d\n", gain);
|
||
|
DBG (2, "gamma = %f\n", gamma);
|
||
|
DBG (2, "in 600dpi pixels:\n");
|
||
|
DBG (2, "left = %d, top = %d\n", left, top);
|
||
|
DBG (2, "right = %d, bottom = %d\n", right, bottom);
|
||
|
|
||
|
/* Validate the input parameters */
|
||
|
if ((left < 0) || (right > CANON_MAX_WIDTH))
|
||
|
{
|
||
|
return SANE_STATUS_INVAL;
|
||
|
}
|
||
|
|
||
|
if ((top < 0) || (bottom > CANON_MAX_HEIGHT))
|
||
|
{
|
||
|
return SANE_STATUS_INVAL;
|
||
|
}
|
||
|
|
||
|
if (((right - left) < 10) || ((bottom - top) < 10))
|
||
|
{
|
||
|
return SANE_STATUS_INVAL;
|
||
|
}
|
||
|
|
||
|
if ((res != 75) &&
|
||
|
(res != 150) &&
|
||
|
(res != 300) &&
|
||
|
(res != 600) &&
|
||
|
(res != 1200))
|
||
|
{
|
||
|
return SANE_STATUS_INVAL;
|
||
|
}
|
||
|
|
||
|
if ((gain < 0) || (gain > 64))
|
||
|
{
|
||
|
return SANE_STATUS_INVAL;
|
||
|
}
|
||
|
|
||
|
if (gamma <= 0.0)
|
||
|
{
|
||
|
return SANE_STATUS_INVAL;
|
||
|
}
|
||
|
|
||
|
/* Store params */
|
||
|
scan->resolution = res;
|
||
|
scan->x1 = left;
|
||
|
scan->x2 = right;
|
||
|
scan->y1 = top;
|
||
|
scan->y2 = bottom;
|
||
|
scan->gain = gain;
|
||
|
scan->gamma = gamma;
|
||
|
scan->flags = forceCal ? FLG_FORCE_CAL : 0;
|
||
|
|
||
|
return SANE_STATUS_GOOD;
|
||
|
}
|
||
|
|
||
|
|
||
|
static SANE_Status
|
||
|
CANON_close_device (CANON_Handle *scan)
|
||
|
{
|
||
|
DBG (3, "CANON_close_device:\n");
|
||
|
sanei_usb_close (scan->fd);
|
||
|
return SANE_STATUS_GOOD;
|
||
|
}
|
||
|
|
||
|
|
||
|
static SANE_Status
|
||
|
CANON_open_device (CANON_Handle *scan, const char *dev)
|
||
|
{
|
||
|
SANE_Word vendor;
|
||
|
SANE_Word product;
|
||
|
SANE_Status res;
|
||
|
|
||
|
DBG (3, "CANON_open_device: `%s'\n", dev);
|
||
|
|
||
|
scan->fname = NULL;
|
||
|
scan->fp = NULL;
|
||
|
scan->flags = 0;
|
||
|
|
||
|
res = sanei_usb_open (dev, &scan->fd);
|
||
|
|
||
|
if (res != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
DBG (1, "CANON_open_device: couldn't open device `%s': %s\n", dev,
|
||
|
sane_strstatus (res));
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
scan->product = "unknown";
|
||
|
|
||
|
#ifndef NO_AUTODETECT
|
||
|
/* We have opened the device. Check that it is a USB scanner. */
|
||
|
if (sanei_usb_get_vendor_product (scan->fd, &vendor, &product) !=
|
||
|
SANE_STATUS_GOOD)
|
||
|
{
|
||
|
DBG (1, "CANON_open_device: sanei_usb_get_vendor_product failed\n");
|
||
|
/* This is not a USB scanner, or SANE or the OS doesn't support it. */
|
||
|
sanei_usb_close (scan->fd);
|
||
|
scan->fd = -1;
|
||
|
return SANE_STATUS_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
/* Make sure we have a CANON scanner */
|
||
|
if (vendor == 0x04a9)
|
||
|
{
|
||
|
scan->product = "Canon";
|
||
|
|
||
|
if (product == 0x2224)
|
||
|
{
|
||
|
scan->product = "CanoScan LiDE 600F";
|
||
|
}
|
||
|
else if (product == 0x2225)
|
||
|
{
|
||
|
scan->product = "CanoScan LiDE 70";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DBG (1, "CANON_open_device: incorrect vendor/product (0x%x/0x%x)\n",
|
||
|
vendor, product);
|
||
|
sanei_usb_close (scan->fd);
|
||
|
scan->fd = -1;
|
||
|
return SANE_STATUS_UNSUPPORTED;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return SANE_STATUS_GOOD;
|
||
|
}
|
||
|
|
||
|
|
||
|
static const char *
|
||
|
CANON_get_device_name (CANON_Handle *scanner)
|
||
|
{
|
||
|
return scanner->product;
|
||
|
}
|
||
|
|
||
|
|
||
|
static SANE_Status
|
||
|
CANON_finish_scan (CANON_Handle *scanner)
|
||
|
{
|
||
|
DBG (3, "CANON_finish_scan:\n");
|
||
|
|
||
|
if (scanner->fp)
|
||
|
{
|
||
|
fclose (scanner->fp);
|
||
|
}
|
||
|
|
||
|
scanner->fp = NULL;
|
||
|
|
||
|
/* remove temp file */
|
||
|
if (scanner->fname)
|
||
|
{
|
||
|
DBG (4, "removing temp file %s\n", scanner->fname);
|
||
|
unlink (scanner->fname);
|
||
|
free (scanner->fname);
|
||
|
}
|
||
|
|
||
|
scanner->fname = NULL;
|
||
|
return SANE_STATUS_GOOD;
|
||
|
}
|
||
|
|
||
|
|
||
|
static SANE_Status
|
||
|
CANON_start_scan (CANON_Handle *scanner)
|
||
|
{
|
||
|
SANE_Status status;
|
||
|
int result;
|
||
|
DBG (3, "CANON_start_scan called\n");
|
||
|
|
||
|
/* choose a temp file name for scan data */
|
||
|
scanner->fname = strdup ("/tmp/scan.XXXXXX");
|
||
|
|
||
|
if (!mktemp (scanner->fname))
|
||
|
{
|
||
|
return SANE_STATUS_IO_ERROR;
|
||
|
}
|
||
|
|
||
|
/* check if calibration needed */
|
||
|
result = init (scanner);
|
||
|
|
||
|
if (result < 0)
|
||
|
{
|
||
|
DBG (1, "Can't talk on USB.\n");
|
||
|
return SANE_STATUS_IO_ERROR;
|
||
|
}
|
||
|
|
||
|
if ((result == 1) || (scanner->flags & FLG_FORCE_CAL))
|
||
|
{
|
||
|
/* calibrate (scanner); */
|
||
|
}
|
||
|
|
||
|
go_home (scanner->fd);
|
||
|
|
||
|
/* scan */
|
||
|
if ((status = scan (scanner)) != SANE_STATUS_GOOD)
|
||
|
{
|
||
|
CANON_finish_scan (scanner);
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/* read the temp file back out */
|
||
|
scanner->fp = fopen (scanner->fname, "r");
|
||
|
DBG (4, "reading %s\n", scanner->fname);
|
||
|
|
||
|
if (!scanner->fp)
|
||
|
{
|
||
|
DBG (1, "open %s", scanner->fname);
|
||
|
return SANE_STATUS_IO_ERROR;
|
||
|
}
|
||
|
|
||
|
return SANE_STATUS_GOOD;
|
||
|
}
|
||
|
|
||
|
|
||
|
static SANE_Status
|
||
|
CANON_read (CANON_Handle *scanner, SANE_Byte *data,
|
||
|
SANE_Int max_length, SANE_Int *length)
|
||
|
{
|
||
|
SANE_Status status;
|
||
|
int red_len;
|
||
|
|
||
|
DBG (5, "CANON_read called\n");
|
||
|
|
||
|
if (!scanner->fp)
|
||
|
{
|
||
|
return SANE_STATUS_INVAL;
|
||
|
}
|
||
|
|
||
|
red_len = fread (data, 1, max_length, scanner->fp);
|
||
|
/* return some data */
|
||
|
if (red_len > 0)
|
||
|
{
|
||
|
*length = red_len;
|
||
|
DBG (5, "CANON_read returned (%d/%d)\n", *length, max_length);
|
||
|
return SANE_STATUS_GOOD;
|
||
|
}
|
||
|
|
||
|
/* EOF or file err */
|
||
|
*length = 0;
|
||
|
|
||
|
if (feof (scanner->fp))
|
||
|
{
|
||
|
DBG (4, "EOF\n");
|
||
|
status = SANE_STATUS_EOF;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DBG (4, "IO ERR\n");
|
||
|
status = SANE_STATUS_IO_ERROR;
|
||
|
}
|
||
|
|
||
|
CANON_finish_scan (scanner);
|
||
|
DBG (5, "CANON_read returned (%d/%d)\n", *length, max_length);
|
||
|
return status;
|
||
|
}
|