(main page) Last update Sunday, September 30, 2001, Bertrik Sikken
(Removed links to some USB logs)



This page describes my interpretation of the USB transfer protocol used by the HP3300C color scanner.

The HP3300C seems to be a parallel port scanner internally. Low level accesses to the parallel port registers are wrapped into USB control packets of type URB_FUNCTION_VENDOR_DEVICE. Image data and gamma/gain/offset tables are transferred using USB bulk transfers.

USB control transfers

USB control transfers are used to write a register of the parallel port inside the HP3300c.
The transfer consists of a standard 8-byte 'setup packet' plus 1 byte data, looking like this for example:

40RequestTypeReservedBitsVendor type request, 40 = PC-to-scanner, C0 = Scanner-to-PC
0cRequest0C when 1 byte is transferred, 04 when more bytes are transferred
0088ValueParallel port register code, see table below
0d74IndexDoes not seem important. In my test program a value of 0 works OK.
0001TransferBufferLengthLength of additional data, always 1 for simple packets
90DataData transferred from or to register

In this particular case register 0x88 (SPP data port) was written with 0x90.

Parallel port register codes

In the setup packet, the fields Value and Data contain the parallel port register and the data to be written to it respectively.

The parallel port register codes are shown in the table below:
CodeParallel port
0x82USB bulk transfer setup
0x83EPP address
0x84EPP data for reading
0x85EPP data for writing
0x86SPP status
0x87SPP control
0x88SPP data
0x89??? (GLGpioOE, output enable?)
0x8A??? (GLGpioRead)
0x8B??? (GLGpioWrite)

This looks very similar (if not identical) to the implementation in the sources of the E3 chipset scanner backend here.

Poll for buttons pressed

A good example of the way several of the transfers shown above are combined to actually do something, is an analysis of the button poll sequence. The button poll takes place about once a second (if device events are enabled in the settings/control panel).

See poll.log (20k). In this log two polls are done (the first starts at 00000000, the second at 99185520). I had just pressed one of the buttons on the front of the scanner, so you can also see a difference between the first and second poll.

0x14SPP controlNeeded to be able to output to the parallel port
0x2EEPP addressEPP Address to write to
0x14SPP controlInit the parallel port again for output
0x34SPP controlFlip the direction bit for input
[data]EPP dataRead data from the address just set
0x14SPP controlInit the parallel port again for output

It turns out that when none of the buttons on the front has been pressed, [data] contains 0x00. When the left button was pressed, it contains 0x04 (bit 2). When the right button was pressed, it contains 0x10 (bit 4).

USB bulk transfers

USB bulk transfers are used for reading image data and for writing the gamma/gain/offset tables.
They are always preceded by a control transfer specifying the type of bulk transfer and the number of bytes to be transferred. This control transfer has its 'value' field set to 0x82 and it contains 8 additional data bytes. The first four bytes seem to indicate the type of transfer. The last four bytes indicate the length of the following bulk transfer.

The table below summarises the types of transfers and the corresponding 8-byte setup packet:
Transfer typeBufferRemark
UsbReadScanner00 00 XX 00 [4-byte length]XX is some variable value, usually 0
UsbReadScannerLines00 00 00 00 00 0C XX 00This command seems a bit odd compared to the others
UsbReadScannerFastXX 04 YY XX [4-byte length]???
UsbWriteScanner01 00 XX 00 [4-byte length] The HP3300 uses this command to write the gamma and gain/offset tables. XX is some variable value, usually 0
UsbWriteScannerFw01 01 00 00 [4-byte length] The HP3400 uses this command to write the gamma and gain/offset tables.
UsbWriteScannerAD01 11 00 00 [4-byte length]???

The first byte indicates a read or a write (01 is a write).
In the USB log I see only packets with the first four bytes set either to {0x00, 0x00, 0x00, 0x00} or {0x01 0x00, 0x00, 0x00), corresponding to simple UsbReadScanner and UsbWriteScanners transfers respectively.

Another thing to note is that scanner register 0x24 is always selected just before any bulk transfer. This register thus seems to be the data transfer register.


Plugging scanner into USB

See plugin.log (73k).
The scanner apparently supports three 'endpoints': Further, just after the pipe-info, we see the following: