ALT Linux Bugzilla
– Attachment 2195 Details for
Bug 12764
[fr] Сканер на LaserJet M1005 MFP
New bug
|
Search
|
[?]
|
Help
Register
|
Log In
[x]
|
Forgot Password
Login:
[x]
|
EN
|
RU
backend code
hpljm1005.c (text/plain), 23.89 KB, created by
algor
on 2007-09-13 10:26:46 MSD
(
hide
)
Description:
backend code
Filename:
MIME Type:
Creator:
algor
Created:
2007-09-13 10:26:46 MSD
Size:
23.89 KB
patch
obsolete
>/* sane - Scanner Access Now Easy. > > Copyright (C) 2007 Philippe Rétornaz > > This file is part of the SANE package. > > This program is free software; you can redistribute it and/or > modify it under the terms of the GNU General Public License as > published by the Free Software Foundation; either version 2 of the > License, or (at your option) any later version. > > This program is distributed in the hope that it will be useful, but > WITHOUT ANY WARRANTY; without even the implied warranty of > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > General Public License for more details. > > You should have received a copy of the GNU General Public License > along with this program; if not, write to the Free Software > Foundation, Inc., 59 Temple Place - Suite 330, Boston, > MA 02111-1307, USA. > > As a special exception, the authors of SANE give permission for > additional uses of the libraries contained in this release of SANE. > > The exception is that, if you link a SANE library with other files > to produce an executable, this does not by itself cause the > resulting executable to be covered by the GNU General Public > License. Your use of that executable is in no way restricted on > account of linking the SANE library code into it. > > This exception does not, however, invalidate any other reasons why > the executable file might be covered by the GNU General Public > License. > > If you submit changes to SANE to the maintainers to be included in > a subsequent release, you agree by submitting the changes that > those changes may be distributed with this exception intact. > > If you write modifications of your own for SANE, it is your choice > whether to permit this exception to apply to your modifications. > If you do not wish that, delete this exception notice. > > This backend is for HP LaserJet M1005 MFP > > Highly inspired from the epson backend >*/ > >#ifdef _AIX >#include <lalloca.h> /* MUST come first for AIX! */ >#endif > >#define BUILD 0 > >#include "../include/sane/config.h" >#include <lalloca.h> > > >#include <limits.h> >#include <stdio.h> >#include <string.h> >#include <stdlib.h> >#include <ctype.h> >#include <fcntl.h> >#include <unistd.h> >#include <errno.h> >#include <netinet/in.h> >#include "../include/sane/sanei_usb.h" >#include "../include/sane/saneopts.h" >#include "../include/sane/sanei_backend.h" >#define BACKEND_NAME hpljm1005 > >#define MAGIC_NUMBER 0x41535001 >#define PKT_READ_STATUS 0x0 >#define PKT_UNKNOW_1 0x1 >#define PKT_START_SCAN 0x2 >#define PKT_GO_IDLE 0x3 >#define PKT_DATA 0x5 >#define PKT_READCONF 0x6 >#define PKT_SETCONF 0x7 >#define PKT_END_DATA 0xe >#define PKT_RESET 0x15 > >#define RED_LAYER 0x3 >#define GREEN_LAYER 0x4 >#define BLUE_LAYER 0x5 >#define GRAY_LAYER 0x6 > > >struct usbdev_s { > SANE_Int vendor_id; > SANE_Int product_id; > SANE_String_Const vendor_s; > SANE_String_Const model_s; > SANE_String_Const type_s; >}; > >/* Zero-terminated USB VID/PID array */ >static struct usbdev_s usbid[] = { > { 0x03f0, 0x3b17, "Hewlett-Packard", "LaserJet M1005", "multi-function peripheral" }, > { 0, 0, NULL, NULL, NULL}, > { 0, 0, NULL, NULL, NULL} >}; > >static int cur_idx; > >#define BR_CONT_MIN 0x1 >#define BR_CONT_MAX 0xb > >#define RGB 1 >#define GRAY 0 > >#define MAX_X_H 0x352 >#define MAX_Y_H 0x490 >#define MAX_X_S 220 >#define MAX_Y_S 330 > >#define OPTION_MAX 9 > >static SANE_Word resolution_list[] = { > 7,75,100,150,200,300,600,1200 >}; >static SANE_Range range_x = {0,MAX_X_S,0}; >static SANE_Range range_y = {0,MAX_Y_S,0}; > >static SANE_Range range_br_cont = {BR_CONT_MIN,BR_CONT_MAX,0}; > >static const SANE_String_Const mode_list[] = { > "Gray", > "Color", > NULL >}; > >#define X1_OFFSET 2 >#define X2_OFFSET 4 >#define Y1_OFFSET 3 >#define Y2_OFFSET 5 >#define RES_OFFSET 1 >#define COLOR_OFFSET 8 >#define BRIGH_OFFSET 6 >#define CONTR_OFFSET 7 > >#define STATUS_IDLE 0 >#define STATUS_SCANNING 1 > >struct device_s { > struct device_s * next; > SANE_String_Const devname; > int idx; /* Index in the usbid array */ > int dn; /* Usb "Handle" */ > SANE_Option_Descriptor optiond[OPTION_MAX]; > char * buffer; > int bufs; > int read_offset; > int write_offset_r; > int write_offset_g; > int write_offset_b; > int status; > int width; > int height; > SANE_Word optionw[OPTION_MAX]; > uint32_t conf_data[512]; > uint32_t packet_data[512]; >}; > >static struct device_s *devlist_head; >static int devlist_count; /* Number of element in the list */ > >/* > * List of pointers to devices - will be dynamically allocated depending > * on the number of devices found. > */ >static SANE_Device **devlist = NULL; > >static void update_img_size(struct device_s *dev) { > /* HACK FIXME */ > switch(dev->optionw[RES_OFFSET]) { > case 75: > dev->height = 880; > dev->width = 640; > break; > case 100: > dev->height = 1180; > dev->width = 848; > break; > case 150: > dev->height = 1775; > dev->width = 1264; > break; > case 200: > dev->width = 1696; > dev->height = 2351; > break; > case 300: > dev->width = 2528; > dev->height = 3510; > break; > case 600: > dev->width = 5088; > dev->height = 7020; > break; > case 1200: > dev->width = 10208; > dev->height = 14025; > break; > } > dev->bufs = dev->width * dev->height; > if(dev->optionw[COLOR_OFFSET] == RGB) > dev->bufs *= 3; >} > >/* This function is copy/pasted from the Epson backend */ >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(SANE_String_Const devname) { > struct device_s * dev; > > dev = malloc(sizeof(struct device_s)); > if(!dev) > return SANE_STATUS_NO_MEM; > memset(dev,0,sizeof(struct device_s)); > > dev->devname = devname; > >/* Init the whole structure with default values */ > /* Number of options */ > dev->optiond[0].name = ""; > dev->optiond[0].title = NULL; > dev->optiond[0].desc = NULL; > dev->optiond[0].type = SANE_TYPE_INT; > dev->optiond[0].unit = SANE_UNIT_NONE; > dev->optiond[0].size = sizeof (SANE_Word); > dev->optionw[0] = OPTION_MAX; > > /* resolution */ > dev->optiond[RES_OFFSET].name = "resolution"; > dev->optiond[RES_OFFSET].title = "resolution"; > dev->optiond[RES_OFFSET].desc = "resolution"; > dev->optiond[RES_OFFSET].type = SANE_TYPE_INT; > dev->optiond[RES_OFFSET].unit = SANE_UNIT_DPI; > dev->optiond[RES_OFFSET].type = SANE_TYPE_INT; > dev->optiond[RES_OFFSET].size = sizeof (SANE_Word); > dev->optiond[RES_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; > dev->optiond[RES_OFFSET].constraint_type = SANE_CONSTRAINT_WORD_LIST; > dev->optiond[RES_OFFSET].constraint.word_list = resolution_list; > dev->optionw[RES_OFFSET] = 75; > > /* scan area */ > dev->optiond[X1_OFFSET].name = "tl-x"; > dev->optiond[X1_OFFSET].title = "tl-x"; > dev->optiond[X1_OFFSET].desc = "tl-x"; > dev->optiond[X1_OFFSET].type = SANE_TYPE_INT; > dev->optiond[X1_OFFSET].unit = SANE_UNIT_MM; > dev->optiond[X1_OFFSET].size = sizeof (SANE_Word); > dev->optiond[X1_OFFSET].cap = /*SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT*/ 0; > dev->optiond[X1_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; > dev->optiond[X1_OFFSET].constraint.range = &range_x; > dev->optionw[X1_OFFSET] = 0; > > dev->optiond[Y1_OFFSET].name = "tl-y"; > dev->optiond[Y1_OFFSET].title = "tl-y"; > dev->optiond[Y1_OFFSET].desc = "tl-y"; > dev->optiond[Y1_OFFSET].type = SANE_TYPE_INT; > dev->optiond[Y1_OFFSET].unit = SANE_UNIT_MM; > dev->optiond[Y1_OFFSET].size = sizeof (SANE_Word); > dev->optiond[Y1_OFFSET].cap = /*SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT*/ 0; > dev->optiond[Y1_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; > dev->optiond[Y1_OFFSET].constraint.range = &range_y; > dev->optionw[Y1_OFFSET] = 0; > > dev->optiond[X2_OFFSET].name = "br-x"; > dev->optiond[X2_OFFSET].title = "br-x"; > dev->optiond[X2_OFFSET].desc = "br-x"; > dev->optiond[X2_OFFSET].type = SANE_TYPE_INT; > dev->optiond[X2_OFFSET].unit = SANE_UNIT_MM; > dev->optiond[X2_OFFSET].size = sizeof (SANE_Word); > dev->optiond[X2_OFFSET].cap = /*SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT*/ 0; > dev->optiond[X2_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; > dev->optiond[X2_OFFSET].constraint.range = &range_x; > dev->optionw[X2_OFFSET] = MAX_X_S; > > dev->optiond[Y2_OFFSET].name = "br-y"; > dev->optiond[Y2_OFFSET].title = "br-y"; > dev->optiond[Y2_OFFSET].desc = "br-y"; > dev->optiond[Y2_OFFSET].type = SANE_TYPE_INT; > dev->optiond[Y2_OFFSET].unit = SANE_UNIT_MM; > dev->optiond[Y2_OFFSET].size = sizeof (SANE_Word); > dev->optiond[Y2_OFFSET].cap = /*SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT*/ 0; > dev->optiond[Y2_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; > dev->optiond[Y2_OFFSET].constraint.range = &range_y; > dev->optionw[Y2_OFFSET] = MAX_Y_S; > > /* brightness */ > dev->optiond[BRIGH_OFFSET].name = "brightness"; > dev->optiond[BRIGH_OFFSET].title = "Brightness"; > dev->optiond[BRIGH_OFFSET].desc = "Set the brightness"; > dev->optiond[BRIGH_OFFSET].type = SANE_TYPE_INT; > dev->optiond[BRIGH_OFFSET].unit = SANE_UNIT_NONE; > dev->optiond[BRIGH_OFFSET].size = sizeof (SANE_Word); > dev->optiond[BRIGH_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; > dev->optiond[BRIGH_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; > dev->optiond[BRIGH_OFFSET].constraint.range = &range_br_cont; > dev->optionw[BRIGH_OFFSET] = 0x6; > > /* contrast */ > dev->optiond[CONTR_OFFSET].name = "contrast"; > dev->optiond[CONTR_OFFSET].title = "Contrast"; > dev->optiond[CONTR_OFFSET].desc = "Set the contrast"; > dev->optiond[CONTR_OFFSET].type = SANE_TYPE_INT; > dev->optiond[CONTR_OFFSET].unit = SANE_UNIT_NONE; > dev->optiond[CONTR_OFFSET].size = sizeof (SANE_Word); > dev->optiond[CONTR_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; > dev->optiond[CONTR_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; > dev->optiond[CONTR_OFFSET].constraint.range = &range_br_cont; > dev->optionw[CONTR_OFFSET] = 0x6; > > /* Color */ > dev->optiond[COLOR_OFFSET].name = SANE_NAME_SCAN_MODE; > dev->optiond[COLOR_OFFSET].title = SANE_TITLE_SCAN_MODE; > dev->optiond[COLOR_OFFSET].desc = SANE_DESC_SCAN_MODE; > dev->optiond[COLOR_OFFSET].type = SANE_TYPE_STRING; > dev->optiond[COLOR_OFFSET].size = max_string_size (mode_list); > dev->optiond[COLOR_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; > dev->optiond[COLOR_OFFSET].constraint_type = SANE_CONSTRAINT_STRING_LIST; > dev->optiond[COLOR_OFFSET].constraint.string_list = mode_list; > dev->optionw[COLOR_OFFSET] = RGB; /* RGB */ > dev->dn = 0; > dev->idx = cur_idx; > dev->status = STATUS_IDLE; > > dev->next = devlist_head; > devlist_head = dev; > devlist_count++; > > > > return SANE_STATUS_GOOD; >} > >SANE_Status >sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { > > if (version_code != NULL) > *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD); > > sanei_usb_init (); > > return SANE_STATUS_GOOD; >} > >void sane_exit(void) { > /* free everything */ > struct device_s *iter; > > if(devlist) { > int i; > for(i = 0; devlist[i]; i++) > free(devlist[i]); > free(devlist); > devlist = NULL; > } > if(devlist_head) { > iter = devlist_head->next; > free(devlist_head); > devlist_head = NULL; > while(iter) { > struct device_s *tmp = iter; > iter = iter->next; > free(tmp); > } > } > devlist_count = 0; >} > >SANE_Status >sane_get_devices (const SANE_Device * **device_list, > SANE_Bool __sane_unused__ local_only) { > struct device_s *iter; > int i; > > devlist_count = 0; > > if(devlist_head) { > iter = devlist_head->next; > free(devlist_head); > devlist_head = NULL; > while(iter) { > struct device_s *tmp = iter; > iter = iter->next; > free(tmp); > } > } > > /* Rebuild our internal scanner list */ > for(cur_idx = 0; usbid[cur_idx].vendor_id; cur_idx++) > sanei_usb_find_devices(usbid[cur_idx].vendor_id, > usbid[cur_idx].product_id, attach); > > if(devlist) { > for(i = 0; devlist[i]; i++) > free(devlist[i]); > free(devlist); > } > > /* rebuild the sane-API scanner list array */ > devlist = malloc(sizeof(devlist[0]) * (devlist_count + 1)); > if(!devlist) > return SANE_STATUS_NO_MEM; > > memset(devlist,0,sizeof(devlist[0]) * (devlist_count + 1)); > > for(i = 0, iter = devlist_head; i < devlist_count; i++, iter = iter->next) { > devlist[i] = malloc(sizeof(SANE_Device)); > if(!devlist[i]) { > int j; > for(j = 0; j < i; j++) > free(devlist[j]); > free(devlist); > devlist = NULL; > return SANE_STATUS_NO_MEM; > } > devlist[i]->name = iter->devname; > devlist[i]->vendor = usbid[iter->idx].vendor_s; > devlist[i]->model = usbid[iter->idx].model_s; > devlist[i]->type = usbid[iter->idx].type_s; > } > if(device_list) > *device_list = (const SANE_Device **) devlist ; > return SANE_STATUS_GOOD; >} > >SANE_Status sane_open(SANE_String_Const name, SANE_Handle *h) { > struct device_s *dev = devlist_head; > int ret; > > if(strlen(name)) > for(; dev; dev = dev->next) > if(!strcmp(name,dev->devname)) > break; > if(!dev) > return SANE_STATUS_INVAL; > > /* Now open the usb device */ > ret = sanei_usb_open(name,&(dev->dn)); > if(ret != SANE_STATUS_GOOD) > return ret; > > /* Claim the first interface */ > ret = sanei_usb_claim_interface(dev->dn,0); > if(ret != SANE_STATUS_GOOD) { > sanei_usb_close(dev->dn); > /* if we cannot claim the interface, this is because > someone else is using it */ > return SANE_STATUS_DEVICE_BUSY; > } >#ifdef HAVE_SANEI_USB_SET_TIMEOUT > sanei_usb_set_timeout(30000); /* 30s timeout */ >#endif > > *h = dev; > > return SANE_STATUS_GOOD; >} > >void sane_close(SANE_Handle h) { > struct device_s *dev = (struct device_s *) h; > > sanei_usb_release_interface(dev->dn,0); > sanei_usb_close(dev->dn); > >} > >const SANE_Option_Descriptor * >sane_get_option_descriptor (SANE_Handle h, SANE_Int option) { > struct device_s *dev = (struct device_s *) h; > > if(option >= OPTION_MAX || option < 0) > return NULL; > return &(dev->optiond[option]); >} > >static SANE_Status getvalue(SANE_Handle h, SANE_Int option, void * v) { > struct device_s *dev = (struct device_s *) h; > > if(option != COLOR_OFFSET) > *((SANE_Word *) v) = dev->optionw[option]; > else { > strcpy ((char *) v, > dev->optiond[option].constraint.string_list[dev->optionw[option]]); > } > return SANE_STATUS_GOOD; >} > >static const char * >search_string_list(const SANE_String_Const * list, SANE_String value) >{ > while (*list != NULL && strcmp(value, *list) != 0) { > ++list; > } > > return ((*list == NULL) ? NULL : (const char *) list); >} > >static SANE_Status >setvalue(SANE_Handle h, SANE_Int option, void * value, SANE_Int * info) { > struct device_s *dev = (struct device_s *) h; > SANE_Status status = SANE_STATUS_GOOD; > int s_unit; > > if(option == 0) > return SANE_STATUS_UNSUPPORTED; > > > status = sanei_constrain_value (&(dev->optiond[option]), value, info); > > if (status != SANE_STATUS_GOOD) > return status; > > > > if(info) > *info |= SANE_INFO_RELOAD_PARAMS; > switch(option) { > case X1_OFFSET: > case X2_OFFSET: > /* X units */ > /* convert into "scanner" unit, then back into mm */ > dev->optionw[option] = *((SANE_Word *) value); > > s_unit = (int) ((dev->optionw[option] / ((double) MAX_X_S)) > * MAX_X_H); > dev->optionw[option] = (s_unit / ((double) MAX_X_H)) > * MAX_X_S; > if(info) > *info |= SANE_INFO_INEXACT; > break; > case Y1_OFFSET: > case Y2_OFFSET: > /* Y units */ > dev->optionw[option] = *((SANE_Word *) value); > > s_unit = (int) ((dev->optionw[option] / ((double) MAX_Y_S)) > * MAX_Y_H); > dev->optionw[option] = (s_unit / ((double) MAX_Y_H)) > * MAX_Y_S; > if(info) > *info |= SANE_INFO_INEXACT; > break; > case COLOR_OFFSET: > if(!strcmp((char *)value, mode_list[0])) > dev->optionw[option] = GRAY; /* Gray */ > else if(!strcmp((char *)value, mode_list[1])) > dev->optionw[option] = RGB; /* RGB */ > else > return SANE_STATUS_INVAL; > break; > default: > dev->optionw[option] = *((SANE_Word *) value); > } > return SANE_STATUS_GOOD; >} > >SANE_Status sane_control_option(SANE_Handle h, SANE_Int option, > SANE_Action a, void * v, > SANE_Int * i) { > > if (option < 0 || option >= OPTION_MAX) > return SANE_STATUS_INVAL; > > if(i) > *i = 0; > > > switch (a) { > case SANE_ACTION_GET_VALUE: > return getvalue(h,option,v); > > case SANE_ACTION_SET_VALUE: > return setvalue(h,option,v,i); > > default: > return SANE_STATUS_INVAL; > } >} > >SANE_Status sane_get_parameters(SANE_Handle h, SANE_Parameters *p) { > struct device_s *dev = (struct device_s *) h; > > if(!p) > return SANE_STATUS_INVAL; > > p->format = dev->optionw[COLOR_OFFSET] == RGB ? SANE_FRAME_RGB : SANE_FRAME_GRAY; > p->last_frame = SANE_TRUE; > p->depth = 8; > > update_img_size(dev); > p->pixels_per_line = dev->width; > p->lines = dev->height; > p->bytes_per_line = p->pixels_per_line; > if(p->format == SANE_FRAME_RGB) > p->bytes_per_line *= 3; > > return SANE_STATUS_GOOD; >} > >static void send_pkt(int command, int data_size, struct device_s *dev) { > size_t size = 32; > memset(dev->packet_data,0,size); > dev->packet_data[0] = htonl(MAGIC_NUMBER); > dev->packet_data[1] = htonl(command); > dev->packet_data[5] = htonl(data_size); > sanei_usb_write_bulk(dev->dn, (unsigned char *) dev->packet_data, &size); >} > >/* s: printer status */ >/* Return the next packet size */ >static int wait_ack(struct device_s *dev, int *s) { > SANE_Status ret; > size_t size = 512; > do { > size = 512; > ret = sanei_usb_read_bulk(dev->dn, (unsigned char *) dev->packet_data, &size); > } while(SANE_STATUS_EOF == ret || size == 0); > if(s) > *s = ntohl(dev->packet_data[4]); > return ntohl(dev->packet_data[5]); >} > >static void send_conf(struct device_s *dev) { > int y1,y2,x1,x2; > size_t size = 100; > y1 = (int) ((dev->optionw[Y1_OFFSET] / ((double) MAX_Y_S)) * MAX_Y_H); > y2 = (int) ((dev->optionw[Y2_OFFSET] / ((double) MAX_Y_S)) * MAX_Y_H); > x1 = (int) ((dev->optionw[X1_OFFSET] / ((double) MAX_X_S)) * MAX_X_H); > x2 = (int) ((dev->optionw[X2_OFFSET] / ((double) MAX_X_S)) * MAX_X_H); > dev->conf_data[0] = htonl(0x15); > dev->conf_data[1] = htonl(dev->optionw[BRIGH_OFFSET]); > dev->conf_data[2] = htonl(dev->optionw[CONTR_OFFSET]); > dev->conf_data[3] = htonl(dev->optionw[RES_OFFSET]); > dev->conf_data[4] = htonl(0x1); > dev->conf_data[5] = htonl(0x1); > dev->conf_data[6] = htonl(0x1); > dev->conf_data[7] = htonl(0x1); > dev->conf_data[8] = 0; > dev->conf_data[9] = 0; > dev->conf_data[10] = htonl(0x8); > dev->conf_data[11] = 0; > dev->conf_data[12] = 0; > dev->conf_data[13] = 0; > dev->conf_data[14] = 0; > dev->conf_data[16] = htonl(y1); > dev->conf_data[17] = htonl(x1); > dev->conf_data[18] = htonl(y2); > dev->conf_data[19] = htonl(x2); > dev->conf_data[20] = 0; > dev->conf_data[21] = 0; > dev->conf_data[22] = htonl(0x491); > dev->conf_data[23] = htonl(0x352); > > if(dev->optionw[COLOR_OFFSET] == RGB) { > dev->conf_data[15] = htonl(0x2); > dev->conf_data[24] = htonl(0x1); > } else { > dev->conf_data[15] = htonl(0x6); > dev->conf_data[24] = htonl(0x0); > } > sanei_usb_write_bulk(dev->dn, (unsigned char *) dev->conf_data, &size); >} > >static SANE_Status get_data(struct device_s *dev) { > int color; > size_t size = 512; > int packet_size; > unsigned char * buffer = (unsigned char *) dev->packet_data; > if(dev->status != STATUS_SCANNING) > return SANE_STATUS_IO_ERROR; > /* first wait a standard data pkt */ > do { > size = 512; > sanei_usb_read_bulk(dev->dn, buffer, &size); > if(size) > if(ntohl(dev->packet_data[0]) == MAGIC_NUMBER) { > if(ntohl(dev->packet_data[1]) == PKT_DATA) > break; > if(ntohl(dev->packet_data[1]) == PKT_END_DATA) { > dev->status = STATUS_IDLE; > send_pkt(PKT_GO_IDLE,0,dev); > wait_ack(dev,NULL); > wait_ack(dev,NULL); > send_pkt(PKT_UNKNOW_1,0,dev); > wait_ack(dev,NULL); > send_pkt(PKT_RESET,0,dev); > return SANE_STATUS_EOF; > } > } > } while(1); > packet_size = ntohl(dev->packet_data[5]); > if(!dev->buffer) { > update_img_size(dev); > dev->buffer = malloc(dev->bufs); > if(!dev->buffer) > return SANE_STATUS_NO_MEM; > dev->write_offset_r = 0; > dev->write_offset_g = 1; > dev->write_offset_b = 2; > } > /* Get the "data header" */ > do { > size = 512; > sanei_usb_read_bulk(dev->dn, buffer,&size); > } while(!size); > color = ntohl(dev->packet_data[0]); > packet_size -= size; > > /* Now, read the data */ > do { > int j; > int i; > int ret; > do { > size = 512; > ret = sanei_usb_read_bulk(dev->dn, buffer, &size); > } while(!size || ret != SANE_STATUS_GOOD); > packet_size -= size; > switch(color) { > case RED_LAYER: > i = dev->write_offset_r + 3*size; > if(i > dev->bufs) > i = dev->bufs; > for(j = 0; dev->write_offset_r < i; > dev->write_offset_r += 3) > dev->buffer[dev->write_offset_r] = buffer[j++]; > break; > case GREEN_LAYER: > i = dev->write_offset_g + 3*size; > if(i > dev->bufs) > i = dev->bufs; > for(j = 0; dev->write_offset_g < i; > dev->write_offset_g += 3) > dev->buffer[dev->write_offset_g] = buffer[j++]; > break; > case BLUE_LAYER: > i = dev->write_offset_b + 3*size; > if(i > dev->bufs) > i = dev->bufs; > for(j = 0; dev->write_offset_b < i; > dev->write_offset_b += 3) > dev->buffer[dev->write_offset_b] = buffer[j++]; > break; > case GRAY_LAYER: > if(dev->write_offset_r + size >= dev->bufs) > size = dev->bufs - dev->write_offset_r; > memcpy(dev->buffer + dev->write_offset_r, > buffer,size); > dev->write_offset_r += size; > break; > } > } while(packet_size > 0); > return SANE_STATUS_GOOD; >} > >SANE_Status sane_start(SANE_Handle h) { > struct device_s *dev = (struct device_s *) h; > int status; > size_t size; > > dev->read_offset = 0; > dev->write_offset_r = 0; > dev->write_offset_g = 1; > dev->write_offset_b = 2; > dev->buffer = NULL; > > send_pkt(PKT_RESET,0,dev); > send_pkt(PKT_READ_STATUS,0,dev); > wait_ack(dev,&status); > if(status) > return SANE_STATUS_IO_ERROR; > > send_pkt(PKT_READCONF,0,dev); > > if(wait_ack(dev,NULL)) { > size = 512; > sanei_usb_read_bulk(dev->dn, > (unsigned char *) dev->conf_data, &size); > } > send_pkt(PKT_SETCONF,100,dev); > send_conf(dev); > wait_ack(dev,NULL); > > send_pkt(PKT_START_SCAN,0,dev); > wait_ack(dev,NULL); > dev->status = STATUS_SCANNING; > return SANE_STATUS_GOOD; >} > >static int min3(int r, int g, int b) { > /* Optimize me ! */ > g--; > b -= 2; > if(r < g && r < b) > return r; > if(b < r && b < g) > return b; > return g; >} > >SANE_Status sane_read(SANE_Handle h, SANE_Byte * buf, > SANE_Int maxlen, SANE_Int * len) { > struct device_s *dev = (struct device_s *) h; > int available; > int ret; > *len = 0; > if(dev->status == STATUS_IDLE) > return SANE_STATUS_IO_ERROR; > if(dev->optionw[COLOR_OFFSET] == RGB) { > while(min3(dev->write_offset_r,dev->write_offset_g, > dev->write_offset_b) <= dev->read_offset) { > ret = get_data(dev); > if(ret != SANE_STATUS_GOOD) { > if(min3(dev->write_offset_r, > dev->write_offset_g, > dev->write_offset_b) > <= dev->read_offset) > return ret; > } > } > available = min3(dev->write_offset_r,dev->write_offset_g, > dev->write_offset_b); > } else { > while(dev->write_offset_r <= dev->read_offset) { > ret = get_data(dev); > if(ret != SANE_STATUS_GOOD) > if(dev->write_offset_r <= dev->read_offset) > return ret; > } > available = dev->write_offset_r; > } > *len = available - dev->read_offset; > if(*len > maxlen) > *len = maxlen; > memcpy(buf,dev->buffer + dev->read_offset,*len); > dev->read_offset += *len; > return SANE_STATUS_GOOD; >} > >void sane_cancel(SANE_Handle h) { > struct device_s *dev = (struct device_s *) h; > size_t size; > SANE_Status ret; > unsigned char * buffer = (unsigned char *) dev->packet_data; > > if(dev->buffer) { > free(dev->buffer); > dev->buffer = NULL; > } > if(dev->status != STATUS_SCANNING) > return; > > do { > size = 512; > sanei_usb_read_bulk(dev->dn, buffer, &size); > if(size) > if(ntohl(dev->packet_data[0]) == MAGIC_NUMBER) { > if(ntohl(dev->packet_data[1]) == PKT_END_DATA) { > dev->status = STATUS_IDLE; > send_pkt(PKT_GO_IDLE,0,dev); > do { > size = 512; > ret = sanei_usb_read_bulk(dev->dn, > buffer, &size); > } while(size == 0 || > ntohl(dev->packet_data[1]) != PKT_END_DATA); > dev->status = STATUS_IDLE; > send_pkt(PKT_GO_IDLE,0,dev); > wait_ack(dev,NULL); > wait_ack(dev,NULL); > send_pkt(PKT_UNKNOW_1,0,dev); > wait_ack(dev,NULL); > send_pkt(PKT_RESET,0,dev); > } > } > } while(1); >} > >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 (SANE_Handle __sane_unused__ handle, > SANE_Int __sane_unused__ * fd) >{ > return SANE_STATUS_UNSUPPORTED; >} > >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 12764
: 2195 |
2196
|
2197