The HP4470c is a USB/Parallel flatbed scanner. This scanner is based on the RealTek RTS8891 scanner chip. I havent been able to obtain the datasheets for this chip so far so the following document outlines observations made about the operations of the device by looking at the USB dumps produced by USBSnoop as well as reverse engineering (disassembly) of the windows drivers supplied by HP. General characteristics: The 4470c has one configuration (1) with a single interface (0), the interface in turn has 3 end points: ep: Type: Direction: 0x81 Bulk IN 0x02 Bulk Out 0x83 Interrupt ? This scanner does not use control pipes at all - all communications to the device occur using bulk mode. The device has 244 registers. These can be accesses one at the time or a whole sequence of registers may be accessed simultaneously. The general command sent over the bus has the following format: command register count [data optional] Both the command and register are 2 bytes. The count is two bytes big and is given with the most significant byte first. Commands: The following commands have been observed: 0x80: Read register: This command is issued with an OUT tranfer on ep 0x81. The count specifies how may bytes are required to be returned from the device. In order to actually read those the host needs to initiate a transfer for the required number of bytes for the IN direction: example: The following reads one register (25) to test the state of the buttons on the front of the device: > transfer type=bulk size=4 ep=0x02 dir=OUT > 80 25 00 01 > transfer type=bulk size=1 ep=0x81 dir=IN < 00 0x88: Set register: This command sets the register or group of registers specified. There is no need to read any data after issuing this command so only one transfer is required. It seems that the maximum packet size is 0xb4 registers to be set at once. So if you need to write all 0xf4 registers its necessary to split into two packets. 0x89: Write data to calibration. This command is used to write 2072 bytes of a sequntially increasing pattern to the scanner. used for calibration. 0x81: Read some calibration data. 0x90: (read 3 bytes. eg. 0x90 0x00 0x00 0x03) this command queries the buffer as to how many bytes are present for download during getting at image. Note that the maximum USB transfer size per request appears to be 0xffc0. 0x91: Read this many bytes from the scanner buffers. Maximum 0xffc0. example: The following resets the button state after reading it (above). > transfer type=bulk size=5 ep=0x02 dir=OUT > 88 25 00 01 00 Note that it seems to be possible to combine packets. Hence if we want to set a variable and immediately read another: > transfer type=bulk size=9 ep=0x02 dir=OUT > 88 da 00 01 a0 80 10 00 02 > transfer type=bulk size=2 ep=0x81 dir=IN < 68 1a Registers: The following registers have been identified: 0x00: This register is normally set to 0xf5, but before reading any actual image data it needs to be set to 0xe5 otherwise all data will be 0x90 (maybe its enabling the CCD?) 0x25: Returns the state of the front button panel. Each bit represents a button. If a button has been pressed, that bit is set. Note that the register will hold its value untill it has been explicitly cleared by being written to. This register only works if 0xb3 has the second bit set (0x04). button icon mask ----------- ---- power 0x80 scanner 0x40 www 0x20 copy 0x10 email 0x08 print 0x04 - 0x02 + 0x01 0x1a: Some more button registers like 0x25: button icon mask ----------- ---- Red triangle 0x01 spanner 0x02 colour 0x04 0x1d: Microswitch for scanner movement. When rewinding the software constantly checks for bit 2. If not touching reg is 0x20, when touching reg is 0x22. 0xb0: This register is called from the function RT_CheckScannerLinked. It seems to always return 0x80. Test for b3 to go from 08 to 00 when the scanner finished moving and is ready. 0xb2: Used for moving: 0xb3: Controls movement. The software seems to issue the sequence 02 00 08 to this register to start with movement. It then checks 08 to see if still moving. When the scanner stops moving it becomes 0. It is also possible to set it to 0 to stop the scanner. The register also need to be set to 0x04 before the button can be read. 0x84: The software reads 0xb (11) bytes from this register on. Disassembly shows that only the last byte is used with 0x60 mask. If not set the lamp needs warming, If set, lamp is ready 0x10: Controls little green LEDs for color selector (0x20 - color) (0x10- BW) bit 7 controls how many bits per color to produce. e.g. 0x20 1 bit per pixel, 0x28 2 bits per pixel 0x11: Controls which light source to use - bit 5 (e.g. 0x1b) on - slide light, off (e.g. 0x3b) - bed light, bit 3 is current movement status - set stopped, cleared moving. bit 6 - direction of movement: set forward, reset reverse. 0x12: 0x13: bit 1 if on- the resulting scan has a zero for each other pixel 0x14: size 2 bytes. 0xda: Controls lamp intensity 0xff is weakest and 0x00 is brightest. If the low nibble of 0xda is reset, than 0x11 resets its 3rd bit. Defaults to 15 0x20-0x22: Three bytes controlling LCD (below). 0x33: bit 8 controls weather to move or not 0x80 moves 0x00 does not. The lower nibble represents the speed - 0x01 is fastest. step size=16/nibble. Note that the number of steps to move is in 0x60-0x64. The actual distance depends on this step size. 0x35: 0x36: controls the direction of movement 0x24 reverse, 0x2c forward. Note that when rewinding the values in 0x60,0x62 are ignored, the scanner always goes back to the home postion and stops. Note that there are a number of step sizes: 0x2c is half the step size of 0x29 0x3a: scan or quick move- 1b scans and 0e moves quickly. 0xd0, 0xd1: signed chars black level and white level. These control the intensities at which (FIXME) 0xd6: 0xcf: 0xd9 turns on the lamp, with its MSB (Set to 0x80 for lamp on 0x00 for off). 0x60,0x62 (2 bytes each LSB first): movement position. This set of registers holds the required number of steps to move. For simple movements (like to reposition the scanner) 0x60 should be 1 less than 0x62. 0x65: scan control, must be 0x20 for scanning, 0x00 for just moving. 0x66 2 bytes: scan from this horizontal pixel. 0x6c 2 bytes: scan to this horizontal pixel. 0x93: vertical calibration goes here (number of lines to shift each color by) 0x91 2 bytes: horizontal calibration goes here 0xe2: Step size. This is multiplied by 0x60 to work out how far to move. Hunches: 0x44: resolution 0xd3: movement related ___ LCD ___: In order to set the numbers on the LCD: transfer type=bulk size=5 ep=0x02 dir=OUT 88 b3 00 01 00 transfer type=bulk size=5 ep=0x02 dir=OUT 88 da 00 01 a7 transfer type=bulk size=6 ep=0x02 dir=OUT 88 20 00 02 ef df Registers 0x20 and 0x21 control 7 bits each of the LCD. The 8'th bit of 0x21 enables/disables the entire display: Legend 0x20 76543210 0x21 HGFEDCBA (7 -enable) 5 2 |~~~~~~| |~~~~~~| 6| 0 |4 3| G |F |------| |------| 1| |D H| |B |______| |______| E C Initialization: Following is the initialization sequence. (to be completed) register 1d is read, anded with 0e0 and or with 20 e0 -> 0x94 scanning: