/* this functions reads button status */ static SANE_Status rts8891_read_buttons (SANE_Int devnum, SANE_Int * mask) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte reg; /* check CONTROL_REG */ sanei_rts88xx_read_reg (devnum, CONTROL_REG, ®); /* read 'base' button status */ sanei_rts88xx_read_reg (devnum, 0x25, ®); DBG (DBG_io, "rts8891_read_buttons: r25=0x%02x\n", reg); *mask |= reg; /* read 'extended' button status */ sanei_rts88xx_read_reg (devnum, 0x1a, ®); DBG (DBG_io, "rts8891_read_buttons: r1a=0x%02x\n", reg); *mask |= reg << 8; /* clear register r25 */ reg = 0x00; sanei_rts88xx_write_reg (devnum, 0x25, ®); /* clear register r1a */ sanei_rts88xx_read_reg (devnum, 0x1a, ®); reg = 0x00; status = sanei_rts88xx_write_reg (devnum, 0x1a, ®); DBG (DBG_info, "rts8891_read_buttons: mask=0x%04x\n", *mask); return status; }
/* * setup nvram */ SANE_Status sanei_rts88xx_setup_nvram (SANE_Int devnum, SANE_Int length, SANE_Byte * value) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte local[2], reg; int i; status = sanei_rts88xx_nvram_ctrl (devnum, length, value); #ifndef HAZARDOUS_EXPERIMENT return SANE_STATUS_GOOD; #endif if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_setup_nvram : failed step #1 ...\n"); return status; } local[0] = 0x18; local[1] = 0x08; for (i = 0; i < 8; i++) { status = sanei_rts88xx_nvram_ctrl (devnum, 2, local); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_setup_nvram : failed loop #%d ...\n", i); return status; } status = sanei_rts88xx_read_reg (devnum, 0x10, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_setup_nvram : register reading failed loop #%d ...\n", i); return status; } DBG (DBG_io, "sanei_rts88xx_setup_nvram: reg[0x10]=0x%02x\n", reg); } reg = 0; status = sanei_rts88xx_write_reg (devnum, CONTROLER_REG, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_setup_nvram : controler register write failed\n"); return status; } reg = 1; status = sanei_rts88xx_write_reg (devnum, CONTROLER_REG, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_setup_nvram : controler register write failed\n"); return status; } return status; }
/* * write to special control register CONTROL_REG=0xb3 */ SANE_Status sanei_rts88xx_write_control (SANE_Int devnum, SANE_Byte value) { SANE_Status status; status = sanei_rts88xx_write_reg (devnum, CONTROL_REG, &value); return status; }
/** * wait for the scanning head to reach home position */ static SANE_Status rts8891_wait_for_home (struct Rts8891_Device *device, SANE_Byte * regs) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte motor, sensor, reg; DBG (DBG_proc, "rts8891_wait_for_home: start\n"); /* wait for controller home bit to raise, no timeout */ /* at each loop we check that motor is on, then that the sensor bit it cleared */ do { sanei_rts88xx_read_reg (device->devnum, CONTROL_REG, &motor); sanei_rts88xx_read_reg (device->devnum, CONTROLER_REG, &sensor); } while ((motor & 0x08) && ((sensor & 0x02) == 0)); /* flag that device has finished parking */ device->parking=SANE_FALSE; /* check for error */ if (((motor & 0x08) == 0x00) && ((sensor & 0x02) == 0)) { DBG (DBG_error, "rts8891_wait_for_home: error, motor stopped before head parked\n"); status = SANE_STATUS_INVAL; } /* re-enable CCD */ regs[0] = regs[0] & 0xef; sanei_rts88xx_cancel (device->devnum); /* reset ? so we don't need to read data */ reg = 0; /* b7: movement on/off, b3-b0 : movement divisor */ sanei_rts88xx_write_reg (device->devnum, 0x33, ®); sanei_rts88xx_write_reg (device->devnum, 0x33, ®); /* movement direction */ sanei_rts88xx_write_reg (device->devnum, 0x36, ®); sanei_rts88xx_cancel (device->devnum); DBG (DBG_proc, "rts8891_wait_for_home: end\n"); return status; }
/* this functions "commits" pending scan command */ static SANE_Status rts8891_commit (SANE_Int devnum, SANE_Byte value) { SANE_Status status; SANE_Byte reg; reg = value; sanei_rts88xx_write_reg (devnum, 0xd3, ®); sanei_rts88xx_cancel (devnum); sanei_rts88xx_write_control (devnum, 0x08); status = sanei_rts88xx_write_control (devnum, 0x08); return status; }
/* 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; }
/* resets lamp */ SANE_Status sanei_rts88xx_reset_lamp (SANE_Int devnum, SANE_Byte * regs) { SANE_Status status; SANE_Byte reg; /* read the 0xda register, then clear lower nibble and write it back */ status = sanei_rts88xx_read_reg (devnum, 0xda, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to read 0xda register\n"); return status; } reg = 0xa0; status = sanei_rts88xx_write_reg (devnum, 0xda, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to write 0xda register\n"); return status; } /* on cleared, get status */ status = sanei_rts88xx_get_status (devnum, regs); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to get status\n"); return status; } DBG (DBG_io, "sanei_rts88xx_reset_lamp: status=0x%02x 0x%02x\n", regs[0x10], regs[0x11]); /* set low nibble to 7 and write it */ reg = reg | 0x07; status = sanei_rts88xx_write_reg (devnum, 0xda, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to write 0xda register\n"); return status; } status = sanei_rts88xx_read_reg (devnum, 0xda, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to read 0xda register\n"); return status; } if (reg != 0xa7) { DBG (DBG_warn, "sanei_rts88xx_reset_lamp: expected reg[0xda]=0xa7, got 0x%02x\n", reg); } /* store read value in shadow register */ regs[0xda] = reg; return status; }