Skip to content

Commit 3b3a6cb

Browse files
committed
Add C implementation of high-level wireline interface
1 parent 87b7bdf commit 3b3a6cb

File tree

4 files changed

+153
-10
lines changed

4 files changed

+153
-10
lines changed

src/secplus.c

+44
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,31 @@ int8_t encode_wireline(const uint32_t rolling, const uint64_t fixed,
439439
return 0;
440440
}
441441

442+
int8_t encode_wireline_command(uint32_t rolling, uint64_t device_id,
443+
uint16_t command, uint32_t payload,
444+
uint8_t *packet) {
445+
uint64_t fixed;
446+
uint32_t data;
447+
448+
if ((device_id >> 40) != 0) {
449+
return -1;
450+
}
451+
452+
if ((command >> 12) != 0) {
453+
return -1;
454+
}
455+
456+
if ((payload >> 20) != 0) {
457+
return -1;
458+
}
459+
460+
fixed = (device_id & 0xf0ffffffff) | ((uint64_t)(command & 0xf00) << 24);
461+
data = ((payload & 0xff) << 24) | ((payload & 0xff00) << 8) |
462+
((payload & 0xf0000) >> 8) | (command & 0xff);
463+
464+
return encode_wireline(rolling, fixed, data, packet);
465+
}
466+
442467
static int8_t decode_wireline_half(const uint8_t *packet_half,
443468
uint32_t *rolling, uint32_t *fixed,
444469
uint16_t *data) {
@@ -488,3 +513,22 @@ int8_t decode_wireline(const uint8_t *packet, uint32_t *rolling,
488513

489514
return 0;
490515
}
516+
517+
int8_t decode_wireline_command(const uint8_t *packet, uint32_t *rolling,
518+
uint64_t *device_id, uint16_t *command,
519+
uint32_t *payload) {
520+
int8_t err = 0;
521+
uint64_t fixed;
522+
uint32_t data;
523+
524+
err = decode_wireline(packet, rolling, &fixed, &data);
525+
if (err < 0) {
526+
return err;
527+
}
528+
529+
*device_id = fixed & 0xf0ffffffff;
530+
*command = ((fixed >> 24) & 0xf00) | (data & 0xff);
531+
*payload = ((data << 8) & 0xf0000) | ((data >> 8) & 0xff00) | (data >> 24);
532+
533+
return 0;
534+
}

src/secplus.h

+8
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ extern int8_t encode_wireline(uint32_t rolling, uint64_t fixed, uint32_t data,
3535
extern int8_t decode_wireline(const uint8_t *packet, uint32_t *rolling,
3636
uint64_t *fixed, uint32_t *data);
3737

38+
extern int8_t encode_wireline_command(uint32_t rolling, uint64_t device_id,
39+
uint16_t command, uint32_t payload,
40+
uint8_t *packet);
41+
42+
extern int8_t decode_wireline_command(const uint8_t *packet, uint32_t *rolling,
43+
uint64_t *device_id, uint16_t *command,
44+
uint32_t *payload);
45+
3846
#ifdef __cplusplus
3947
}
4048
#endif

test/avr_test.c

+36-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ void get_bytes(uint8_t *in, uint8_t len) {
1111
}
1212
}
1313

