
$Id: protocol-info.txt 1651 2007-09-03 01:37:06Z isely $

Mike Isely <isely@pobox.com>

Note: Unless otherwise specified, offsets and addresses below are all
written in hex.

		    Encoder communication protocol

The most significant part of the pvrusb2 device is the Conexant
CX23416 mpeg-2 encoder chip.  Unfortunately its operation is shrouded
in mystery due to the fact that there is no datasheet freely available
for it (and this in fact appears to be the entire reason for the
existence of the ivtv driver - the author wanted to reverse-engineer
that chip).  What I do know about this part comes from examining what
Aurelien had coded previously here and from examining how the ivtv
driver interacts with the chip.

Unlike the ivtv driver, the pvrusb2 driver interacts indirectly with
the CX23416.  The ivtv driver has the luxury of directly manipulating
the encoder's registers through PCI bus cycles, while we instead have
to proxy everything over USB through the 8051 within the pvrusb2
device.  Thus for the pvrusb2 driver, there are really two levels of
interaction: Manipulation of the encoder's registers, and manipulation
of the 8051 via USB to cause that manipulation of the encoder's
registers.  Described right here is the actual encoder register
manipulation (which is the same as for ivtv).  To understand exactly
how that is proxied over USB (the second level of interaction), see
the next section below about USB Endpoint #1 command codes,
specifically looking at commands 01, 02, 04, 05, and 28.

The interface between the CX23416 encoder and the outside world seems
to be entirely based on reading / writing a 32 bit register space
implemented by the encoder.  The ivtv driver maps blocks of these
registers as "mailboxes", and can exchange information with the
encoder through multiple mailboxes at a time.  In the case of the
pvrusb2 device, there is only effectively a single mailbox ever used
at offset 0x44 in the encoder's memory, and we do all commands through
that single point.

Within that single mailbox, specific 32 bit register offsets have
specific meanings.  This is true in ivtv and true here as well.  The
meanings are:

    +00   : flag word
    +01   : command code
    +02   : return value (apparently, we don't use this right now)
    +03   : timeout
    +04-0f: up to 12 words of arguments

We execute commands to the encoder purely by reading / writing the
registers which form the mailbox.  The handshake sequence works like
this:

  Step #1: Write out the command code, timeout, and up to 12
  command-related arguments into appropriate mailbox offset locations.

  Step #2: Write the bit pattern 0x03 ("driver done" | "driver busy")
  into the flags word.

  Step #3: Poll the flag word, watching for the pattern 0x7 ("firmware
  done" or'ed into the mask).  Until bit d2 is set, the encoder is
  still working on the command.

  Step #4: Read back all 16 words.  These usually should match what we
  put there, though I've empirically seen some changes happen (which
  get logged) which I don't yet understand.

  Step #5: Write a zero into the flag word.

The known command codes are defined in in cx2341x.h (found in v4l-dvb
or in the ivtv directory of a driver snapshot).  The known flag bits
for the flag word are defined in pvrusb2-encoder.c with the
IVTV_MBOX_xxxx macro definitions.  As you might expect, these comes
straight out of ivtv.

Normally step #3 only takes 1 or maybe 2 polls.  However I've seen
cases where the encoder apparently loses its mind and we poll here
forever.  When this happens, it's possible to recover by reloading the
encoder's firmware (yuck).  The current implementation of the pvrusb2
driver implements this recovery.

Currently the pvrusb2 driver is setting a constant value for the
"timeout" - which happens to match what the Windows driver mostly
does, but the ivtv driver seems to be more creative about setting that
value.

It is important to emphasize here that this level of communication
with the encoder is essentially IDENTICAL to what happens in ivtv -
it's just a question of manipulating word locations within a mailbox
to effect a transaction with the encoder.  With ivtv, there are
multiple mailboxes possible, with the pvrusb2 hardware there appears
to only be a single mailbox.

