1 //####COPYRIGHTBEGIN####
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
6 // This program is part of the eCos host tools.
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 2 of the License, or (at your option)
13 // This program is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc.,
20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 // ----------------------------------------------------------------------------
24 //####COPYRIGHTEND####
25 //=================================================================
27 // eCosTestSerialFilter.cpp
29 // Serial test filter class
31 //=================================================================
32 //=================================================================
33 //#####DESCRIPTIONBEGIN####
36 // Contributors: jskov
38 // Description: This filter sits between GDB and the test running on
39 // the target, allowing testing of the serial driver
40 // without confusing GDB.
42 // o Add timeout setup and handling for recovery, can rely on testing
43 // agent to control global timeout.
44 // o Saving chunks that caused transfer failure?
45 // - In SEND with echo, do CRC on 32-byte sub-packets
46 // o Additional To Do items under each sub-protocol function.
47 // o Option to get all serial IO written (in hex, > and < prepends
48 // input/output lines) to a file.
49 // o Clean up the mess in this file....
50 //####DESCRIPTIONEND####
54 #include "eCosTestSerialFilter.h"
55 #include "eCosThreadUtils.h"
62 CeCosTestSerialFilter::CeCosTestSerialFilter():
63 m_bOptConsoleOutput(false),
64 m_bOptSerDebug(false),
65 m_bOptFilterTrace(false),
66 m_xUnreadBuffer(NULL),
67 m_nUnreadBufferIndex(0),
68 m_nUnreadBufferSize(0),
69 m_xStoredTraceBuffer(NULL),
70 m_nStoredTraceBufferSize(0),
74 m_bFirstCommandSeen(false),
79 CeCosTestSerialFilter::~CeCosTestSerialFilter()
83 //------------------------
86 // Encode string in an O-packet and send it to GDB.
88 CeCosTestSerialFilter::GDBWrite(const char* pszStr)
91 static const char hexchars[] = "0123456789abcdef";
92 char* packet = new char[strlen(pszStr)*2+6];
97 unsigned char crc = 'O';
104 char h = hexchars[(c >> 4) & 0x0f];
105 char l = hexchars[c & 0x0f];
108 crc = (unsigned char) (crc + h + l);
112 *p++ = hexchars[(crc >> 4) & 0x0f];
113 *p++ = hexchars[crc & 0x0f];
115 // Only try to send once. If it fails, it's probably because
116 // GDB has disconnected.
117 m_cGDBSocket->send(packet, p - packet);
118 m_cGDBSocket->recv(&c, 1);
125 CeCosTestSerialFilter::ConsoleWrite(const char* pszStr)
127 fputs(pszStr, stderr);
132 CeCosTestSerialFilter::Trace(const char* pszFormat, ...)
136 va_start (marker, pszFormat);
138 for(int nLength=100;nLength;) {
139 char *buf=new char[1+nLength];
140 int n=vsnprintf(buf+4, nLength-4, pszFormat, marker );
142 nLength*=2; // NT behavior
143 } else if (n<nLength){
144 memcpy(buf,"[f] ",4);
145 if (m_bOptConsoleOutput) {
150 nLength=0; // trigger exit from loop
152 nLength=n+1; // UNIX behavior generally, or NT behavior when buffer size exactly matches required length
162 CeCosTestSerialFilter::Log(const char* pszFormat, ...)
165 va_start (marker, pszFormat);
167 for(int nLength=100;nLength;) {
168 char *buf=new char[1+nLength];
169 int n=vsnprintf(buf, nLength, pszFormat, marker );
171 nLength*=2; // NT behavior
172 } else if (n<nLength){
173 if (m_bOptConsoleOutput) {
178 nLength=0; // trigger exit from loop
180 nLength=n+1; // UNIX behavior generally, or NT behavior when buffer size exactly matches required length
190 CeCosTestSerialFilter::PrintHex(const unsigned char* d1, int len, data_origin_t origin/*=SF_TARGET*/)
198 int count = MIN(width, len);
202 p += sprintf(p, "T");
205 p += sprintf(p, "F");
208 p += sprintf(p, ":%04x ", offset);
210 for (i = 0; i < count; i++)
211 p += sprintf(p, "%02x ", d1[i]);
212 for ( ; i < width ; i++)
213 p += sprintf(p, ".. ");
215 // Print ASCII string
216 p += sprintf(p, "'");
217 for (i = 0; i < count; i++) {
219 if (' ' > c || 'z' < c)
221 p += sprintf(p, "%c", c);
234 CeCosTestSerialFilter::TargetWrite(CeCosSerial &pSer,
235 const unsigned char* buffer, int len)
237 unsigned int __written;
239 if (m_bOptFilterTrace)
240 PrintHex(buffer, len, SF_FILTER);
243 if (!(pSer.Write((void*) buffer, len, __written))) {
244 fprintf(stderr, "Writing %d bytes to serial failed\n", len);
245 fprintf(stderr, "%s", (LPCTSTR)pSer.ErrString());
246 throw "serial write failed";
256 CeCosTestSerialFilter::TargetRead(CeCosSerial &pSer,
257 unsigned char* buffer, int len)
260 int __total_read = 0;
261 unsigned char* __buffer_base = buffer;
263 int __timeout_failure = 0;
264 int __orig_len = len;
267 // First check for unread data.
268 if (m_nUnreadBufferSize) {
271 while (i < len && m_nUnreadBufferIndex < m_nUnreadBufferSize) {
272 buffer[i++] = m_xUnreadBuffer[m_nUnreadBufferIndex++];
276 if (m_nUnreadBufferIndex == m_nUnreadBufferSize) {
277 free(m_xUnreadBuffer);
278 m_nUnreadBufferSize = 0;
279 m_nUnreadBufferIndex = 0;
282 // Then read directly from serial.
283 if (!(pSer.Read((void*) buffer, len, __read))) {
284 fprintf(stderr,"Reading %d bytes from serial failed (read %d).\n",
286 char *pszErr=pSer.ErrString().GetCString();
287 fprintf(stderr, "%s", pszErr);
289 throw "serial read failed";
293 __total_read += __read;
295 for (i = 0; i < __read; i++) {
296 if ('$' == buffer[i]) {
298 Log("FAIL:<target crashed>\n");
300 Trace("**** Detected $ -- resuming as null filter ****\n");
302 Trace("Data received %d bytes (of %d) from target:\n",
303 __total_read, __orig_len);
304 PrintHex(__buffer_base, __total_read);
307 filter_abort_t* msg = new filter_abort_t();
308 msg->data_ptr = &buffer[i];
309 msg->data_len = __read - i;
316 CeCosThreadUtils::Sleep(20);
318 if (25 == __timeouts) {
320 if (5 == __timeout_failure++) {
321 Log("FAIL:<target timed out>\n");
323 Trace("**** Timed out while reading -- resuming as null filter\n");
325 Trace("Data received %d bytes (of %d) from target:\n",
326 __total_read, __orig_len);
327 PrintHex(__buffer_base, __total_read);
330 static const char kill_msg[] = "$X00#b8";
332 filter_abort_t* msg = new filter_abort_t();
333 msg->data_len = strlen(kill_msg);
334 msg->data_ptr = (const unsigned char *)kill_msg;
341 __timeout_failure = 0;
352 // Send C ASCII string to target.
354 CeCosTestSerialFilter::TargetASCIIWrite(CeCosSerial &pSer, const char* s)
356 TargetWrite(pSer, (const unsigned char*) s, strlen(s));
359 //------------------------
360 // Configuration Command.
361 // Set serial configuration.
363 CeCosTestSerialFilter::SetConfig(CeCosSerial &pSer,
364 const ser_cfg_t* new_cfg,
367 // Note that for flow control, we assume that *both* receive and transmit
368 // flow control are set or not set
370 old_cfg->baud_rate = pSer.GetBaud();
371 old_cfg->parity = (0 != pSer.GetParity()) ? true : false;
372 old_cfg->data_bits = pSer.GetDataBits();
373 old_cfg->stop_bits = pSer.GetStopBits();
374 old_cfg->flags = pSer.GetXONXOFFFlowControl() ? FLOW_XONXOFF_RX : 0;
375 old_cfg->flags |= pSer.GetRTSCTSFlowControl() ? FLOW_RTSCTS_RX : 0;
376 old_cfg->flags |= pSer.GetDSRDTRFlowControl() ? FLOW_DSRDTR_RX : 0;
379 pSer.SetBaud(new_cfg->baud_rate, false);
380 pSer.SetParity(new_cfg->parity, false);
381 pSer.SetDataBits(new_cfg->data_bits, false);
382 pSer.SetXONXOFFFlowControl((new_cfg->flags&FLOW_XONXOFF_RX) != 0, false);
383 pSer.SetRTSCTSFlowControl((new_cfg->flags&FLOW_RTSCTS_RX) != 0, false);
384 pSer.SetDSRDTRFlowControl((new_cfg->flags&FLOW_DSRDTR_RX) != 0, false);
385 return pSer.SetStopBits(new_cfg->stop_bits, true); // apply settings
388 // Return false if the serial configuration is not valid for the host.
390 CeCosTestSerialFilter::VerifyConfig(CeCosSerial &pSer, ser_cfg_t* new_cfg)
395 // Try changing to the new config, recording the result. Then restore
396 // the original config.
397 rc = SetConfig(pSer, new_cfg, &old_cfg);
398 SetConfig(pSer, &old_cfg, NULL);
403 //-----------------------------------------------------------------------------
404 // Configuration changing function.
406 // First change to the new config and back again to determine if the driver
407 // can handle the config.
408 // If not, return error.
410 // Then query the host for its capability to use the config:
412 // "@CONFIG:<baud rate code>:<#data bits>:<#stop bits>:<parity on/off>!"
416 // On ER, return error.
418 // On OK, change to the new configuration. Resynchronize with the host:
419 // Target waits for host to send S(ync)
420 // [host will delay at least .1 secs after changing baud rate so the
421 // line has time to settle.]
423 // When receiving S(ync), target replies OK to the host which then
424 // acknowledges with D(one).
426 // Host can also send R(esync) which means it didn't receieve the OK. If
427 // so the target resends its S(ync) message.
429 // If the synchronization has not succeeded within 1 second
430 // (configurable in the protocol), both host and target will revert to
431 // the previous configuration and attempt to synchronize again. If
432 // this fails, this call will hang and the host will consider the test
436 // Host&protocol currently only supports:
439 CeCosTestSerialFilter::CMD_ChangeConfig(CeCosSerial &pSer, char* cfg_str)
441 ser_cfg_t new_cfg, old_cfg;
443 ParseConfig(cfg_str, &new_cfg);
445 // Return without changing the config if it's not valid.
446 if (!VerifyConfig(pSer, &new_cfg)) {
447 TargetASCIIWrite(pSer, "ER");
451 // Tell target we're ready to go, wait 1/10 sec, and then change
453 TargetASCIIWrite(pSer, "OK");
454 CeCosThreadUtils::Sleep(100);
455 SetConfig(pSer, &new_cfg, &old_cfg);
458 for (loops = 0; loops < 3; loops++) {
459 unsigned int len, read;
460 unsigned char buffer[2];
461 int delay_mticks = 0; // millisecond-ticks. 10 of these per target tick
463 // Start by sending a Sync.
464 TargetASCIIWrite(pSer, "S");
471 if (!pSer.Read((void*) buffer, len, read)) {
472 throw "CMD_ChangeConfig: serial read failure";
476 // If only one char read, try to get the next one.
478 unsigned int read2 = 0;
480 if (!pSer.Read((void*) &buffer[1], len, read2)) {
481 throw "CMD_ChangeConfig: serial read failure";
487 PrintHex(buffer, read);
489 if ('O' == buffer[0] && 'K' == buffer[1]) {
491 TargetASCIIWrite(pSer, "D");
492 Trace("Config change succeeded.\n");
495 // Garbage, ask target to resend its OK message.
496 TargetASCIIWrite(pSer, "R");
499 // Resend Sync message.
500 TargetASCIIWrite(pSer, "S");
503 CeCosThreadUtils::Sleep(1);
506 if (100 == delay_mticks/10)
510 SetConfig(pSer, &old_cfg, NULL);
514 Log("FAIL:<target timed out>\n");
515 Trace("**** Timed out while changing config\n");
517 static const char kill_msg[] = "$X00#b8";
519 filter_abort_t* msg = new filter_abort_t();
520 msg->data_len = strlen(kill_msg);
521 msg->data_ptr = (const unsigned char *)kill_msg;
526 // Set default configuration.
528 CeCosTestSerialFilter::CMD_DefaultConfig(CeCosSerial &pSer)
530 static const ser_cfg_t default_ser_cfg = { 9600,
532 CeCosSerial::ONE_STOP_BIT,
535 TargetASCIIWrite(pSer, "OK");
536 SetConfig(pSer, &default_ser_cfg, NULL);
539 // Parse config string from target and set new_cfg accordingly.
540 // String from target is:
541 // <baud rate>:<data bits>:<stop bits>:<parity>:....
543 CeCosTestSerialFilter::ParseConfig(char* args, ser_cfg_t* new_cfg)
545 int ecos_parity, ecos_stop_bits, ecos_baud_rate, ecos_flags;
547 CeCosSerial::StopBitsType t2h_stop_bits[3] = {
548 CeCosSerial::ONE_STOP_BIT,
549 CeCosSerial::ONE_POINT_FIVE_STOP_BITS,
550 CeCosSerial::TWO_STOP_BITS};
553 SET_VALUE(int, ecos_baud_rate);
554 SET_VALUE(int, new_cfg->data_bits);
555 SET_VALUE(int, ecos_stop_bits);
556 SET_VALUE(int, ecos_parity);
557 SET_VALUE(int, ecos_flags);
559 new_cfg->parity = (ecos_parity != 0) ? true : false;
560 new_cfg->stop_bits = t2h_stop_bits[ecos_stop_bits - 1];
562 // flags is an optional field
563 if ( -1 == ecos_flags )
564 new_cfg->flags = FLOW_NONE;
566 new_cfg->flags = ecos_flags;
568 // eCos->human translation of serial baud rate. This table must
569 // match the one in io/serial/current/include/serialio.h
570 static const int tt_baud_rate[] = {
595 if (ecos_baud_rate > 0 && ecos_baud_rate < (int) sizeof(tt_baud_rate))
596 ecos_baud_rate = tt_baud_rate[ecos_baud_rate];
600 new_cfg->baud_rate = ecos_baud_rate;
602 Trace("Parsed Config baud=%d, bParity=%d, stopbits=%d, databits=%d\n",
603 new_cfg->baud_rate, (int) new_cfg->parity, new_cfg->stop_bits,
605 Trace("Parsed Config xonxoff_rx=%d,tx=%d, rtscts_rx=%d,tx=%d, "
606 "dsrdtr_rx=%d,tx=%d\n",
607 (new_cfg->flags & FLOW_XONXOFF_RX) != 0,
608 (new_cfg->flags & FLOW_XONXOFF_TX) != 0,
609 (new_cfg->flags & FLOW_RTSCTS_RX) != 0,
610 (new_cfg->flags & FLOW_RTSCTS_TX) != 0,
611 (new_cfg->flags & FLOW_DSRDTR_RX) != 0,
612 (new_cfg->flags & FLOW_DSRDTR_TX) != 0);
615 // Always make sure CRC fits in 31 bits. Bit of a hack, but we want
616 // to send CRC as ASCII without too much hassle.
618 CeCosTestSerialFilter::DoCRC(unsigned char* data, int size)
623 for (i = 0, crc = 0; i < size; i++) {
624 crc = (crc << 1) ^ data[i]; // FIXME: standard definition?
635 CeCosTestSerialFilter::SendChecksum(CeCosSerial &pSer, int crc)
640 len = sprintf(buffer, "%d!", crc);
642 TargetWrite(pSer, (const unsigned char*)buffer, len);
646 CeCosTestSerialFilter::SendStatus(CeCosSerial &pSer, int state)
649 TargetWrite(pSer, (unsigned char*) &msg_ok, 2);
651 TargetWrite(pSer, (unsigned char*) &msg_er, 2);
655 // Receive test DONE message from target.
657 CeCosTestSerialFilter::ReceiveDone(CeCosSerial &pSer,
658 unsigned char* data_in, int size)
660 static const char msg_done[] = "DONE";
661 unsigned char data_reply[4];
664 TargetRead(pSer, data_reply, 4);
665 while (0 != strncmp((char*) data_reply, msg_done, 4)) {
667 if (data_in && size) {
668 Trace("Data received from target:\n");
669 PrintHex(data_in, size);
672 Trace("Receiving junk instead of DONE:\n");
675 PrintHex(data_reply, 4);
677 data_reply[0] = data_reply[1];
678 data_reply[1] = data_reply[2];
679 data_reply[2] = data_reply[3];
681 // The TargetRead call will handle recovery in case of timeout...
682 TargetRead(pSer, &data_reply[3], 1);
686 //-----------------------------------------------------------------------------
687 // Test binary data transmission.
689 // <byte size>:<mode>
691 // <4 bytes binary checksum><#size bytes data>
692 // If echo mode, also:
694 // <#size bytes data>
696 // OK/ER - according to CRC match on incomin data
701 // o Add mode/flag specifying 5-8 bit transfer.
702 // Test that 0xff gets masked off accordingly when transfered.
703 // (This should be an INFO result if failing)
704 // o Clean up the DUPLEX_ECHO implementation. Currently it's an ugly hack
705 // that doesn't match the arguments / behavior of the two other modes.
707 CeCosTestSerialFilter::CMD_TestBinary(CeCosSerial &pSer, char* args)
711 unsigned char *data_out, *data_in;
719 SET_VALUE(int, size);
720 SET_VALUE(cyg_mode_t, mode);
722 // Change behavior for DUPLEX mode.
723 if (MODE_DUPLEX_ECHO == mode) {
725 size = 1024; // must be at least 4*block_size
729 data_out = (unsigned char*) malloc(size);
731 fprintf(stderr, "Could not allocate %d byte buffer for data!\n", size);
732 throw "data_out malloc failed";
734 data_in = (unsigned char*) malloc(size);
736 fprintf(stderr, "Could not allocate %d byte buffer for data!\n", size);
737 throw "data_in malloc failed";
740 for (i = 0; i < size; i++) {
741 // Output 255 chars, not 256 so that we aren't a multiple/factor of the
742 // likely buffer sizes in the system, this can mask problems as I've
744 unsigned char c = (unsigned char) (count++ % 255);
745 // don't allow $s and @s in the data, nor 0x03 (GDB C-c), nor flow
747 if ('$' == c || '@' == c || 0x03 == c || 0x11 == c || 0x13 == c)
748 c = (unsigned char) '*';
753 crc = DoCRC(data_out, size);
755 // Send checksum to target.
756 SendChecksum(pSer, crc);
758 // Give the target 1/10th of a sec to digest it
759 CeCosThreadUtils::Sleep(100);
764 // Simple transmit. Don't expect target to echo data back.
765 TargetWrite(pSer, data_out, size);
766 ReceiveDone(pSer, NULL, 0);
773 TargetWrite(pSer, data_out, size);
774 Trace("Finished write, waiting for target echo.\n");
776 // Expect target to echo the data
777 TargetRead(pSer, data_in, size);
779 // Check echoed data, and reply OK/ER accordingly.
780 in_crc = DoCRC(data_in, size);
781 SendStatus(pSer, (in_crc == crc));
784 // Dump seen/expected on console.
786 Trace("Data seen:\n");
787 PrintHex(data_in, size);
789 Trace("Data expected:\n");
790 PrintHex(data_out, size);
794 ReceiveDone(pSer, data_in, size);
798 case MODE_DUPLEX_ECHO:
803 // This is a simple implementation (maybe too simple).
804 // Host sends 4 packets with the same size (64 bytes atm).
805 // Target echoes in this way:
806 // packet1 -> packet1
807 // packet2 -> packet2, packet2
808 // packet3 -> packet3
809 // packet4 -> /dev/null
811 // The reads/writes are interleaved in a way that should ensure
812 // the target out buffer to be full before the target starts to read
813 // packet3. That is, the target should be both receiving (packet3)
814 // and sending (packet2) at the same time.
816 // This code needs restructuring. It's not very obvious what's
817 // happening: The same block of data is output several times,
818 // the target echoes the data back (one of the blocks is
819 // echoed twice). Then the echoed data is compared agains the
820 // outgoing data block.
823 while (loop_count--) {
825 for (i = 0; i < block_size*4; i++)
828 // out1: block_size -> block_size
829 TargetWrite(pSer, data_out, block_size);
831 // out2: block_size -> 2 x block_size
832 TargetWrite(pSer, data_out, block_size);
835 TargetRead(pSer, data_in, block_size);
837 // out3: block_size -> block_size
838 TargetWrite(pSer, data_out, block_size);
841 TargetRead(pSer, &data_in[block_size], 2*block_size);
843 // out4: block_size -> 0
844 TargetWrite(pSer, data_out, block_size);
847 TargetRead(pSer, &data_in[block_size*3], block_size);
849 if (0 == loop_count % 10)
850 Trace("%d loops to go\n", loop_count);
854 for (j = 0; j < 4 && !fail; j++) {
855 for (i = 0; i < block_size && !fail; i++) {
856 if (data_out[i] != data_in[j*block_size + i]) {
858 Trace("Failed at byte %d\n", j*block_size + i);
860 Trace("Data seen:\n");
861 PrintHex(&data_in[j*block_size],
864 Trace("Data expected:\n");
865 PrintHex(data_out, block_size);
872 // Check echoed data, and reply OK/ER accordingly.
873 SendStatus(pSer, (!fail));
874 ReceiveDone(pSer, data_in, block_size*4);
878 Trace("Unknown mode. Ignoring.\n");
886 //-----------------------------------------------------------------------------
887 // Test transformations on text transmissions
889 // This test transmits null-terminated C strings back and forth. Since
890 // the translation is under test and may fail, the length of the data is
891 // (potentially) unknown. Sending with a null-terminator allows proper
892 // recovery even if the translations do not work as intended.
895 // <flags>!<4 bytes binary checksum><C string>
902 // Receive data, verify CRC, resend data.
903 // Send OK/ER reply when done.
905 // Receive data, echo data, verify CRC.
906 // Send OK/ER reply when done.
911 CeCosTestSerialFilter::CMD_TestText(CeCosSerial &pSer, char* /*args*/)
916 //-----------------------------------------------------------------------------
917 // Reply to PING packet from target.
923 CeCosTestSerialFilter::CMD_TestPing(CeCosSerial &pSer, char* /*args*/)
928 //-----------------------------------------------------------------------------
929 // Dispatch test command.
931 CeCosTestSerialFilter::DispatchCommand(CeCosSerial &pSer, char* cmd)
935 args = strchr(cmd, (int) ':');
937 Trace("Bogus command (%s) Ignoring.\n", cmd);
943 Trace("Dispatching command %s.\n", cmd);
945 if (0 == strcmp("CONFIG", cmd)) {
946 CMD_ChangeConfig(pSer, args);
948 else if (0 == strcmp("DEFCONFIG", cmd)) {
949 // Note: Currently the arguments are ignored. 9600 8N1 is default.
950 CMD_DefaultConfig(pSer);
952 else if (0 == strcmp("BINARY", cmd)) {
953 CMD_TestBinary(pSer, args);
955 else if (0 == strcmp("TEXT", cmd)) {
956 CMD_TestText(pSer, args);
958 else if (0 == strcmp("PING", cmd)) {
959 CMD_TestPing(pSer, args);
962 Trace("Unknown command '%s'.\n", cmd);
964 Trace("Command %s completed.\n", cmd);
968 SerialFilterFunction(void*& pBuf,
974 CeCosTestSerialFilter* p = (CeCosTestSerialFilter*) pParem;
975 return p->FilterFunctionProper(pBuf, nRead, serial, socket);
979 CeCosTestSerialFilter::FilterFunctionProper(void*& pBuf,
984 char* buffer = (char*) pBuf;
986 // Don't do anything in the null filter mode.
990 // Allows trace to be called without a reference to the socket...
991 m_cGDBSocket = &socket;
993 // Put in trace buffer in case we have to leave it because the packet
995 m_xStoredTraceBuffer = (unsigned char *)
996 realloc( m_xStoredTraceBuffer, m_nStoredTraceBufferSize + nRead );
997 if ( NULL == m_xStoredTraceBuffer )
998 throw "Could not allocate stored trace buffer";
999 memcpy( m_xStoredTraceBuffer + m_nStoredTraceBufferSize, buffer, nRead );
1000 m_nStoredTraceBufferSize += nRead;
1002 // Now search for distinct packets, delimited by '@' (filter commands)
1003 // and '$' (GDB packets)
1004 unsigned int i, newStart=0;
1005 for (i=0; i<m_nStoredTraceBufferSize; i++) {
1006 if ( m_xStoredTraceBuffer[i] == '@' ||
1007 m_xStoredTraceBuffer[i] == '$' ) {
1008 if (m_bOptSerDebug &&
1009 (m_bOptConsoleOutput || m_bFirstCommandSeen)) {
1011 // Output the serial data if option enabled - but only if
1012 // dumping state to the console or after the first command
1013 // has been seen from the filter. GDB gets confused by
1014 // O-packets if they appear when it's trying to connect.
1016 PrintHex(&m_xStoredTraceBuffer[newStart], i - newStart);
1022 // If we managed to print output, rejig the buffer size, and shunt
1023 // the new start of the data to the front of the trace buffer
1024 m_nStoredTraceBufferSize -= newStart;
1026 memmove( m_xStoredTraceBuffer, &m_xStoredTraceBuffer[newStart],
1027 m_nStoredTraceBufferSize );
1030 // Command handling.
1031 // If we are not presently reading a command, look for the
1035 for (; i < nRead; i++) {
1036 if ('@' == buffer[i]) {
1038 // Send the data before the marker.
1040 socket.send(buffer, i);
1045 // If reading a command, look for the end marker.
1048 while (i < nRead && m_nCmdIndex < MAX_CMD_LEN) {
1050 m_aCmd[m_nCmdIndex++] = c;
1053 m_nUnreadBufferIndex = 0;
1054 m_nUnreadBufferSize = nRead - i;
1056 (unsigned char*) malloc(m_nUnreadBufferSize);
1057 if (!m_xUnreadBuffer) {
1058 m_nUnreadBufferSize = 0;
1059 throw "Could not allocate unread buffer!";
1064 m_xUnreadBuffer[ix++] = buffer[i++];
1070 if (MAX_CMD_LEN == m_nCmdIndex) {
1071 Trace("Received too long command. Ignoring it!\n");
1074 } else if ('!' == c) {
1075 // Was the command completed?
1076 m_aCmd[m_nCmdIndex - 1] = 0;// terminate cmd
1080 // First command dispatched. Initialize serial to nonblocking.
1081 if (!m_bFirstCommandSeen) {
1082 m_bFirstCommandSeen = true;
1083 serial.SetBlockingReads(false);
1087 // skip @ when passing ptr
1088 DispatchCommand(serial, &m_aCmd[1]);
1090 catch (filter_abort_t* msg) {
1091 // This allows the filter to unwind, wherever in the
1092 // protocol it may be, when a $ is detected from the
1093 // target side. When this happens, we may have a
1094 // trap/exception on the target and we want the user
1095 // to access the target via GDB without intervention.
1097 // Do nothing from next call.
1098 m_bNullFilter = true;
1100 // Copy the start of the $-packet to the inbuffer.
1101 unsigned char *d = (unsigned char*) pBuf;
1102 const unsigned char *s = msg->data_ptr;
1103 unsigned int len = msg->data_len;
1105 // It should be possible to re-allocate buffer. Didn't seem
1106 // to work properly though. Probably won't be a problem
1107 // since we would normally only see 1-2 bytes of the
1110 throw "Not enough room for $-message";
1115 nRead = msg->data_len;
1123 nRead = 0; // Never leave anything for caller
1124 // This is a violation of the intended
1125 // filter function behavior.