SpaceOS wire protocol codecs for host-guest communication
at main 87 lines 2.9 kB view raw
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