In the next section about "USB Endpoint #1 command codes", the
following command codes are used to implement communication with the
mailbox:

  01 - Encoder Memory Write - This command is used to write to a range
       of mailbox offsets.

  02 - Encoder Memory Read - This command is used to read back the
       flag word at any time.

  28 - Encoder Memory Block Read - This command is used to read back
       the complete contents of the entire mailbox.

In addition to this "high level" mailbox communication, there are
miscellaneous other registers which can be read / written to the
encoder.  The pvrusb2 driver uses these other registers mostly to
control GPIO signals and to initially configure the encoder as part of
the firmware download process.  The pvrusb2 hardware provides two
additional command codes for this: code 04 which writes to a register,
and code 05 which reads from a register.


		    USB Endpoint #1 command codes

Basic communication with the pvrusb2 hardware happens over USB
endpoints 0x01 (driver -> hardware) and 0x81 (hardware -> driver).
Packets are a maximum of 64 bytes in either direction.  The first byte
of any packet going from the driver to the hardware is always a
command code; successive bytes in that packet are defined by the
command in question.  There are about 30 or so commands that the
device understands.  The following is a list of those command codes
that the 8051 (within the device) recognizes, along with notes about
each command, to the best of my knowledge:

01 - Encoder Memory Write

  This is used to write data to the encoder's memory.  This command
  makes it possible to efficiently write to multiple locations.  The
  format is somewhat non-intuitive:

    +00   : 01
    +01-04: <32 bit little-endian word>
    +05-07: <target address for word, big-endian>

  The last 7 bytes can be repeated (packed, no padding) to write out
  multiple words.  Typically this command will be used to write 8
  words at a time, thus the entire packet size is 57 bytes (there's a
  hardware limit of 64 bytes per packet, which is probably why only 8
  words are sent at a time).  To write out more than 8 words, multiple
  of these commands are sent, with the offsets adjusted appropriately.

  The communications mailbox used by the pvrusb2 driver is at offset
  0x44 in the memory space of the encoder.

  There are no bytes to read back.


02 - Encoder Memory Read

  This is used to read back a word of encoder memory.  The format is
  similar to command code (01), except this command returns data.  The
  expected packet format is:

    +00   : 02
    +01-04: 00000000
    +05-07: <target address to read, big-endian>

  The data returned will be exactly 4 bytes, the little-endian
  contents of the target word.

  The communications mailbox used by the pvrusb2 driver is at offset
  0x44 in the memory space of the encoder.  The first word of that
  mailbox is a flag register, and this command is used to poll that
  word.


04 - Write 32 bit encoder register

  This commmand writes a single word of encoder memory.  The expected
  packet format is:

    +00   : 04
    +01-04: <32 bit little-endian register value>
    +05   : XX
    +06-07: <16 bit big-endian target address>

  There is no return value.


05 - Read 32 bit encoder register

  This is the counterpart to the "Write 32 bit register" (04)
  command.  The expected packet format is:

    +00   : 05
    +01-05: XX
    +06-07: <16 bit big-endian target address>

  Expect 4 bytes in return, which will be the register value in
  little-endian form.


06 - Memory Select

  This command takes a single byte argument and passes directly out to
  the encoder (same pathway as the register read / write gunk).  This
  appears to be part of firmware download preparation.  The expected
  packet format is:

    +00   : 06
    +01   : <arg>

  There are no return bytes.

  The windows driver seems to always send zero for the argument.


08 - I2C write

  This is the main way to send arbitrary blocks of I2C data to a chip
  in the device.  The expected packet format is:

    +00   : 08
    +01   : <i2c addr>
    +02   : <length>
    +03...: {data}

  Expect 1 byte as a return code, whose value will be 08 for
  success, or 06 (bus error) or 07 (no ack) for failure.  I believe a
  bus error should only happen in a multi-master I2C bus, and the "no
  ack" case should only happen if no I2C device responds to the I/O.


