/* * epsonds.c - Epson ESC/I-2 driver. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * 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, version 2. */ #define EPSONDS_VERSION 1 #define EPSONDS_REVISION 1 #define EPSONDS_BUILD 0 /* debugging levels: * * 32 eds_send * 30 eds_recv * 20 sane_read and related * 18 sane_read and related * 17 setvalue, getvalue, control_option * 16 * 15 esci2_img * 13 image_cb * 12 eds_control * 11 all received params * 10 some received params * 9 * 8 esci2_xxx * 7 open/close/attach * 6 print_params * 5 basic functions * 3 JPEG decompressor * 1 scanner info and capabilities * 0 errors */ #include "sane/config.h" #include #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include "sane/saneopts.h" #include "sane/sanei_config.h" #include "sane/sanei_tcp.h" #include "sane/sanei_udp.h" #include "epsonds.h" #include "epsonds-usb.h" #include "epsonds-io.h" #include "epsonds-cmd.h" #include "epsonds-ops.h" #include "epsonds-jpeg.h" #include "epsonds-net.h" static SANE_Status setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info); /* * Definition of the mode_param struct, that is used to * specify the valid parameters for the different scan modes. * * The depth variable gets updated when the bit depth is modified. */ static unsigned char LUT[][256] = { {// 0 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 }, { // 1 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x02,0x03,0x04,0x06,0x07,0x09,0x0B,0x0D, 0x10,0x12,0x14,0x17,0x19,0x1B,0x1E,0x20, 0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30, 0x32,0x33,0x35,0x37,0x39,0x3B,0x3C,0x3E, 0x40,0x41,0x43,0x45,0x46,0x48,0x4A,0x4B, 0x4D,0x4F,0x50,0x52,0x53,0x55,0x57,0x58, 0x5A,0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64, 0x66,0x67,0x69,0x6A,0x6C,0x6D,0x6F,0x70, 0x71,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B, 0x7D,0x7E,0x7F,0x81,0x82,0x84,0x85,0x86, 0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x90,0x91, 0x92,0x94,0x95,0x96,0x98,0x99,0x9A,0x9C, 0x9D,0x9E,0xA0,0xA1,0xA2,0xA3,0xA5,0xA6, 0xA7,0xA8,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0, 0xB1,0xB3,0xB4,0xB5,0xB6,0xB8,0xB9,0xBA, 0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4, 0xC5,0xC6,0xC7,0xC9,0xCA,0xCB,0xCC,0xCD, 0xCF,0xD0,0xD1,0xD2,0xD3,0xD5,0xD6,0xD7, 0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE0, 0xE1,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, 0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF3, 0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFB,0xFC, 0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF }, { // 2 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x02,0x03,0x04,0x05,0x07,0x08,0x0A,0x0C, 0x0E,0x10,0x12,0x14,0x16,0x16,0x19,0x1B, 0x1D,0x1F,0x21,0x23,0x25,0x27,0x28,0x2A, 0x2C,0x2E,0x30,0x32,0x33,0x35,0x37,0x39, 0x3A,0x3C,0x3E,0x40,0x41,0x43,0x45,0x46, 0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52,0x53, 0x55,0x57,0x58,0x5A,0x5B,0x5D,0x5F,0x60, 0x62,0x63,0x65,0x66,0x68,0x69,0x6B,0x6C, 0x6E,0x6F,0x71,0x72,0x74,0x75,0x77,0x78, 0x7A,0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84, 0x86,0x87,0x88,0x8A,0x8B,0x8D,0x8E,0x90, 0x91,0x92,0x94,0x95,0x97,0x98,0x99,0x9B, 0x9C,0x9E,0x9F,0xA0,0xA2,0xA3,0xA5,0xA7, 0xA9,0xAA,0xAB,0xAD,0xAE,0xB0,0xB1,0xB2, 0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,0xBC,0xBD, 0xBE,0xC0,0xC1,0xC2,0xC4,0xC5,0xC6,0xC8, 0xC9,0xCA,0xCC,0xCD,0xCE,0xD0,0xD1,0xD2, 0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDD, 0xDE,0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7, 0xE8,0xE9,0xEB,0xEC,0xED,0xEF,0xF0,0xF1, 0xF2,0xF4,0xF5,0xF6,0xF7,0xF9,0xFA,0xFB, 0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { // 3 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x07, 0x08,0x0A,0x0C,0x0E,0x10,0x12,0x14,0x16, 0x18,0x1A,0x1C,0x1E,0x20,0x22,0x24,0x26, 0x28,0x2A,0x2B,0x2D,0x2F,0x31,0x33,0x34, 0x36,0x38,0x39,0x3B,0x3D,0x3E,0x40,0x42, 0x43,0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4F, 0x50,0x52,0x53,0x55,0x56,0x58,0x59,0x5B, 0x5D,0x5E,0x60,0x61,0x63,0x64,0x66,0x67, 0x69,0x6A,0x6B,0x6D,0x6E,0x70,0x71,0x73, 0x74,0x76,0x77,0x79,0x7A,0x7B,0x7D,0x7E, 0x80,0x81,0x83,0x84,0x85,0x87,0x88,0x8A, 0x8B,0x8C,0x8E,0x8F,0x90,0x92,0x93,0x95, 0x96,0x97,0x99,0x9A,0x9B,0x9D,0x9E,0x9F, 0xA1,0xA2,0xA3,0xA5,0xA6,0xA7,0xA9,0xAA, 0xAB,0xAD,0xAE,0xAF,0xB1,0xB2,0xB3,0xB5, 0xB6,0xB7,0xB9,0xBA,0xBB,0xBD,0xBE,0xBF, 0xC0,0xC2,0xC3,0xC4,0xC6,0xC7,0xC8,0xC9, 0xCB,0xCC,0xCD,0xCF,0xD0,0xD1,0xD2,0xD4, 0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDC,0xDF, 0xE0,0xE1,0xE3,0xE4,0xE5,0xE6,0xE8,0xE9, 0xEA,0xEB,0xED,0xEE,0xEF,0xF0,0xF2,0xF3, 0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFD, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { //4 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03, 0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E,0x10, 0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20, 0x22,0x24,0x26,0x28,0x2A,0x2B,0x2D,0x2F, 0x31,0x33,0x34,0x36,0x38,0x39,0x3B,0x3D, 0x3E,0x40,0x42,0x43,0x45,0x47,0x48,0x4A, 0x4B,0x4D,0x4F,0x50,0x52,0x53,0x55,0x56, 0x58,0x59,0x5B,0x5D,0x5E,0x60,0x61,0x63, 0x64,0x66,0x67,0x69,0x6A,0x6B,0x6D,0x6E, 0x70,0x71,0x73,0x74,0x76,0x77,0x79,0x7A, 0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84,0x85, 0x87,0x88,0x8A,0x8B,0x8C,0x8E,0x8F,0x90, 0x92,0x93,0x95,0x96,0x97,0x99,0x9A,0x9B, 0x9D,0x9E,0x9F,0xA1,0xA2,0xA3,0xA5,0xA6, 0xA7,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB1, 0xB2,0xB3,0xB5,0xB6,0xB7,0xB9,0xBA,0xBB, 0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,0xC6, 0xC7,0xC8,0xC9,0xCB,0xCC,0xCD,0xCF,0xD0, 0xD1,0xD2,0xD4,0xD5,0xD6,0xD7,0xD9,0xDA, 0xDB,0xDC,0xDE,0xDF,0xE0,0xE1,0xE3,0xE5, 0xE6,0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF, 0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9, 0xFA,0xFB,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { // 5 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,0x05,0x07,0x08,0x0A, 0x0C,0x0E,0x10,0x12,0x14,0x16,0x18,0x1A, 0x1C,0x1E,0x20,0x22,0x24,0x26,0x28,0x2A, 0x2B,0x2D,0x2F,0x31,0x33,0x34,0x36,0x38, 0x39,0x3B,0x3D,0x3E,0x40,0x42,0x43,0x45, 0x47,0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52, 0x53,0x55,0x56,0x58,0x59,0x5B,0x5D,0x5E, 0x60,0x61,0x63,0x64,0x66,0x67,0x69,0x6A, 0x6B,0x6D,0x6E,0x70,0x71,0x73,0x74,0x76, 0x77,0x79,0x7A,0x7B,0x7D,0x7E,0x80,0x81, 0x83,0x84,0x85,0x87,0x88,0x8A,0x8B,0x8C, 0x8E,0x8F,0x90,0x92,0x93,0x95,0x96,0x97, 0x99,0x9A,0x9B,0x9D,0x9E,0x9F,0xA1,0xA2, 0xA3,0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,0xAD, 0xAE,0xAF,0xB1,0xB2,0xB3,0xB5,0xB6,0xB7, 0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,0xC0,0xC2, 0xC3,0xC4,0xC6,0xC7,0xC8,0xC9,0xCB,0xCC, 0xCD,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,0xD6, 0xD7,0xD9,0xDA,0xDB,0xDC,0xDE,0xDF,0xE0, 0xE3,0xE4,0xE5,0xE6,0xE8,0xE9,0xEA,0xEB, 0xED,0xEE,0xEF,0xF0,0xF2,0xF3,0xF4,0xF5, 0xF6,0xF8,0xF9,0xFA,0xFB,0xFD,0xFE,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { // 6 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, 0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E, 0x10,0x12,0x14,0x16,0x18,0x18,0x1A,0x1C, 0x1E,0x20,0x22,0x24,0x26,0x27,0x29,0x2B, 0x2C,0x2E,0x30,0x31,0x33,0x35,0x36,0x38, 0x39,0x3B,0x3C,0x3E,0x40,0x41,0x43,0x44, 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50, 0x51,0x52,0x54,0x55,0x56,0x58,0x59,0x5B, 0x5C,0x5D,0x5F,0x60,0x61,0x63,0x64,0x65, 0x67,0x68,0x69,0x6A,0x6C,0x6D,0x6E,0x70, 0x71,0x72,0x73,0x75,0x76,0x77,0x78,0x7A, 0x7B,0x7C,0x7D,0x7E,0x80,0x81,0x82,0x83, 0x85,0x86,0x87,0x88,0x89,0x8A,0x8C,0x8D, 0x8E,0x8F,0x90,0x92,0x93,0x94,0x95,0x96, 0x97,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, 0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8, 0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1, 0xB2,0xB3,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA, 0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC4, 0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC, 0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { // 7 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, 0x03,0x04,0x05,0x06,0x07,0x09,0x0B,0x0C, 0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C, 0x1E,0x20,0x21,0x23,0x25,0x27,0x28,0x2A, 0x2C,0x2D,0x2F,0x31,0x32,0x34,0x36,0x37, 0x39,0x3B,0x3C,0x3E,0x3F,0x41,0x42,0x44, 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50, 0x51,0x53,0x54,0x56,0x57,0x59,0x5A,0x5C, 0x5D,0x5F,0x60,0x61,0x63,0x64,0x66,0x67, 0x68,0x6A,0x6B,0x6D,0x6E,0x6F,0x71,0x72, 0x73,0x75,0x76,0x78,0x79,0x7A,0x7C,0x7D, 0x7E,0x80,0x81,0x82,0x84,0x85,0x86,0x88, 0x89,0x8A,0x8B,0x8D,0x8E,0x8F,0x91,0x92, 0x93,0x95,0x96,0x97,0x98,0x9A,0x9B,0x9C, 0x9E,0x9F,0xA0,0xA1,0xA3,0xA4,0xA5,0xA6, 0xA8,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB0, 0xB2,0xB3,0xB4,0xB5,0xB7,0xB8,0xB9,0xBA, 0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4, 0xC5,0xC7,0xC8,0xC9,0xCA,0xCB,0xCD,0xCE, 0xCF,0xD0,0xD1,0xD3,0xD4,0xD5,0xD6,0xD7, 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xE0,0xE1, 0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEA, 0xEB,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3, 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFC,0xFD, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, } }; static unsigned char LUT_R[][256] = { { // 0 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 }, { // 1 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x02,0x03,0x04,0x06,0x07,0x09,0x0B,0x0D, 0x10,0x12,0x14,0x17,0x19,0x1B,0x1E,0x20, 0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30, 0x32,0x33,0x35,0x37,0x39,0x3B,0x3C,0x3E, 0x40,0x41,0x43,0x45,0x46,0x48,0x4A,0x4B, 0x4D,0x4F,0x50,0x52,0x53,0x55,0x57,0x58, 0x5A,0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64, 0x66,0x67,0x69,0x6A,0x6C,0x6D,0x6F,0x70, 0x71,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B, 0x7D,0x7E,0x7F,0x81,0x82,0x84,0x85,0x86, 0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x90,0x91, 0x92,0x94,0x95,0x96,0x98,0x99,0x9A,0x9C, 0x9D,0x9E,0xA0,0xA1,0xA2,0xA3,0xA5,0xA6, 0xA7,0xA8,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0, 0xB1,0xB3,0xB4,0xB5,0xB6,0xB8,0xB9,0xBA, 0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4, 0xC5,0xC6,0xC7,0xC9,0xCA,0xCB,0xCC,0xCD, 0xCF,0xD0,0xD1,0xD2,0xD3,0xD5,0xD6,0xD7, 0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE0, 0xE1,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, 0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF3, 0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFB,0xFC, 0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF }, { // 2 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, 0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E, 0x10,0x12,0x14,0x16,0x19,0x1B,0x1D,0x1F, 0x21,0x23,0x25,0x27,0x28,0x2A,0x2C,0x2E, 0x30,0x32,0x33,0x35,0x37,0x39,0x3A,0x3C, 0x3E,0x40,0x41,0x43,0x45,0x46,0x48,0x4A, 0x4B,0x4D,0x4F,0x50,0x52,0x53,0x55,0x57, 0x58,0x5A,0x5B,0x5D,0x5F,0x60,0x62,0x63, 0x65,0x66,0x68,0x69,0x6B,0x6C,0x6E,0x6F, 0x71,0x72,0x74,0x75,0x77,0x78,0x7A,0x7B, 0x7D,0x7E,0x80,0x81,0x83,0x84,0x86,0x87, 0x88,0x8A,0x8B,0x8D,0x8E,0x90,0x91,0x92, 0x94,0x95,0x97,0x98,0x99,0x9B,0x9C,0x9E, 0x9F,0xA0,0xA2,0xA3,0xA5,0xA6,0xA7,0xA9, 0xAA,0xAB,0xAD,0xAE,0xB0,0xB1,0xB2,0xB4, 0xB5,0xB6,0xB8,0xB9,0xBA,0xBC,0xBD,0xBE, 0xC0,0xC1,0xC2,0xC4,0xC5,0xC6,0xC8,0xC9, 0xCA,0xCC,0xCD,0xCE,0xD0,0xD1,0xD2,0xD4, 0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDD,0xDE, 0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7,0xE8, 0xE9,0xEB,0xEC,0xED,0xEF,0xF0,0xF1,0xF2, 0xF4,0xF5,0xF6,0xF7,0xF9,0xFA,0xFB,0xFC, 0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,0x05,0x07,0x08,0x0A, 0x0C,0x0E,0x10,0x12,0x14,0x16,0x18,0x1A, 0x1C,0x1E,0x20,0x22,0x24,0x26,0x28,0x2A, 0x2B,0x2D,0x2F,0x31,0x33,0x34,0x36,0x38, 0x39,0x3B,0x3D,0x3E,0x40,0x42,0x43,0x45, 0x47,0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52, 0x53,0x55,0x56,0x58,0x59,0x5B,0x5D,0x5E, 0x60,0x61,0x63,0x64,0x66,0x67,0x69,0x6A, 0x6B,0x6D,0x6E,0x70,0x71,0x73,0x74,0x76, 0x77,0x79,0x7A,0x7B,0x7D,0x7E,0x80,0x81, 0x83,0x84,0x85,0x87,0x88,0x8A,0x8B,0x8C, 0x8E,0x8F,0x90,0x92,0x93,0x95,0x96,0x97, 0x99,0x9A,0x9B,0x9D,0x9E,0x9F,0xA1,0xA2, 0xA3,0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,0xAD, 0xAE,0xAF,0xB1,0xB2,0xB3,0xB5,0xB6,0xB7, 0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,0xC0,0xC2, 0xC3,0xC4,0xC6,0xC7,0xC8,0xC9,0xCB,0xCC, 0xCD,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,0xD6, 0xD7,0xD9,0xDA,0xDB,0xDC,0xDE,0xDF,0xE0, 0xE1,0xE3,0xE4,0xE5,0xE5,0xE6,0xE8,0xE9, 0xEA,0xEB,0xED,0xEE,0xEF,0xF0,0xF2,0xF3, 0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFD, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05, 0x07,0x08,0x0A,0x0C,0x0E,0x10,0x12,0x14, 0x16,0x18,0x1A,0x1C,0x1E,0x20,0x22,0x24, 0x26,0x28,0x2A,0x2B,0x2D,0x2F,0x31,0x33, 0x34,0x36,0x38,0x39,0x3B,0x3D,0x3E,0x40, 0x42,0x43,0x45,0x47,0x48,0x4A,0x4B,0x4D, 0x4F,0x50,0x52,0x53,0x55,0x56,0x58,0x59, 0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64,0x66, 0x67,0x69,0x6A,0x6B,0x6D,0x6E,0x70,0x71, 0x73,0x74,0x76,0x77,0x79,0x7A,0x7B,0x7D, 0x7E,0x80,0x81,0x83,0x84,0x85,0x87,0x88, 0x8A,0x8B,0x8C,0x8E,0x8F,0x90,0x92,0x93, 0x95,0x96,0x97,0x99,0x9A,0x9B,0x9D,0x9E, 0x9F,0xA1,0xA2,0xA3,0xA5,0xA6,0xA7,0xA9, 0xAA,0xAB,0xAD,0xAE,0xAF,0xB1,0xB2,0xB3, 0xB5,0xB6,0xB7,0xB9,0xBA,0xBB,0xBD,0xBE, 0xBF,0xC0,0xC2,0xC3,0xC4,0xC6,0xC7,0xC8, 0xC9,0xCB,0xCC,0xCD,0xCF,0xD0,0xD1,0xD2, 0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDC, 0xDE,0xDF,0xE0,0xE1,0xE3,0xE4,0xE5,0xE6, 0xE8,0xE9,0xEA,0xEB,0xEB,0xED,0xEE,0xEF, 0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9, 0xFA,0xFB,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, 0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E, 0x10,0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E, 0x20,0x22,0x24,0x26,0x28,0x2A,0x2B,0x2D, 0x2F,0x31,0x33,0x34,0x36,0x38,0x39,0x3B, 0x3D,0x3E,0x40,0x42,0x43,0x45,0x47,0x48, 0x4A,0x4B,0x4D,0x4F,0x50,0x52,0x53,0x55, 0x56,0x58,0x59,0x5B,0x5D,0x5E,0x60,0x61, 0x63,0x64,0x66,0x67,0x69,0x6A,0x6B,0x6D, 0x6E,0x70,0x71,0x73,0x74,0x76,0x77,0x79, 0x7A,0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84, 0x85,0x87,0x88,0x8A,0x8B,0x8C,0x8E,0x8F, 0x90,0x92,0x93,0x95,0x96,0x97,0x99,0x9A, 0x9B,0x9D,0x9E,0x9F,0xA1,0xA2,0xA3,0xA5, 0xA6,0xA7,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF, 0xB1,0xB2,0xB3,0xB5,0xB6,0xB7,0xB9,0xBA, 0xBB,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4, 0xC6,0xC7,0xC8,0xC9,0xCB,0xCC,0xCD,0xCF, 0xD0,0xD1,0xD2,0xD4,0xD5,0xD6,0xD7,0xD9, 0xDA,0xDB,0xDC,0xDE,0xDF,0xE0,0xE1,0xE3, 0xE4,0xE5,0xE6,0xE8,0xE9,0xEA,0xEB,0xED, 0xEE,0xEF,0xF0,0xF2,0xF3,0xF4,0xF5,0xF6, 0xF8,0xF9,0xFA,0xFB,0xFD,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x02,0x03,0x04,0x05,0x06,0x08,0x0A,0x0C, 0x0E,0x10,0x12,0x14,0x16,0x19,0x1B,0x1D, 0x1F,0x20,0x22,0x24,0x26,0x28,0x2A,0x2B, 0x2D,0x2F,0x31,0x32,0x34,0x35,0x37,0x39, 0x3A,0x3C,0x3D,0x3F,0x41,0x42,0x44,0x45, 0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x4F,0x51, 0x52,0x54,0x55,0x57,0x58,0x59,0x5B,0x5C, 0x5E,0x5F,0x60,0x62,0x63,0x64,0x66,0x67, 0x68,0x6A,0x6B,0x6C,0x6E,0x6F,0x70,0x72, 0x73,0x74,0x75,0x77,0x78,0x79,0x7B,0x7C, 0x7D,0x7E,0x80,0x81,0x82,0x83,0x85,0x86, 0x87,0x88,0x89,0x8B,0x8C,0x8D,0x8E,0x90, 0x91,0x92,0x93,0x94,0x96,0x97,0x98,0x99, 0x9A,0x9B,0x9D,0x9E,0x9F,0xA0,0xA1,0xA2, 0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAB,0xAC, 0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB4,0xB5, 0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBD,0xBE, 0xBF,0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6, 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, 0xD0,0xD1,0xD2,0xD3,0xD4,0xD6,0xD7,0xD8, 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0, 0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xEA, 0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2, 0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA, 0xFB,0xFC,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, 0x03,0x04,0x05,0x06,0x07,0x09,0x0B,0x0C, 0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C, 0x1E,0x20,0x21,0x23,0x25,0x27,0x28,0x2A, 0x2C,0x2D,0x2F,0x31,0x32,0x34,0x36,0x37, 0x39,0x3B,0x3C,0x3E,0x3F,0x41,0x42,0x44, 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50, 0x51,0x53,0x54,0x56,0x57,0x59,0x5A,0x5C, 0x5D,0x5F,0x60,0x61,0x63,0x64,0x66,0x67, 0x68,0x6A,0x6B,0x6D,0x6E,0x6F,0x71,0x72, 0x73,0x75,0x76,0x78,0x79,0x7A,0x7C,0x7D, 0x7E,0x80,0x81,0x82,0x84,0x85,0x86,0x88, 0x89,0x8A,0x8B,0x8D,0x8E,0x8F,0x91,0x92, 0x93,0x95,0x96,0x97,0x98,0x9A,0x9B,0x9C, 0x9E,0x9F,0xA0,0xA1,0xA3,0xA4,0xA5,0xA6, 0xA8,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB0, 0xB2,0xB3,0xB4,0xB5,0xB7,0xB8,0xB9,0xBA, 0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4, 0xC5,0xC7,0xC8,0xC9,0xCA,0xCB,0xCD,0xCE, 0xCF,0xD0,0xD1,0xD3,0xD4,0xD5,0xD6,0xD7, 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xE0,0xE1, 0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEA, 0xEB,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3, 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFC,0xFD, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF } }; static unsigned char LUT_G[][256] = { { 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 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x02,0x03,0x04,0x06,0x07,0x09,0x0B,0x0D, 0x10,0x12,0x14,0x17,0x19,0x1B,0x1E,0x20, 0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30, 0x32,0x33,0x35,0x37,0x39,0x3B,0x3C,0x3E, 0x40,0x41,0x43,0x45,0x46,0x48,0x4A,0x4B, 0x4D,0x4F,0x50,0x52,0x53,0x55,0x57,0x58, 0x5A,0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64, 0x66,0x67,0x69,0x6A,0x6C,0x6D,0x6F,0x70, 0x71,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B, 0x7D,0x7E,0x7F,0x81,0x82,0x84,0x85,0x86, 0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x90,0x91, 0x92,0x94,0x95,0x96,0x98,0x99,0x9A,0x9C, 0x9D,0x9E,0xA0,0xA1,0xA2,0xA3,0xA5,0xA6, 0xA7,0xA8,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0, 0xB1,0xB3,0xB4,0xB5,0xB6,0xB8,0xB9,0xBA, 0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4, 0xC5,0xC6,0xC7,0xC9,0xCA,0xCB,0xCC,0xCD, 0xCF,0xD0,0xD1,0xD2,0xD3,0xD5,0xD6,0xD7, 0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE0, 0xE1,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, 0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF3, 0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFB,0xFC, 0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x02,0x03,0x04,0x05,0x07,0x08,0x0A,0x0C, 0x0E,0x10,0x12,0x14,0x16,0x16,0x19,0x1B, 0x1D,0x1F,0x21,0x23,0x25,0x27,0x28,0x2A, 0x2C,0x2E,0x30,0x32,0x33,0x35,0x37,0x39, 0x3A,0x3C,0x3E,0x40,0x41,0x43,0x45,0x46, 0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52,0x53, 0x55,0x57,0x58,0x5A,0x5B,0x5D,0x5F,0x60, 0x62,0x63,0x65,0x66,0x68,0x69,0x6B,0x6C, 0x6E,0x6F,0x71,0x72,0x74,0x75,0x77,0x78, 0x7A,0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84, 0x86,0x87,0x88,0x8A,0x8B,0x8D,0x8E,0x90, 0x91,0x92,0x94,0x95,0x97,0x98,0x99,0x9B, 0x9C,0x9E,0x9F,0xA0,0xA2,0xA3,0xA5,0xA7, 0xA9,0xAA,0xAB,0xAD,0xAE,0xB0,0xB1,0xB2, 0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,0xBC,0xBD, 0xBE,0xC0,0xC1,0xC2,0xC4,0xC5,0xC6,0xC8, 0xC9,0xCA,0xCC,0xCD,0xCE,0xD0,0xD1,0xD2, 0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDD, 0xDE,0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7, 0xE8,0xE9,0xEB,0xEC,0xED,0xEF,0xF0,0xF1, 0xF2,0xF4,0xF5,0xF6,0xF7,0xF9,0xFA,0xFB, 0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x07, 0x08,0x0A,0x0C,0x0E,0x10,0x12,0x14,0x16, 0x18,0x1A,0x1C,0x1E,0x20,0x22,0x24,0x26, 0x28,0x2A,0x2B,0x2D,0x2F,0x31,0x33,0x34, 0x36,0x38,0x39,0x3B,0x3D,0x3E,0x40,0x42, 0x43,0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4F, 0x50,0x52,0x53,0x55,0x56,0x58,0x59,0x5B, 0x5D,0x5E,0x60,0x61,0x63,0x64,0x66,0x67, 0x69,0x6A,0x6B,0x6D,0x6E,0x70,0x71,0x73, 0x74,0x76,0x77,0x79,0x7A,0x7B,0x7D,0x7E, 0x80,0x81,0x83,0x84,0x85,0x87,0x88,0x8A, 0x8B,0x8C,0x8E,0x8F,0x90,0x92,0x93,0x95, 0x96,0x97,0x99,0x9A,0x9B,0x9D,0x9E,0x9F, 0xA1,0xA2,0xA3,0xA5,0xA6,0xA7,0xA9,0xAA, 0xAB,0xAD,0xAE,0xAF,0xB1,0xB2,0xB3,0xB5, 0xB6,0xB7,0xB9,0xBA,0xBB,0xBD,0xBE,0xBF, 0xC0,0xC2,0xC3,0xC4,0xC6,0xC7,0xC8,0xC9, 0xCB,0xCC,0xCD,0xCF,0xD0,0xD1,0xD2,0xD4, 0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDC,0xDF, 0xE0,0xE1,0xE3,0xE4,0xE5,0xE6,0xE8,0xE9, 0xEA,0xEB,0xED,0xEE,0xEF,0xF0,0xF2,0xF3, 0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFD, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03, 0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E,0x10, 0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20, 0x22,0x24,0x26,0x28,0x2A,0x2B,0x2D,0x2F, 0x31,0x33,0x34,0x36,0x38,0x39,0x3B,0x3D, 0x3E,0x40,0x42,0x43,0x45,0x47,0x48,0x4A, 0x4B,0x4D,0x4F,0x50,0x52,0x53,0x55,0x56, 0x58,0x59,0x5B,0x5D,0x5E,0x60,0x61,0x63, 0x64,0x66,0x67,0x69,0x6A,0x6B,0x6D,0x6E, 0x70,0x71,0x73,0x74,0x76,0x77,0x79,0x7A, 0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84,0x85, 0x87,0x88,0x8A,0x8B,0x8C,0x8E,0x8F,0x90, 0x92,0x93,0x95,0x96,0x97,0x99,0x9A,0x9B, 0x9D,0x9E,0x9F,0xA1,0xA2,0xA3,0xA5,0xA6, 0xA7,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB1, 0xB2,0xB3,0xB5,0xB6,0xB7,0xB9,0xBA,0xBB, 0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,0xC6, 0xC7,0xC8,0xC9,0xCB,0xCC,0xCD,0xCF,0xD0, 0xD1,0xD2,0xD4,0xD5,0xD6,0xD7,0xD9,0xDA, 0xDB,0xDC,0xDE,0xDF,0xE0,0xE1,0xE3,0xE5, 0xE6,0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF, 0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9, 0xFA,0xFB,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,0x05,0x07,0x08,0x0A, 0x0C,0x0E,0x10,0x12,0x14,0x16,0x18,0x1A, 0x1C,0x1E,0x20,0x22,0x24,0x26,0x28,0x2A, 0x2B,0x2D,0x2F,0x31,0x33,0x34,0x36,0x38, 0x39,0x3B,0x3D,0x3E,0x40,0x42,0x43,0x45, 0x47,0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52, 0x53,0x55,0x56,0x58,0x59,0x5B,0x5D,0x5E, 0x60,0x61,0x63,0x64,0x66,0x67,0x69,0x6A, 0x6B,0x6D,0x6E,0x70,0x71,0x73,0x74,0x76, 0x77,0x79,0x7A,0x7B,0x7D,0x7E,0x80,0x81, 0x83,0x84,0x85,0x87,0x88,0x8A,0x8B,0x8C, 0x8E,0x8F,0x90,0x92,0x93,0x95,0x96,0x97, 0x99,0x9A,0x9B,0x9D,0x9E,0x9F,0xA1,0xA2, 0xA3,0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,0xAD, 0xAE,0xAF,0xB1,0xB2,0xB3,0xB5,0xB6,0xB7, 0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,0xC0,0xC2, 0xC3,0xC4,0xC6,0xC7,0xC8,0xC9,0xCB,0xCC, 0xCD,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,0xD6, 0xD7,0xD9,0xDA,0xDB,0xDC,0xDE,0xDF,0xE0, 0xE3,0xE4,0xE5,0xE6,0xE8,0xE9,0xEA,0xEB, 0xED,0xEE,0xEF,0xF0,0xF2,0xF3,0xF4,0xF5, 0xF6,0xF8,0xF9,0xFA,0xFB,0xFD,0xFE,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, 0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E, 0x10,0x12,0x14,0x16,0x18,0x18,0x1A,0x1C, 0x1E,0x20,0x22,0x24,0x26,0x27,0x29,0x2B, 0x2C,0x2E,0x30,0x31,0x33,0x35,0x36,0x38, 0x39,0x3B,0x3C,0x3E,0x40,0x41,0x43,0x44, 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50, 0x51,0x52,0x54,0x55,0x56,0x58,0x59,0x5B, 0x5C,0x5D,0x5F,0x60,0x61,0x63,0x64,0x65, 0x67,0x68,0x69,0x6A,0x6C,0x6D,0x6E,0x70, 0x71,0x72,0x73,0x75,0x76,0x77,0x78,0x7A, 0x7B,0x7C,0x7D,0x7E,0x80,0x81,0x82,0x83, 0x85,0x86,0x87,0x88,0x89,0x8A,0x8C,0x8D, 0x8E,0x8F,0x90,0x92,0x93,0x94,0x95,0x96, 0x97,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, 0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8, 0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1, 0xB2,0xB3,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA, 0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC4, 0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC, 0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { // 7 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, 0x03,0x04,0x05,0x06,0x07,0x09,0x0B,0x0C, 0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C, 0x1E,0x20,0x21,0x23,0x25,0x27,0x28,0x2A, 0x2C,0x2D,0x2F,0x31,0x32,0x34,0x36,0x37, 0x39,0x3B,0x3C,0x3E,0x3F,0x41,0x42,0x44, 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50, 0x51,0x53,0x54,0x56,0x57,0x59,0x5A,0x5C, 0x5D,0x5F,0x60,0x61,0x63,0x64,0x66,0x67, 0x68,0x6A,0x6B,0x6D,0x6E,0x6F,0x71,0x72, 0x73,0x75,0x76,0x78,0x79,0x7A,0x7C,0x7D, 0x7E,0x80,0x81,0x82,0x84,0x85,0x86,0x88, 0x89,0x8A,0x8B,0x8D,0x8E,0x8F,0x91,0x92, 0x93,0x95,0x96,0x97,0x98,0x9A,0x9B,0x9C, 0x9E,0x9F,0xA0,0xA1,0xA3,0xA4,0xA5,0xA6, 0xA8,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB0, 0xB2,0xB3,0xB4,0xB5,0xB7,0xB8,0xB9,0xBA, 0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4, 0xC5,0xC7,0xC8,0xC9,0xCA,0xCB,0xCD,0xCE, 0xCF,0xD0,0xD1,0xD3,0xD4,0xD5,0xD6,0xD7, 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xE0,0xE1, 0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEA, 0xEB,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3, 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFC,0xFD, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, } }; static unsigned char LUT_B[][256] = { { 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 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x02,0x03,0x04,0x06,0x07,0x09,0x0B,0x0D, 0x10,0x12,0x14,0x17,0x19,0x1B,0x1E,0x20, 0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30, 0x32,0x33,0x35,0x37,0x39,0x3B,0x3C,0x3E, 0x40,0x41,0x43,0x45,0x46,0x48,0x4A,0x4B, 0x4D,0x4F,0x50,0x52,0x53,0x55,0x57,0x58, 0x5A,0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64, 0x66,0x67,0x69,0x6A,0x6C,0x6D,0x6F,0x70, 0x71,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B, 0x7D,0x7E,0x7F,0x81,0x82,0x84,0x85,0x86, 0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x90,0x91, 0x92,0x94,0x95,0x96,0x98,0x99,0x9A,0x9C, 0x9D,0x9E,0xA0,0xA1,0xA2,0xA3,0xA5,0xA6, 0xA7,0xA8,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0, 0xB1,0xB3,0xB4,0xB5,0xB6,0xB8,0xB9,0xBA, 0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4, 0xC5,0xC6,0xC7,0xC9,0xCA,0xCB,0xCC,0xCD, 0xCF,0xD0,0xD1,0xD2,0xD3,0xD5,0xD6,0xD7, 0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE0, 0xE1,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, 0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF3, 0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFB,0xFC, 0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x02,0x03,0x04,0x05,0x07,0x08,0x0A,0x0C, 0x0E,0x10,0x12,0x14,0x16,0x16,0x19,0x1B, 0x1D,0x1F,0x21,0x23,0x25,0x27,0x28,0x2A, 0x2C,0x2E,0x30,0x32,0x33,0x35,0x37,0x39, 0x3A,0x3C,0x3E,0x40,0x41,0x43,0x45,0x46, 0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52,0x53, 0x55,0x57,0x58,0x5A,0x5B,0x5D,0x5F,0x60, 0x62,0x63,0x65,0x66,0x68,0x69,0x6B,0x6C, 0x6E,0x6F,0x71,0x72,0x74,0x75,0x77,0x78, 0x7A,0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84, 0x86,0x87,0x88,0x8A,0x8B,0x8D,0x8E,0x90, 0x91,0x92,0x94,0x95,0x97,0x98,0x99,0x9B, 0x9C,0x9E,0x9F,0xA0,0xA2,0xA3,0xA5,0xA7, 0xA9,0xAA,0xAB,0xAD,0xAE,0xB0,0xB1,0xB2, 0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,0xBC,0xBD, 0xBE,0xC0,0xC1,0xC2,0xC4,0xC5,0xC6,0xC8, 0xC9,0xCA,0xCC,0xCD,0xCE,0xD0,0xD1,0xD2, 0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDD, 0xDE,0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7, 0xE8,0xE9,0xEB,0xEC,0xED,0xEF,0xF0,0xF1, 0xF2,0xF4,0xF5,0xF6,0xF7,0xF9,0xFA,0xFB, 0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x01,0x02,0x03,0x04,0x05,0x07,0x08, 0x0A,0x0C,0x0E,0x10,0x12,0x14,0x16,0x18, 0x1A,0x1C,0x1E,0x20,0x22,0x24,0x26,0x28, 0x2A,0x2B,0x2D,0x2F,0x31,0x33,0x34,0x36, 0x38,0x39,0x3B,0x3D,0x3E,0x40,0x42,0x43, 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4F,0x50, 0x52,0x53,0x55,0x56,0x58,0x59,0x5B,0x5D, 0x5E,0x60,0x61,0x63,0x64,0x66,0x67,0x69, 0x6A,0x6B,0x6D,0x6E,0x70,0x71,0x73,0x74, 0x76,0x77,0x79,0x7A,0x7B,0x7D,0x7E,0x80, 0x81,0x83,0x84,0x85,0x87,0x88,0x8A,0x8B, 0x8C,0x8E,0x8F,0x90,0x92,0x93,0x95,0x96, 0x97,0x99,0x9A,0x9B,0x9D,0x9E,0x9F,0xA1, 0xA2,0xA3,0xA5,0xA6,0xA7,0xA9,0xAA,0xAB, 0xAD,0xAE,0xAF,0xB1,0xB2,0xB3,0xB5,0xB6, 0xB7,0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,0xC0, 0xC2,0xC3,0xC4,0xC6,0xC7,0xC8,0xC9,0xCB, 0xCC,0xCD,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5, 0xD6,0xD7,0xD9,0xDA,0xDB,0xDC,0xDE,0xDF, 0xE0,0xE1,0xE3,0xE4,0xE5,0xE6,0xE8,0xE9, 0xEA,0xEB,0xED,0xEE,0xEF,0xF0,0xF2,0xF3, 0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFD, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04, 0x05,0x07,0x08,0x0A,0x0C,0x0E,0x10,0x12, 0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20,0x22, 0x24,0x26,0x28,0x2A,0x2B,0x2D,0x2F,0x31, 0x33,0x34,0x36,0x38,0x39,0x3B,0x3D,0x3E, 0x40,0x42,0x43,0x45,0x47,0x48,0x4A,0x4B, 0x4D,0x4F,0x50,0x52,0x53,0x55,0x56,0x58, 0x59,0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64, 0x66,0x67,0x69,0x6A,0x6B,0x6D,0x6E,0x70, 0x71,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B, 0x7D,0x7E,0x80,0x81,0x83,0x84,0x85,0x87, 0x88,0x8A,0x8B,0x8C,0x8E,0x8F,0x90,0x92, 0x93,0x95,0x96,0x97,0x99,0x9A,0x9B,0x9D, 0x9E,0x9F,0xA1,0xA2,0xA3,0xA5,0xA6,0xA7, 0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB1,0xB2, 0xB3,0xB5,0xB6,0xB7,0xB9,0xBA,0xBB,0xBD, 0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,0xC6,0xC7, 0xC8,0xC9,0xCB,0xCC,0xCD,0xCF,0xD0,0xD1, 0xD2,0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,0xDB, 0xDC,0xDE,0xDF,0xE0,0xE1,0xE3,0xE4,0xE5, 0xE6,0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF, 0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9, 0xFA,0xFB,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x02,0x03,0x04,0x05,0x07,0x08,0x0A,0x0C, 0x0E,0x10,0x12,0x14,0x16,0x16,0x18,0x1A, 0x1C,0x1E,0x20,0x22,0x24,0x26,0x28,0x2A, 0x2B,0x2D,0x2F,0x31,0x33,0x34,0x36,0x38, 0x39,0x3B,0x3D,0x3E,0x40,0x42,0x43,0x45, 0x47,0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52, 0x53,0x55,0x56,0x58,0x59,0x5B,0x5D,0x5E, 0x60,0x61,0x63,0x64,0x66,0x67,0x69,0x6A, 0x6B,0x6D,0x6E,0x70,0x71,0x73,0x74,0x76, 0x77,0x79,0x7A,0x7B,0x7D,0x7E,0x80,0x81, 0x83,0x84,0x85,0x87,0x88,0x8A,0x8B,0x8C, 0x8E,0x8F,0x90,0x92,0x93,0x95,0x96,0x97, 0x99,0x9A,0x9B,0x9D,0x9E,0x9F,0xA1,0xA3, 0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,0xAD,0xAE, 0xAF,0xB1,0xB2,0xB3,0xB5,0xB6,0xB7,0xB9, 0xBA,0xBB,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3, 0xC4,0xC6,0xC7,0xC8,0xC9,0xCB,0xCC,0xCD, 0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,0xD6,0xD7, 0xD9,0xDA,0xDB,0xDC,0xDE,0xDF,0xE0,0xE1, 0xE3,0xE4,0xE5,0xE6,0xE8,0xE9,0xEA,0xEB, 0xED,0xEE,0xEF,0xF0,0xF2,0xF3,0xF4,0xF5, 0xF6,0xF8,0xF9,0xFA,0xFB,0xFD,0xFE,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03, 0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E,0x10, 0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20, 0x22,0x24,0x26,0x27,0x29,0x2B,0x2C,0x2E, 0x30,0x31,0x33,0x35,0x36,0x38,0x39,0x3B, 0x3C,0x3E,0x40,0x41,0x43,0x44,0x45,0x47, 0x48,0x4B,0x4D,0x4E,0x50,0x51,0x52,0x54, 0x55,0x56,0x58,0x59,0x5B,0x5C,0x5D,0x5F, 0x60,0x61,0x63,0x64,0x65,0x67,0x68,0x69, 0x6A,0x6C,0x6D,0x6E,0x70,0x71,0x72,0x73, 0x75,0x76,0x77,0x78,0x7A,0x7B,0x7C,0x7D, 0x7E,0x80,0x81,0x82,0x83,0x85,0x86,0x87, 0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x8F,0x90, 0x92,0x93,0x94,0x95,0x96,0x96,0x97,0x99, 0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xA1,0xA2, 0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xAA,0xAB, 0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3, 0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC, 0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,0xC5, 0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD, 0xCE,0xCF,0xD0,0xD1,0xD2,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, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, 0x03,0x04,0x05,0x06,0x07,0x09,0x0B,0x0C, 0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C, 0x1E,0x20,0x21,0x23,0x25,0x27,0x28,0x2A, 0x2C,0x2D,0x2F,0x31,0x32,0x34,0x36,0x37, 0x39,0x3B,0x3C,0x3E,0x3F,0x41,0x42,0x44, 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50, 0x51,0x53,0x54,0x56,0x57,0x59,0x5A,0x5C, 0x5D,0x5F,0x60,0x61,0x63,0x64,0x66,0x67, 0x68,0x6A,0x6B,0x6D,0x6E,0x6F,0x71,0x72, 0x73,0x75,0x76,0x78,0x79,0x7A,0x7C,0x7D, 0x7E,0x80,0x81,0x82,0x84,0x85,0x86,0x88, 0x89,0x8A,0x8B,0x8D,0x8E,0x8F,0x91,0x92, 0x93,0x95,0x96,0x97,0x98,0x9A,0x9B,0x9C, 0x9E,0x9F,0xA0,0xA1,0xA3,0xA4,0xA5,0xA6, 0xA8,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB0, 0xB2,0xB3,0xB4,0xB5,0xB7,0xB8,0xB9,0xBA, 0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4, 0xC5,0xC7,0xC8,0xC9,0xCA,0xCB,0xCD,0xCE, 0xCF,0xD0,0xD1,0xD3,0xD4,0xD5,0xD6,0xD7, 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xE0,0xE1, 0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEA, 0xEB,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3, 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFC,0xFD, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, } }; //// profile array //// typedef struct { int productID; // USB PID char productName[50]; // ESCI/2 procduct name char deviceID[50]; // device ID (same as bonjour mdl name) int lutID; // look up table no }epsonds_profile_map; const epsonds_profile_map epsonds_models_predefined[] = { {0x0145, "DS-5500","DS-5500", 7}, {0x0145, "DS-6500","DS-6500", 7}, {0x0145, "DS-7500","DS-7500", 7}, {0x0146, "DS-50000","DS-50000", 7}, {0x0146, "DS-60000","DS-60000", 7}, {0x0146, "DS-70000","DS-70000", 7}, {0x014C, "DS-510","DS-510", 7}, {0x0150, "DS-560","DS-560", 7}, {0x0152, "DS-40","DS-40", 7}, {0x014D, "DS-760","DS-760", 7}, {0x014D, "DS-860","DS-860", 7}, {0x0154, "DS-520","DS-520", 7}, {0x08BC, "PID 08BC","PX-M7050 Series", 7}, {0x08BC, "PID 08BC","WF-8510 Series", 7}, {0x08BC, "PID 08BC","WF-8590 Series", 7}, {0x08CC, "PID 08CC","PX-M7050FX Series", 7}, {0x08CC, "PID 08CC","WF-R8590 Series", 7}, {0x0165, "DS-410","DS-410", 7}, {0x016C, "ES-50","ES-50", 6}, {0x0160, "DS-70","DS-70", 6}, {0x016D, "ES-55R","ES-55R", 6}, {0x018C, "RR-60","RR-60", 6}, {0x016E, "ES-60W","ES-60W", 6}, {0x0166, "DS-80W","DS-80W", 6}, {0x016F, "ES-65WR","ES-65WR", 6}, {0x018B, "RR-70W","RR-70W", 6}, {0x016E, "ES-60WW","ES-60WW", 6}, {0x016E, "ES-60WB","ES-60WB", 6}, {0x015C, "DS-1630","DS-1630", 4}, {0x015D, "DS-1610","DS-1610", 4}, {0x015E, "DS-1660W","DS-1660W", 4}, {0x0159, "DS-310","DS-310", 5}, {0x0159, "ES-200","ES-200", 5}, {0x0162, "DS-320","DS-320", 5}, {0x015A, "DS-360W","DS-360W", 5}, {0x015A, "ES-300W","ES-300W", 5}, {0x0177, "ES-300WR","ES-300WR", 5}, {0x0181, "ES-400II","ES-400II", 2}, {0x0183, "DS-535II","DS-535II", 2}, {0x0184, "DS-531","DS-531", 2}, {0x0182, "DS-530II","DS-530II", 2}, {0x0185, "ES-500WII","ES-500WII", 2}, {0x0188, "DS-571W","DS-571W", 2}, {0x0187, "DS-575WII","DS-575WII", 2}, {0x0186, "DS-570WII","DS-570WII", 2}, {0x017F, "ES-580W","ES-580W", 2}, {0x0180, "RR-600W","RR-600W", 2}, {0x0167, "DS-535","DS-535", 2}, {0x017A, "DS-535H","DS-535H", 2}, {0x0156, "ES-400","ES-400", 2}, {0x0155, "DS-530","DS-530", 2}, {0x016B, "FF-680W","FF-680W", 2}, {0x0157, "DS-570W","DS-570W", 2}, {0x0157, "ES-500W","ES-500W", 2}, {0x0169, "DS-575W","DS-575W", 2}, {0x0176, "ES-500WR","ES-500WR", 2}, {0x114E, "PID 114E","EW-052A Series", 7}, {0x114E, "PID 114E","XP-2100 Series", 7}, {0x1135, "PID 1135","ET-2700 Series", 7}, {0x1135, "PID 1135","L4150 Series", 7}, {0x114A, "PID 114A","ET-M2140 Series", 7}, {0x114A, "PID 114A","M2140 Series", 7}, {0x114F, "PID 114F","ET-M3140 Series", 7}, {0x114F, "PID 114F","M3140 Series", 7}, {0x1143, "PID 1143","L3150 Series", 7}, {0x1143, "PID 1143","ET-2710 Series", 7}, {0x118A, "PID 118A","ET-2810 Series", 7}, {0x118A, "PID 118A","L3250 Series", 7}, {0x119B, "PID 119B","XP-2150 Series", 7}, {0x00, "","", 0x00 } }; typedef struct { epsonds_profile_map *array; int used; int size; }epsonds_profile_map_array; static epsonds_profile_map_array stProfileMapArray; static void insert_profile_map(epsonds_profile_map_array *a, epsonds_profile_map element); static void init_profile_maps(epsonds_profile_map_array *a, size_t initialSize) { a->array = malloc(initialSize * sizeof(epsonds_profile_map)); a->used = 0; a->size = initialSize; for (int i = 0; epsonds_models_predefined[i].productID != 0; i++) { //DBG(6, "epsonds_models_predefined[i].productID = %x\n", epsonds_models_predefined[i].productID ); insert_profile_map(a, epsonds_models_predefined[i]); } } static void insert_profile_map(epsonds_profile_map_array *a, epsonds_profile_map element) { if (a->used == a->size) { a->size *= 2; a->array = realloc(a->array, a->size * sizeof(epsonds_profile_map)); } a->array[a->used++] = element; } static void free_profile_maps(epsonds_profile_map_array *a) { free(a->array); a->array = NULL; a->used = a->size = 0; } ///////////////////////// struct mode_param mode_params[] = { {0, 0x00, 0x30, 1}, {0, 0x00, 0x30, 8}, {1, 0x02, 0x00, 8}, {0, 0x00, 0x30, 1} }; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; /* Define the different scan sources */ #define STRING_FLATBED SANE_I18N("Flatbed") #define STRING_ADFFRONT SANE_I18N("ADF Front") #define STRING_ADFDUPLEX SANE_I18N("ADF Duplex") /* order will be fixed: fb, adf, tpu */ SANE_String_Const source_list[] = { NULL, NULL, NULL, NULL }; /* * List of pointers to devices - will be dynamically allocated depending * on the number of devices found. */ static const SANE_Device **devlist; /* Some utility functions */ static size_t max_string_size(const 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; } static SANE_Status attach_one_usb(SANE_String_Const devname); static SANE_Status attach_one_net(SANE_String_Const devname); static SANE_Status acquire_jpeg_data(epsonds_scanner* s); static SANE_Status acquire_and_decode_jpeg_data(epsonds_scanner* s); static SANE_Status acquire_raw_data(epsonds_scanner* s); static void print_params(const SANE_Parameters params) { DBG(6, "params.format = %d\n", params.format); DBG(6, "params.last_frame = %d\n", params.last_frame); DBG(6, "params.bytes_per_line = %d\n", params.bytes_per_line); DBG(6, "params.pixels_per_line = %d\n", params.pixels_per_line); DBG(6, "params.lines = %d\n", params.lines); DBG(6, "params.depth = %d\n", params.depth); } static void close_scanner(epsonds_scanner *s) { DBG(7, "%s: fd = %d\n", __func__, s->fd); if (s->scanning) { sane_cancel(s); } if (s->fd == -1) goto free; if (s->locked) { DBG(7, " unlocking scanner\n"); esci2_fin(s); } if (s->hw->connection == SANE_EPSONDS_NET) { epsonds_net_unlock(s); sanei_tcp_close(s->fd); } else if (s->hw->connection == SANE_EPSONDS_USB) { sanei_usb_close(s->fd); } free: free(s->front.ring); free(s->back.ring); free(s->line_buffer); free(s); DBG(7, "%s: ZZZ\n", __func__); } static SANE_Status open_scanner(epsonds_scanner *s) { SANE_Status status = SANE_STATUS_INVAL; DBG(7, "%s: %s\n", __func__, s->hw->sane.name); if (s->fd != -1) { DBG(5, "scanner is already open: fd = %d\n", s->fd); return SANE_STATUS_GOOD; /* no need to open the scanner */ } if (s->hw->connection == SANE_EPSONDS_NET) { unsigned char buf[5]; /* device name has the form net:ipaddr */ status = sanei_tcp_open(&s->hw->name[4], 1865, &s->fd); if (status == SANE_STATUS_GOOD) { ssize_t read; struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); s->netlen = 0; DBG(32, "awaiting welcome message\n"); /* the scanner sends a kind of welcome msg */ // XXX check command type, answer to connect is 0x80 read = eds_recv(s, buf, 5, &status); if (read != 5) { sanei_tcp_close(s->fd); s->fd = -1; return SANE_STATUS_IO_ERROR; } DBG(32, "welcome message received, locking the scanner...\n"); /* lock the scanner for use by sane */ status = epsonds_net_lock(s); if (status != SANE_STATUS_GOOD) { DBG(1, "%s cannot lock scanner: %s\n", s->hw->sane.name, sane_strstatus(status)); sanei_tcp_close(s->fd); s->fd = -1; return status; } DBG(32, "scanner locked\n"); } } else if (s->hw->connection == SANE_EPSONDS_USB) { status = sanei_usb_open(s->hw->sane.name, &s->fd); if (status == SANE_STATUS_GOOD) { sanei_usb_set_timeout(USB_TIMEOUT); } } else { DBG(1, "unknown connection type: %d\n", s->hw->connection); } if (status == SANE_STATUS_ACCESS_DENIED) { DBG(1, "please check that you have permissions on the device.\n"); DBG(1, "if this is a multi-function device with a printer,\n"); DBG(1, "disable any conflicting driver (like usblp).\n"); } if (status != SANE_STATUS_GOOD) DBG(1, "%s open failed: %s\n", s->hw->sane.name, sane_strstatus(status)); else DBG(5, " opened correctly\n"); return status; } static int num_devices; /* number of scanners attached to backend */ static epsonds_device *first_dev; /* first EPSON scanner in list */ static struct epsonds_scanner * scanner_create(struct epsonds_device *dev, SANE_Status *status) { struct epsonds_scanner *s; s = malloc(sizeof(struct epsonds_scanner)); if (s == NULL) { *status = SANE_STATUS_NO_MEM; return NULL; } /* clear verything */ memset(s, 0x00, sizeof(struct epsonds_scanner)); s->fd = -1; s->hw = dev; return s; } static struct epsonds_scanner * device_detect(const char *name, int type, SANE_Status *status) { struct epsonds_scanner *s; struct epsonds_device *dev; DBG(1, "%s, %s, type: %d\n", __func__, name, type); /* try to find the device in our list */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp(dev->sane.name, name) == 0) { DBG(1, " found cached device\n"); // the device might have been just probed, sleep a bit. if (dev->connection == SANE_EPSONDS_NET) { sleep(1); } return scanner_create(dev, status); } } /* not found, create new if valid */ if (type == SANE_EPSONDS_NODEV) { *status = SANE_STATUS_INVAL; return NULL; } /* alloc and clear our device structure */ dev = malloc(sizeof(*dev)); if (!dev) { *status = SANE_STATUS_NO_MEM; return NULL; } memset(dev, 0x00, sizeof(struct epsonds_device)); s = scanner_create(dev, status); if (s == NULL) return NULL; dev->connection = type; dev->model = strdup("(undetermined)"); dev->name = strdup(name); dev->sane.name = dev->name; dev->sane.vendor = "Epson"; dev->sane.model = dev->model; dev->sane.type = "ESC/I-2"; *status = open_scanner(s); if (*status != SANE_STATUS_GOOD) { free(s); return NULL; } eds_dev_init(dev); /* lock scanner */ *status = eds_lock(s); if (*status != SANE_STATUS_GOOD) { goto close; } /* discover capabilities */ *status = esci2_info(s); if (*status != SANE_STATUS_GOOD) goto close; *status = esci2_capa(s); if (*status != SANE_STATUS_GOOD) goto close; *status = esci2_resa(s); if (*status != SANE_STATUS_GOOD) goto close; // assume 1 and 8 bit are always supported eds_add_depth(s->hw, 1); eds_add_depth(s->hw, 8); // setup area according to available options if (s->hw->has_fb) { dev->x_range = &dev->fbf_x_range; dev->y_range = &dev->fbf_y_range; dev->alignment = dev->fbf_alignment; } else if (s->hw->has_adf) { dev->x_range = &dev->adf_x_range; dev->y_range = &dev->adf_y_range; dev->alignment = dev->adf_alignment; } else { DBG(0, "unable to lay on the flatbed or feed the feeder. is that a scanner??\n"); } *status = eds_dev_post_init(dev); if (*status != SANE_STATUS_GOOD) goto close; DBG(1, "scanner model: %s\n", dev->model); s->hw->lut_id = 0; for (int i = 0; i < stProfileMapArray.used; i++) { epsonds_profile_map* map = &stProfileMapArray.array[i]; if (strcmp(map->productName, dev->model) == 0) { {//Convert to user friendly model name free(s->hw->model); char* deviceName = (char*)malloc(strlen(map->deviceID) + 1); memset(deviceName, 0, strlen(map->deviceID) + 1); strncpy(deviceName, map->deviceID, strlen(map->deviceID)); s->hw->model = deviceName; s->hw->sane.model = s->hw->model; } {// set lutid s->hw->lut_id = map->lutID; } break; } } DBG(1, "scanner lut_id: %d\n", s->hw->lut_id); num_devices++; dev->next = first_dev; first_dev = dev; return s; close: DBG(1, " failed\n"); close_scanner(s); return NULL; } static SANE_Status attach(const char *name, int type) { SANE_Status status; epsonds_scanner * s; DBG(7, "%s: devname = %s, type = %d\n", __func__, name, type); s = device_detect(name, type, &status); if (s == NULL) return status; close_scanner(s); return status; } SANE_Status attach_one_usb(const char *dev) { DBG(7, "%s: dev = %s\n", __func__, dev); return attach(dev, SANE_EPSONDS_USB); } static SANE_Status attach_one_net(const char *dev) { char name[39 + 4]; DBG(7, "%s: dev = %s\n", __func__, dev); strcpy(name, "net:"); strcat(name, dev); return attach(name, SANE_EPSONDS_NET); } static void found_net_device(const char* device_name, const char* ip) { DBG(7, "Found %s: ip = %s\n", device_name, ip); int foundSupportedDevice = 0; // search models for (int i = 0; i < stProfileMapArray.used; i++) { if (strcmp(stProfileMapArray.array[i].deviceID, device_name) == 0) { foundSupportedDevice = 1; break; } } if (foundSupportedDevice) { char name[39 + 4]; strcpy(name, "net:"); strncat(name, ip, 39); int foundCache = 0; // search cache and prents duplicated model for (epsonds_device* dev = first_dev; dev; dev = dev->next) { if (strcmp(dev->sane.name, name) == 0) { foundCache = 1; } } if (foundCache == 0) { attach(name, SANE_EPSONDS_NET); } } } static void splitProfileName(const char* input, int* outProductID, char *outProductName, char* outDeviceID, int* outLutID) { char target[1024]; strncpy(target, input, 1023); strtok(target, ":");//profile //productID char* pid = strtok(NULL, ","); sscanf(pid, "%x", (unsigned int*)outProductID); //productName char* productName = strtok(NULL, ","); strncpy(outProductName, productName, 49); //deviceID char* deviceID = strtok(NULL, ","); strncpy(outDeviceID, deviceID, 49); //lutID char* lutID = strtok(NULL, ","); sscanf(lutID, "%d", outLutID); } static SANE_Status attach_one_config(SANEI_Config __sane_unused__ *config, const char *line, void *data) { int vendor, product; SANE_Bool local_only = *(SANE_Bool*) data; int len = strlen(line); DBG(7, "%s: len = %d, line = %s\n", __func__, len, line); if (strncmp(line, "profile", 7) == 0 ) { DBG(7, " found profile device profile\n"); epsonds_profile_map profle_map; splitProfileName(line, &profle_map.productID, profle_map.productName, profle_map.deviceID, &profle_map.lutID); DBG(7, "Found profile : %x %s %s %d\n", profle_map.productID, profle_map.productName, profle_map.deviceID, profle_map.lutID); insert_profile_map(&stProfileMapArray, profle_map); }else if (sscanf(line, "usb %i %i", &vendor, &product) == 2) { DBG(7, " user configured device\n"); if (vendor != SANE_EPSONDS_VENDOR_ID) return SANE_STATUS_INVAL; /* this is not an Epson device */ sanei_usb_attach_matching_devices(line, attach_one_usb); } else if (strncmp(line, "usb", 3) == 0 && len == 3) { DBG(7, " probing usb devices\n"); for (int i = 0; i < stProfileMapArray.used; i++) { int usbPid = stProfileMapArray.array[i].productID; sanei_usb_find_devices(SANE_EPSONDS_VENDOR_ID, usbPid, attach_one_usb); } } else if (strncmp(line, "net", 3) == 0) { if (!local_only) { /* remove the "net" sub string */ const char *name = sanei_config_skip_whitespace(line + 3); if (strncmp(name, "autodiscovery", 13) == 0) { #if WITH_AVAHI epsonds_searchDevices(found_net_device); #else // currently does not support //e2_network_discovery(); #endif } else attach_one_net(name); } } else { DBG(0, "unable to parse config line: %s\n", line); } return SANE_STATUS_GOOD; } static void free_devices(void) { epsonds_device *dev, *next; for (dev = first_dev; dev; dev = next) { next = dev->next; free(dev->name); free(dev->model); free(dev); } free(devlist); first_dev = NULL; } static void probe_devices(SANE_Bool local_only) { DBG(5, "%s\n", __func__); free_devices(); sanei_configure_attach(EPSONDS_CONFIG_FILE, NULL, attach_one_config, &local_only); } /**** SANE API ****/ SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) { DBG_INIT(); init_profile_maps(&stProfileMapArray, 100); DBG(2, "%s: " PACKAGE " " VERSION "\n", __func__); DBG(1, "epsonds backend, version %i.%i.%i\n", EPSONDS_VERSION, EPSONDS_REVISION, EPSONDS_BUILD); if (version_code != NULL) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, EPSONDS_BUILD); sanei_usb_init(); return SANE_STATUS_GOOD; } void sane_exit(void) { DBG(5, "** %s\n", __func__); free_profile_maps(&stProfileMapArray); free_devices(); } SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only) { int i; epsonds_device *dev; DBG(5, "** %s local_only = %d \n", __func__, local_only); probe_devices(local_only); devlist = malloc((num_devices + 1) * sizeof(devlist[0])); if (!devlist) { DBG(1, "out of memory (line %d)\n", __LINE__); return SANE_STATUS_NO_MEM; } DBG(5, "%s - results:\n", __func__); for (i = 0, dev = first_dev; i < num_devices && dev; dev = dev->next, i++) { DBG(1, " %d (%d): %s\n", i, dev->connection, dev->model); devlist[i] = &dev->sane; } devlist[i] = NULL; *device_list = devlist; return SANE_STATUS_GOOD; } static SANE_Status init_options(epsonds_scanner *s) { DBG(5, "init_options\n"); int i; for (i = 0; i < NUM_OPTIONS; i++) { s->opt[i].size = sizeof(SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Scan Mode" group: */ s->opt[OPT_STANDARD_GROUP].name = SANE_NAME_STANDARD; s->opt[OPT_STANDARD_GROUP].title = SANE_TITLE_STANDARD; s->opt[OPT_STANDARD_GROUP].desc = SANE_DESC_STANDARD; s->opt[OPT_STANDARD_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_STANDARD_GROUP].cap = 0; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size(mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].w = 0; /* Lineart */ /* bit depth */ s->opt[OPT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_DEPTH].unit = SANE_UNIT_BIT; s->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_DEPTH].constraint.word_list = s->hw->depth_list; s->val[OPT_DEPTH].w = s->hw->depth_list[1]; /* the first "real" element is the default */ /* default is Lineart, disable depth selection */ s->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; /* range */ if (s->hw->dpi_range.quant) { s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; } else { /* list */ s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->res_list; s->val[OPT_RESOLUTION].w = s->hw->res_list[1]; } /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = s->hw->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = s->hw->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range->max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range->max; /* "Optional equipment" group: */ s->opt[OPT_EQU_GROUP].title = SANE_I18N("Optional equipment"); s->opt[OPT_EQU_GROUP].desc = ""; s->opt[OPT_EQU_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_EQU_GROUP].cap = SANE_CAP_ADVANCED; /* source */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].size = max_string_size(source_list); s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = source_list; s->val[OPT_SOURCE].w = 0; s->opt[OPT_EJECT].name = "eject"; s->opt[OPT_EJECT].title = SANE_I18N("Eject"); s->opt[OPT_EJECT].desc = SANE_I18N("Eject the sheet in the ADF"); s->opt[OPT_EJECT].type = SANE_TYPE_BUTTON; if (!s->hw->adf_has_eject) s->opt[OPT_EJECT].cap |= SANE_CAP_INACTIVE; s->opt[OPT_LOAD].name = "load"; s->opt[OPT_LOAD].title = SANE_I18N("Load"); s->opt[OPT_LOAD].desc = SANE_I18N("Load a sheet in the ADF"); s->opt[OPT_LOAD].type = SANE_TYPE_BUTTON; if (!s->hw->adf_has_load) s->opt[OPT_LOAD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ADF_SKEW].name = "adf-skew"; s->opt[OPT_ADF_SKEW].title = SANE_I18N("ADF Skew Correction"); s->opt[OPT_ADF_SKEW].desc = SANE_I18N("Enables ADF skew correction"); s->opt[OPT_ADF_SKEW].type = SANE_TYPE_BOOL; s->val[OPT_ADF_SKEW].w = 0; s->opt[OPT_ADF_CRP].name = "adf-crp"; s->opt[OPT_ADF_CRP].title = SANE_I18N("ADF CRP Correction"); s->opt[OPT_ADF_CRP].desc = SANE_I18N("Enables ADF auto cropping"); // s->opt[OPT_ADF_CRP].type = SANE_TYPE_BOOL; s->val[OPT_ADF_CRP].w = 0; if (!s->hw->adf_has_skew) { s->val[OPT_ADF_SKEW].w = 0; s->opt[OPT_ADF_SKEW].cap |= SANE_CAP_INACTIVE; } if(!s->hw->adf_has_crp) { s->val[OPT_ADF_CRP].w = 0; s->opt[OPT_ADF_CRP].cap |= SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; } SANE_Status sane_open(SANE_String_Const name, SANE_Handle *handle) { SANE_Status status; epsonds_scanner *s = NULL; DBG(7, "** %s: name = '%s'\n", __func__, name); /* probe if empty device name provided */ if (name[0] == '\0') { probe_devices(SANE_FALSE); if (first_dev == NULL) { DBG(1, "no devices detected\n"); return SANE_STATUS_INVAL; } s = device_detect(first_dev->sane.name, first_dev->connection, &status); if (s == NULL) { DBG(1, "cannot open a perfectly valid device (%s)," " please report to the authors\n", name); return SANE_STATUS_INVAL; } } else { if (strncmp(name, "net:", 4) == 0) { s = device_detect(name, SANE_EPSONDS_NET, &status); if (s == NULL) return status; } else if (strncmp(name, "libusb:", 7) == 0) { s = device_detect(name, SANE_EPSONDS_USB, &status); if (s == NULL) return status; } else { DBG(1, "invalid device name: %s\n", name); return SANE_STATUS_INVAL; } } /* s is always valid here */ DBG(5, "%s: handle obtained\n", __func__); init_options(s); *handle = (SANE_Handle)s; status = open_scanner(s); if (status != SANE_STATUS_GOOD) { free(s); return status; } /* lock scanner if required */ if (!s->locked) { status = eds_lock(s); } setvalue((SANE_Handle)s, OPT_MODE, (void*)SANE_VALUE_SCAN_MODE_COLOR, NULL); return status; } void sane_close(SANE_Handle handle) { epsonds_scanner *s = (epsonds_scanner *)handle; DBG(1, "** %s\n", __func__); close_scanner(s); } const SANE_Option_Descriptor * sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) { epsonds_scanner *s = (epsonds_scanner *) handle; if (option < 0 || option >= NUM_OPTIONS) return NULL; return s->opt + option; } static const SANE_String_Const * search_string_list(const SANE_String_Const *list, SANE_String value) { while (*list != NULL && strcmp(value, *list) != 0) list++; return ((*list == NULL) ? NULL : list); } /* * Handles setting the source (flatbed, transparency adapter (TPU), * or auto document feeder (ADF)). * * For newer scanners it also sets the focus according to the * glass / TPU settings. */ static void change_source(epsonds_scanner *s, SANE_Int optindex, char *value) { int force_max = SANE_FALSE; DBG(1, "%s: optindex = %d, source = '%s'\n", __func__, optindex, value); s->val[OPT_SOURCE].w = optindex; /* if current selected area is the maximum available, * keep this setting on the new source. */ if (s->val[OPT_TL_X].w == s->hw->x_range->min && s->val[OPT_TL_Y].w == s->hw->y_range->min && s->val[OPT_BR_X].w == s->hw->x_range->max && s->val[OPT_BR_Y].w == s->hw->y_range->max) { force_max = SANE_TRUE; } if (strcmp(STRING_ADFFRONT, value) == 0 || strcmp(STRING_ADFDUPLEX, value) == 0) { s->hw->x_range = &s->hw->adf_x_range; s->hw->y_range = &s->hw->adf_y_range; s->hw->alignment = s->hw->adf_alignment; } else if (strcmp(TPU_STR, value) == 0) { s->hw->x_range = &s->hw->tpu_x_range; s->hw->y_range = &s->hw->tpu_y_range; } else { /* neither ADF nor TPU active, assume FB */ s->hw->x_range = &s->hw->fbf_x_range; s->hw->y_range = &s->hw->fbf_y_range; s->hw->alignment = s->hw->fbf_alignment; } s->opt[OPT_BR_X].constraint.range = s->hw->x_range; s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max) s->val[OPT_TL_X].w = s->hw->x_range->min; if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max) s->val[OPT_TL_Y].w = s->hw->y_range->min; if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max) s->val[OPT_BR_X].w = s->hw->x_range->max; if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max) s->val[OPT_BR_Y].w = s->hw->y_range->max; } static SANE_Status getvalue(SANE_Handle handle, SANE_Int option, void *value) { epsonds_scanner *s = (epsonds_scanner *)handle; SANE_Option_Descriptor *sopt = &(s->opt[option]); Option_Value *sval = &(s->val[option]); DBG(17, "%s: option = %d\n", __func__, option); switch (option) { case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_DEPTH: case OPT_ADF_SKEW: *((SANE_Word *) value) = sval->w; break; case OPT_MODE: case OPT_SOURCE: strcpy((char *) value, sopt->constraint.string_list[sval->w]); break; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } static SANE_Status setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info) { epsonds_scanner *s = (epsonds_scanner *) handle; SANE_Option_Descriptor *sopt = &(s->opt[option]); Option_Value *sval = &(s->val[option]); SANE_Status status; const SANE_String_Const *optval = NULL; int optindex = 0; SANE_Bool reload = SANE_FALSE; DBG(17, "** %s: option = %d, value = %p\n", __func__, option, value); status = sanei_constrain_value(sopt, value, info); if (status != SANE_STATUS_GOOD) return status; if (info && value && (*info & SANE_INFO_INEXACT) && sopt->type == SANE_TYPE_INT) DBG(17, " constrained val = %d\n", *(SANE_Word *) value); if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) { optval = search_string_list(sopt->constraint.string_list, (char *) value); if (optval == NULL) return SANE_STATUS_INVAL; optindex = optval - sopt->constraint.string_list; } /* block faulty frontends */ if (sopt->cap & SANE_CAP_INACTIVE) { DBG(1, " tried to modify a disabled parameter"); return SANE_STATUS_INVAL; } switch (option) { case OPT_ADF_SKEW: case OPT_RESOLUTION: case OPT_ADF_CRP: sval->w = *((SANE_Word *) value); reload = SANE_TRUE; break; case OPT_BR_X: case OPT_BR_Y: if (SANE_UNFIX(*((SANE_Word *) value)) == 0) { DBG(17, " invalid br-x or br-y\n"); return SANE_STATUS_INVAL; } // fall through case OPT_TL_X: case OPT_TL_Y: sval->w = *((SANE_Word *) value); if (NULL != info) *info |= SANE_INFO_RELOAD_PARAMS; if (option == OPT_BR_X) { DBG(17, "OPT_BR_X = %d\n", sval->w); } if (option == OPT_BR_Y) { DBG(17, "OPT_BR_Y = %d\n", sval->w); } if (option == OPT_TL_X) { DBG(17, "OPT_TL_X = %d\n", sval->w); } if (option == OPT_TL_Y) { DBG(17, "OPT_TL_Y = %d\n", sval->w); } // adf crop set to off s->val[OPT_ADF_CRP].w = 0; break; case OPT_SOURCE: change_source(s, optindex, (char *) value); reload = SANE_TRUE; break; case OPT_MODE: { DBG(17, " OPT_MODE = index %d\n", optindex); /* use JPEG mode if RAW is not available when bpp > 1 */ if (optindex > 0 && !s->hw->has_raw) { s->mode_jpeg = 1; } else { s->mode_jpeg = 0; } sval->w = optindex; /* if binary, then disable the bit depth selection */ if (optindex == 0) { s->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE; } else { if (s->hw->depth_list[0] == 1) s->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE; else { s->opt[OPT_DEPTH].cap &= ~SANE_CAP_INACTIVE; s->val[OPT_DEPTH].w = mode_params[optindex].depth; } } reload = SANE_TRUE; break; } case OPT_DEPTH: sval->w = *((SANE_Word *) value); mode_params[s->val[OPT_MODE].w].depth = sval->w; reload = SANE_TRUE; break; case OPT_LOAD: esci2_mech(s, "#ADFLOAD"); break; case OPT_EJECT: esci2_mech(s, "#ADFEJCT"); break; default: return SANE_STATUS_INVAL; } if (reload && info != NULL) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; } SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info) { DBG(17, "** %s: action = %x, option = %d\n", __func__, action, option); if (option < 0 || option >= NUM_OPTIONS) return SANE_STATUS_INVAL; if (info != NULL) *info = 0; switch (action) { case SANE_ACTION_GET_VALUE: return getvalue(handle, option, value); case SANE_ACTION_SET_VALUE: return setvalue(handle, option, value, info); default: return SANE_STATUS_INVAL; } return SANE_STATUS_INVAL; } static void setBit (SANE_Byte* bytes, SANE_Int bitIndex, SANE_Bool isTrue) { SANE_Int octet = bitIndex / 8; SANE_Byte bit = 7 - (bitIndex % 8); if (isTrue) { bytes[octet] |= (1 << bit); } else { bytes[octet] &= ~(1 << bit); } } static SANE_Bool getBit (SANE_Byte* bytes, SANE_Int bitIndex) { SANE_Int octet = bitIndex / 8; SANE_Byte mask = 1 << (7 - (bitIndex % 8)); if( bytes[octet] & mask ){ return SANE_TRUE; } return SANE_FALSE; } static void swapPixel1(SANE_Int x1, SANE_Int y1, SANE_Int x2, SANE_Int y2, SANE_Byte* bytes, SANE_Byte bitsPerSample, SANE_Int samplesPerPixel, SANE_Int bytesPerRow) { SANE_Int pixelBits = bitsPerSample * samplesPerPixel; SANE_Int widthBits = bytesPerRow * 8; SANE_Byte temp = getBit(bytes, widthBits * y1 + x1 * pixelBits); { SANE_Byte right = getBit(bytes, widthBits * y2 + x2 * pixelBits); setBit(bytes, widthBits * y1 + x1 * pixelBits, right); } setBit(bytes, widthBits * y2 + x2 * pixelBits, temp); } static void swapPixel8(SANE_Int x1, SANE_Int y1, SANE_Int x2, SANE_Int y2, SANE_Byte* bytes, SANE_Byte bitsPerSample, SANE_Int samplesPerPixel, SANE_Int bytesPerRow) { SANE_Int pixelBytes = samplesPerPixel * bitsPerSample / 8; for (SANE_Byte i = 0; i < pixelBytes; i++) { SANE_Byte temp = bytes[y1 * bytesPerRow + (pixelBytes * x1 + i)]; bytes[y1 * bytesPerRow + (pixelBytes * x1 + i)] = bytes[y2 * bytesPerRow + (pixelBytes * x2 + i)]; bytes[y2 * bytesPerRow + (pixelBytes * x2 + i)] = temp; } } static void swapPixel(SANE_Int x1, SANE_Int y1, SANE_Int x2, SANE_Int y2, SANE_Byte* bytes, SANE_Byte bitsPerSample, SANE_Int samplesPerPixel, SANE_Int bytesPerRow) { if (bitsPerSample == 1) { swapPixel1(x1, y1, x2, y2, bytes, bitsPerSample, samplesPerPixel, bytesPerRow); }else if(bitsPerSample == 8 || bitsPerSample == 16){ swapPixel8(x1, y1, x2, y2, bytes, bitsPerSample, samplesPerPixel, bytesPerRow); } } void upside_down_backside_image(epsonds_scanner *s) { // get all data from ring_buffer if (eds_ring_avail(&s->back) && (strcmp(s->hw->sane.model, (char*)"DS-1630") == 0 || strcmp(s->hw->sane.model, (char*)"DS-1610") == 0 || strcmp(s->hw->sane.model, (char*)"DS-1660W") == 0)) { SANE_Int bytesPerLine = s->params.bytes_per_line; SANE_Int imageSize = bytesPerLine * s->height_back; SANE_Byte* workBuffer = malloc(imageSize); // if there is not enough memory, do nothing. if (workBuffer) { eds_ring_read(&s->back, workBuffer, imageSize); SANE_Int samplesPerPxel = 3; if (s->params.format == SANE_FRAME_RGB) { samplesPerPxel = 3; } else if (s->params.format == SANE_FRAME_GRAY) { samplesPerPxel = 1; } SANE_Int half = (s->height_back / 2) - 1; if (half < 0) { half = 0; } if((s->height_back % 2) == 1) { SANE_Int ymid = ( (s->height_back - 1 ) / 2 ); for(SANE_Int x = 0;x < (s->width_back / 2); x++) { swapPixel(x, ymid, s->width_back - x - 1, ymid, workBuffer, s->params.depth, samplesPerPxel, s->params.bytes_per_line); } } if (s->height_back != 1) { for(SANE_Int x = 0; x < s->width_back; x++) { for(SANE_Int y = 0;y <= half; y++) { swapPixel(x, y, s->width_back - x - 1, s->height_back - y -1, workBuffer, s->params.depth, samplesPerPxel, s->params.bytes_per_line); } } } eds_ring_write(&s->back, workBuffer, imageSize); free(workBuffer); workBuffer = NULL; } } } SANE_Status get_next_image(epsonds_scanner *s) { SANE_Status status = SANE_STATUS_GOOD; if (s->acquirePage == 0 && s->current == &s->front) { DBG(20, "** %s: get_next_image\n", __func__); /*page info will be updatted by pen*/ s->width_back = 0; s->width_front = 0; s->height_back = 0; s->height_front = 0; if (s->mode_jpeg) { status = acquire_and_decode_jpeg_data(s); }else{ status = acquire_raw_data(s); } if (status != SANE_STATUS_GOOD) { eds_ring_flush(&s->front); eds_ring_flush(&s->back); eds_ring_destory(&s->front); eds_ring_destory(&s->back); } DBG(20," ringFront = %d ringBack = %d\n", eds_ring_avail(&s->front), eds_ring_avail(&s->back)); s->acquirePage = 1; } return status; } SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters *params) { epsonds_scanner *s = (epsonds_scanner *)handle; DBG(5, "** %s\n", __func__); if (params == NULL) DBG(1, "%s: params is NULL\n", __func__); /* * If sane_start was already called, then just retrieve the parameters * from the scanner data structure */ if (s->scanning) { DBG(5, "scan in progress, returning saved params structure\n"); } else { /* otherwise initialize the params structure */ eds_init_parameters(s); } SANE_Status status = SANE_STATUS_GOOD; status = get_next_image(s); // if size auto, update page size value if(s->val[OPT_ADF_CRP].w) { // frontside if (s->current == &s->front) { DBG(20, "front side \n"); if (s->width_front != 0 && s->height_front != 0) { if (s->params.format == SANE_FRAME_RGB) { s->params.bytes_per_line = s->width_front * 3; s->params.pixels_per_line = s->width_front; } if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 8) { s->params.bytes_per_line = s->width_front; s->params.pixels_per_line = s->width_front; } if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 1) { s->params.bytes_per_line = (s->width_front + 7)/8; s->params.pixels_per_line = s->width_front; } s->params.lines = s->height_front; } } // backside if (s->current == &s->back) { DBG(20, "back side \n"); if (s->width_back != 0 && s->height_back != 0) { if (s->params.format == SANE_FRAME_RGB) { s->params.bytes_per_line = s->width_back * 3; s->params.pixels_per_line = s->width_back; } if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 8) { s->params.bytes_per_line = s->width_back; s->params.pixels_per_line = s->width_back; } if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 1) { s->params.bytes_per_line = (s->width_back + 7)/8; s->params.pixels_per_line = s->width_back; } s->params.lines = s->height_back; } } } if (params != NULL) *params = s->params; print_params(s->params); DBG(20, "s->params.line = %d s->params.bytes_per_line = %d s->params.pixels_per_line = %d \n", s->params.lines, s->params.bytes_per_line , s->params.pixels_per_line ); return status; } typedef float ColorMatrix[3][3]; #define CCT_TABLE_SIZE 9 static int get_roundup_index(double frac[], int n) { int i, index = -1; double max_val = 0.0; for (i=0; i0) continue; if (min_val>frac[i]) { index = i; min_val = frac[i]; } } return index; } void ESCIRoundColorCorrectionMatrix(int mult, double org_cct[], int rnd_cct[]) { int i, j, index; double mult_cct[CCT_TABLE_SIZE], frac[CCT_TABLE_SIZE]; int sum[3]; int loop; for (i=0; imult) { index = get_rounddown_index(&frac[i*3], 3); if (index!=-1) { rnd_cct[i*3+index] --; mult_cct[i*3+index] = rnd_cct[i*3+index]; sum[i]--; } } } } while ((++loop<2)&&((sum[0]!=mult)||(sum[1]!=mult)||(sum[2]!=mult))); } /* * This function is part of the SANE API and gets called from the front end to * start the scan process. */ #define CMD_BUF_SIZE 1000 SANE_Status sane_start(SANE_Handle handle) { epsonds_scanner *s = (epsonds_scanner *)handle; char buf[65]; /* add one more byte to correct buffer overflow issue */ char cmd[CMD_BUF_SIZE]; /* take care not to overflow */ SANE_Status status = 0; s->pages++; DBG(5, "** %s, pages = %d, scanning = %d, backside = %d, front fill: %d, back fill: %d\n", __func__, s->pages, s->scanning, s->backside, eds_ring_avail(&s->front), eds_ring_avail(&s->back)); s->eof = 0; s->canceling = 0; s->acquirePage = 0; if ((s->pages % 2) == 1) { s->current = &s->front; } else if (eds_ring_avail(&s->back)) { DBG(5, "back side\n"); s->current = &s->back; } /* scan already in progress? (one pass adf) */ if (s->scanning || eds_ring_avail(&s->back) > 0) { DBG(5, " scan in progress, returning early\n"); return get_next_image(s); } if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFFRONT) == 0 || strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFDUPLEX) == 0) { if (s->scanEnd) { s->scanEnd = 0; return SANE_STATUS_NO_DOCS; } }else{ s->scanEnd = 0; } /* calc scanning parameters */ status = eds_init_parameters(s); if (status != SANE_STATUS_GOOD) { DBG(1, " parameters initialization failed\n"); return status; } /* allocate line buffer */ s->line_buffer = realloc(s->line_buffer, s->params.bytes_per_line); if (s->line_buffer == NULL) return SANE_STATUS_NO_MEM; /* transfer buffer size, bsz */ /* XXX read value from scanner */ s->bsz = (1048576 * 4); /* transfer buffer */ s->buf = realloc(s->buf, s->bsz); if (s->buf == NULL) return SANE_STATUS_NO_MEM; print_params(s->params); /* set scanning parameters */ s->isDuplexScan = 0; /* document source */ if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFFRONT) == 0 || strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFDUPLEX) == 0) { SANE_Int status = esci2_stat(s); if (status == SANE_STATUS_NO_DOCS) { return SANE_STATUS_NO_DOCS; } SANE_Int duplexMode = (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFDUPLEX) == 0); sprintf(buf, "#ADF%s%s%s", duplexMode ? "DPLX" : "", s->val[OPT_ADF_SKEW].w ? "SKEW" : "", s->val[OPT_ADF_CRP].w ? "CRP " : "" ); if (duplexMode) { s->isDuplexScan = 1; } s->isflatbedScan = 0; } else if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_FLATBED) == 0) { strcpy(buf, "#FB "); s->isflatbedScan = 1; } else { /* XXX */ } strcpy(cmd, buf); s->needToConvertBW = 0; if (s->params.format == SANE_FRAME_GRAY) { if (s->params.depth == 1 && s->hw->has_mono == 0) { sprintf(buf, "#COLM008"); s->needToConvertBW = 1; s->mode_jpeg = 1; }else { sprintf(buf, "#COLM%03d", s->params.depth); } } else if (s->params.format == SANE_FRAME_RGB) { sprintf(buf, "#COLC%03d", s->params.depth * 3); } strcat(cmd, buf); /* image transfer format */ if (!s->mode_jpeg) { if (s->params.depth > 1 || s->hw->has_raw) { strcat(cmd, "#FMTRAW "); } } else { strcat(cmd, "#FMTJPG #JPGd090"); } /* set GMM */ if (s->params.depth == 1) { sprintf(buf, "#GMMUG10"); } else { sprintf(buf, "#GMMUG18"); } strcat(cmd, buf); /* resolution (RSMi not always supported) */ if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFFRONT) == 0 && s->val[OPT_RESOLUTION].w > 600) { DBG(0, "Automatic Document Feeder supported resolution of 600dpi or less. \n"); } else if (s->val[OPT_RESOLUTION].w > 999) { sprintf(buf, "#RSMi%07d#RSSi%07d", s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w); } else { sprintf(buf, "#RSMd%03d#RSSd%03d", s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w); } if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFDUPLEX) == 0 && s->val[OPT_RESOLUTION].w > 600) { DBG(0, "Automatic Document Feeder supported resolution of 600dpi or less. \n"); } else if (s->val[OPT_RESOLUTION].w > 999) { sprintf(buf, "#RSMi%07d#RSSi%07d", s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w); } else { sprintf(buf, "#RSMd%03d#RSSd%03d", s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w); } strcat(cmd, buf); if (strcmp(s->hw->sane.model, (char*)"DS-70") == 0 || strcmp(s->hw->sane.model, (char*)"ES-65WR") == 0 || strcmp(s->hw->sane.model, (char*)"ES-60W") == 0 || strcmp(s->hw->sane.model, (char*)"DS-80W") == 0 || strcmp(s->hw->sane.model, (char*)"ES-55R") == 0 || strcmp(s->hw->sane.model, (char*)"ES-50") == 0){ sprintf(buf, "#BSZi0262144"); strcat(cmd, buf); } else { sprintf(buf, "#BSZi1048576"); strcat(cmd, buf); } /* scanning area */ sprintf(buf, "#ACQi%07di%07di%07di%07d", s->left, s->top, s->params.pixels_per_line, s->params.lines); if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFFRONT) == 0 || strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFDUPLEX) == 0) { status = esci2_stat(s); if (status != SANE_STATUS_GOOD) { goto end; } } strcat(cmd, buf); int pos = 0; { for (int i = 0; i < CMD_BUF_SIZE; i++) { // find end of string if(cmd[i] == 0) { pos = i; break; } } if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 8) { DBG(10, "SANE_FRAME_GRAY\n"); cmd[pos++] = '#'; cmd[pos++] = 'G'; cmd[pos++] = 'M'; cmd[pos++] = 'T'; cmd[pos++] = 'M'; cmd[pos++] = 'O'; cmd[pos++] = 'N'; cmd[pos++] = 'O'; cmd[pos++] = 'h'; cmd[pos++] = '1'; cmd[pos++] = '0'; cmd[pos++] = '0'; for(int count = 0; count < 256; count++) { cmd[pos++] = LUT[s->hw->lut_id][count]; } } if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 1) { DBG(10, "SANE_FRAME_GRAY\n"); cmd[pos++] = '#'; cmd[pos++] = 'G'; cmd[pos++] = 'M'; cmd[pos++] = 'T'; cmd[pos++] = 'M'; cmd[pos++] = 'O'; cmd[pos++] = 'N'; cmd[pos++] = 'O'; cmd[pos++] = 'h'; cmd[pos++] = '1'; cmd[pos++] = '0'; cmd[pos++] = '0'; for(int count = 0; count < 256; count++) { cmd[pos++] = LUT[0][count]; } } else if (s->params.format == SANE_FRAME_RGB) { DBG(10, "SANE_FRAME_RGB\n"); cmd[pos++] = '#'; cmd[pos++] = 'G'; cmd[pos++] = 'M'; cmd[pos++] = 'T'; cmd[pos++] = 'R'; cmd[pos++] = 'E'; cmd[pos++] = 'D'; cmd[pos++] = ' '; cmd[pos++] = 'h'; cmd[pos++] = '1'; cmd[pos++] = '0'; cmd[pos++] = '0'; for(int count = 0; count < 256; count++) { cmd[pos++] = LUT_R[s->hw->lut_id][count]; } cmd[pos++] = '#'; cmd[pos++] = 'G'; cmd[pos++] = 'M'; cmd[pos++] = 'T'; cmd[pos++] = 'G'; cmd[pos++] = 'R'; cmd[pos++] = 'N'; cmd[pos++] = ' '; cmd[pos++] = 'h'; cmd[pos++] = '1'; cmd[pos++] = '0'; cmd[pos++] = '0'; for(int count = 0; count < 256; count++) { cmd[pos++] = LUT_G[s->hw->lut_id][count]; } cmd[pos++] = '#'; cmd[pos++] = 'G'; cmd[pos++] = 'M'; cmd[pos++] = 'T'; cmd[pos++] = 'B'; cmd[pos++] = 'L'; cmd[pos++] = 'U'; cmd[pos++] = ' '; cmd[pos++] = 'h'; cmd[pos++] = '1'; cmd[pos++] = '0'; cmd[pos++] = '0'; for(int count = 0; count < 256; count++) { cmd[pos++] = LUT_B[s->hw->lut_id][count]; } } cmd[pos] = 0; } {// Set Color Matrix if (s->params.format == SANE_FRAME_RGB && s->hw->lut_id != 0 )/*Color Matrix Target devide and color Scan*/ { ColorMatrix matrix; // DS-530 if (s->hw->lut_id == 2) { // R matrix[0][0] = 1.0229; matrix[0][1] = 0.0009; matrix[0][2] = -0.0238; // G matrix[1][0] = 0.0031; matrix[1][1] = 1.0287; matrix[1][2] = -0.0318; //B matrix[2][0] = 0.0044; matrix[2][1] = -0.1150; matrix[2][2] = 1.1106; } // DS-1660W Flatbed if (s->hw->lut_id == 4) { // R matrix[0][0] = 1.0229; matrix[0][1] = 0.0009; matrix[0][2] = -0.0238; // G matrix[1][0] = 0.0031; matrix[1][1] = 1.0287; matrix[1][2] = -0.0318; //B matrix[2][0] = 0.0044; matrix[2][1] = -0.1150; matrix[2][2] = 1.1106; } // DS-320 if (s->hw->lut_id == 5) { // R matrix[0][0] = 1.0250; matrix[0][1] = 0.0004; matrix[0][2] = -0.0254; // G matrix[1][0] = 0.0003; matrix[1][1] = 1.0022; matrix[1][2] = -0.0025; //B matrix[2][0] = 0.0049; matrix[2][1] = -0.0949; matrix[2][2] = 1.0900; } // ES-50 if (s->hw->lut_id == 6) { // R matrix[0][0] = 1.0383; matrix[0][1] = -0.0021; matrix[0][2] = -0.0362; // G matrix[1][0] = 0.0046; matrix[1][1] = 1.0576; matrix[1][2] = -0.0622; //B matrix[2][0] = 0.0235; matrix[2][1] = -0.2396; matrix[2][2] = 1.2161; } // R matrix[0][0] = 0.9864; matrix[0][1] = 0.0248; matrix[0][2] = -0.0112; // G matrix[1][0] = 0.0021; matrix[1][1] = 1.0100; matrix[1][2] = -0.0112; //B matrix[2][0] = 0.0139; matrix[2][1] = -0.1249; matrix[2][2] = 1.1110; // Set Matrix value { cmd[pos++] = '#'; cmd[pos++] = 'C'; cmd[pos++] = 'M'; cmd[pos++] = 'X'; cmd[pos++] = 'U'; cmd[pos++] = 'M'; cmd[pos++] = '0'; cmd[pos++] = '8'; cmd[pos++] = 'h'; cmd[pos++] = '0'; cmd[pos++] = '0'; cmd[pos++] = '9'; } // Matrix to be sent to scanner must be following d1-d9 order: // // G R B // G [d1 d4 d7] // R [d2 d5 d8] // B [d3 d6 d9] // // So, we will convert it with index table. char index[9] = {4, 1, 7, 3, 0, 6, 5, 2, 8}; double flatten[9] = {0}; for (int row = 0; row < 3; row++) { for (int col = 0; col < 3; col++) { flatten[row * 3 + col] = matrix[row][col]; } } int rounded[9] = {0}; ESCIRoundColorCorrectionMatrix(32, flatten, rounded); char ordered[9] = {0}; for (int row = 0; row < 3; row++) { for (int col = 0; col < 3; col++) { int val = rounded[row * 3 + col]; unsigned char oct = (unsigned char)abs(val); oct |= ((val < 0) ? (1 << 7) : 0); ordered[(signed char)index[row * 3 + col]] = oct; } } { cmd[pos++] = ordered[0]; cmd[pos++] = ordered[1]; cmd[pos++] = ordered[2]; cmd[pos++] = ordered[3]; cmd[pos++] = ordered[4]; cmd[pos++] = ordered[5]; cmd[pos++] = ordered[6]; cmd[pos++] = ordered[7]; cmd[pos++] = ordered[8]; cmd[pos++] = 0; //padding cmd[pos++] = 0; //padding cmd[pos++] = 0; //padding DBG(1, "color matrix\n"); for (int i = 0; i < 9; i++) { DBG(1, "%d\n", ordered[i]); } } cmd[pos] = 0; } } status = esci2_para(s, cmd, pos); if (status != SANE_STATUS_GOOD) { goto end; } /* start scanning */ DBG(1, "%s: scanning...\n", __func__); /* switch to data state */ status = esci2_trdt(s); if (status != SANE_STATUS_GOOD) { goto end; } /* first page is page 1 */ s->pages = 1; s->scanning = 1; s->dummy = 0; s->scanEnd = 0; end: if (status != SANE_STATUS_GOOD) { DBG(1, "%s: start failed: %s\n", __func__, sane_strstatus(status)); } return status; } static SANE_Status acquire_jpeg_data(epsonds_scanner* s) { SANE_Int read = 0; SANE_Int jpegBufSize = s->params.bytes_per_line * s->params.lines; if (s->needToConvertBW) { jpegBufSize = s->params.pixels_per_line * s->params.lines; } s->frontJpegBuf = malloc(jpegBufSize); s->backJpegBuf = malloc(jpegBufSize); s->frontJpegBufLen = 0; s->backJpegBufLen = 0; // load all images, decode and fill buffer SANE_Int status = SANE_STATUS_GOOD; int eofFront = 0; int eofBack = 0; status = eds_ring_init(&s->front, (s->params.bytes_per_line) * s->params.lines); if (status != SANE_STATUS_GOOD) { return status; } status = eds_ring_init(&s->back, (s->params.bytes_per_line) * s->params.lines); if (status != SANE_STATUS_GOOD) { return status; } while (1) { status = esci2_img(s, &read); DBG(20, "acquire_jpeg_data read: %d, eof: %d, backside: %d, status: %d\n", read, s->eof, s->backside, status); if (read) { if (s->backside) { SANE_Byte* backBuffer = s->backJpegBuf + s->backJpegBufLen; memcpy(backBuffer, s->buf, read); s->backJpegBufLen += read; }else{ SANE_Byte* frontBuffer = s->frontJpegBuf + s->frontJpegBufLen ; memcpy(frontBuffer, s->buf, read); s->frontJpegBufLen += read; } } if (status == SANE_STATUS_GOOD) { DBG(20, "continue acquire image\n"); continue; } else if (status == SANE_STATUS_EOF) { if (s->backside) { DBG(20, "eofBack\n"); eofBack = 1; }else{ DBG(20, "eofFront\n"); eofFront = 1; } }else if (status == SANE_STATUS_CANCELLED) { // cancel cleanup esci2_can(s); free(s->frontJpegBuf); free(s->backJpegBuf); s->frontJpegBuf = NULL; s->backJpegBuf = NULL; return status; }else{ // error occurs cleanup free(s->frontJpegBuf); free(s->backJpegBuf); s->frontJpegBuf = NULL; s->backJpegBuf = NULL; return status; } if (s->isDuplexScan) { DBG(20, "eofFront = %d eofBack = %d\n", eofFront, eofBack); // acquire finish if (eofFront && eofBack) { DBG(20, "eofFront && eofBack end\n"); break; } }else{ if (eofFront) { DBG(20, "eofFront end\n"); break; } } } return SANE_STATUS_GOOD; } static SANE_Status acquire_raw_data(epsonds_scanner* s) { SANE_Int read = 0; // load all images, decode and fill buffer SANE_Int status = SANE_STATUS_GOOD; int eofFront = 0; int eofBack = 0; int firstWrite = 1; while (1) { DBG(20, "acquire_raw_data loop start\n"); status = esci2_img(s, &read); DBG(20, "acquire_raw_data read: %d, eof: %d, backside: %d, status: %d\n", read, s->eof, s->backside, status); if (read) { if (firstWrite) { status = eds_ring_init(&s->front, (s->params.bytes_per_line + s->dummy) * s->params.lines); if (status != SANE_STATUS_GOOD) { return status; } status = eds_ring_init(&s->back, (s->params.bytes_per_line + s->dummy) * s->params.lines); if (status != SANE_STATUS_GOOD) { return status; } firstWrite = 0; } DBG(20, "eds_ring_write start\n"); status = eds_ring_write(s->backside ? &s->back : &s->front, s->buf, read); DBG(20, "eds_ring_write end\n"); } DBG(20, "acquire_raw_data3\n"); if (status == SANE_STATUS_GOOD) { DBG(20, "contiune acquire image\n"); continue; } else if (status == SANE_STATUS_EOF) { if (s->backside) { eofBack = 1; }else{ eofFront = 1; } } else if (status == SANE_STATUS_CANCELLED) { esci2_can(s); return status; }else{ // error occurs cleanup return status; } if (s->isDuplexScan) { // acquire finish if (eofFront && eofBack) { break; } }else{ if (eofFront) { break; } } } int needBytes = (s->params.bytes_per_line + s->dummy) * s->params.lines; { int available = eds_ring_avail(&s->front); if (available < needBytes) { int required = needBytes - available; unsigned char* padding = (unsigned char*)malloc(required); memset(padding, 255, required); eds_ring_write(&s->front, padding, required); free(padding); } } { int available = eds_ring_avail(&s->back); if (available > 0 && available < needBytes) { int required = needBytes - available; unsigned char* padding = (unsigned char*)malloc(required); memset(padding, 255, required); eds_ring_write(&s->back, padding, required); free(padding); } } if (s->isDuplexScan) { upside_down_backside_image(s); } DBG(20, "acquire_raw_data finish"); return SANE_STATUS_GOOD; } static SANE_Status acquire_and_decode_jpeg_data(epsonds_scanner* s) { SANE_Int status = acquire_jpeg_data(s); if (status == SANE_STATUS_GOOD) { DBG(20, "** %s: sane status = %d needToConvertBW = %d \n", __func__, status, s->needToConvertBW); // process front page if (s->frontJpegBufLen > 0) { eds_decode_jpeg(s, s->frontJpegBuf, s->frontJpegBufLen, &s->front,0, s->needToConvertBW); free(s->frontJpegBuf); s->frontJpegBuf = NULL; } // process back page if (s->backJpegBufLen > 0) { eds_decode_jpeg(s, s->backJpegBuf, s->backJpegBufLen, &s->back, 1, s->needToConvertBW); free(s->backJpegBuf); s->backJpegBuf = NULL; } if (s->isDuplexScan) { upside_down_backside_image(s); } }else{ DBG(20, "** %s: sane finish status = %d\n", __func__, status); return status; } return status; } int sumLength = 0; /* this moves data from our buffers to SANE */ SANE_Status sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length) { epsonds_scanner *s = (epsonds_scanner *)handle; SANE_Int read = 0; if (s->canceling) { esci2_can(s); *length = 0; return SANE_STATUS_CANCELLED; } int available = eds_ring_avail(s->current); /* anything in the buffer? pass it to the frontend */ if (available > 0) { DBG(18, "reading from ring buffer, %d left\n", available); eds_copy_image_from_ring(s, data, max_length, &read); // data is empty fin if (read == 0) { *length = 0; eds_ring_flush(s->current); eds_ring_destory(s->current); DBG(18, "returns EOF 2\n"); return SANE_STATUS_EOF; } *length = read; return SANE_STATUS_GOOD; }else{ *length = 0; eds_ring_flush(s->current); eds_ring_destory(s->current); DBG(18, "returns EOF 1\n"); return SANE_STATUS_EOF; } } /* * void sane_cancel(SANE_Handle handle) * * Set the cancel flag to true. The next time the backend requests data * from the scanner the CAN message will be sent. */ void sane_cancel(SANE_Handle handle) { DBG(1, "** %s\n", __func__); ((epsonds_scanner *)handle)->canceling = SANE_TRUE; } /* * SANE_Status sane_set_io_mode() * * not supported - for asynchronous I/O */ SANE_Status sane_set_io_mode(SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { return SANE_STATUS_UNSUPPORTED; } /* * SANE_Status sane_get_select_fd() * * not supported - for asynchronous I/O */ SANE_Status sane_get_select_fd(SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ *fd) { return SANE_STATUS_UNSUPPORTED; }