Henning Meier-Geinitz wrote: >[segfault of xscanimage with avision backend] > >On Sat, Sep 24, 2005 at 07:39:51AM -0500, Dan McGhee wrote: > > >>Starting program: /usr/bin/xscanimage >> >>*[This is the point at which I clicked "scan" in the preview window]* >> >>Program received signal SIGSEGV, Segmentation fault. >>0x08057467 in gsg_sync (dialog=0x80ef4f0) at gtkglue.c:1424 >>1424 curve = GTK_GAMMA_CURVE (dialog->element[i].widget)->curve; >>(gdb) bt >>#0 0x08057467 in gsg_sync (dialog=0x80ef4f0) at gtkglue.c:1424 >> >> > >The code is: > > > if (opt->type != SANE_TYPE_INT && opt->type != SANE_TYPE_FIXED) > continue; > > if (opt->size == sizeof (SANE_Word)) > continue; > > /* ok, we're dealing with an active vector */ > > optlen = opt->size / sizeof (SANE_Word); > optval = alloca (optlen * sizeof (optval[0])); > vector = alloca (optlen * sizeof (vector[0])); > > curve = GTK_GAMMA_CURVE (dialog->element[i].widget)->curve; > >So I looked into the avision backend for a SANE_TYPE_INT or >SANE_TYPE_FIXED option with a length != SANE_Word. There are the four >gamma vectors but they look ok. The only thing that looks fishy is >this (avision.c): > > s->opt[OPT_NUM_OPTS].name = ""; > s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; > s->opt[OPT_NUM_OPTS].desc = ""; > s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; > s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; > s->opt[OPT_NUM_OPTS].size = sizeof(SANE_TYPE_INT); > >The last line is wrong (it must be sizeof(SANE_Word)). SANE_TYPE_INT >is an enum. Is this automatically and "int" or can it be shorter? I'm >not sure if this is actually the problem but you could try that: > > s->opt[OPT_NUM_OPTS].size = sizeof (SANE_Word); > >in avision.c and recompile+install. > > Just to remind you, I'm not using the version of avision released in backends-1.0.16. I'm using Rev. 280 of avision from SVN. It is patched with the file Falk Rohsiepe sent me and then Rene posted a patch here last month.
I'm really a "noob" at reading code, so right now about the only thing I can do is gather and report data. In the version of avision.c that I currently have--the patched one--I ran: 'grep -in -A 5 -B 5 SANE_Word avision.c' I have attached the resulting file. I know there's probably a lot of extraneous info there, but I don't know how to filter out the extra stuff. I also ran: ` grep -in \-A 5 -B 5 sizof\(SANE_Word\) avision.c` with no results. `grep -in \-A 5 -B 5 OPT_NUM_OPTS avision.c` yielded 899- dev->speed_range.min = (SANE_Int)0; 5900- dev->speed_range.max = (SANE_Int)4; 5901- dev->speed_range.quant = (SANE_Int)1; 5902- 5903: init_option_int (s, OPT_NUM_OPTS, "", SANE_TITLE_NUM_OPTIONS, "", 5904- SANE_UNIT_NONE, SANE_CAP_SOFT_DETECT, 0, 0, 5905- NUM_OPTIONS); 5906- 5907- /* "Mode" group: */ 5908- init_option_group (s, OPT_MODE_GROUP, SANE_TITLE_SCAN_MODE); -- 7605- case OPT_SPEED: 7606- case OPT_TL_X: 7607- case OPT_TL_Y: 7608- case OPT_BR_X: 7609- case OPT_BR_Y: 7610: case OPT_NUM_OPTS: 7611- 7612- case OPT_BRIGHTNESS: 7613- case OPT_CONTRAST: 7614- case OPT_QSCAN: 7615- case OPT_QCALIB: >If that's not the problem, I guess Rene has to do some debugging >because without a scanner supported by the avision backend I can't >help more. > > > If you give me specific directions, I can run the commands and post back. @Rene and Falk I can do the same for both of you too. >Does the segfault also occur with sane-backends 1.0.16? > > I'm going by memory, which fails as I age, and I think there may be a regression between avision released in backends-1.0.15 and Rev 280. I THINK I remember xscanimage working with the patch applied to avision in 1.0.15, but I'm not sure. If I have the time I will rebuild it and report. Thanks for the help, Henning. Dan -------------- next part -------------- 1462- SANE_FIX (0), /* minimum */ 1463- SANE_FIX (100), /* maximum */ 1464- SANE_FIX (1) /* quantization */ 1465- }; 1466- 1467:static const SANE_Word bool_list[] = 1468- { 1469- 2, /* 2 members */ 1470- SANE_FALSE, 1471- SANE_TRUE 1472- }; -- 1524- DBG (3, "constrain_value: while trying to set %.3f\n", 1525- SANE_UNFIX(*(SANE_Fixed*)value)); 1526- } 1527- else { 1528- DBG (3, "constrain_value: while trying to set %lu\n", 1529: (u_long)*(SANE_Word*)value); 1530- } 1531- } 1532- return r; 1533-} 1534- -- 3221- 3222- return SANE_STATUS_GOOD; 3223-} 3224- 3225-static SANE_Status 3226:set_frame (Avision_Scanner* s, SANE_Word frame) 3227-{ 3228- struct { 3229- struct command_send cmd; 3230- u_int8_t data[8]; 3231- } scmd; -- 5681- 5682-static void 5683-init_option_int (Avision_Scanner *s, int idx, 5684- const char* name, const char* title, const char* desc, 5685- SANE_Unit unit, SANE_Int cap, 5686: const SANE_Word* valid_list, const SANE_Range* valid_range, 5687- SANE_Int value) 5688-{ 5689- s->opt[idx].name = name; 5690- s->opt[idx].title = title; 5691- s->opt[idx].desc = desc; 5692- s->opt[idx].type = SANE_TYPE_INT; 5693- s->opt[idx].unit = unit; 5694: s->opt[idx].size = sizeof (SANE_Word); 5695- s->opt[idx].cap = cap; 5696- if (valid_list) { 5697- s->opt[idx].constraint_type = SANE_CONSTRAINT_WORD_LIST; 5698- s->opt[idx].constraint.word_list = valid_list; 5699- } -- 5709- 5710-static void 5711-init_option_int_vec (Avision_Scanner *s, int idx, 5712- const char* name, const char* title, const char* desc, 5713- SANE_Unit unit, SANE_Int cap, 5714: const SANE_Word* valid_list, const SANE_Range* valid_range, 5715- SANE_Int* value, SANE_Int value_len) 5716-{ 5717- s->opt[idx].name = name; 5718- s->opt[idx].title = title; 5719- s->opt[idx].desc = desc; 5720- s->opt[idx].type = SANE_TYPE_INT; 5721- s->opt[idx].unit = unit; 5722: s->opt[idx].size = value_len * sizeof (SANE_Word); 5723- s->opt[idx].cap = cap; 5724- if (valid_list) { 5725- s->opt[idx].constraint_type = SANE_CONSTRAINT_WORD_LIST; 5726- s->opt[idx].constraint.word_list = valid_list; 5727- } -- 5737- 5738-static void 5739-init_option_fix (Avision_Scanner *s, int idx, 5740- const char* name, const char* title, const char* desc, 5741- SANE_Unit unit, SANE_Int cap, 5742: const SANE_Word* valid_list, const SANE_Range* valid_range, 5743- SANE_Fixed value) 5744-{ 5745- s->opt[idx].name = name; 5746- s->opt[idx].title = title; 5747- s->opt[idx].desc = desc; 5748- s->opt[idx].type = SANE_TYPE_FIXED; 5749- s->opt[idx].unit = unit; 5750: s->opt[idx].size = sizeof (SANE_Word); 5751- s->opt[idx].cap = cap; 5752- if (valid_list) { 5753- s->opt[idx].constraint_type = SANE_CONSTRAINT_WORD_LIST; 5754- s->opt[idx].constraint.word_list = valid_list; 5755- } -- 5766-#ifdef NEEDED 5767-static void 5768-init_option_fix_vec (Avision_Scanner *s, int idx, 5769- const char* name, const char* title, const char* desc, 5770- SANE_Unit unit, SANE_Int cap, 5771: const SANE_Word* valid_list, const SANE_Range* valid_range, 5772- SANE_Fixed* value, SANE_Int value_len) 5773-{ 5774- s->opt[idx].name = name; 5775- s->opt[idx].title = title; 5776- s->opt[idx].desc = desc; -- 5846- s->opt[idx].name = name; 5847- s->opt[idx].title = title; 5848- s->opt[idx].desc = desc; 5849- s->opt[idx].type = SANE_TYPE_BOOL; 5850- s->opt[idx].unit = SANE_UNIT_NONE; 5851: s->opt[idx].size = sizeof (SANE_Word); 5852- s->opt[idx].cap = cap; 5853- s->opt[idx].constraint_type = SANE_CONSTRAINT_NONE; 5854- s->val[idx].w = value; 5855-} 5856- -- 5873- 5874- memset (s->opt, 0, sizeof (s->opt)); 5875- memset (s->val, 0, sizeof (s->val)); 5876- 5877- for (i = 0; i < NUM_OPTIONS; ++ i) { 5878: s->opt[i].size = sizeof (SANE_Word); 5879- s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 5880- } 5881- 5882- /* Init the SANE option from the scanner inquiry data */ 5883- -- 7536- SANE_Action action, void* val, SANE_Int* info) 7537-{ 7538- Avision_Scanner* s = handle; 7539- Avision_Device* dev = s->hw; 7540- SANE_Status status; 7541: SANE_Word cap; 7542- 7543- DBG (3, "sane_control_option: option=%d, action=%d\n", 7544- (int)option, (int)action); 7545- 7546- if (info) -- 7577- DBG (3, "sane_control_option: queried for %d (%s): %.3f\n", 7578- option, s->opt[option].name, 7579- (double)SANE_UNFIX(s->val[option].w)); 7580- break; 7581- case SANE_TYPE_INT: 7582: if (s->opt[option].size > (int)sizeof (SANE_Word)) { 7583- int i; 7584- DBG (3, "sane_control_option: queried for %d (%s):\n", 7585- option, s->opt[option].name); 7586: for (i = 0; i < (int)(s->opt[option].size/sizeof(SANE_Word)); ++i) 7587- DBG (3, "sane_control_option: %lu\n", 7588- (long)s->val[option].wa[i]); 7589- } 7590- else 7591- DBG (3, "sane_control_option: queried for %d (%s): %lu\n", -- 7624- case OPT_CCT_7: 7625- case OPT_CCT_8: 7626- case OPT_CCT_9: 7627- case OPT_CCT_HW: 7628- 7629: *(SANE_Word*) val = s->val[option].w; 7630- return SANE_STATUS_GOOD; 7631- 7632- /* specially treated word options */ 7633- /* FR: shouldn't this better be a string, word array or bitmask? 7634- having to query in order is counter-intuitive. */ -- 7644- case OPT_BUTTON_5: 7645- case OPT_BUTTON_6: 7646- case OPT_BUTTON_7: 7647- 7648- /* copy the button state */ 7649: *(SANE_Word*) val = s->val[option].w; 7650- /* clear the button state */ 7651- s->val[option].w = SANE_FALSE; 7652- 7653- return SANE_STATUS_GOOD; 7654- -- 7689- DBG (3, "sane_control_option: ordered to set %d (%s) to %.3f\n", 7690- option, s->opt[option].name, 7691- (double)SANE_UNFIX(*(SANE_Fixed*)val)); 7692- break; 7693- case SANE_TYPE_INT: 7694: if (s->opt[option].size > (int)sizeof (SANE_Word)) { 7695- int i; 7696- DBG (3, "sane_control_option: ordered to set %d (%s) to:\n", 7697- option, s->opt[option].name); 7698: for (i = 0; i < (int)(s->opt[option].size/sizeof(SANE_Word)); ++i) 7699- DBG (3, "sane_control_option: %lu\n", 7700: (long)((SANE_Word*)val)[i]); 7701- } 7702- else 7703- DBG (3, "sane_control_option: ordered to set %d (%s) to %lu\n", 7704: option, s->opt[option].name, (long)*(SANE_Word*)val); 7705- break; 7706- case SANE_TYPE_BUTTON: 7707- DBG (3, "sane_control_option: button %d (%s) activated\n", 7708- option, s->opt[option].name); 7709- break; 7710- default: 7711- DBG (3, "sane_control_option: ordered to set %d (%s) to %lu\n", 7712: option, s->opt[option].name, (long)*(SANE_Word*)val); 7713- break; 7714- } 7715- if (!SANE_OPTION_IS_SETTABLE (cap)) 7716- return SANE_STATUS_INVAL; 7717- -- 7728- case OPT_CONTRAST: 7729- case OPT_QSCAN: 7730- case OPT_QCALIB: 7731- case OPT_CCT_HW: 7732- 7733: s->val[option].w = *(SANE_Word*) val; 7734- return SANE_STATUS_GOOD; 7735- 7736- case OPT_CCT_1: 7737- case OPT_CCT_2: 7738- case OPT_CCT_3: -- 7740- case OPT_CCT_5: 7741- case OPT_CCT_6: 7742- case OPT_CCT_7: 7743- case OPT_CCT_8: 7744- case OPT_CCT_9: 7745: s->val[option].w = *(SANE_Word*) val; 7746- set_3x3_matrix (s); 7747- return SANE_STATUS_GOOD; 7748- 7749- /* side-effect-free word-array options: */ 7750- case OPT_GAMMA_VECTOR: -- 7759- case OPT_TL_X: 7760- case OPT_TL_Y: 7761- case OPT_BR_X: 7762- case OPT_BR_Y: 7763- 7764: s->val[option].w = *(SANE_Word*) val; 7765- 7766- if (dev->hw->feature_type & AV_WINDOW_BUG) { 7767- if ((s->scale_mode == AV_SCALE_HWONLY) && adjust_hwdpi (s)) { 7768- if (info) 7769- *info |= SANE_INFO_INEXACT | SANE_INFO_RELOAD_OPTIONS; -- 7775- 7776- return SANE_STATUS_GOOD; 7777- 7778- case OPT_GAMMA_RELATIVE: 7779- 7780: if (s->val[option].w != *(SANE_Word*) val) { 7781- int i, j; 7782- SANE_Int* tt; 7783: s->val[option].w = *(SANE_Word*) val; 7784- 7785- if (s->val[option].w) 7786- tt = default_gamma (); 7787- else 7788- tt = default_inverse_gamma (); -- 7857- *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 7858- return SANE_STATUS_GOOD; 7859- } 7860- case OPT_FRAME: 7861- { 7862: SANE_Word frame = *((SANE_Word *) val); 7863- 7864- status = set_frame (s, frame); 7865- if (status == SANE_STATUS_GOOD) { 7866- s->val[OPT_FRAME].w = frame; 7867- dev->current_frame = frame; From henn...@meier-geinitz.de Sun Sep 25 16:41:37 2005 From: henn...@meier-geinitz.de (Henning Meier-Geinitz) Date: Sun Sep 25 16:42:14 2005 Subject: [sane-devel] Lexmark X1100 backend available In-Reply-To: <4335e529.9020...@rogers.com> References: <4335e529.9020...@rogers.com> Message-ID: <20050925164137.gd29...@meier-geinitz.de> Hi, On Sat, Sep 24, 2005 at 07:45:45PM -0400, Fred Odendaal wrote: > I've put a patch file for the Lexmark X1100 backend on my website. > Instructions for getting it are at > http://ca.geocities.com/freshsh...@rogers.com/scanner_driver/download.html Ok, let's have a look (I only mention stuff that hasn't already been listed by other people): AUTHORS: - your email address is missing configure.in - is missing (ok, for now it's ok but the final patch that should go to CVS should have configure.in patched, not configure) backend/Makefile.in: | libsane-lexmark.la: $(addsuffix .lo,$(EXTRA_lexmark)) See below for comments. | libsane-lexmark.la: ../sanei/sanei_config2.lo Are you sure that you need this (this is used for SCSI devices) backend/lexmark.c | static SANE_String_Const mode_list[] = { | "Color", "Gray", "Black & White", NULL | }; "Lineart" is used in most backends instead of "Black & White". See also include/saneopts.h: #define SANE_VALUE_SCAN_MODE_COLOR SANE_I18N("Color") #define SANE_VALUE_SCAN_MODE_GRAY SANE_I18N("Gray") #define SANE_VALUE_SCAN_MODE_LINEART SANE_I18N("Lineart") | SANE_Status | init_options (Lexmark_Device * lexmark_device) All functions that are not part of the SANE API must be either static or start with "sanei_lexmark_". I would make everything static and only rename the functions in lexmark-x1100.c that are called from lexmark.c "sanei_lexmark_". Or, as a workaround, just #include lexmark-x1100.c in lexmark.c and make everything but the API functions static. See doc/backend-writing.txt for details. | sane_init In my experience it's a good idea to print the version/build number of the backend in a DBG message. That way you always know what version was used when you get a bug report. For an example, see gt68xx.c. | in sane_start | sane_get_parameters (handle, 0); check return value? |if ((lexmark_device->params.lines == 0) || | (lexmark_device->params.pixels_per_line == 0) || | (lexmark_device->params.bytes_per_line == 0)) | return SANE_STATUS_INVAL; A DBG message twelling what's wrong would be nice. backend/lexmark-x1100.c: - no problems found One additional thing: You could write a test for the chipset used in these scanners in tools/check-usb-chip.c. That way it's easy to find out which other scanners also use the same chipset. Once you have implemented the changes mentioned here and you have a manual page, please provide another patch so the backend can be included into CVS. Bye, Henning