09 - I2C write followed by read

  This is the main way to perform a full I2C transaction to a chip in
  the device.  The transaction is composed of a write of some number
  of bytes followed by a read of some number of bytes, using an I2C
  restart sequence so that the operation is atomic.  The expected
  packet format is:

    +00   : 09
    +01   : <write length>
    +02   : <read length>
    +03   : <i2c addr>
    +04...: {write data}

  The first byte returned is a return code for the transaction, whose
  value follows the same pattern as the I2C write (08) command.
  Successive bytes will be the requested data for the read portion of
  the transaction.  It appears to be OK to use a write length of zero,
  thus degenerating the command into a pure read.


0A - Mysterious setup

  The windows driver does not seem to use this command.

  This command takes three mystery bytes and write them to 3 fixed
  locations in 8051 memory.  The expected packet format is:

    +00   : 0A
    +01   : <mystery byte 1>
    +02   : <mystery byte 2>
    +03   : <mystery byte 3>

  These bytes are used apparently by the EA command and nothing else.

  The FX2 firmware for 24xxx devices don't seem to implement this
  command.


0B - Hi speed mode report

  This command reports whether or not the device is operating in USB
  2.0 high speed mode.  There are no extra bytes to send.  The return
  value will be zero if the device is not in high speed mode, or 80 if
  it is.


0C - I2C batch write (multiple write to same target)

  This command is similar to the I2C write (08) command, except it's
  possible here to specify multiple writes in a single command.  All
  writes go to the same I2C device, and the blocks of bytes must all
  be the same length.  This sort of command is useful for initializing
  lots of registers all at once for a single device.  The expected
  packet format is:

    +00   : 0C
    +01   : <i2c addr>
    +02   : <block count>
    +03   : <write length per block>
    +04...: {write data}

  The data to write is passed in serially at offset 04, in order.  For
  example, if the block count is 3 and the write length is 2, then
  there will be 6 bytes of data, organized as 3 groups of 2 bytes
  each.  The 8051 will execute 3 separate I2C write sequences to the
  given device, passing down each successive block of data.  Expect
  one byte in response, whose definition once again is the same as
  that for the I2C write (08) command.


22 - I2C single byte write followed by single byte read

  The windows driver does not seem to use this command.

  This command operations similar to command (09), but in a more
  limited fashion (i.e. size is fixed to be 1 byte in each direction).
  This command's function is essentially a subset of command (09).
  The return data is the same as for command (09).  Perhaps this is
  old code, no longer used.  The expected packet format is:

    +00   : 22
    +01   : <write data byte>
    +02   : <i2c addr>

  The FX2 firmware for 24xxx devices doesn't seem to implement this
  command.


24 - I2C 2 byte write

  The windows driver does not seem to use this command.

  This appears to be a cheesy command for writing two quick bytes to
  an I2C device.  There is no return value, so there's no way to know
  if it worked.  The expected packet format is:

    +00   : 24
    +01   : <data byte 2>
    +02   : <data byte 1>
    +03   : <i2c addr>


28 - Encoder Memory Block Read

  This is used to read back 16 consecutive words of encoder memory.
  The format is similar to command code (02), except this command
  returns lots of data instead of just one word.  The expected packet
  format is:

    +00   : 28
    +01-04: 00000000
    +05-07: <target address to read, big-endian>

  The data returned will be exactly 64 bytes, the little-endian
  contents of each word starting at the specified target address.


36 - Capture Video Start

  This command takes no additional data nor does it return anything.
  Internally it appears to manipulate lots of registers having to do
  with endpoint #4 (which is the video stream).  It appears that this
  might be enabling endpoint #4 to start operating.


37 - Capture Video Stop

  This command takes no additional data nor does it return anything.
  Internally it appears to manipulate a few registers having to do
  with endpoint #4 (which is the video stream).  It appears that this
  might be shutting down endpoint #4.


38

39

40

41

42

43 - Capture VBI(?) Start

  This command takes no additional data nor does it return anything.
  Internally it appears to manipulate lots of registers having to do
  with endpoint #8 (VBI?).  It appears that this might be enabling
  endpoint #8 to start operating.  Note: a side-by-side inspection of
  the code reveals that it is identical to what command 36 does except
  the endpoint is 8 instead of 4.


  The FX2 firmware for 24xxx devices doesn't seem to implement this
  command.

