blob: e3f4aae0ae08483615fa485f8f066bcc3e3d98e8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/* SPDX-License-Identifier: Unlicense
*/
#include "gdbremote_parser.hpp"
using namespace GDBRemote;
static inline bool is_hex_digit(uint8_t byte)
{
return byte >= '0' && byte <= '9'
|| byte >= 'A' && byte < 'F'
|| byte >= 'a' && byte <= 'f';
}
static inline uint8_t parseChecksumFromHexChars(uint8_t first, uint8_t second)
{
// Assume, that given bytes are valid hex digits in ASCII
first = ((first & 0x40) ? (first + 9) : first) & 0x0f;
second = ((second & 0x40) ? (second + 9) : second) & 0x0f;
return ((first << 4) | second) & 0xff;
}
std::unique_ptr<ExchangeResult> ExchangeContext::Consume(uint8_t byte)
{
switch (_parsing_state) {
case ParsingState::kIdle:
if (byte == '$') {
transit(ParsingState::kPacketData);
}
break;
case ParsingState::kPacketData:
if (byte == '#') {
transit(ParsingState::kChecksum1);
} else {
_checksum = (_checksum + byte) & 0xff;
_packet_data += byte;
}
break;
case ParsingState::kPacketDataBinSecond:
// TODO escaped and binary data
break;
case ParsingState::kChecksum1:
if (is_hex_digit(byte)) {
transit(ParsingState::kChecksum2);
_given_checksum_first_byte = byte;
} else {
transit(ParsingState::kIdle);
return ExchangeResult::Nak();
}
break;
case ParsingState::kChecksum2:
const uint8_t checksum = _checksum;
std::string packet_data(std::move(_packet_data));
transit(ParsingState::kIdle);
if (is_hex_digit(byte)) {
const uint8_t given_checksum =
parseChecksumFromHexChars(_given_checksum_first_byte, byte);
if (given_checksum == checksum) {
return ExchangeResult::Ack(packet_data);
} else {
printf(
"Checksum mismatch received: %02X, expected: %02X\n",
given_checksum, checksum);
printf("Packet data: \"%s\"\n", packet_data.c_str());
return ExchangeResult::Nak();
}
} else {
return ExchangeResult::Nak();
}
break;
}
return nullptr;
}
std::string ExchangeContext::WrapDataToSend(Packet packet)
{
(void) packet;
return std::string{};
}
void ExchangeContext::transit(ParsingState new_state)
{
printf(
"GDBRemote ParsingState: %s -> %s\n",
parsingStateToString(_parsing_state),
parsingStateToString(new_state));
switch (new_state) {
case ParsingState::kIdle:
_checksum = 0;
_packet_data.clear();
break;
case ParsingState::kPacketData:
break;
case ParsingState::kPacketDataBinSecond:
break;
case ParsingState::kChecksum1:
break;
case ParsingState::kChecksum2:
break;
}
_parsing_state = new_state;
}
const char* ExchangeContext::parsingStateToString(ParsingState state)
{
switch (state) {
case ParsingState::kIdle:
return "Idle";
case ParsingState::kPacketData:
return "PacketData";
case ParsingState::kPacketDataBinSecond:
return "PacketDataBinSecond";
case ParsingState::kChecksum1:
return "Checksum1";
case ParsingState::kChecksum2:
return "Checksum2";
}
return "?";
}
|