[Prism54-devel] GW3887 firmware upload
Sebastien B
sebastien.b at swissinfo.org
Sun Apr 10 09:55:01 UTC 2005
Hello,
I have looked in the prism54-usb source code :
- I have fixed the problem with escaping the last character, you just have to
return one character less in case there's not enough space. Here's the code :
static unsigned int firmware_escape_write_buffer(char *output, char *input,
unsigned int *write)
{
unsigned int i, j;
i = 0;
j = 0;
while (j < *write) {
switch(input[i]) {
case '~':
if((j-*write) < 2) {
*write = j;
return i;
}
output[j++] = '}';
output[j++] = '^';
break;
case '}':
if((j-*write) < 2) {
*write = j;
return i;
}
output[j++] = '}';
output[j++] = ']';
break;
default:
output[j++] = input[i];
}
i++;
}
*write = j;
return i;
}
- To simplify the upload process, you don't have to send the start sequence in
the same URB as the first block of firmware data. This makes the code much
clearer :) Works at least with the WG111.
Here's the function I wrote for FreeBSD (can be easily adapted for Linux) :
static int p54u_load_firmware2(struct p54u_softc *sc)
{
static const char start_string[6] = "~~~~<\r";
static const char go_string[6] = "y g\r";
int read, written, remains;
char *data;
p54u_dbg_usb("Loading the firmware");
written = sizeof(start_string);
memcpy(sc->data_tx.buf, &start_string[0], written);
if(usbd_bulk_transfer(sc->data_tx.xfer, sc->data_tx.pipe_handle,
USBD_NO_COPY, USBD_NO_TIMEOUT/*P54U_TRANSFER_TIMEOUT*/, sc->data_tx.buf,
&written, "p54u_load_firmware2_1") != USBD_NORMAL_COMPLETION) {
p54u_err("Could not send start command");
sc->err = 1;
return 0;
}
data = (char *)&lmac_3887_data;
remains = sizeof(lmac_3887_data);
while(remains > 0) {
written = remains > P54U_FW_BLOCK ? P54U_FW_BLOCK : remains;
read = firmware_escape_write_buffer(sc->data_tx.buf, data, &written);
if(usbd_bulk_transfer(sc->data_tx.xfer, sc->data_tx.pipe_handle,
USBD_NO_COPY, USBD_NO_TIMEOUT/*P54U_TRANSFER_TIMEOUT*/, sc->data_tx.buf,
&written, "p54u_load_firmware2_2") != USBD_NORMAL_COMPLETION) {
p54u_err("Could not send firmware block");
sc->err = 1;
return 0;
}
data += read;
remains -= read;
}
p54u_dbg_usb("Firmware sent, starting it");
written = sizeof(go_string);
memcpy(sc->data_tx.buf, &go_string[0], written);
*(uint32_t *)(sc->data_tx.buf) = htole32(0x8fe19579); /* maybe 79 is y, e18f
is a length, 95 an opcode */
if(usbd_bulk_transfer(sc->data_tx.xfer, sc->data_tx.pipe_handle,
USBD_NO_COPY, USBD_NO_TIMEOUT/*P54U_TRANSFER_TIMEOUT*/, sc->data_tx.buf,
&written, "p54u_load_firmware2_3") != USBD_NORMAL_COMPLETION) {
p54u_err("Could not send GO command");
sc->err = 1;
return 0;
}
p54u_dbg_usb("Send command OK");
do {
read = P54U_MAX_FRAME_SIZE;
if(usbd_bulk_transfer(sc->data_rx.xfer, sc->data_rx.pipe_handle,
USBD_NO_COPY|USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT/*P54U_TRANSFER_TIMEOUT*/,
sc->data_rx.buf, &read, "p54u_load_firmware2_r1") != USBD_NORMAL_COMPLETION)
{
p54u_err("Could not get device response to firmware");
sc->err = 1;
return 0;
}
*((char *)sc->data_rx.buf+read) = 0;
p54u_dbg_usb("Device response : %s", (char *)sc->data_rx.buf);
if(memcmp(sc->data_rx.buf, "ERROR", 5) == 0) {
p54u_err("Got ERROR response to firmware upload");
sc->err = 1;
return 0;
}
} while(*(char *)sc->data_rx.buf != 'g');
p54u_dbg_usb("Firmware startup succeeded");
return 1;
}
Regards,
Sebastien
More information about the Prism54-devel
mailing list