14+
void get_uint16(uint16_t *in) {
15+
for (int8_t i = 0; i < 2; i++) {
16+
*in >>= 8;
17+
*in |= (uint32_t)special_input_port << 8;
18+
}
19+
}
20+
1421
void get_uint32(uint32_t *in) {
1522
for (int8_t i = 0; i < 4; i++) {
1623
*in >>= 8;
@@ -31,6 +38,13 @@ void put_bytes(uint8_t *out, uint8_t len) {
3138
}
3239
}
3340

41+
void put_uint16(uint16_t out) {
42+
for (int8_t i = 0; i < 2; i++) {
43+
special_output_port = out & 0xff;
44+
out >>= 8;
45+
}
46+
}
47+
3448
void put_uint32(uint32_t out) {
3549
for (int8_t i = 0; i < 4; i++) {
3650
special_output_port = out & 0xff;
@@ -54,6 +68,7 @@ int main() {
5468
uint32_t rolling;
5569
uint32_t fixed_v1;
5670
uint64_t fixed_v2;
71+
uint16_t command;
5772
uint32_t data;
5873

5974
uint8_t buf[40];
@@ -95,36 +110,54 @@ int main() {
95110
put_bytes(buf, 19);
96111
break;
97112
case 5:
113+
get_uint32(&rolling);
114+
get_uint64(&fixed_v2);
115+
get_uint16(&command);
116+
get_uint32(&data);
117+
err = encode_wireline_command(rolling, fixed_v2, command, data, buf);
118+
put_err(err);
119+
put_bytes(buf, 19);
120+
break;
121+
case 6:
98122
get_bytes(buf, 40);
99123
err = decode_v1(&buf[0], &buf[20], &rolling, &fixed_v1);
100124
put_err(err);
101125
put_uint32(rolling);
102126
put_uint32(fixed_v1);
103127
break;
104-
case 6:
128+
case 7:
105129
get_bytes(buf, 10);
106130
err = decode_v2(0, &buf[0], &buf[5], &rolling, &fixed_v2, &data);
107131
put_err(err);
108132
put_uint32(rolling);
109133
put_uint64(fixed_v2);
110134
put_uint32(data);
111135
break;
112-
case 7:
136+
case 8:
113137
get_bytes(buf, 16);
114138
err = decode_v2(1, &buf[0], &buf[8], &rolling, &fixed_v2, &data);
115139
put_err(err);
116140
put_uint32(rolling);
117141
put_uint64(fixed_v2);
118142
put_uint32(data);
119143
break;
120-
case 8:
144+
case 9:
121145
get_bytes(buf, 19);
122146
err = decode_wireline(buf, &rolling, &fixed_v2, &data);
123147
put_err(err);
124148
put_uint32(rolling);
125149
put_uint64(fixed_v2);
126150
put_uint32(data);
127151
break;
152+
case 10:
153+
get_bytes(buf, 19);
154+
err = decode_wireline_command(buf, &rolling, &fixed_v2, &command, &data);
155+
put_err(err);
156+
put_uint32(rolling);
157+
put_uint64(fixed_v2);
158+
put_uint16(command);
159+
put_uint32(data);
160+
break;
128161
}
129162
}
130163

test_secplus.py

+65-7
Original file line numberDiff line numberDiff line change
@@ -671,25 +671,25 @@ def test_encode_wireline_command_device_id_limit(self):
671671
secplus.encode_wireline_command(rolling, device_id, command, payload)
672672
self.assertIn(str(cm.exception), ["Device ID must be less than 2^40", "Invalid input"])
673673

674-
def test_encode_wireline_command_limit(self):
674+
def test_encode_wireline_command_command_limit(self):
675675
rolling = 2**28 - 1
676676
device_id = 2**40 - 1
677677
command = 2**12
678678
payload = 2**20 - 1
679679

680680
with self.assertRaises(ValueError) as cm:
681681
secplus.encode_wireline_command(rolling, device_id, command, payload)
682-
self.assertEqual(str(cm.exception), "Command must be less than 2^12")
682+
self.assertIn(str(cm.exception), ["Command must be less than 2^12", "Invalid input"])
683683

684-
def test_encode_wireline_payload_limit(self):
684+
def test_encode_wireline_command_payload_limit(self):
685685
rolling = 2**28 - 1
686686
device_id = 2**40 - 1
687687
command = 2**12 - 1
688688
payload = 2**20
689689

690690
with self.assertRaises(ValueError) as cm:
691691
secplus.encode_wireline_command(rolling, device_id, command, payload)
692-
self.assertEqual(str(cm.exception), "Payload value must be less than 2^20")
692+
self.assertIn(str(cm.exception), ["Payload value must be less than 2^20", "Invalid input"])
693693

694694
def test_decode_wireline_command_bits_8_9(self):
695695
for code in self.wireline_codes:
@@ -741,6 +741,8 @@ def substitute_c():
741741
libsecplus.decode_v2.restype = c_int8
742742
libsecplus.encode_wireline.restype = c_int8
743743
libsecplus.decode_wireline.restype = c_int8
744+
libsecplus.encode_wireline_command.restype = c_int8
745+
libsecplus.decode_wireline_command.restype = c_int8
744746

745747
def encode(rolling, fixed):
746748
if rolling >= 2**32:
@@ -845,6 +847,33 @@ def decode_wireline(code):
845847

846848
secplus.decode_wireline = decode_wireline
847849

850+
def encode_wireline_command(rolling, device_id, command, payload):
851+
packet = create_string_buffer(os.urandom(19), 19)
852+
err = libsecplus.encode_wireline_command(c_uint32(rolling), c_uint64(device_id), c_uint16(command), c_uint32(payload), packet)
853+
if err < 0:
854+
raise ValueError("Invalid input")
855+
return packet.raw
856+
857+
secplus.encode_wireline_command = encode_wireline_command
858+
859+
def decode_wireline_command(code):
860+
if not isinstance(code, bytes):
861+
raise ValueError("Input must be bytes")
862+
if len(code) != 19:
863+
raise ValueError("Input must be 19 bytes long")
864+
865+
rolling = c_uint32()
866+
device_id = c_uint64()
867+
command = c_uint16()
868+
payload = c_uint32()
869+
870+
err = libsecplus.decode_wireline_command(code, byref(rolling), byref(device_id), byref(command), byref(payload))
871+
if err < 0:
872+
raise ValueError("Invalid input")
873+
return rolling.value, device_id.value, command.value, payload.value
874+
875+
secplus.decode_wireline_command = decode_wireline_command
876+
848877

849878
def substitute_avr():
850879
import subprocess
@@ -869,7 +898,7 @@ def encode(rolling, fixed):
869898
secplus.encode = encode
870899

871900
def decode(code):
872-
sim.stdin.write(bytes([5]))
901+
sim.stdin.write(bytes([6]))
873902
sim.stdin.write(bytes(code))
874903
sim.stdin.flush()
875904
err, rolling, fixed = struct.unpack("<BLL", sim.stdout.read(9))
@@ -909,7 +938,7 @@ def encode_v2(rolling, fixed, data=None):
909938
secplus.encode_v2 = encode_v2
910939

911940
def decode_v2(code):
912-
command = 6 if len(code) == 80 else 7
941+
command = 7 if len(code) == 80 else 8
913942

914943
code_bytes = []
915944
for offset in range(0, len(code), 8):
@@ -951,7 +980,7 @@ def decode_wireline(code):
951980
if len(code) != 19:
952981
raise ValueError("Input must be 19 bytes long")
953982

954-
sim.stdin.write(bytes([8]))
983+
sim.stdin.write(bytes([9]))
955984
sim.stdin.write(code)
956985
sim.stdin.flush()
957986
err, rolling, fixed, data = struct.unpack("<BLQL", sim.stdout.read(17))
@@ -962,6 +991,35 @@ def decode_wireline(code):
962991

963992
secplus.decode_wireline = decode_wireline
964993

994+
def encode_wireline_command(rolling, device_id, command, payload):
995+
sim.stdin.write(struct.pack("<BLQHL", 5, rolling, device_id, command, payload))
996+
sim.stdin.flush()
997+
err = sim.stdout.read(1)[0]
998+
packet = sim.stdout.read(19)
999+
1000+
if err != 0:
1001+
raise ValueError("Invalid input")
1002+
return packet
1003+
1004+
secplus.encode_wireline_command = encode_wireline_command
1005+
1006+
def decode_wireline_command(code):
1007+
if not isinstance(code, bytes):
1008+
raise ValueError("Input must be bytes")
1009+
if len(code) != 19:
1010+
raise ValueError("Input must be 19 bytes long")
1011+
1012+
sim.stdin.write(bytes([10]))
1013+
sim.stdin.write(code)
1014+
sim.stdin.flush()
1015+
err, rolling, device_id, command, payload = struct.unpack("<BLQHL", sim.stdout.read(19))
1016+
1017+
if err != 0:
1018+
raise ValueError("Invalid input")
1019+
return rolling, device_id, command, payload
1020+
1021+
secplus.decode_wireline_command = decode_wireline_command
1022+
9651023
return sim
9661024

9671025

0 commit comments

Comments
 (0)