44 - Capture VBI(?) Stop

  This command takes no additional data nor does it return anything.
  Internally it appears to manipulate a few registers having to do
  with endpoint #8 (VBI?).  It appears that this might be shutting
  down endpoint #8.  Note: a side-by-side inspection of the code
  reveals that it is nearly identical to what command 37 does except
  the endpoint is 8 instead of 4.


  The FX2 firmware for 24xxx devices doesn't seem to implement this
  command.

46

52 - Stop Endpoint #2

  This command takes no additional data nor does it return anything.
  Internally it appears to manipulate a few registers having to do
  with endpoint #2 (firmware).  It appears that this might be shutting
  down endpoint #2.  Note: a side-by-side inspection of the code
  reveals that it is nearly identical to what command 37 does except
  the endpoint is 2 instead of 4.

  This command also seems to clear some pins on IOC.


D0

  The FX2 firmware for 29xxx devices doesn't seem to implement this
  command.


D1

  The FX2 firmware for 29xxx devices doesn't seem to implement this
  command.


D2

  The FX2 firmware for 29xxx devices doesn't seem to implement this
  command.


DC - Encoder suspend

  The windows driver does not seem to use this command.

  This command takes no additional arguments and returns nothing.
  Possibly this puts the encoder into a non-functional state.  It does
  something similar to command DD to the encoder but different bits
  are manipulated.  One other significant thing is that it sets the
  error state variable - which might indicate that the encoder has
  been put into a non-usable state.  Possibly this is a debugging aid?

  Followup 30-Dec-2005 - The cxusb driver also has an FX2 and in that
  case this command is a suspend or power off.  It looks eerily
  similar to here.


DD - Encoder reset

  This command takes no additional arguments and returns nothing.
  This appears to do everything that command DE does but it also
  reinitializes USB and seems to force the encoder through some kind
  of temporary state change (probably a reset).  This is probably some
  kind of recovery / reset action.


DE - Encoder resume

  This command takes no additional arguments and returns nothing.
  (However it seems that the Windows driver likes sending along with
  an additional zero.)  This seems to clear out various bits of state
  and does something to reset the encoder.

  Followup 30-Dec-2005 - The cxusb driver also has an FX2 and in that
  case this command is a resume or power on.  It looks eerily similar
  to here.


E8

  The windows driver does not seem to use this command.

  This command is identical to 52 except that IOC is not touched.

  The FX2 firmware for 24xxx devices doesn't seem to implement this
  command.


E9

  The windows driver does not seem to use this command.

  All this command seems to do is clear the config register for
  endpoint #2 (firmware).

  The FX2 firmware for 24xxx devices doesn't seem to implement this
  command.


EA - Mystery manipulation

  The windows driver does not seem to use this command.

  This command uses the three bytes set up by the 0A command to
  manipulate a 32 bit register.  This command takes no arguments and
  returns no data.  The operation it seems to perform is to form a
  register ID from mystery byte 2 and mystery byte 3 (using mystery
  byte 2 as the high byte) to which a value 01040000 is written to.
  This same register is then repeatedly read back until the second
  byte (the one with the 04 in it) comes back with the value 10.  Then
  the process seems to be repeated 254 more times.  This command looks
  like its only purpose is to find an easy way to wedge the 8051
  (there is no retry counter here).

  The FX2 firmware for 24xxx devices doesn't seem to implement this
  command.


EB - Get eeprom I2C address

  This command takes no additional data but returns a single byte,
  which will be the I2C address of the eeprom or zero if there is no
  eeprom present.

EC - Get IR code

  This returns 4 bytes, embedded in which is a "standard" 13 bit IR
  code.  The result appears to be in the 2nd and 3rd received bytes,
  left-justified (i.e. shift right 3 bits to get the value).  The
  first byte has a status: 3=means no code; 1 means a code is
  present.  The Windows driver is also sending 00 02 1a but I think
  that might be garbage data.  Not really sure.

  The FX2 firmware for 29xxx devices doesn't seem to implement this
  command (because on 29xxx devices IR is handled with a dedicated I2C
  chip).


