/* * Wait until the scanner is ready. */ static SANE_Status leo_wait_scanner (Leo_Scanner * dev) { SANE_Status status; int timeout; CDB cdb; DBG (DBG_proc, "leo_wait_scanner: enter\n"); MKSCSI_TEST_UNIT_READY (cdb); /* Set the timeout to 60 seconds. */ timeout = 60; while (timeout > 0) { /* test unit ready */ status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); if (status == SANE_STATUS_GOOD) { return SANE_STATUS_GOOD; } sleep (1); }; DBG (DBG_proc, "leo_wait_scanner: scanner not ready\n"); return (SANE_STATUS_IO_ERROR); }
/* Return the number of byte that can be read. */ static SANE_Status get_filled_data_length (Leo_Scanner * dev, size_t * to_read) { size_t size; CDB cdb; SANE_Status status; DBG (DBG_proc, "get_filled_data_length: enter\n"); *to_read = 0; size = 0x10; MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (size != 0x10) { DBG (DBG_error, "get_filled_data_length: GET DATA BUFFER STATUS returned an invalid size (%ld)\n", (long) size); return SANE_STATUS_IO_ERROR; } hexdump (DBG_info2, "get_filled_data_length return", dev->buffer, size); *to_read = B24TOI (&dev->buffer[9]); DBG (DBG_info, "get_filled_data_length: to read = %ld\n", (long) *to_read); DBG (DBG_proc, "get_filled_data_length: exit, status=%d\n", status); return (status); }
/* Read the size of the scan. */ static SANE_Status leo_get_scan_size (Leo_Scanner * dev) { size_t size; CDB cdb; SANE_Status status; DBG (DBG_proc, "leo_get_scan_size: enter\n"); size = 0x10; MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (size != 0x10) { DBG (DBG_error, "leo_get_scan_size: GET DATA BUFFER STATUS returned an invalid size (%ld)\n", (long) size); return SANE_STATUS_IO_ERROR; } hexdump (DBG_info2, "leo_get_scan_size return", dev->buffer, size); dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); /* The number of lines if the number of lines left plus the number * of lines already waiting in the buffer. */ dev->params.lines = B16TOI (&dev->buffer[12]) + (B24TOI (&dev->buffer[9]) / dev->params.bytes_per_line); switch (dev->scan_mode) { case LEO_BW: case LEO_HALFTONE: dev->params.pixels_per_line &= ~0x7; dev->params.bytes_per_line = dev->params.pixels_per_line / 8; break; case LEO_GRAYSCALE: dev->params.bytes_per_line = dev->params.pixels_per_line; break; case LEO_COLOR: dev->params.bytes_per_line = dev->params.pixels_per_line * 3; break; } DBG (DBG_proc, "leo_get_scan_size: exit, status=%d\n", status); DBG (DBG_proc, "lines=%d, bpl=%d\n", dev->params.lines, dev->params.bytes_per_line); return (status); }
/* Start a scan. */ static SANE_Status leo_scan (Leo_Scanner * dev) { CDB cdb; SANE_Status status; DBG (DBG_proc, "leo_scan: enter\n"); MKSCSI_SCAN (cdb); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "leo_scan: exit, status=%d\n", status); return status; }
int sanei_epson_scsi_write (int fd, const void *buf, size_t buf_size, SANE_Status * status) { u_char *cmd; cmd = t_alloca (8 + buf_size, u_char); memset (cmd, 0, 8); cmd[0] = WRITE_6_COMMAND; cmd[2] = buf_size >> 16; cmd[3] = buf_size >> 8; cmd[4] = buf_size; memcpy (cmd + 8, buf, buf_size); if (SANE_STATUS_GOOD == (*status = sanei_scsi_cmd2 (fd, cmd, 6, cmd + 8, buf_size, NULL, NULL))) return buf_size; return 0; }
/* Send the halftone pattern */ static SANE_Status leo_send_halftone_pattern (Leo_Scanner * dev) { int i; const halftone_pattern_t *pattern; SANE_Status status; size_t size; CDB cdb; DBG (DBG_proc, "leo_send_halftone_pattern: enter\n"); if (dev->scan_mode == LEO_HALFTONE) { i = get_string_list_index (halftone_pattern_list, dev->val[OPT_HALFTONE_PATTERN].s); pattern = halftone_pattern_val[i]; assert (pattern != NULL); size = sizeof (halftone_pattern_t); assert (size == 256); MKSCSI_SEND_10 (cdb, 0x02, 0x0F, size); hexdump (DBG_info2, "leo_send_gamma:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, pattern, size, NULL, NULL); } else { status = SANE_STATUS_GOOD; } DBG (DBG_proc, "leo_send_halftone_pattern: exit, status=%d\n", status); return status; }
/* Read the image from the scanner and fill the temporary buffer with it. */ static SANE_Status leo_fill_image (Leo_Scanner * dev) { SANE_Status status; size_t size; CDB cdb; unsigned char *image; DBG (DBG_proc, "leo_fill_image: enter\n"); assert (dev->image_begin == dev->image_end); assert (dev->real_bytes_left > 0); dev->image_begin = 0; dev->image_end = 0; while (dev->real_bytes_left) { /* * Try to read the maximum number of bytes. */ size = 0; while (size == 0) { status = get_filled_data_length (dev, &size); if (status) return (status); if (size == 0) usleep (100000); /* sleep 1/10th of second */ } if (size > dev->real_bytes_left) size = dev->real_bytes_left; if (size > dev->image_size - dev->image_end) size = dev->image_size - dev->image_end; /* The scanner seems to hang if more than 32KB are read. */ if (size > 0x7fff) size = 0x7fff; /* Always read a multiple of a line. */ size = size - (size % dev->params.bytes_per_line); if (size == 0) { /* Probably reached the end of the buffer. * Check, just in case. */ assert (dev->image_end != 0); return (SANE_STATUS_GOOD); } DBG (DBG_info, "leo_fill_image: to read = %ld bytes (bpl=%d)\n", (long) size, dev->params.bytes_per_line); MKSCSI_READ_10 (cdb, 0, 0, size); hexdump (DBG_info2, "leo_fill_image: READ_10 CDB", cdb.data, 10); image = dev->image + dev->image_end; status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, image, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "leo_fill_image: cannot read from the scanner\n"); return status; } /* Some format conversion. */ if (dev->scan_mode == LEO_COLOR) { /* Reorder the lines. The scanner gives color by color for * each line. */ unsigned char *src = image; int nb_lines = size / dev->params.bytes_per_line; int i, j; for (i = 0; i < nb_lines; i++) { unsigned char *dest = dev->buffer; for (j = 0; j < dev->params.pixels_per_line; j++) { *dest = src[j + 0 * dev->params.pixels_per_line]; dest++; *dest = src[j + 1 * dev->params.pixels_per_line]; dest++; *dest = src[j + 2 * dev->params.pixels_per_line]; dest++; } /* Copy the line back. */ memcpy (src, dev->buffer, dev->params.bytes_per_line); src += dev->params.bytes_per_line; } } dev->image_end += size; dev->real_bytes_left -= size; DBG (DBG_info, "leo_fill_image: real bytes left = %ld\n", (long) dev->real_bytes_left); } return (SANE_STATUS_GOOD); /* unreachable */ }
/* Set a window. */ static SANE_Status leo_set_window (Leo_Scanner * dev) { size_t size; CDB cdb; unsigned char window[48]; SANE_Status status; DBG (DBG_proc, "leo_set_window: enter\n"); size = sizeof (window); MKSCSI_SET_WINDOW (cdb, size); memset (window, 0, size); /* size of the windows descriptor block */ window[7] = sizeof (window) - 8; window[1] = sizeof (window) - 2; /* X and Y resolution */ Ito16 (dev->x_resolution, &window[10]); Ito16 (dev->y_resolution, &window[12]); /* Upper Left (X,Y) */ Ito32 (dev->x_tl, &window[14]); Ito32 (dev->y_tl, &window[18]); /* Width and length */ Ito32 (dev->width, &window[22]); Ito32 (dev->length, &window[26]); /* Image Composition */ switch (dev->scan_mode) { case LEO_BW: window[33] = 0x00; break; case LEO_HALFTONE: window[33] = 0x01; break; case LEO_GRAYSCALE: window[33] = 0x02; break; case LEO_COLOR: window[33] = 0x05; break; } /* Depth */ window[34] = dev->depth; /* Unknown - invariants */ window[31] = 0x80; window[43] = 0x01; hexdump (DBG_info2, "windows", window, sizeof (window)); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, window, sizeof (window), NULL, NULL); DBG (DBG_proc, "leo_set_window: exit, status=%d\n", status); return status; }
/* Inquiry a device and returns TRUE if is supported. */ static int leo_identify_scanner (Leo_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; int i; DBG (DBG_proc, "leo_identify_scanner: enter\n"); size = 5; MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "leo_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } size = dev->buffer[4] + 5; /* total length of the inquiry data */ if (size < 36) { DBG (DBG_error, "leo_identify_scanner: not enough data to identify device\n"); return (SANE_FALSE); } MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "leo_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } dev->scsi_type = dev->buffer[0] & 0x1f; memcpy (dev->scsi_vendor, dev->buffer + 0x08, 0x08); dev->scsi_vendor[0x08] = 0; memcpy (dev->scsi_product, dev->buffer + 0x10, 0x010); dev->scsi_product[0x10] = 0; memcpy (dev->scsi_version, dev->buffer + 0x20, 0x04); dev->scsi_version[0x04] = 0; DBG (DBG_info, "device is \"%s\" \"%s\" \"%s\"\n", dev->scsi_vendor, dev->scsi_product, dev->scsi_version); /* Lookup through the supported scanners table to find if this * backend supports that one. */ for (i = 0; i < NELEMS (scanners); i++) { if (dev->scsi_type == scanners[i].scsi_type && strcmp (dev->scsi_vendor, scanners[i].scsi_vendor) == 0 && strcmp (dev->scsi_product, scanners[i].scsi_product) == 0) { DBG (DBG_error, "leo_identify_scanner: scanner supported\n"); /* Get the full inquiry, since that scanner does not fill the length correctly. */ size = 0x30; MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status != SANE_STATUS_GOOD) { return (SANE_FALSE); } hexdump (DBG_info2, "inquiry", dev->buffer, size); dev->def = &(scanners[i]); dev->res_range.min = 1; dev->res_range.max = B16TOI (&dev->buffer[42]); dev->x_resolution_max = B16TOI (&dev->buffer[40]); dev->y_resolution_max = B16TOI (&dev->buffer[42]); return (SANE_TRUE); } } DBG (DBG_proc, "leo_identify_scanner: exit, device not supported\n"); return (SANE_FALSE); }
/* Send the gamma */ static SANE_Status leo_send_gamma (Leo_Scanner * dev) { CDB cdb; SANE_Status status; struct { unsigned char gamma_R[GAMMA_LENGTH]; unsigned char gamma_G[GAMMA_LENGTH]; /* also gray */ unsigned char gamma_B[GAMMA_LENGTH]; } param; size_t i; size_t size; DBG (DBG_proc, "leo_send_gamma: enter\n"); size = sizeof (param); assert (size == 3 * GAMMA_LENGTH); MKSCSI_SEND_10 (cdb, 0x03, 0x01, size); if (dev->val[OPT_CUSTOM_GAMMA].w) { /* Use the custom gamma. */ if (dev->scan_mode == LEO_GRAYSCALE) { /* Gray */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = dev->gamma_GRAY[i]; param.gamma_G[i] = 0; param.gamma_B[i] = 0; } } else { /* Color */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = dev->gamma_R[i]; param.gamma_G[i] = dev->gamma_G[i]; param.gamma_B[i] = dev->gamma_B[i]; } } } else { for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = gamma_init[i]; param.gamma_G[i] = gamma_init[i]; param.gamma_B[i] = gamma_init[i]; } } hexdump (DBG_info2, "leo_send_gamma:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, ¶m, size, NULL, NULL); DBG (DBG_proc, "leo_send_gamma: exit, status=%d\n", status); return (status); }