BCA 2000 firmware - btsimonh/Behringer-BCA-2000-ASIO-driver GitHub Wiki
The BCA-2000 firmware and FPGA code is all contained within Berhinger's BCA2000.sys driver. As the unit at cold boot contains no runnable code or FPGA programming, we must extract the firmware and FPGA code from the driver in order to operate the unit.
Examining the driver using a PE dump utility, it has an area called 'PAGEDATA'. The first part of this data is the 8051 code, in the form of blocks to program over the USB. Each block in in the form:
char BlockLen;
unsigned short Address;
char Type;
char Data[]; // variable length
the last block has BlockLen=0, Address = 0, Type = 1
e.g. first block:
0E 00 01 00 90 E6 00 E0 FA 74 E7 5A 90 E6 00 44 10 F0
second block
0E 0E 01 00 00 00 00 00 00 00 90 E6 0B E4 F0 12 0F C8
.....
second to last block:
01 68 17 00 22
last (terminating) block:
00 00 00 01
For our purposes, I wrote a small programme which took these blocks and created a complete binary 8k image of the firmware, and we download that using the Cypress firmware USB commands, pausing the processor first, and then running the processor afterwards. As soon as the firmware runs, the unit will change it's VID and PID.
After the 8051 firmware in the .sys file comes the FPGA code. In the 2.1.0.6 driver, it starts 8 bytes after the last firmware block.
This is downloaded into the BCA-2000 over proprietary USB commands in chunks of 32 bytes. (vendor commands 0x10 and 0x11 to endpoint 1).
The FPGA image starts with FF FF FF FF and ends with 3F FF FF FF.
I don't know if there is any structure to the data, I identified what we needed to send by usb sniffing.
I extracted the FPGA code into a second binary file for upload.
The USB commands for FPGA upload look like:
First command, send a chunk of 32 bytes:
-- URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
PipeHandle = 82306a9c [endpoint 0x00000001]
TransferFlags = 00000002 (USBD_TRANSFER_DIRECTION_OUT, USBD_SHORT_TRANSFER_OK)
TransferBufferLength = 00000034
TransferBuffer = 8235c870
TransferBufferMDL = 00000000
00000000: 10 32 12 4b 84 27 12 4b c4 26 d1 24 e8 12 d4 64
00000010: e8 12 44 e2 42 66 28 4c e4 28 d2 42 e4 88 42 f4
00000020: 82 28 5f 29 06 1e 46 19 e2 41 94 23 56 b4 43 42
00000030: b4 43 92 84
UrbLink = 00000000
last command, terminating the load:
-- URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
PipeHandle = 8257634c [endpoint 0x00000001]
TransferFlags = 00000002 (USBD_TRANSFER_DIRECTION_OUT, USBD_SHORT_TRANSFER_OK)
TransferBufferLength = 00000034
TransferBuffer = 825c24b8
TransferBufferMDL = 00000000
00000000: 11 00 ff 3f ff ff ff 80 f8 e2 61 ff ff ff ff ff
00000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
00000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
00000030: ff ff ff ff
UrbLink = 00000000