1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci ScanMaker 3840 Backend 4141cc406Sopenharmony_ci Copyright (C) 2005-7 Earle F. Philhower, III 5141cc406Sopenharmony_ci earle@ziplabel.com - http://www.ziplabel.com 6141cc406Sopenharmony_ci 7141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 8141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 9141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 10141cc406Sopenharmony_ci License, or (at your option) any later version. 11141cc406Sopenharmony_ci 12141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 13141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 14141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15141cc406Sopenharmony_ci General Public License for more details. 16141cc406Sopenharmony_ci 17141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 18141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 21141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 24141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 25141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 26141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 27141cc406Sopenharmony_ci account of linking the SANE library code into it. 28141cc406Sopenharmony_ci 29141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 30141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 31141cc406Sopenharmony_ci License. 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 34141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 35141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 38141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 39141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci*/ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci#include <stdio.h> 44141cc406Sopenharmony_ci#include <stdarg.h> 45141cc406Sopenharmony_ci#include <math.h> 46141cc406Sopenharmony_ci#include "sm3840_lib.h" 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci#ifndef BACKENDNAME 49141cc406Sopenharmony_ci/* For standalone compilation */ 50141cc406Sopenharmony_cistatic void 51141cc406Sopenharmony_ciDBG (int ignored, const char *fmt, ...) 52141cc406Sopenharmony_ci{ 53141cc406Sopenharmony_ci va_list a; 54141cc406Sopenharmony_ci va_start (a, fmt); 55141cc406Sopenharmony_ci vfprintf (stderr, fmt, a); 56141cc406Sopenharmony_ci va_end (a); 57141cc406Sopenharmony_ci} 58141cc406Sopenharmony_ci#else 59141cc406Sopenharmony_ci/* For SANE compilation, convert libusb to sanei_usb */ 60141cc406Sopenharmony_cistatic int 61141cc406Sopenharmony_cimy_usb_bulk_write (p_usb_dev_handle dev, int ep, 62141cc406Sopenharmony_ci unsigned char *bytes, int size, int timeout) 63141cc406Sopenharmony_ci{ 64141cc406Sopenharmony_ci SANE_Status status; 65141cc406Sopenharmony_ci size_t my_size; 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci (void) timeout; 68141cc406Sopenharmony_ci (void) ep; 69141cc406Sopenharmony_ci my_size = size; 70141cc406Sopenharmony_ci status = 71141cc406Sopenharmony_ci sanei_usb_write_bulk ((SANE_Int) dev, (SANE_Byte *) bytes, &my_size); 72141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 73141cc406Sopenharmony_ci my_size = -1; 74141cc406Sopenharmony_ci return my_size; 75141cc406Sopenharmony_ci} 76141cc406Sopenharmony_ci 77141cc406Sopenharmony_cistatic int 78141cc406Sopenharmony_cimy_usb_bulk_read (p_usb_dev_handle dev, int ep, 79141cc406Sopenharmony_ci unsigned char *bytes, int size, int timeout) 80141cc406Sopenharmony_ci{ 81141cc406Sopenharmony_ci SANE_Status status; 82141cc406Sopenharmony_ci size_t my_size; 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci (void) timeout; 85141cc406Sopenharmony_ci (void) ep; 86141cc406Sopenharmony_ci my_size = size; 87141cc406Sopenharmony_ci status = 88141cc406Sopenharmony_ci sanei_usb_read_bulk ((SANE_Int) dev, (SANE_Byte *) bytes, &my_size); 89141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 90141cc406Sopenharmony_ci my_size = -1; 91141cc406Sopenharmony_ci return my_size; 92141cc406Sopenharmony_ci} 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_cistatic int 95141cc406Sopenharmony_cimy_usb_control_msg (p_usb_dev_handle dev, int requesttype, 96141cc406Sopenharmony_ci int request, int value, int index, 97141cc406Sopenharmony_ci unsigned char *bytes, int size, int timeout) 98141cc406Sopenharmony_ci{ 99141cc406Sopenharmony_ci SANE_Status status; 100141cc406Sopenharmony_ci 101141cc406Sopenharmony_ci (void) timeout; 102141cc406Sopenharmony_ci status = sanei_usb_control_msg ((SANE_Int) dev, (SANE_Int) requesttype, 103141cc406Sopenharmony_ci (SANE_Int) request, (SANE_Int) value, 104141cc406Sopenharmony_ci (SANE_Int) index, (SANE_Int) size, 105141cc406Sopenharmony_ci (SANE_Byte *) bytes); 106141cc406Sopenharmony_ci return status; 107141cc406Sopenharmony_ci} 108141cc406Sopenharmony_ci#endif 109141cc406Sopenharmony_ci 110141cc406Sopenharmony_ci 111141cc406Sopenharmony_ci/* Sanitize and convert scan parameters from inches to pixels */ 112141cc406Sopenharmony_cistatic void 113141cc406Sopenharmony_ciprepare_params (SM3840_Params * params) 114141cc406Sopenharmony_ci{ 115141cc406Sopenharmony_ci if (params->gray) 116141cc406Sopenharmony_ci params->gray = 1; 117141cc406Sopenharmony_ci if (params->lineart) { 118141cc406Sopenharmony_ci params->gray = 1; 119141cc406Sopenharmony_ci params->lineart = 1; 120141cc406Sopenharmony_ci } 121141cc406Sopenharmony_ci if (params->halftone) { 122141cc406Sopenharmony_ci params->gray = 1; 123141cc406Sopenharmony_ci params->halftone = 1; 124141cc406Sopenharmony_ci } 125141cc406Sopenharmony_ci if (params->dpi != 1200 && params->dpi != 600 && params->dpi != 300 126141cc406Sopenharmony_ci && params->dpi != 150) 127141cc406Sopenharmony_ci params->dpi = 150; 128141cc406Sopenharmony_ci if (params->bpp != 8 && params->bpp != 16) 129141cc406Sopenharmony_ci params->bpp = 8; 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_ci /* Sanity check input sizes */ 132141cc406Sopenharmony_ci if (params->top < 0) 133141cc406Sopenharmony_ci params->top = 0; 134141cc406Sopenharmony_ci if (params->left < 0) 135141cc406Sopenharmony_ci params->left = 0; 136141cc406Sopenharmony_ci if (params->width < 0) 137141cc406Sopenharmony_ci params->width = 0; 138141cc406Sopenharmony_ci if (params->height < 0) 139141cc406Sopenharmony_ci params->height = 0; 140141cc406Sopenharmony_ci if ((params->top + params->height) > 11.7) 141141cc406Sopenharmony_ci params->height = 11.7 - params->top; 142141cc406Sopenharmony_ci if ((params->left + params->width) > 8.5) 143141cc406Sopenharmony_ci params->width = 8.5 - params->left; 144141cc406Sopenharmony_ci 145141cc406Sopenharmony_ci params->topline = params->top * params->dpi; 146141cc406Sopenharmony_ci params->scanlines = params->height * params->dpi; 147141cc406Sopenharmony_ci params->leftpix = params->left * params->dpi; 148141cc406Sopenharmony_ci params->leftpix &= ~1; /* Always start on even pixel boundary for remap */ 149141cc406Sopenharmony_ci /* Scanpix always a multiple of 128 */ 150141cc406Sopenharmony_ci params->scanpix = params->width * params->dpi; 151141cc406Sopenharmony_ci params->scanpix = (params->scanpix + 127) & ~127; 152141cc406Sopenharmony_ci 153141cc406Sopenharmony_ci /* Sanity check outputs... */ 154141cc406Sopenharmony_ci if (params->topline < 0) 155141cc406Sopenharmony_ci params->topline = 0; 156141cc406Sopenharmony_ci if (params->scanlines < 1) 157141cc406Sopenharmony_ci params->scanlines = 1; 158141cc406Sopenharmony_ci if (params->leftpix < 0) 159141cc406Sopenharmony_ci params->leftpix = 0; 160141cc406Sopenharmony_ci if (params->scanpix < 128) 161141cc406Sopenharmony_ci params->scanpix = 128; 162141cc406Sopenharmony_ci 163141cc406Sopenharmony_ci /* Some handy calculations */ 164141cc406Sopenharmony_ci params->linelen = 165141cc406Sopenharmony_ci params->scanpix * (params->bpp / 8) * (params->gray ? 1 : 3); 166141cc406Sopenharmony_ci} 167141cc406Sopenharmony_ci 168141cc406Sopenharmony_ci#ifndef BACKENDNAME 169141cc406Sopenharmony_ciusb_dev_handle * 170141cc406Sopenharmony_cifind_device (unsigned int idVendor, unsigned int idProduct) 171141cc406Sopenharmony_ci{ 172141cc406Sopenharmony_ci struct usb_bus *bus; 173141cc406Sopenharmony_ci struct usb_device *dev; 174141cc406Sopenharmony_ci 175141cc406Sopenharmony_ci usb_init (); 176141cc406Sopenharmony_ci usb_find_busses (); 177141cc406Sopenharmony_ci usb_find_devices (); 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_ci for (bus = usb_get_busses (); bus; bus = bus->next) 180141cc406Sopenharmony_ci for (dev = bus->devices; dev; dev = dev->next) 181141cc406Sopenharmony_ci if (dev->descriptor.idVendor == idVendor && 182141cc406Sopenharmony_ci dev->descriptor.idProduct == idProduct) 183141cc406Sopenharmony_ci return usb_open (dev); 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_ci return NULL; 186141cc406Sopenharmony_ci} 187141cc406Sopenharmony_ci#endif 188141cc406Sopenharmony_ci 189141cc406Sopenharmony_cistatic void 190141cc406Sopenharmony_ciidle_ab (p_usb_dev_handle udev) 191141cc406Sopenharmony_ci{ 192141cc406Sopenharmony_ci int i; 193141cc406Sopenharmony_ci unsigned char buff[8] = { 0x64, 0x65, 0x16, 0x17, 0x64, 0x65, 0x44, 0x45 }; 194141cc406Sopenharmony_ci for (i = 0; i < 8; i++) 195141cc406Sopenharmony_ci { 196141cc406Sopenharmony_ci usb_control_msg (udev, 0x40, 0x0c, 0x0090, 0x0000, buff + i, 197141cc406Sopenharmony_ci 0x0001, wr_timeout); 198141cc406Sopenharmony_ci } 199141cc406Sopenharmony_ci} 200141cc406Sopenharmony_ci 201141cc406Sopenharmony_ci/* CW: 40 04 00b0 0000 <len> : <reg1> <value1> <reg2> <value2> ... */ 202141cc406Sopenharmony_cistatic void 203141cc406Sopenharmony_ciwrite_regs (p_usb_dev_handle udev, int regs, int reg1, int val1, 204141cc406Sopenharmony_ci ... /* int reg, int val, ... */ ) 205141cc406Sopenharmony_ci{ 206141cc406Sopenharmony_ci unsigned char buff[512]; 207141cc406Sopenharmony_ci va_list marker; 208141cc406Sopenharmony_ci int i; 209141cc406Sopenharmony_ci 210141cc406Sopenharmony_ci va_start (marker, val1); 211141cc406Sopenharmony_ci buff[0] = reg1; 212141cc406Sopenharmony_ci buff[1] = val1; 213141cc406Sopenharmony_ci for (i = 1; i < regs; i++) 214141cc406Sopenharmony_ci { 215141cc406Sopenharmony_ci buff[i * 2] = va_arg (marker, int); 216141cc406Sopenharmony_ci buff[i * 2 + 1] = va_arg (marker, int); 217141cc406Sopenharmony_ci } 218141cc406Sopenharmony_ci va_end (marker); 219141cc406Sopenharmony_ci 220141cc406Sopenharmony_ci usb_control_msg (udev, 0x40, 0x04, 0x00b0, 0x0000, buff, 221141cc406Sopenharmony_ci regs * 2, wr_timeout); 222141cc406Sopenharmony_ci} 223141cc406Sopenharmony_ci 224141cc406Sopenharmony_cistatic int 225141cc406Sopenharmony_ciwrite_vctl (p_usb_dev_handle udev, int request, int value, 226141cc406Sopenharmony_ci int index, unsigned char byte) 227141cc406Sopenharmony_ci{ 228141cc406Sopenharmony_ci return usb_control_msg (udev, 0x40, request, value, index, 229141cc406Sopenharmony_ci &byte, 1, wr_timeout); 230141cc406Sopenharmony_ci} 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_cistatic int 233141cc406Sopenharmony_ciread_vctl (p_usb_dev_handle udev, int request, int value, 234141cc406Sopenharmony_ci int index, unsigned char *byte) 235141cc406Sopenharmony_ci{ 236141cc406Sopenharmony_ci return usb_control_msg (udev, 0xc0, request, value, index, 237141cc406Sopenharmony_ci byte, 1, wr_timeout); 238141cc406Sopenharmony_ci} 239141cc406Sopenharmony_ci 240141cc406Sopenharmony_ci#ifndef BACKENDNAME 241141cc406Sopenharmony_ci/* Copy from a USB data pipe to a file with optional header */ 242141cc406Sopenharmony_cistatic void 243141cc406Sopenharmony_cirecord_head (p_usb_dev_handle udev, char *fname, int bytes, char *header) 244141cc406Sopenharmony_ci{ 245141cc406Sopenharmony_ci FILE *fp; 246141cc406Sopenharmony_ci unsigned char buff[65536]; 247141cc406Sopenharmony_ci int len; 248141cc406Sopenharmony_ci int toread; 249141cc406Sopenharmony_ci 250141cc406Sopenharmony_ci fp = fopen (fname, "wb"); 251141cc406Sopenharmony_ci if (header) 252141cc406Sopenharmony_ci fprintf (fp, "%s", header); 253141cc406Sopenharmony_ci do 254141cc406Sopenharmony_ci { 255141cc406Sopenharmony_ci toread = (bytes > 65536) ? 65536 : bytes; 256141cc406Sopenharmony_ci len = usb_bulk_read (udev, 1, buff, toread, rd_timeout); 257141cc406Sopenharmony_ci if (len > 0) 258141cc406Sopenharmony_ci { 259141cc406Sopenharmony_ci fwrite (buff, len, 1, fp); 260141cc406Sopenharmony_ci bytes -= len; 261141cc406Sopenharmony_ci } 262141cc406Sopenharmony_ci else 263141cc406Sopenharmony_ci { 264141cc406Sopenharmony_ci DBG (2, "TIMEOUT\n"); 265141cc406Sopenharmony_ci } 266141cc406Sopenharmony_ci } 267141cc406Sopenharmony_ci while (bytes); 268141cc406Sopenharmony_ci fclose (fp); 269141cc406Sopenharmony_ci} 270141cc406Sopenharmony_ci 271141cc406Sopenharmony_ci/* Copy from a USB data pipe to a file without header */ 272141cc406Sopenharmony_cistatic void 273141cc406Sopenharmony_cirecord (p_usb_dev_handle udev, char *fname, int bytes) 274141cc406Sopenharmony_ci{ 275141cc406Sopenharmony_ci record_head (udev, fname, bytes, ""); 276141cc406Sopenharmony_ci} 277141cc406Sopenharmony_ci#endif 278141cc406Sopenharmony_ci 279141cc406Sopenharmony_cistatic int 280141cc406Sopenharmony_cimax (int a, int b) 281141cc406Sopenharmony_ci{ 282141cc406Sopenharmony_ci return (a > b) ? a : b; 283141cc406Sopenharmony_ci} 284141cc406Sopenharmony_ci 285141cc406Sopenharmony_ci 286141cc406Sopenharmony_ci#define DPI1200SHUFFLE 6 287141cc406Sopenharmony_cistatic void 288141cc406Sopenharmony_cirecord_line (int reset, 289141cc406Sopenharmony_ci p_usb_dev_handle udev, 290141cc406Sopenharmony_ci unsigned char *storeline, 291141cc406Sopenharmony_ci int dpi, int scanpix, int gray, int bpp16, 292141cc406Sopenharmony_ci int *save_i, 293141cc406Sopenharmony_ci unsigned char **save_scan_line, 294141cc406Sopenharmony_ci unsigned char **save_dpi1200_remap, 295141cc406Sopenharmony_ci unsigned char **save_color_remap) 296141cc406Sopenharmony_ci{ 297141cc406Sopenharmony_ci unsigned char *scan_line, *dpi1200_remap; 298141cc406Sopenharmony_ci unsigned char *color_remap; 299141cc406Sopenharmony_ci int i; 300141cc406Sopenharmony_ci int red_delay, blue_delay, green_delay; 301141cc406Sopenharmony_ci int j; 302141cc406Sopenharmony_ci int linelen; 303141cc406Sopenharmony_ci int pixsize; 304141cc406Sopenharmony_ci unsigned char *ptrcur, *ptrprev; 305141cc406Sopenharmony_ci unsigned char *savestoreline; 306141cc406Sopenharmony_ci int lineptr, outline, bufflines; 307141cc406Sopenharmony_ci 308141cc406Sopenharmony_ci i = *save_i; 309141cc406Sopenharmony_ci scan_line = *save_scan_line; 310141cc406Sopenharmony_ci dpi1200_remap = *save_dpi1200_remap; 311141cc406Sopenharmony_ci color_remap = *save_color_remap; 312141cc406Sopenharmony_ci 313141cc406Sopenharmony_ci pixsize = (gray ? 1 : 3) * (bpp16 ? 2 : 1); 314141cc406Sopenharmony_ci linelen = scanpix * pixsize; 315141cc406Sopenharmony_ci 316141cc406Sopenharmony_ci if (gray) 317141cc406Sopenharmony_ci { 318141cc406Sopenharmony_ci red_delay = 0; 319141cc406Sopenharmony_ci blue_delay = 0; 320141cc406Sopenharmony_ci green_delay = 0; 321141cc406Sopenharmony_ci } 322141cc406Sopenharmony_ci else if (dpi == 150) 323141cc406Sopenharmony_ci { 324141cc406Sopenharmony_ci red_delay = 0; 325141cc406Sopenharmony_ci blue_delay = 6; 326141cc406Sopenharmony_ci green_delay = 3; 327141cc406Sopenharmony_ci } 328141cc406Sopenharmony_ci else if (dpi == 300) 329141cc406Sopenharmony_ci { 330141cc406Sopenharmony_ci red_delay = 0; 331141cc406Sopenharmony_ci blue_delay = 12; 332141cc406Sopenharmony_ci green_delay = 6; 333141cc406Sopenharmony_ci } 334141cc406Sopenharmony_ci else if (dpi == 600) 335141cc406Sopenharmony_ci { 336141cc406Sopenharmony_ci red_delay = 0; 337141cc406Sopenharmony_ci blue_delay = 24; 338141cc406Sopenharmony_ci green_delay = 12; 339141cc406Sopenharmony_ci } 340141cc406Sopenharmony_ci else /*(dpi==1200) */ 341141cc406Sopenharmony_ci { 342141cc406Sopenharmony_ci red_delay = 0; 343141cc406Sopenharmony_ci blue_delay = 48; 344141cc406Sopenharmony_ci green_delay = 24; 345141cc406Sopenharmony_ci } 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci bufflines = max (max (red_delay, blue_delay), green_delay) + 1; 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci if (reset) 350141cc406Sopenharmony_ci { 351141cc406Sopenharmony_ci if (dpi1200_remap) 352141cc406Sopenharmony_ci free (dpi1200_remap); 353141cc406Sopenharmony_ci if (scan_line) 354141cc406Sopenharmony_ci free (scan_line); 355141cc406Sopenharmony_ci if (color_remap) 356141cc406Sopenharmony_ci free (color_remap); 357141cc406Sopenharmony_ci 358141cc406Sopenharmony_ci *save_color_remap = color_remap = 359141cc406Sopenharmony_ci (unsigned char *) malloc (bufflines * linelen); 360141cc406Sopenharmony_ci 361141cc406Sopenharmony_ci *save_scan_line = scan_line = (unsigned char *) calloc (linelen, 1); 362141cc406Sopenharmony_ci if (dpi == 1200) 363141cc406Sopenharmony_ci *save_dpi1200_remap = dpi1200_remap = 364141cc406Sopenharmony_ci (unsigned char *) calloc (linelen, DPI1200SHUFFLE); 365141cc406Sopenharmony_ci else 366141cc406Sopenharmony_ci *save_dpi1200_remap = dpi1200_remap = NULL; 367141cc406Sopenharmony_ci 368141cc406Sopenharmony_ci *save_i = i = 0; /* i is our linenumber */ 369141cc406Sopenharmony_ci } 370141cc406Sopenharmony_ci 371141cc406Sopenharmony_ci while (1) 372141cc406Sopenharmony_ci { /* We'll exit inside the loop... */ 373141cc406Sopenharmony_ci usb_bulk_read (udev, 1, scan_line, linelen, rd_timeout); 374141cc406Sopenharmony_ci if (dpi == 1200) 375141cc406Sopenharmony_ci { 376141cc406Sopenharmony_ci ptrcur = dpi1200_remap + (linelen * (i % DPI1200SHUFFLE)); 377141cc406Sopenharmony_ci ptrprev = 378141cc406Sopenharmony_ci dpi1200_remap + 379141cc406Sopenharmony_ci (linelen * ((i - (DPI1200SHUFFLE - 2)) % DPI1200SHUFFLE)); 380141cc406Sopenharmony_ci } 381141cc406Sopenharmony_ci else 382141cc406Sopenharmony_ci { 383141cc406Sopenharmony_ci ptrcur = scan_line; 384141cc406Sopenharmony_ci ptrprev = NULL; 385141cc406Sopenharmony_ci } 386141cc406Sopenharmony_ci if (gray) 387141cc406Sopenharmony_ci { 388141cc406Sopenharmony_ci memcpy (ptrcur, scan_line, linelen); 389141cc406Sopenharmony_ci } 390141cc406Sopenharmony_ci else 391141cc406Sopenharmony_ci { 392141cc406Sopenharmony_ci int pixsize = bpp16 ? 2 : 1; 393141cc406Sopenharmony_ci int pix = linelen / (3 * pixsize); 394141cc406Sopenharmony_ci unsigned char *outbuff = ptrcur; 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci outline = i; 397141cc406Sopenharmony_ci lineptr = i % bufflines; 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ci memcpy (color_remap + linelen * lineptr, scan_line, linelen); 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci outline++; 402141cc406Sopenharmony_ci if (outline > bufflines) 403141cc406Sopenharmony_ci { 404141cc406Sopenharmony_ci int redline = (outline + red_delay) % bufflines; 405141cc406Sopenharmony_ci int greenline = (outline + green_delay) % bufflines; 406141cc406Sopenharmony_ci int blueline = (outline + blue_delay) % bufflines; 407141cc406Sopenharmony_ci unsigned char *rp, *gp, *bp; 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ci rp = color_remap + linelen * redline; 410141cc406Sopenharmony_ci gp = color_remap + linelen * greenline + 1 * pixsize; 411141cc406Sopenharmony_ci bp = color_remap + linelen * blueline + 2 * pixsize; 412141cc406Sopenharmony_ci 413141cc406Sopenharmony_ci for (j = 0; j < pix; j++) 414141cc406Sopenharmony_ci { 415141cc406Sopenharmony_ci if (outbuff) 416141cc406Sopenharmony_ci { 417141cc406Sopenharmony_ci *(outbuff++) = *rp; 418141cc406Sopenharmony_ci if (pixsize == 2) 419141cc406Sopenharmony_ci *(outbuff++) = *(rp + 1); 420141cc406Sopenharmony_ci *(outbuff++) = *gp; 421141cc406Sopenharmony_ci if (pixsize == 2) 422141cc406Sopenharmony_ci *(outbuff++) = *(gp + 1); 423141cc406Sopenharmony_ci *(outbuff++) = *bp; 424141cc406Sopenharmony_ci if (pixsize == 2) 425141cc406Sopenharmony_ci *(outbuff++) = *(bp + 1); 426141cc406Sopenharmony_ci } 427141cc406Sopenharmony_ci rp += 3 * pixsize; 428141cc406Sopenharmony_ci gp += 3 * pixsize; 429141cc406Sopenharmony_ci bp += 3 * pixsize; 430141cc406Sopenharmony_ci } 431141cc406Sopenharmony_ci } 432141cc406Sopenharmony_ci lineptr = (lineptr + 1) % bufflines; 433141cc406Sopenharmony_ci } 434141cc406Sopenharmony_ci 435141cc406Sopenharmony_ci if (dpi != 1200) 436141cc406Sopenharmony_ci { 437141cc406Sopenharmony_ci if (i > blue_delay) 438141cc406Sopenharmony_ci { 439141cc406Sopenharmony_ci savestoreline = storeline; 440141cc406Sopenharmony_ci for (j = 0; j < scanpix; j++) 441141cc406Sopenharmony_ci { 442141cc406Sopenharmony_ci memcpy (storeline, ptrcur + linelen - (j + 1) * pixsize, 443141cc406Sopenharmony_ci pixsize); 444141cc406Sopenharmony_ci storeline += pixsize; 445141cc406Sopenharmony_ci } 446141cc406Sopenharmony_ci if (dpi == 150) 447141cc406Sopenharmony_ci { 448141cc406Sopenharmony_ci /* 150 DPI skips every 4th returned line */ 449141cc406Sopenharmony_ci if (i % 4) 450141cc406Sopenharmony_ci { 451141cc406Sopenharmony_ci i++; 452141cc406Sopenharmony_ci *save_i = i; 453141cc406Sopenharmony_ci if (bpp16) 454141cc406Sopenharmony_ci fix_endian_short ((unsigned short *) storeline, 455141cc406Sopenharmony_ci scanpix); 456141cc406Sopenharmony_ci return; 457141cc406Sopenharmony_ci } 458141cc406Sopenharmony_ci storeline = savestoreline; 459141cc406Sopenharmony_ci } 460141cc406Sopenharmony_ci else 461141cc406Sopenharmony_ci { 462141cc406Sopenharmony_ci i++; 463141cc406Sopenharmony_ci *save_i = i; 464141cc406Sopenharmony_ci if (bpp16) 465141cc406Sopenharmony_ci fix_endian_short ((unsigned short *) storeline, scanpix); 466141cc406Sopenharmony_ci return; 467141cc406Sopenharmony_ci } 468141cc406Sopenharmony_ci } 469141cc406Sopenharmony_ci } 470141cc406Sopenharmony_ci else /* dpi==1200 */ 471141cc406Sopenharmony_ci { 472141cc406Sopenharmony_ci if (i > (DPI1200SHUFFLE + blue_delay)) 473141cc406Sopenharmony_ci { 474141cc406Sopenharmony_ci for (j = 0; j < scanpix; j++) 475141cc406Sopenharmony_ci { 476141cc406Sopenharmony_ci if (1 == (j & 1)) 477141cc406Sopenharmony_ci memcpy (storeline, ptrcur + linelen - (j + 1) * pixsize, 478141cc406Sopenharmony_ci pixsize); 479141cc406Sopenharmony_ci else 480141cc406Sopenharmony_ci memcpy (storeline, ptrprev + linelen - (j + 1) * pixsize, 481141cc406Sopenharmony_ci pixsize); 482141cc406Sopenharmony_ci storeline += pixsize; 483141cc406Sopenharmony_ci } /* end for */ 484141cc406Sopenharmony_ci i++; 485141cc406Sopenharmony_ci *save_i = i; 486141cc406Sopenharmony_ci if (bpp16) 487141cc406Sopenharmony_ci fix_endian_short ((unsigned short *) storeline, scanpix); 488141cc406Sopenharmony_ci return; 489141cc406Sopenharmony_ci } /* end if >dpi1200shuffle */ 490141cc406Sopenharmony_ci } /* end if dpi1200 */ 491141cc406Sopenharmony_ci i++; 492141cc406Sopenharmony_ci } /* end for */ 493141cc406Sopenharmony_ci} 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_ci#ifndef BACKENDNAME 497141cc406Sopenharmony_ci/* Record an image to a file with remapping/reordering/etc. */ 498141cc406Sopenharmony_civoid 499141cc406Sopenharmony_cirecord_image (p_usb_dev_handle udev, char *fname, int dpi, 500141cc406Sopenharmony_ci int scanpix, int scanlines, int gray, char *head, int bpp16) 501141cc406Sopenharmony_ci{ 502141cc406Sopenharmony_ci FILE *fp; 503141cc406Sopenharmony_ci int i; 504141cc406Sopenharmony_ci int save_i; 505141cc406Sopenharmony_ci unsigned char *save_scan_line; 506141cc406Sopenharmony_ci unsigned char *save_dpi1200_remap; 507141cc406Sopenharmony_ci unsigned char *save_color_remap; 508141cc406Sopenharmony_ci unsigned char *storeline; 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci save_i = 0; 511141cc406Sopenharmony_ci save_scan_line = save_dpi1200_remap = save_color_remap = NULL; 512141cc406Sopenharmony_ci storeline = 513141cc406Sopenharmony_ci (unsigned char *) malloc (scanpix * (gray ? 1 : 3) * (bpp16 ? 2 : 1)); 514141cc406Sopenharmony_ci 515141cc406Sopenharmony_ci fp = fopen (fname, "wb"); 516141cc406Sopenharmony_ci if (head) 517141cc406Sopenharmony_ci fprintf (fp, "%s", head); 518141cc406Sopenharmony_ci 519141cc406Sopenharmony_ci for (i = 0; i < scanlines; i++) 520141cc406Sopenharmony_ci { 521141cc406Sopenharmony_ci record_line ((i == 0) ? 1 : 0, udev, storeline, dpi, scanpix, gray, 522141cc406Sopenharmony_ci bpp16, &save_i, &save_scan_line, &save_dpi1200_remap, 523141cc406Sopenharmony_ci &save_color_remap); 524141cc406Sopenharmony_ci fwrite (storeline, scanpix * (gray ? 1 : 3) * (bpp16 ? 2 : 1), 1, fp); 525141cc406Sopenharmony_ci } 526141cc406Sopenharmony_ci fclose (fp); 527141cc406Sopenharmony_ci if (save_scan_line) 528141cc406Sopenharmony_ci free (save_scan_line); 529141cc406Sopenharmony_ci if (save_dpi1200_remap) 530141cc406Sopenharmony_ci free (save_dpi1200_remap); 531141cc406Sopenharmony_ci if (save_color_remap) 532141cc406Sopenharmony_ci free (save_color_remap); 533141cc406Sopenharmony_ci free (storeline); 534141cc406Sopenharmony_ci} 535141cc406Sopenharmony_ci#endif 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_cistatic void 538141cc406Sopenharmony_cirecord_mem (p_usb_dev_handle udev, unsigned char **dest, int bytes) 539141cc406Sopenharmony_ci{ 540141cc406Sopenharmony_ci unsigned char *mem; 541141cc406Sopenharmony_ci unsigned char buff[65536]; 542141cc406Sopenharmony_ci int len; 543141cc406Sopenharmony_ci 544141cc406Sopenharmony_ci mem = (unsigned char *) malloc (bytes); 545141cc406Sopenharmony_ci *dest = mem; 546141cc406Sopenharmony_ci do 547141cc406Sopenharmony_ci { 548141cc406Sopenharmony_ci len = 549141cc406Sopenharmony_ci usb_bulk_read (udev, 1, buff, bytes > 65536 ? 65536 : bytes, 550141cc406Sopenharmony_ci rd_timeout); 551141cc406Sopenharmony_ci if (len > 0) 552141cc406Sopenharmony_ci { 553141cc406Sopenharmony_ci memcpy (mem, buff, len); 554141cc406Sopenharmony_ci bytes -= len; 555141cc406Sopenharmony_ci mem += len; 556141cc406Sopenharmony_ci } 557141cc406Sopenharmony_ci } 558141cc406Sopenharmony_ci while (bytes); 559141cc406Sopenharmony_ci} 560141cc406Sopenharmony_ci 561141cc406Sopenharmony_ci 562141cc406Sopenharmony_cistatic void 563141cc406Sopenharmony_cireset_scanner (p_usb_dev_handle udev) 564141cc406Sopenharmony_ci{ 565141cc406Sopenharmony_ci unsigned char rd_byte; 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ci DBG (2, "+reset_scanner\n"); 568141cc406Sopenharmony_ci write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff, 569141cc406Sopenharmony_ci 0xa2, 0xff); 570141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00); 571141cc406Sopenharmony_ci write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00); 572141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00); 573141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00); 574141cc406Sopenharmony_ci write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 575141cc406Sopenharmony_ci 0x88, 0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 576141cc406Sopenharmony_ci 0xc2, 0x00, 0xc3, 0x00, 0xc4, 0x00, 0xc5, 0x00, 577141cc406Sopenharmony_ci 0xc6, 0x00, 0xc7, 0x00, 0xc8, 0x00, 0xc0, 0x00); 578141cc406Sopenharmony_ci write_regs (udev, 16, 0x84, 0x94, 0x80, 0xd1, 0x80, 0xc1, 0x82, 0x7f, 579141cc406Sopenharmony_ci 0xcf, 0x04, 0xc1, 0x02, 0xc2, 0x00, 0xc3, 0x06, 580141cc406Sopenharmony_ci 0xc4, 0xff, 0xc5, 0x40, 0xc6, 0x8c, 0xc7, 0xdc, 581141cc406Sopenharmony_ci 0xc8, 0x20, 0xc0, 0x72, 0x89, 0xff, 0x86, 0xff); 582141cc406Sopenharmony_ci write_regs (udev, 7, 0xa8, 0x80, 0x83, 0xa2, 0x85, 0xc8, 0x83, 0x82, 583141cc406Sopenharmony_ci 0x85, 0xaf, 0x83, 0x00, 0x93, 0x00); 584141cc406Sopenharmony_ci write_regs (udev, 3, 0xa8, 0x0a, 0x8c, 0x08, 0x94, 0x00); 585141cc406Sopenharmony_ci write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a); 586141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); 587141cc406Sopenharmony_ci read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); 588141cc406Sopenharmony_ci write_regs (udev, 1, 0x97, 0x0b); 589141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); 590141cc406Sopenharmony_ci read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); 591141cc406Sopenharmony_ci write_regs (udev, 1, 0x97, 0x0f); 592141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); 593141cc406Sopenharmony_ci read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); 594141cc406Sopenharmony_ci write_regs (udev, 1, 0x97, 0x05); 595141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); 596141cc406Sopenharmony_ci read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); 597141cc406Sopenharmony_ci DBG (2, "-reset_scanner\n"); 598141cc406Sopenharmony_ci} 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_cistatic void 601141cc406Sopenharmony_cipoll1 (p_usb_dev_handle udev) 602141cc406Sopenharmony_ci{ 603141cc406Sopenharmony_ci unsigned char rd_byte; 604141cc406Sopenharmony_ci DBG (2, "+poll1\n"); 605141cc406Sopenharmony_ci do 606141cc406Sopenharmony_ci { 607141cc406Sopenharmony_ci write_regs (udev, 1, 0x97, 0x00); 608141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); 609141cc406Sopenharmony_ci read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); 610141cc406Sopenharmony_ci } 611141cc406Sopenharmony_ci while (0 == (rd_byte & 0x40)); 612141cc406Sopenharmony_ci DBG (2, "-poll1\n"); 613141cc406Sopenharmony_ci} 614141cc406Sopenharmony_ci 615141cc406Sopenharmony_cistatic void 616141cc406Sopenharmony_cipoll2 (p_usb_dev_handle udev) 617141cc406Sopenharmony_ci{ 618141cc406Sopenharmony_ci unsigned char rd_byte; 619141cc406Sopenharmony_ci DBG (2, "+poll2\n"); 620141cc406Sopenharmony_ci do 621141cc406Sopenharmony_ci { 622141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); 623141cc406Sopenharmony_ci read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); 624141cc406Sopenharmony_ci } 625141cc406Sopenharmony_ci while (0 == (rd_byte & 0x02)); 626141cc406Sopenharmony_ci DBG (2, "-poll2\n"); 627141cc406Sopenharmony_ci} 628141cc406Sopenharmony_ci 629141cc406Sopenharmony_ci#ifndef BACKENDNAME 630141cc406Sopenharmony_cistatic void 631141cc406Sopenharmony_cicheck_buttons (p_usb_dev_handle udev, int *scan, int *print, int *mail) 632141cc406Sopenharmony_ci{ 633141cc406Sopenharmony_ci unsigned char rd_byte; 634141cc406Sopenharmony_ci 635141cc406Sopenharmony_ci write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a); 636141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); 637141cc406Sopenharmony_ci read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); 638141cc406Sopenharmony_ci if (scan) 639141cc406Sopenharmony_ci { 640141cc406Sopenharmony_ci if (0 == (rd_byte & 1)) 641141cc406Sopenharmony_ci *scan = 1; 642141cc406Sopenharmony_ci else 643141cc406Sopenharmony_ci *scan = 0; 644141cc406Sopenharmony_ci } 645141cc406Sopenharmony_ci if (print) 646141cc406Sopenharmony_ci { 647141cc406Sopenharmony_ci if (0 == (rd_byte & 2)) 648141cc406Sopenharmony_ci *print = 1; 649141cc406Sopenharmony_ci else 650141cc406Sopenharmony_ci *print = 0; 651141cc406Sopenharmony_ci } 652141cc406Sopenharmony_ci if (mail) 653141cc406Sopenharmony_ci { 654141cc406Sopenharmony_ci if (0 == (rd_byte & 4)) 655141cc406Sopenharmony_ci *mail = 1; 656141cc406Sopenharmony_ci else 657141cc406Sopenharmony_ci *mail = 0; 658141cc406Sopenharmony_ci } 659141cc406Sopenharmony_ci write_regs (udev, 1, 0x97, 0x0b); 660141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); 661141cc406Sopenharmony_ci read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); 662141cc406Sopenharmony_ci idle_ab (udev); 663141cc406Sopenharmony_ci write_regs (udev, 1, 0x97, 0x0f); 664141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); 665141cc406Sopenharmony_ci read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); 666141cc406Sopenharmony_ci idle_ab (udev); 667141cc406Sopenharmony_ci write_regs (udev, 1, 0x97, 0x05); 668141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); 669141cc406Sopenharmony_ci read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); 670141cc406Sopenharmony_ci idle_ab (udev); 671141cc406Sopenharmony_ci} 672141cc406Sopenharmony_ci#endif 673141cc406Sopenharmony_ci 674141cc406Sopenharmony_cistatic int 675141cc406Sopenharmony_cilut (int val, double gain, int offset) 676141cc406Sopenharmony_ci{ 677141cc406Sopenharmony_ci /* int offset = 1800; */ 678141cc406Sopenharmony_ci /* double exponent = 3.5; */ 679141cc406Sopenharmony_ci return (offset + 8192.0 * (pow ((8192.0 - val) / 8192.0, gain))); 680141cc406Sopenharmony_ci} 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ci 683141cc406Sopenharmony_cistatic void 684141cc406Sopenharmony_cicalc_lightmap (unsigned short *buff, 685141cc406Sopenharmony_ci unsigned short *storage, int index, int dpi, 686141cc406Sopenharmony_ci double gain, int offset) 687141cc406Sopenharmony_ci{ 688141cc406Sopenharmony_ci int val, line; 689141cc406Sopenharmony_ci int px = 5632; 690141cc406Sopenharmony_ci int i; 691141cc406Sopenharmony_ci 692141cc406Sopenharmony_ci line = px * 3; 693141cc406Sopenharmony_ci 694141cc406Sopenharmony_ci for (i = 0; i < px; i++) 695141cc406Sopenharmony_ci { 696141cc406Sopenharmony_ci if ((i >= 2) && (i <= (px - 2))) 697141cc406Sopenharmony_ci { 698141cc406Sopenharmony_ci val = 0; 699141cc406Sopenharmony_ci val += 1 * buff[i * 3 + index - 3 * 2]; 700141cc406Sopenharmony_ci val += 3 * buff[i * 3 + index - 3 * 1]; 701141cc406Sopenharmony_ci val += 5 * buff[i * 3 + index + 3 * 0]; 702141cc406Sopenharmony_ci val += 3 * buff[i * 3 + index + 3 * 1]; 703141cc406Sopenharmony_ci val += 1 * buff[i * 3 + index + 3 * 2]; 704141cc406Sopenharmony_ci val += 2 * buff[i * 3 + index - 3 * 1 + line]; 705141cc406Sopenharmony_ci val += 3 * buff[i * 3 + index + 3 * 0 + line]; 706141cc406Sopenharmony_ci val += 2 * buff[i * 3 + index + 3 * 1 + line]; 707141cc406Sopenharmony_ci val += 1 * buff[i * 3 + index + 3 * 0 + 2 * line]; 708141cc406Sopenharmony_ci val /= 21; 709141cc406Sopenharmony_ci } 710141cc406Sopenharmony_ci else 711141cc406Sopenharmony_ci { 712141cc406Sopenharmony_ci val = 1 * buff[i * 3 + index]; 713141cc406Sopenharmony_ci } 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci val = val >> 3; 716141cc406Sopenharmony_ci if (val > 8191) 717141cc406Sopenharmony_ci val = 8191; 718141cc406Sopenharmony_ci val = lut (val, gain, offset); 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci if (val > 8191) 721141cc406Sopenharmony_ci val = 8191; 722141cc406Sopenharmony_ci if (val < 0) 723141cc406Sopenharmony_ci val = 0; 724141cc406Sopenharmony_ci storage[i * (dpi == 1200 ? 2 : 1)] = val; 725141cc406Sopenharmony_ci if (dpi == 1200) 726141cc406Sopenharmony_ci storage[i * 2 + 1] = val; 727141cc406Sopenharmony_ci } 728141cc406Sopenharmony_ci 729141cc406Sopenharmony_ci fix_endian_short (storage, (dpi == 1200) ? i * 2 : i); 730141cc406Sopenharmony_ci} 731141cc406Sopenharmony_ci 732141cc406Sopenharmony_ci 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci 735141cc406Sopenharmony_ci/*#define VALMAP 0x1fff */ 736141cc406Sopenharmony_ci/*#define SCANMAP 0x2000*/ 737141cc406Sopenharmony_ci#define RAWPIXELS600 7320 738141cc406Sopenharmony_ci#define RAWPIXELS1200 14640 739141cc406Sopenharmony_ci 740141cc406Sopenharmony_cistatic void 741141cc406Sopenharmony_ciselect_pixels (unsigned short *map, int dpi, int start, int end) 742141cc406Sopenharmony_ci{ 743141cc406Sopenharmony_ci int i; 744141cc406Sopenharmony_ci int skip, offset; 745141cc406Sopenharmony_ci unsigned short VALMAP = 0x1fff; 746141cc406Sopenharmony_ci unsigned short SCANMAP = 0x2000; 747141cc406Sopenharmony_ci 748141cc406Sopenharmony_ci fix_endian_short (&VALMAP, 1); 749141cc406Sopenharmony_ci fix_endian_short (&SCANMAP, 1); 750141cc406Sopenharmony_ci 751141cc406Sopenharmony_ci /* Clear the pixel-on flags for all bits */ 752141cc406Sopenharmony_ci for (i = 0; i < ((dpi == 1200) ? RAWPIXELS1200 : RAWPIXELS600); i++) 753141cc406Sopenharmony_ci map[i] &= VALMAP; 754141cc406Sopenharmony_ci 755141cc406Sopenharmony_ci /* 300 and 150 have subsampling */ 756141cc406Sopenharmony_ci if (dpi == 300) 757141cc406Sopenharmony_ci skip = -2; 758141cc406Sopenharmony_ci else if (dpi == 150) 759141cc406Sopenharmony_ci skip = -4; 760141cc406Sopenharmony_ci else 761141cc406Sopenharmony_ci skip = -1; 762141cc406Sopenharmony_ci 763141cc406Sopenharmony_ci /* 1200 has 2x pixels so start at 2x the offset */ 764141cc406Sopenharmony_ci if (dpi == 1200) 765141cc406Sopenharmony_ci offset = 234 + (8.5 * 1200); 766141cc406Sopenharmony_ci else 767141cc406Sopenharmony_ci offset = 117 + (8.5 * 600); 768141cc406Sopenharmony_ci 769141cc406Sopenharmony_ci if (0 == (offset & 1)) 770141cc406Sopenharmony_ci offset++; 771141cc406Sopenharmony_ci 772141cc406Sopenharmony_ci DBG (2, "offset=%d start=%d skip=%d\n", offset, start, skip); 773141cc406Sopenharmony_ci 774141cc406Sopenharmony_ci for (i = 0; i < end; i++) 775141cc406Sopenharmony_ci { 776141cc406Sopenharmony_ci int x; 777141cc406Sopenharmony_ci x = offset + (start * skip) + (i * skip); 778141cc406Sopenharmony_ci if (x < 0 || x > ((dpi == 1200) ? RAWPIXELS1200 : RAWPIXELS600)) 779141cc406Sopenharmony_ci DBG (2, "ERR %d\n", x); 780141cc406Sopenharmony_ci else 781141cc406Sopenharmony_ci map[x] |= SCANMAP; 782141cc406Sopenharmony_ci } 783141cc406Sopenharmony_ci} 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci 786141cc406Sopenharmony_cistatic void 787141cc406Sopenharmony_ciset_lightmap_white (unsigned short *map, int dpi, int color) 788141cc406Sopenharmony_ci{ 789141cc406Sopenharmony_ci int i; 790141cc406Sopenharmony_ci unsigned short VALMAP = 0x1fff; 791141cc406Sopenharmony_ci unsigned short SCANMAP = 0x2000; 792141cc406Sopenharmony_ci 793141cc406Sopenharmony_ci fix_endian_short (&VALMAP, 1); 794141cc406Sopenharmony_ci fix_endian_short (&SCANMAP, 1); 795141cc406Sopenharmony_ci 796141cc406Sopenharmony_ci if (dpi != 1200) 797141cc406Sopenharmony_ci { 798141cc406Sopenharmony_ci memset (map, 0, RAWPIXELS600 * 2); 799141cc406Sopenharmony_ci if (color != 0) 800141cc406Sopenharmony_ci return; /* Only 1st has enables... */ 801141cc406Sopenharmony_ci for (i = 0; i < 22; i++) 802141cc406Sopenharmony_ci map[7 + i] = SCANMAP; /* Get some black... */ 803141cc406Sopenharmony_ci for (i = 0; i < 1024; i++) 804141cc406Sopenharmony_ci map[2048 + i] = SCANMAP; /* And some white... */ 805141cc406Sopenharmony_ci } 806141cc406Sopenharmony_ci else 807141cc406Sopenharmony_ci { 808141cc406Sopenharmony_ci memset (map, 0, RAWPIXELS1200 * 2); 809141cc406Sopenharmony_ci if (color != 0) 810141cc406Sopenharmony_ci return; 811141cc406Sopenharmony_ci for (i = 16; i < 61; i++) 812141cc406Sopenharmony_ci map[i] = SCANMAP; 813141cc406Sopenharmony_ci for (i = 4076; i < 6145; i++) 814141cc406Sopenharmony_ci map[i] = SCANMAP; 815141cc406Sopenharmony_ci /* 3rd is all clear */ 816141cc406Sopenharmony_ci } 817141cc406Sopenharmony_ci} 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_ci 820141cc406Sopenharmony_cistatic void 821141cc406Sopenharmony_ciset_lamp_timer (p_usb_dev_handle udev, int timeout_in_mins) 822141cc406Sopenharmony_ci{ 823141cc406Sopenharmony_ci write_regs (udev, 7, 0xa8, 0x80, 0x83, 0xa2, 0x85, 0xc8, 0x83, 0x82, 824141cc406Sopenharmony_ci 0x85, 0xaf, 0x83, 0x00, 0x93, 0x00); 825141cc406Sopenharmony_ci write_regs (udev, 3, 0xa8, timeout_in_mins * 2, 0x8c, 0x08, 0x94, 0x00); 826141cc406Sopenharmony_ci idle_ab (udev); 827141cc406Sopenharmony_ci write_regs (udev, 4, 0x83, 0x20, 0x8d, 0x26, 0x83, 0x00, 0x8d, 0xff); 828141cc406Sopenharmony_ci} 829141cc406Sopenharmony_ci 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_cistatic void 832141cc406Sopenharmony_cicalculate_lut8 (double *poly, int skip, unsigned char *dest) 833141cc406Sopenharmony_ci{ 834141cc406Sopenharmony_ci int i; 835141cc406Sopenharmony_ci double sum, x; 836141cc406Sopenharmony_ci if (!poly || !dest) 837141cc406Sopenharmony_ci return; 838141cc406Sopenharmony_ci for (i = 0; i < 8192; i += skip) 839141cc406Sopenharmony_ci { 840141cc406Sopenharmony_ci sum = poly[0]; 841141cc406Sopenharmony_ci x = (double) i; 842141cc406Sopenharmony_ci sum += poly[1] * x; 843141cc406Sopenharmony_ci x = x * i; 844141cc406Sopenharmony_ci sum += poly[2] * x; 845141cc406Sopenharmony_ci x = x * i; 846141cc406Sopenharmony_ci sum += poly[3] * x; 847141cc406Sopenharmony_ci x = x * i; 848141cc406Sopenharmony_ci sum += poly[4] * x; 849141cc406Sopenharmony_ci x = x * i; 850141cc406Sopenharmony_ci sum += poly[5] * x; 851141cc406Sopenharmony_ci x = x * i; 852141cc406Sopenharmony_ci sum += poly[6] * x; 853141cc406Sopenharmony_ci x = x * i; 854141cc406Sopenharmony_ci sum += poly[7] * x; 855141cc406Sopenharmony_ci x = x * i; 856141cc406Sopenharmony_ci sum += poly[8] * x; 857141cc406Sopenharmony_ci x = x * i; 858141cc406Sopenharmony_ci sum += poly[9] * x; 859141cc406Sopenharmony_ci x = x * i; 860141cc406Sopenharmony_ci if (sum < 0) 861141cc406Sopenharmony_ci sum = 0; 862141cc406Sopenharmony_ci if (sum > 255) 863141cc406Sopenharmony_ci sum = 255; 864141cc406Sopenharmony_ci *dest = (unsigned char) sum; 865141cc406Sopenharmony_ci dest++; 866141cc406Sopenharmony_ci } 867141cc406Sopenharmony_ci} 868141cc406Sopenharmony_ci 869141cc406Sopenharmony_cistatic void 870141cc406Sopenharmony_cidownload_lut8 (p_usb_dev_handle udev, int dpi, int incolor) 871141cc406Sopenharmony_ci{ 872141cc406Sopenharmony_ci double color[10] = { 0.0, 1.84615261590892E-01, -2.19613868292657E-04, 873141cc406Sopenharmony_ci 1.79549523214101E-07, -8.69378513113239E-11, 874141cc406Sopenharmony_ci 2.56694911984996E-14, -4.67288886157239E-18, 875141cc406Sopenharmony_ci 5.11622894146250E-22, -3.08729724411991E-26, 876141cc406Sopenharmony_ci 7.88581670873938E-31 877141cc406Sopenharmony_ci }; 878141cc406Sopenharmony_ci double gray[10] = { 0.0, 1.73089945056694E-01, -1.39794924306080E-04, 879141cc406Sopenharmony_ci 9.70266873814926E-08, -4.57503008236968E-11, 880141cc406Sopenharmony_ci 1.37092321631794E-14, -2.54395068387198E-18, 881141cc406Sopenharmony_ci 2.82432084125966E-22, -1.71787408822688E-26, 882141cc406Sopenharmony_ci 4.40306800664567E-31 883141cc406Sopenharmony_ci }; 884141cc406Sopenharmony_ci unsigned char *lut; 885141cc406Sopenharmony_ci 886141cc406Sopenharmony_ci DBG (2, "+download_lut8\n"); 887141cc406Sopenharmony_ci switch (dpi) 888141cc406Sopenharmony_ci { 889141cc406Sopenharmony_ci case 150: 890141cc406Sopenharmony_ci case 300: 891141cc406Sopenharmony_ci case 600: 892141cc406Sopenharmony_ci lut = (unsigned char *) malloc (4096); 893141cc406Sopenharmony_ci if (!lut) 894141cc406Sopenharmony_ci return; 895141cc406Sopenharmony_ci 896141cc406Sopenharmony_ci if (!incolor) 897141cc406Sopenharmony_ci { 898141cc406Sopenharmony_ci calculate_lut8 (gray, 2, lut); 899141cc406Sopenharmony_ci write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x07, 0xb3, 0xff, 900141cc406Sopenharmony_ci 0xb4, 0x2f, 0xb5, 0x07); 901141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00); 902141cc406Sopenharmony_ci usb_bulk_write (udev, 2, lut, 4096, wr_timeout); 903141cc406Sopenharmony_ci } 904141cc406Sopenharmony_ci else 905141cc406Sopenharmony_ci { 906141cc406Sopenharmony_ci calculate_lut8 (color, 2, lut); 907141cc406Sopenharmony_ci write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x10, 0xb2, 0x07, 0xb3, 0xff, 908141cc406Sopenharmony_ci 0xb4, 0x1f, 0xb5, 0x07); 909141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00); 910141cc406Sopenharmony_ci usb_bulk_write (udev, 2, lut, 4096, wr_timeout); 911141cc406Sopenharmony_ci write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x07, 0xb3, 0xff, 912141cc406Sopenharmony_ci 0xb4, 0x2f, 0xb5, 0x07); 913141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00); 914141cc406Sopenharmony_ci usb_bulk_write (udev, 2, lut, 4096, wr_timeout); 915141cc406Sopenharmony_ci write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x30, 0xb2, 0x07, 0xb3, 0xff, 916141cc406Sopenharmony_ci 0xb4, 0x3f, 0xb5, 0x07); 917141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00); 918141cc406Sopenharmony_ci usb_bulk_write (udev, 2, lut, 4096, wr_timeout); 919141cc406Sopenharmony_ci } 920141cc406Sopenharmony_ci break; 921141cc406Sopenharmony_ci 922141cc406Sopenharmony_ci case 1200: 923141cc406Sopenharmony_ci default: 924141cc406Sopenharmony_ci lut = (unsigned char *) malloc (8192); 925141cc406Sopenharmony_ci if (!lut) 926141cc406Sopenharmony_ci return; 927141cc406Sopenharmony_ci 928141cc406Sopenharmony_ci if (!incolor) 929141cc406Sopenharmony_ci { 930141cc406Sopenharmony_ci calculate_lut8 (gray, 1, lut); 931141cc406Sopenharmony_ci write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x06, 0xb3, 0xff, 932141cc406Sopenharmony_ci 0xb4, 0x5f, 0xb5, 0x06); 933141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00); 934141cc406Sopenharmony_ci usb_bulk_write (udev, 2, lut, 8192, wr_timeout); 935141cc406Sopenharmony_ci } 936141cc406Sopenharmony_ci else 937141cc406Sopenharmony_ci { 938141cc406Sopenharmony_ci calculate_lut8 (color, 1, lut); 939141cc406Sopenharmony_ci write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x06, 0xb3, 0xff, 940141cc406Sopenharmony_ci 0xb4, 0x3f, 0xb5, 0x06); 941141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00); 942141cc406Sopenharmony_ci usb_bulk_write (udev, 2, lut, 8192, wr_timeout); 943141cc406Sopenharmony_ci write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x06, 0xb3, 0xff, 944141cc406Sopenharmony_ci 0xb4, 0x5f, 0xb5, 0x06); 945141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00); 946141cc406Sopenharmony_ci usb_bulk_write (udev, 2, lut, 8192, wr_timeout); 947141cc406Sopenharmony_ci write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x60, 0xb2, 0x06, 0xb3, 0xff, 948141cc406Sopenharmony_ci 0xb4, 0x7f, 0xb5, 0x06); 949141cc406Sopenharmony_ci write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00); 950141cc406Sopenharmony_ci usb_bulk_write (udev, 2, lut, 8192, wr_timeout); 951141cc406Sopenharmony_ci } 952141cc406Sopenharmony_ci break; 953141cc406Sopenharmony_ci } 954141cc406Sopenharmony_ci 955141cc406Sopenharmony_ci free (lut); 956141cc406Sopenharmony_ci DBG (2, "-download_lut8\n"); 957141cc406Sopenharmony_ci} 958141cc406Sopenharmony_ci 959141cc406Sopenharmony_ci 960141cc406Sopenharmony_cistatic void 961141cc406Sopenharmony_ciset_gain_black (p_usb_dev_handle udev, 962141cc406Sopenharmony_ci int r_gain, int g_gain, int b_gain, 963141cc406Sopenharmony_ci int r_black, int g_black, int b_black) 964141cc406Sopenharmony_ci{ 965141cc406Sopenharmony_ci write_regs (udev, 1, 0x80, 0x00); 966141cc406Sopenharmony_ci write_regs (udev, 1, 0x80, 0x01); 967141cc406Sopenharmony_ci write_regs (udev, 1, 0x04, 0x80); 968141cc406Sopenharmony_ci write_regs (udev, 1, 0x04, 0x00); 969141cc406Sopenharmony_ci write_regs (udev, 1, 0x00, 0x00); 970141cc406Sopenharmony_ci write_regs (udev, 1, 0x01, 0x03); 971141cc406Sopenharmony_ci write_regs (udev, 1, 0x02, 0x04); 972141cc406Sopenharmony_ci write_regs (udev, 1, 0x03, 0x11); 973141cc406Sopenharmony_ci write_regs (udev, 1, 0x05, 0x00); 974141cc406Sopenharmony_ci write_regs (udev, 1, 0x28, r_gain); 975141cc406Sopenharmony_ci write_regs (udev, 1, 0x29, g_gain); 976141cc406Sopenharmony_ci write_regs (udev, 1, 0x2a, b_gain); 977141cc406Sopenharmony_ci write_regs (udev, 1, 0x20, r_black); 978141cc406Sopenharmony_ci write_regs (udev, 1, 0x21, g_black); 979141cc406Sopenharmony_ci write_regs (udev, 1, 0x22, b_black); 980141cc406Sopenharmony_ci write_regs (udev, 1, 0x24, 0x00); 981141cc406Sopenharmony_ci write_regs (udev, 1, 0x25, 0x00); 982141cc406Sopenharmony_ci write_regs (udev, 1, 0x26, 0x00); 983141cc406Sopenharmony_ci} 984141cc406Sopenharmony_ci 985141cc406Sopenharmony_ci/* Handle short endianness issues */ 986141cc406Sopenharmony_cistatic void 987141cc406Sopenharmony_cifix_endian_short (unsigned short *data, int count) 988141cc406Sopenharmony_ci{ 989141cc406Sopenharmony_ci unsigned short testvalue = 255; 990141cc406Sopenharmony_ci unsigned char *firstbyte = (unsigned char *) &testvalue; 991141cc406Sopenharmony_ci int i; 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ci if (*firstbyte == 255) 994141cc406Sopenharmony_ci return; /* INTC endianness */ 995141cc406Sopenharmony_ci 996141cc406Sopenharmony_ci DBG (2, "swapping endianness...\n"); 997141cc406Sopenharmony_ci for (i = 0; i < count; i++) 998141cc406Sopenharmony_ci data[i] = ((data[i] >> 8) & 0x00ff) | ((data[i] << 8) & 0xff00); 999141cc406Sopenharmony_ci} 1000