mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
httpd: emit valid JSON from send_l2
The MAC table listing wrote its separator once per iteration rather than once per object. An entry the table engine reports as invalid produces no object, so it contributed a bare comma, and two in a row give ",," which JSON.parse rejects. The whole table then fails to load, not just the row that was missing. The separator now goes before each object and the closing bracket after the loop, which is the shape send_vlanlist already uses further down the file. The next index for an invalid entry was computed as h | low + 1, and the addition binds tighter than the or. That agrees with (h | low) + 1 except when the low byte reads 0xff and bit 8 of the index is already set, eight of the 4096 combinations. There the result is the start of the current block of 256 rather than the start of the next one, so the walk repeats a block it has already covered. Reading the index once after the branch rather than once in each arm removes the second copy of that expression along with the bug. The VLAN now comes first in each object. It is taken from the same L2_DATA_OUT_B read that decides whether the entry is valid, which saves reading that register a second time. The page addresses the fields by name, so the order they arrive in does not matter to it. A bound check on the output buffer goes in for consistency with send_vlanlist. Thirty entries of at most 74 bytes plus the brackets fit in the 2500 byte buffer with 179 to spare, so nothing changes today, but the margin was nowhere stated and L2_MAX_TRANSFER is a tunable. 5 bytes of BANK1, nothing in BANK2, xdata or internal RAM. Built for SWTGW218AS and KP_9000_6XHML_X2 on sdcc 4.5.0.
This commit is contained in:
+27
-25
@@ -356,6 +356,7 @@ void send_l2(uint16_t idx)
|
||||
*/
|
||||
__xdata uint16_t entry = idx & 0xfff;
|
||||
__xdata uint16_t first_entry = 0xffff; // An illegal entry index
|
||||
bool first = true;
|
||||
char_to_html('[');
|
||||
while (1) {
|
||||
entries_left--;
|
||||
@@ -369,9 +370,22 @@ void send_l2(uint16_t idx)
|
||||
} while (sfr_data[3] & TBL_EXECUTE);
|
||||
|
||||
reg_read_m(RTL837x_L2_DATA_OUT_B);
|
||||
if ((sfr_data[0] & 0x20)) { // Check entry is valid
|
||||
bool valid = (sfr_data[0] & 0x20) != 0;
|
||||
if (valid) {
|
||||
/* separator + 74-byte worst-case entry + closing "]" */
|
||||
if (slen + 76 > TCP_OUTBUF_SIZE)
|
||||
break;
|
||||
if (!first)
|
||||
char_to_html(',');
|
||||
first = false;
|
||||
|
||||
// VLAN, taken from the read above instead of reading the register twice
|
||||
slen += strtox(outbuf + slen, "{\"vlan\":\"");
|
||||
charhex_to_html(sfr_data[0] & 0x0f);
|
||||
byte_to_html(sfr_data[1]);
|
||||
|
||||
// MAC
|
||||
slen += strtox(outbuf + slen, "{\"mac\":\"");
|
||||
slen += strtox(outbuf + slen, "\",\"mac\":\"");
|
||||
byte_to_html(sfr_data[2]); char_to_html(':');
|
||||
byte_to_html(sfr_data[3]); char_to_html(':');
|
||||
port = (sfr_data[0] >> 6) & 0x3;
|
||||
@@ -381,12 +395,6 @@ void send_l2(uint16_t idx)
|
||||
byte_to_html(sfr_data[2]); char_to_html(':');
|
||||
byte_to_html(sfr_data[3]);
|
||||
|
||||
// VLAN
|
||||
slen += strtox(outbuf + slen, "\",\"vlan\":\"");
|
||||
reg_read_m(RTL837x_L2_DATA_OUT_B);
|
||||
charhex_to_html(sfr_data[0] & 0x0f);
|
||||
byte_to_html(sfr_data[1]);
|
||||
|
||||
// type
|
||||
reg_read_m(RTL837x_L2_DATA_OUT_C);
|
||||
if (sfr_data[2] & 0x1)
|
||||
@@ -396,32 +404,26 @@ void send_l2(uint16_t idx)
|
||||
|
||||
port |= (sfr_data[3] & 0x3) << 2;
|
||||
itoa_html(port);
|
||||
}
|
||||
|
||||
// Index
|
||||
reg_read_m(RTL837x_TBL_DATA_0);
|
||||
entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3];
|
||||
// Index
|
||||
reg_read_m(RTL837x_TBL_DATA_0);
|
||||
entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3];
|
||||
if (valid) {
|
||||
slen += strtox(outbuf + slen, ",\"idx\":\"");
|
||||
byte_to_html(entry >> 8);
|
||||
byte_to_html(entry);
|
||||
char_to_html('"');
|
||||
char_to_html('}');
|
||||
entry += 1; // We want the next entry following after the current entry
|
||||
} else {
|
||||
reg_read_m(RTL837x_TBL_DATA_0);
|
||||
entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3] + 1;
|
||||
}
|
||||
if (first_entry == 0xffff) {
|
||||
char_to_html(',');
|
||||
entry += 1; // We want the next entry following after the current entry
|
||||
|
||||
if (first_entry == 0xffff)
|
||||
first_entry = entry;
|
||||
} else {
|
||||
if (first_entry == entry || !entries_left) {
|
||||
char_to_html(']');
|
||||
break;
|
||||
} else {
|
||||
char_to_html(',');
|
||||
}
|
||||
}
|
||||
else if (first_entry == entry || !entries_left)
|
||||
break;
|
||||
}
|
||||
char_to_html(']');
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user