Exemplo n.º 1
0
static int
hexnumstr (char *buf, ULONGEST num)
{
  int i;
  int len = hexnumlen (num);

  buf[len] = '\0';

  for (i = len - 1; i >= 0; i--)
    {
      buf[i] = "0123456789abcdef"[(num & 0xf)];
      num >>= 4;
    }

  return len;
}
// Based on routines in gdb/remote.c
int
CeCosTestDownloadFilter::put_binary (unsigned char* buf, int len,
                                     unsigned long dl_address,
                                     int packet_size,
                                     CeCosSerial& serial)
{
    int i;
    unsigned char csum;
    Buffer buf2(packet_size);
    unsigned char ch;
    int tcount = 0;
    unsigned char *p, *p2, *plen;

    while (len > 0) {
        /* Subtract header overhead from MAX payload size:
           $M<memaddr>,<len>:#nn */
        int max_buf_size =
            buf2.Size()
            - ( 2 + hexnumlen(dl_address) + 1 + hexnumlen(buf2.Size()) + 4);

        /* Copy the packet into buffer BUF2, encapsulating it
           and giving it a checksum.  */
        int todo = MIN (len, max_buf_size);

        p = (unsigned char*) buf2.Data();
        *p++ = '$';

        // Add X header.
        *p++ = 'X';
        p += hexnumstr(p, dl_address);
        *p++ = ',';
        plen = p;			/* remember where len field goes */
        p += hexnumstr(p, todo);
        *p++ = ':';

        int escaped = 0;
        for (i = 0;
                (i < todo) && (i + escaped) < (max_buf_size - 2);
                i++)
        {
            switch (buf[i] & 0xff)
            {
            case '$':
            case '#':
            case 0x7d:
                /* These must be escaped */
                escaped++;
                *p++ = 0x7d;
                *p++ = (unsigned char) ((buf[i] & 0xff) ^ 0x20);
                break;
            default:
                *p++ = (unsigned char) (buf[i] & 0xff);
                break;
            }
        }

        if (i < todo)
        {
            /* Escape chars have filled up the buffer prematurely,
               and we have actually sent fewer bytes than planned.
               Fix-up the length field of the packet.  */

            /* FIXME: will fail if new len is a shorter string than
               old len.  */

            plen += hexnumstr (plen, i);
            *plen++ = ':';
        }

        // Calculate checksum
        p2 = (unsigned char*)buf2.Data();
        p2++; // skip $
        csum = 0;
        while (p2 < p)
            csum = (unsigned char)(csum + *p2++);
        *p++ = '#';
        *p++ = (unsigned char) tohex ((csum >> 4) & 0xf);
        *p++ = (unsigned char) tohex (csum & 0xf);

        /* Send it over and over until we get a positive ack.  */

        int resend = 1;
        const unsigned char* write_ptr = (const unsigned char*) buf2.Data();
        int write_len = (int)p-(int)buf2.Data();
        while (resend)
        {
            unsigned int __written;

            Trace("Sending bytes for %p-%p\n", dl_address, dl_address+i);
            TargetWrite(serial, write_ptr, write_len);

            /* read until either a timeout occurs (-2) or '+' is read */
            for(;;)
            {
                unsigned int __read;
                serial.Read(&ch, 1, __read);

                if (0 == __read) {
                    tcount ++;
                    if (tcount > 3) {
                        Trace("Timeout in putpkt_binary\n");
                        return 0;
                    }
                    break;		/* Retransmit buffer */
                }

                switch (ch)
                {
                case '+':
                    // Now expect OK packet from target
                    unsigned char ok_msg[6];// $OK#9a
                    serial.Read(ok_msg, 6, __read);

                    // Reply with ACK
                    serial.Write((void*)"+", 1, __written);

                    // And process next packet.
                    resend = 0;
                    break;

                case '-':
                    // Bad packet CRC. Retransmit.
                    Trace ("Bad CRC\n");
                    break;

                default:
                    Trace("Got junk..%02x\n", ch);
                    continue;           // keep reading
                }
                break;		/* Here to retransmit */
            }
        }

        len -= i;
        dl_address += i;
        buf += i;
    }

    return 1;
}