SpaceOS wire protocol codecs for host-guest communication
1let page_size = 4096
2
3(* Field offsets *)
4let off_heartbeat = 0x000
5let off_heartbeat_ack = 0x008
6let off_time_version = 0x010
7let off_time_seconds = 0x014
8let off_time_nanos = 0x01C
9let off_guest_status = 0x020
10let off_host_cmd = 0x024
11let off_guest_cmd_ack = 0x028
12let off_health_string = 0x100
13let health_string_len = 256
14
15(* uint64 big-endian accessors *)
16let heartbeat buf = Bytes.get_int64_be buf off_heartbeat
17let set_heartbeat buf v = Bytes.set_int64_be buf off_heartbeat v
18let heartbeat_ack buf = Bytes.get_int64_be buf off_heartbeat_ack
19let set_heartbeat_ack buf v = Bytes.set_int64_be buf off_heartbeat_ack v
20
21(* uint32 big-endian accessors *)
22let time_version buf = Int32.to_int (Bytes.get_int32_be buf off_time_version)
23
24let set_time_version buf v =
25 Bytes.set_int32_be buf off_time_version (Int32.of_int v)
26
27let time_seconds buf = Bytes.get_int64_be buf off_time_seconds
28let set_time_seconds buf v = Bytes.set_int64_be buf off_time_seconds v
29let time_nanos buf = Int32.to_int (Bytes.get_int32_be buf off_time_nanos)
30
31let set_time_nanos buf v =
32 Bytes.set_int32_be buf off_time_nanos (Int32.of_int v)
33
34let guest_status buf = Int32.to_int (Bytes.get_int32_be buf off_guest_status)
35
36let set_guest_status buf v =
37 Bytes.set_int32_be buf off_guest_status (Int32.of_int v)
38
39let host_cmd buf = Int32.to_int (Bytes.get_int32_be buf off_host_cmd)
40let set_host_cmd buf v = Bytes.set_int32_be buf off_host_cmd (Int32.of_int v)
41let guest_cmd_ack buf = Int32.to_int (Bytes.get_int32_be buf off_guest_cmd_ack)
42
43let set_guest_cmd_ack buf v =
44 Bytes.set_int32_be buf off_guest_cmd_ack (Int32.of_int v)
45
46let health_string buf =
47 let s = Bytes.sub_string buf off_health_string health_string_len in
48 (* Find null terminator *)
49 match String.index_opt s '\x00' with
50 | Some i -> String.sub s 0 i
51 | None -> s
52
53let set_health_string buf s =
54 let len = min health_string_len (String.length s) in
55 Bytes.blit_string s 0 buf off_health_string len;
56 (* Null-terminate *)
57 if len < health_string_len then
58 Bytes.fill buf (off_health_string + len) (health_string_len - len) '\x00'
59
60(* Mission time with seqlock *)
61type mission_time = { seconds : int64; nanos : int }
62
63let write_mission_time buf t =
64 let v = time_version buf + 1 in
65 set_time_version buf v;
66 (* odd = write in progress *)
67 set_time_seconds buf t.seconds;
68 set_time_nanos buf t.nanos;
69 set_time_version buf (v + 1)
70(* even = write complete *)
71
72let read_mission_time buf =
73 let rec loop () =
74 let v1 = time_version buf in
75 if v1 land 1 <> 0 then loop () (* spin-wait: host is mid-write *)
76 else
77 let seconds = time_seconds buf in
78 let nanos = time_nanos buf in
79 let v2 = time_version buf in
80 if v1 <> v2 then loop () (* torn read, retry *) else { seconds; nanos }
81 in
82 loop ()
83
84(* Command word bits *)
85let cmd_shutdown = 1 lsl 0
86let cmd_param_reload = 1 lsl 1
87let cmd_dp_ack = 1 lsl 2