[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