static SANE_Status attach_one_device (SANE_String_Const devname) { Mustek_Usb_Device *dev; SANE_Status status; RIE (attach (devname, &dev, SANE_FALSE)); if (dev) { /* Keep track of newly attached devices so we can set options as necessary. */ if (new_dev_len >= new_dev_alloced) { new_dev_alloced += 4; if (new_dev) new_dev = realloc (new_dev, new_dev_alloced * sizeof (new_dev[0])); else new_dev = malloc (new_dev_alloced * sizeof (new_dev[0])); if (!new_dev) { DBG (1, "attach_one_device: out of memory\n"); return SANE_STATUS_NO_MEM; } } new_dev[new_dev_len++] = dev; } return SANE_STATUS_GOOD; }
enum vmmerr cpu_emul_realmode_int (u8 num) { u16 seg, off; ulong rflags, rip; u16 cs; ulong idtr_base, idtr_limit; struct cpu_stack st; /* FIXME: IDTR LIMIT CHECK */ /* FIXME: stack limit check */ current->vmctl.read_idtr (&idtr_base, &idtr_limit); RIE (read_linearaddr_w (idtr_base + ((u32)num << 2) + 0, &off)); RIE (read_linearaddr_w (idtr_base + ((u32)num << 2) + 2, &seg)); current->vmctl.read_flags (&rflags); current->vmctl.read_sreg_sel (SREG_CS, &cs); current->vmctl.read_ip (&rip); RIE (cpu_stack_get (&st)); RIE (cpu_stack_push (&st, &rflags, OPTYPE_16BIT)); RIE (cpu_stack_push (&st, &cs, OPTYPE_16BIT)); RIE (cpu_stack_push (&st, &rip, OPTYPE_16BIT)); current->vmctl.write_realmode_seg (SREG_CS, seg); current->vmctl.write_ip (off); rflags &= ~(RFLAGS_TF_BIT | RFLAGS_AC_BIT); current->vmctl.write_flags (rflags); RIE (cpu_stack_set (&st)); cpu_emul_cli (); return VMMERR_SUCCESS; }
SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Mustek_Usb_Scanner *s = handle; SANE_Status status; DBG (5, "sane_get_parameters: start\n"); RIE (calc_parameters (s)); if (params) *params = s->params; DBG (5, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; }
enum vmmerr cpu_emul_realmode_int (u8 num) { u16 seg, off; ulong rflags, rip; u16 cs; ulong idtr_base, idtr_limit; struct cpu_stack st; /* FIXME: IDTR LIMIT CHECK */ /* FIXME: stack limit check */ current->vmctl.read_idtr (&idtr_base, &idtr_limit); RIE (read_linearaddr_w (idtr_base + ((u32)num << 2) + 0, &off)); RIE (read_linearaddr_w (idtr_base + ((u32)num << 2) + 2, &seg)); current->vmctl.read_flags (&rflags); current->vmctl.read_sreg_sel (SREG_CS, &cs); current->vmctl.read_ip (&rip); #ifdef DISABLE_TCG_BIOS if (num == 0x1A) { ulong rax; current->vmctl.read_general_reg (GENERAL_REG_RAX, &rax); rax &= 0xFFFF; if (rax == 0xBB00) { /* TCG_StatusCheck function */ current->vmctl.write_flags (rflags | RFLAGS_CF_BIT); return VMMERR_SUCCESS; } } #endif /* DISABLE_TCG_BIOS */ RIE (cpu_stack_get (&st)); RIE (cpu_stack_push (&st, &rflags, OPTYPE_16BIT)); RIE (cpu_stack_push (&st, &cs, OPTYPE_16BIT)); RIE (cpu_stack_push (&st, &rip, OPTYPE_16BIT)); current->vmctl.write_realmode_seg (SREG_CS, seg); current->vmctl.write_ip (off); rflags &= ~(RFLAGS_TF_BIT | RFLAGS_AC_BIT); current->vmctl.write_flags (rflags); RIE (cpu_stack_set (&st)); cpu_emul_cli (); return VMMERR_SUCCESS; }
SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Mustek_Usb_Device *dev; SANE_Status status; Mustek_Usb_Scanner *s; SANE_Int value; DBG (5, "sane_open: start (devicename = `%s')\n", devicename); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { DBG (5, "sane_open: couldn't find `%s' in devlist, trying attach)\n", devicename); RIE (attach (devicename, &dev, SANE_TRUE)); } else DBG (5, "sane_open: found `%s' in devlist\n", dev->name); } else { /* empty devicname -> use first device */ dev = first_dev; if (dev) DBG (5, "sane_open: empty devicename, trying `%s'\n", dev->name); } if (!dev) return SANE_STATUS_INVAL; if (dev->chip->scanner_type == MT_UNKNOWN) { DBG (0, "sane_open: the type of your scanner is unknown, edit " "mustek_usb.conf before using the scanner\n"); return SANE_STATUS_INVAL; } s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->hw = dev; RIE (init_options (s)); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; strcpy (s->hw->device_name, dev->name); RIE (usb_high_scan_turn_power (s->hw, SANE_TRUE)); RIE (usb_high_scan_back_home (s->hw)); s->hw->scan_buffer = (SANE_Byte *) malloc (SCAN_BUFFER_SIZE * 2); if (!s->hw->scan_buffer) { DBG (5, "sane_open: couldn't malloc s->hw->scan_buffer (%d bytes)\n", SCAN_BUFFER_SIZE * 2); return SANE_STATUS_NO_MEM; } s->hw->scan_buffer_len = 0; s->hw->scan_buffer_start = s->hw->scan_buffer; s->hw->temp_buffer = (SANE_Byte *) malloc (SCAN_BUFFER_SIZE); if (!s->hw->temp_buffer) { DBG (5, "sane_open: couldn't malloc s->hw->temp_buffer (%d bytes)\n", SCAN_BUFFER_SIZE); return SANE_STATUS_NO_MEM; } s->hw->temp_buffer_len = 0; s->hw->temp_buffer_start = s->hw->temp_buffer; for (value = 0; value < 256; value++) { s->linear_gamma_table[value] = value; s->red_gamma_table[value] = value; s->green_gamma_table[value] = value; s->blue_gamma_table[value] = value; s->gray_gamma_table[value] = value; } s->red_table = s->linear_gamma_table; s->green_table = s->linear_gamma_table; s->blue_table = s->linear_gamma_table; s->gray_table = s->linear_gamma_table; DBG (5, "sane_open: exit\n"); return SANE_STATUS_GOOD; }
static SANE_Status init_options (Mustek_Usb_Scanner * s) { SANE_Int option; SANE_Status status; DBG (5, "init_options: start\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (option = 0; option < NUM_OPTIONS; ++option) { s->opt[option].size = sizeof (SANE_Word); s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 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; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ mode_list[0] = SANE_VALUE_SCAN_MODE_COLOR; mode_list[1] = SANE_VALUE_SCAN_MODE_GRAY; mode_list[2] = SANE_VALUE_SCAN_MODE_LINEART; mode_list[3] = NULL; 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].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[1]); /* 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_FIXED; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 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; if (s->hw->chip->scanner_type == MT_600CU) s->hw->dpi_range.max = SANE_FIX (600); else s->hw->dpi_range.max = SANE_FIX (1200); /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_PREVIEW].w = SANE_FALSE; /* "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; s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* 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; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &u8_range; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->val[OPT_THRESHOLD].w = 128; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* gray gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR].wa = &s->gray_gamma_table[0]; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->red_gamma_table[0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->green_gamma_table[0]; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->blue_gamma_table[0]; RIE (calc_parameters (s)); DBG (5, "init_options: exit\n"); return SANE_STATUS_GOOD; }
SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Mustek_Usb_Scanner *s = handle; SANE_Word lines_to_read, lines_read; SANE_Status status; DBG (5, "sane_read: start\n"); if (!s) { DBG (1, "sane_read: handle is null!\n"); return SANE_STATUS_INVAL; } if (!buf) { DBG (1, "sane_read: buf is null!\n"); return SANE_STATUS_INVAL; } if (!len) { DBG (1, "sane_read: len is null!\n"); return SANE_STATUS_INVAL; } *len = 0; if (!s->scanning) { DBG (3, "sane_read: scan was cancelled, is over or has not been " "initiated yet\n"); return SANE_STATUS_CANCELLED; } if (s->hw->scan_buffer_len == 0) { if (s->read_rows > 0) { lines_to_read = SCAN_BUFFER_SIZE / (s->hw->width * s->hw->bpp / 8); if (lines_to_read > s->read_rows) lines_to_read = s->read_rows; s->hw->temp_buffer_start = s->hw->temp_buffer; s->hw->temp_buffer_len = (s->hw->width * s->hw->bpp / 8) * lines_to_read; DBG (4, "sane_read: reading %d source lines\n", lines_to_read); RIE (usb_high_scan_get_rows (s->hw, s->hw->temp_buffer, lines_to_read, SANE_FALSE)); RIE (fit_lines (s, s->hw->temp_buffer, s->hw->scan_buffer, lines_to_read, &lines_read)); s->read_rows -= lines_to_read; if ((s->total_lines + lines_read) > s->height_dots) lines_read = s->height_dots - s->total_lines; s->total_lines += lines_read; DBG (4, "sane_read: %d destination lines, %d total\n", lines_read, s->total_lines); s->hw->scan_buffer_start = s->hw->scan_buffer; s->hw->scan_buffer_len = (s->width_dots * s->bpp / 8) * lines_read; } else { DBG (4, "sane_read: scan finished -- exit\n"); return SANE_STATUS_EOF; } } if (s->hw->scan_buffer_len == 0) { DBG (4, "sane_read: scan finished -- exit\n"); return SANE_STATUS_EOF; } *len = MIN (max_len, (SANE_Int) s->hw->scan_buffer_len); memcpy (buf, s->hw->scan_buffer_start, *len); DBG (4, "sane_read: exit, read %d bytes from scan_buffer; " "%ld bytes remaining\n", *len, (long int) (s->hw->scan_buffer_len - *len)); s->hw->scan_buffer_len -= (*len); s->hw->scan_buffer_start += (*len); s->total_bytes += (*len); return SANE_STATUS_GOOD; }
SANE_Status sane_start (SANE_Handle handle) { Mustek_Usb_Scanner *s = handle; SANE_Status status; SANE_String val; Colormode color_mode; SANE_Word dpi, x, y, width, height; DBG (5, "sane_start: start\n"); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ s->total_bytes = 0; s->total_lines = 0; RIE (calc_parameters (s)); if (s->width_dots <= 0) { DBG (0, "sane_start: top left x > bottom right x --- exiting\n"); return SANE_STATUS_INVAL; } if (s->height_dots <= 0) { DBG (0, "sane_start: top left y > bottom right y --- exiting\n"); return SANE_STATUS_INVAL; } val = s->val[OPT_MODE].s; if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) color_mode = GRAY8; else if (!strcmp (val, SANE_VALUE_SCAN_MODE_GRAY)) color_mode = GRAY8; else /* Color */ color_mode = RGB24; dpi = SANE_UNFIX (s->val[OPT_RESOLUTION].w); x = s->tl_x_dots; y = s->tl_y_dots; width = s->width_dots; height = s->height_dots; if (!s->hw->is_prepared) { RIE (usb_high_scan_prepare (s->hw)); RIE (usb_high_scan_reset (s->hw)); } RIE (usb_high_scan_set_threshold (s->hw, 128)); RIE (usb_high_scan_embed_gamma (s->hw, NULL)); RIE (usb_high_scan_suggest_parameters (s->hw, dpi, x, y, width, height, color_mode)); RIE (usb_high_scan_setup_scan (s->hw, s->hw->scan_mode, s->hw->x_dpi, s->hw->y_dpi, 0, s->hw->x, s->hw->y, s->hw->width)); DBG (3, "sane_start: wanted: dpi=%d, x=%d, y=%d, width=%d, height=%d, " "scan_mode=%d\n", dpi, x, y, width, height, color_mode); DBG (3, "sane_start: got: x_dpi=%d, y_dpi=%d, x=%d, y=%d, width=%d, " "height=%d, scan_mode=%d\n", s->hw->x_dpi, s->hw->y_dpi, s->hw->x, s->hw->y, s->hw->width, s->hw->height, s->hw->scan_mode); s->scanning = SANE_TRUE; s->read_rows = s->hw->height; s->hw->line_switch = s->hw->height; s->hw->line_offset = 0; s->hw->scan_buffer_len = 0; DBG (5, "sane_start: exit\n"); return SANE_STATUS_GOOD; }
SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Mustek_Usb_Scanner *s = handle; SANE_Status status; SANE_Word cap; SANE_Int myinfo = 0; DBG (5, "sane_control_option: start: action = %s, option = %s (%d)\n", (action == SANE_ACTION_GET_VALUE) ? "get" : (action == SANE_ACTION_SET_VALUE) ? "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", s->opt[option].name, option); if (info) *info = 0; if (s->scanning) { DBG (1, "sane_control_option: don't call this function while " "scanning\n"); return SANE_STATUS_DEVICE_BUSY; } if (option >= NUM_OPTIONS || option < 0) { DBG (1, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", option); return SANE_STATUS_INVAL; } cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (2, "sane_control_option: option %d is inactive\n", option); return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_THRESHOLD: case OPT_CUSTOM_GAMMA: *(SANE_Word *) val = s->val[option].w; break; /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); break; /* string options: */ case OPT_MODE: strcpy (val, s->val[option].s); break; default: DBG (2, "sane_control_option: can't get unknown option %d\n", option); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (2, "sane_control_option: option %d is not settable\n", option); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (2, "sane_control_option: sanei_constrain_value returned %s\n", sane_strstatus (status)); return status; } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *) val; RIE (calc_parameters (s)); myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_THRESHOLD: s->val[option].w = *(SANE_Word *) val; break; /* Boolean */ case OPT_PREVIEW: s->val[option].w = *(SANE_Bool *) val; break; /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); check_gamma_table (s->val[option].wa); break; case OPT_CUSTOM_GAMMA: s->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; myinfo |= SANE_INFO_RELOAD_OPTIONS; if (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) { s->red_table = s->red_gamma_table; s->green_table = s->green_gamma_table; s->blue_table = s->blue_gamma_table; s->gray_table = s->gray_gamma_table; if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { s->red_table = s->linear_gamma_table; s->green_table = s->linear_gamma_table; s->blue_table = s->linear_gamma_table; s->gray_table = s->linear_gamma_table; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } break; case OPT_MODE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); RIE (calc_parameters (s)); s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0) { s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; break; default: DBG (2, "sane_control_option: can't set unknown option %d\n", option); } } else { DBG (2, "sane_control_option: unknown action %d for option %d\n", action, option); return SANE_STATUS_INVAL; } if (info) *info = myinfo; DBG (5, "sane_control_option: exit\n"); return SANE_STATUS_GOOD; }