/** * Waits for data being available while optionally polling motor. There is a timeout * to prevent scanner waiting forever non coming data. */ SANE_Status sanei_rts88xx_wait_data (SANE_Int devnum, SANE_Bool busy, SANE_Word * count) { SANE_Status status; SANE_Byte control; /* poll the available byte count until not 0 */ while (SANE_TRUE) { status = sanei_rts88xx_data_count (devnum, count); if (*count != 0) { DBG (DBG_io, "sanei_rts88xx_wait_data: %d bytes available\n", *count); return SANE_STATUS_GOOD; } /* check that the scanner is busy scanning */ if (busy) { sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); if ((control & 0x08) == 0 && (*count == 0)) { DBG (DBG_error, "sanei_rts88xx_wait_data: scanner stopped being busy before data are available\n"); return SANE_STATUS_IO_ERROR; } } } /* we hit timeout */ return SANE_STATUS_IO_ERROR; }
/* reads data from scanner. * First we wait for some data to be available and then loop reading * from scanner until the required amount is reached. * We handle non blocking I/O by returning immediatly (with SANE_STATUS_BUSY) * if there is no data available from scanner. But once read is started, * all the required amount is read. Once wait for data succeeded, we still poll * for data in order no to read it too fast, but we don' take care of non blocking * mode since we cope with it on first data wait. */ static SANE_Status read_data (struct Rts8891_Session *session, SANE_Byte * dest, SANE_Int length) { SANE_Status status = SANE_STATUS_GOOD; SANE_Int count, read, len, dummy; struct Rts8891_Device *dev = session->dev; static FILE *raw = NULL; /* for debugging purpose we need it static */ SANE_Byte control = 0x08; unsigned char buffer[RTS88XX_MAX_XFER_SIZE]; DBG (DBG_proc, "read_data: start\n"); DBG (DBG_proc, "read_data: requiring %d bytes\n", length); /* wait for data being available and handle non blocking mode */ /* only when data reading hasn't produce any data yet */ if (dev->read == 0) { do { status = sanei_rts88xx_data_count (dev->devnum, &count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_data: failed to wait for data\n"); return status; } if (count == 0) { sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if ((control & 0x08) == 0 && (count == 0)) { DBG (DBG_error, "read_data: scanner stopped being busy before data are available\n"); return SANE_STATUS_IO_ERROR; } } /* in case there is no data, we return BUSY since this mean */ /* that scanning head hasn't reach is position and data hasn't */ /* come yet */ if (session->non_blocking && count == 0) { dev->regs[LAMP_REG] = 0x8d; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); DBG (DBG_io, "read_data: no data vailable\n"); DBG (DBG_proc, "read_data: end\n"); return SANE_STATUS_DEVICE_BUSY; } } while (count == 0); } else { /* start of read for a new block */ status = sanei_rts88xx_data_count (dev->devnum, &count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_data: failed to wait for data\n"); return status; } if (count == 0) { sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if ((control & 0x08) == 0 && (count == 0)) { DBG (DBG_error, "read_data: scanner stopped being busy before data are available\n"); return SANE_STATUS_IO_ERROR; } } } /* fill scanned data buffer */ read = 0; /* now loop reading data until we have the amount requested */ /* we also take care of not reading too much data */ while (read < length && dev->read < dev->to_read && ((control & 0x08) == 0x08)) { /* used to sync */ if (dev->read == 0) { status = sanei_rts88xx_data_count (dev->devnum, &dummy); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_data: failed to read data count\n"); return status; } } /* if there is data to read, read it */ if (count > 0) { len = count; if (len > RTS88XX_MAX_XFER_SIZE) { len = RTS88XX_MAX_XFER_SIZE; } /* we only read even size blocks of data */ if (len & 1) { DBG (DBG_io, "read_data: round to next even number\n"); len++; } if (len > length - read) { len = length - read; } status = sanei_rts88xx_read_data (dev->devnum, &len, dest + read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_data: failed to read from scanner\n"); return status; } /* raw data tracing */ if (DBG_LEVEL >= DBG_io2) { /* open a new file only when no data scanned */ if (dev->read == 0) { raw = fopen ("raw_data.pnm", "wb"); if (raw != NULL) { /* PNM header */ fprintf (raw, "P%c\n%d %d\n255\n", session->params.format == SANE_FRAME_RGB || session->emulated_gray == SANE_TRUE ? '6' : '5', dev->pixels, dev->lines); } } if (raw != NULL) { fwrite (dest + read, 1, len, raw); } } /* move pointer and counter */ read += len; dev->read += len; DBG (DBG_io2, "read_data: %d/%d\n", dev->read, dev->to_read); } /* in fast scan mode, read data count * in slow scan, head moves by the amount of data read */ status = sanei_rts88xx_data_count (dev->devnum, &count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_data: failed to read data count\n"); return status; } /* if no data, check if still scanning */ if (count == 0 && dev->read < dev->to_read) { sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if ((control & 0x08) == 0x00) { DBG (DBG_error, "read_data: scanner stopped being busy before data are available\n"); return SANE_STATUS_IO_ERROR; } } } /* end of physical reads */ if (dev->read >= dev->to_read) { /* check there is no more data in case of a bug */ sanei_rts88xx_data_count (dev->devnum, &count); if (count > 0) { DBG (DBG_warn, "read_data: %d bytes are still available from scanner\n", count); /* flush left-over data */ while (count > 0) { len = count; if (len > RTS88XX_MAX_XFER_SIZE) { len = RTS88XX_MAX_XFER_SIZE; } /* we only read even size blocks of data */ if (len & 1) { len++; } sanei_rts88xx_read_data (dev->devnum, &len, buffer); sanei_rts88xx_data_count (dev->devnum, &count); } } /* wait for motor to stop at the end of the scan */ do { sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); } while ((control & 0x08) != 0); /* close log file if needed */ if (DBG_LEVEL >= DBG_io2) { if (raw != NULL) { fclose (raw); raw = NULL; } } } DBG (DBG_io, "read_data: read %d bytes from scanner\n", length); DBG (DBG_proc, "read_data: end\n"); return status; }
/* * Does a simple scan based on the given register set, returning data in a * preallocated buffer of the claimed size. * sanei_rts88xx_data_count cannot be made reliable, when the announced data * amount is read, it may no be ready, leading to errors. To work around * it, we read data count one more time before reading. */ static SANE_Status rts8891_simple_scan (SANE_Int devnum, SANE_Byte * regs, int regcount, SANE_Int format, SANE_Word total, unsigned char *image) { SANE_Word count, read, len, dummy; SANE_Status status = SANE_STATUS_GOOD; SANE_Byte control; rts8891_write_all (devnum, regs, regcount); rts8891_commit (devnum, format); read = 0; count = 0; while (count == 0) { status = sanei_rts88xx_data_count (devnum, &count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "simple_scan: failed to wait for data\n"); return status; } if (count == 0) { status = sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); if (((control & 0x08) == 0) || (status != SANE_STATUS_GOOD)) { DBG (DBG_error, "simple_scan: failed to wait for data\n"); return SANE_STATUS_IO_ERROR; } } } /* data reading */ read = 0; while ((read < total) && (count != 0 || (control & 0x08) == 0x08)) { /* sync ? */ status = sanei_rts88xx_data_count (devnum, &dummy); /* read */ if (count > 0) { len = count; /* read even size unless last chunk */ if ((len & 1) && (read + len < total)) { len++; } if (len > RTS88XX_MAX_XFER_SIZE) { len = RTS88XX_MAX_XFER_SIZE; } if (len > 0) { status = sanei_rts88xx_read_data (devnum, &len, image + read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "simple_scan: failed to read from scanner\n"); return status; } read += len; } } /* don't try to read data count if we have enough data */ if (read < total) { status = sanei_rts88xx_data_count (devnum, &count); } else { count = 0; } if (count == 0) { sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); } } /* sanity check */ if (read < total) { DBG (DBG_io2, "simple_scan: ERROR, %d bytes missing ... \n", total - read); } /* wait for the motor to stop */ do { sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); } while ((control & 0x08) == 0x08); return status; }