Exemplo n.º 1
0
bool BootProtocolProcess(const void* data, size_t data_len) {
  assert(!data_len || data);

  while (data_len > 0) {
    if (data_len >= rx_message_remaining) {
      if (rx_message_state == WAIT_FILE) {
        int i;
        for (i = 0; i < rx_message_remaining; ++i)
          file_checksum += ((const uint8_t *) data)[i];
        if (!IOIOFileHandleBuffer(data, rx_message_remaining)) return false;
      } else {
        // copy a chunk of data to rx_msg
        memcpy(((BYTE *) &rx_msg) + rx_buffer_cursor, data, rx_message_remaining);
        rx_buffer_cursor += rx_message_remaining;
      }
      data += rx_message_remaining;
      data_len -= rx_message_remaining;
      rx_message_remaining = 0;
    } else {
      if (rx_message_state == WAIT_FILE) {
        int i;
        for (i = 0; i < data_len; ++i)
          file_checksum += ((const uint8_t *) data)[i];
        if (!IOIOFileHandleBuffer(data, data_len)) return false;
      } else {
        // copy a chunk of data to rx_msg
        memcpy(((BYTE *) &rx_msg) + rx_buffer_cursor, data, data_len);
        rx_buffer_cursor += data_len;
      }
      rx_message_remaining -= data_len;
      data_len = 0;
    }

    // change state
    if (rx_message_remaining == 0) {
      switch (rx_message_state) {
        case WAIT_TYPE:
          rx_message_state = WAIT_ARGS;
          if (rx_msg.type >= MESSAGE_TYPE_LIMIT) {
            log_printf("Unexpected message type: 0x%x", rx_msg.type);
            return false;
          }
          rx_message_remaining = incoming_arg_size[rx_msg.type];
          if (rx_message_remaining) break;
          // fall-through on purpose

        case WAIT_ARGS:
          rx_message_state = WAIT_TYPE;
          rx_message_remaining = 1;
          rx_buffer_cursor = 0;
          if (!MessageDone()) return false;
          if (rx_message_remaining) break;
          // fall-through on purpose

        case WAIT_FILE:
          if (!IOIOFileDone()) {
            log_printf("Unexpected end of file");
            return false;
          } else {
            log_printf("Image done successfully");
          }
          SendChecksum(file_checksum);
          rx_message_state = WAIT_TYPE;
          rx_message_remaining = 1;
          break;
      }
    }
  }
  return true;
}
Exemplo n.º 2
0
//-----------------------------------------------------------------------------
// Test binary data transmission.
// Format in:
//  <byte size>:<mode>
// Format out:
//  <4 bytes binary checksum><#size bytes data>
// If echo mode, also:
//    Format in:
//     <#size bytes data>
//    Format out:
//     OK/ER - according to CRC match on incomin data
// Format in:
//  DONE
//
// To Do:
//  o Add mode/flag specifying 5-8 bit transfer.
//     Test that 0xff gets masked off accordingly when transfered.
//     (This should be an INFO result if failing)
//  o Clean up the DUPLEX_ECHO implementation. Currently it's an ugly hack
//    that doesn't match the arguments / behavior of the two other modes.
void
CeCosTestSerialFilter::CMD_TestBinary(CeCosSerial &pSer, char* args)
{
    int size;
    cyg_mode_t mode;
    unsigned char *data_out, *data_in;
    int i;
    int crc;

    int loop_count = 0;

    INIT_VALUE(args);

    SET_VALUE(int, size);
    SET_VALUE(cyg_mode_t, mode);

    // Change behavior for DUPLEX mode.
    if (MODE_DUPLEX_ECHO == mode) {
        loop_count = size;
        size = 1024;                    // must be at least 4*block_size
    }

    // Generate data.
    data_out = (unsigned char*) malloc(size);
    if (!data_out) {
        fprintf(stderr, "Could not allocate %d byte buffer for data!\n", size);
        throw "data_out malloc failed";
    }
    data_in = (unsigned char*) malloc(size);
    if (!data_in) {
        fprintf(stderr, "Could not allocate %d byte buffer for data!\n", size);
        throw "data_in malloc failed";
    }
    int count = 0;
    for (i = 0; i < size; i++) {
        // Output 255 chars, not 256 so that we aren't a multiple/factor of the
        // likely buffer sizes in the system, this can mask problems as I've
        // found to my cost!
        unsigned char c = (unsigned char) (count++ % 255);
        // don't allow $s and @s in the data, nor 0x03 (GDB C-c), nor flow
        // control chars
        if ('$' == c || '@' == c || 0x03 == c || 0x11 == c || 0x13 == c)
            c = (unsigned char) '*';
        data_out[i] = c;
    }

    // Do checksum.
    crc = DoCRC(data_out, size);

    // Send checksum to target.
    SendChecksum(pSer, crc);

    // Give the target 1/10th of a sec to digest it
    CeCosThreadUtils::Sleep(100);

    switch (mode) {
    case MODE_NO_ECHO:
    {
        // Simple transmit. Don't expect target to echo data back.
        TargetWrite(pSer, data_out, size);
        ReceiveDone(pSer, NULL, 0);
    }
    break;
    case MODE_EOP_ECHO:
    {
        int in_crc;

        TargetWrite(pSer, data_out, size);
        Trace("Finished write, waiting for target echo.\n");

        // Expect target to echo the data
        TargetRead(pSer, data_in, size);

        // Check echoed data, and reply OK/ER accordingly.
        in_crc = DoCRC(data_in, size);
        SendStatus(pSer, (in_crc == crc));


        // Dump seen/expected on console.
        if (in_crc != crc) {
            Trace("Data seen:\n");
            PrintHex(data_in, size);
            Trace("<end>\n");
            Trace("Data expected:\n");
            PrintHex(data_out, size);
            Trace("<end>\n");
        }

        ReceiveDone(pSer, data_in, size);

    }
    break;
    case MODE_DUPLEX_ECHO:
    {
        int block_size = 64;
        int fail, j;

        // This is a simple implementation (maybe too simple).
        // Host sends 4 packets with the same size (64 bytes atm).
        // Target echoes in this way:
        //  packet1 -> packet1
        //  packet2 -> packet2, packet2
        //  packet3 -> packet3
        //  packet4 -> /dev/null
        //
        // The reads/writes are interleaved in a way that should ensure
        // the target out buffer to be full before the target starts to read
        // packet3. That is, the target should be both receiving (packet3)
        // and sending (packet2) at the same time.

        // This code needs restructuring. It's not very obvious what's
        // happening: The same block of data is output several times,
        // the target echoes the data back (one of the blocks is
        // echoed twice). Then the echoed data is compared agains the
        // outgoing data block.

        fail = 0;
        while (loop_count--) {
            int i;
            for (i = 0; i < block_size*4; i++)
                data_in[i] = 0;

            // out1: block_size -> block_size
            TargetWrite(pSer, data_out, block_size);

            // out2: block_size -> 2 x block_size
            TargetWrite(pSer, data_out, block_size);

            // in1:
            TargetRead(pSer, data_in, block_size);

            // out3: block_size -> block_size
            TargetWrite(pSer, data_out, block_size);
        
            // in2:
            TargetRead(pSer, &data_in[block_size], 2*block_size);

            // out4: block_size -> 0
            TargetWrite(pSer, data_out, block_size);
        
            // in3:
            TargetRead(pSer, &data_in[block_size*3], block_size);

            if (0 == loop_count % 10)
                Trace("%d loops to go\n", loop_count);

            // Verify data.
            if (!fail) {
                for (j = 0; j < 4 && !fail; j++) {
                    for (i = 0; i < block_size && !fail; i++) {
                        if (data_out[i] != data_in[j*block_size + i]) {
                            fail = 1;
                            Trace("Failed at byte %d\n", j*block_size + i);
                            
                            Trace("Data seen:\n");
                            PrintHex(&data_in[j*block_size], 
                                           block_size);
                            Trace("<end>\n");
                            Trace("Data expected:\n");
                            PrintHex(data_out, block_size);
                            Trace("<end>\n");
                        }
                    }
                }
            }
        }
        // Check echoed data, and reply OK/ER accordingly.
        SendStatus(pSer, (!fail));
        ReceiveDone(pSer, data_in, block_size*4);
    }
    break;
    default:
        Trace("Unknown mode. Ignoring.\n");
    }

    // Free buffer.
    free(data_in);
    free(data_out);
}