From 86399a4cdf03803dc04e00140156aeb6a7e9207d Mon Sep 17 00:00:00 2001 From: xenia Date: Fri, 26 Apr 2024 02:41:04 -0400 Subject: [PATCH] meow meow --- lib/dune | 2 +- lib/eio_device.ml | 0 lib/eio_serial.ml | 79 ++++++++++++++++++++++++++++++++++++++++++++++ lib/eio_serial.mli | 18 +++++++++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 lib/eio_device.ml create mode 100644 lib/eio_serial.mli diff --git a/lib/dune b/lib/dune index 5bcf563..26d511e 100644 --- a/lib/dune +++ b/lib/dune @@ -1,4 +1,4 @@ (library (name bk910x) (public_name bk910x) - (libraries eio xlog)) + (libraries eio eio_linux xlog)) diff --git a/lib/eio_device.ml b/lib/eio_device.ml new file mode 100644 index 0000000..e69de29 diff --git a/lib/eio_serial.ml b/lib/eio_serial.ml index e69de29..5afa651 100644 --- a/lib/eio_serial.ml +++ b/lib/eio_serial.ml @@ -0,0 +1,79 @@ +open Eio.Std + +type t = { + fd : Eio_unix.Fd.t +} + +type parity = +| Parity_none +| Parity_even +| Parity_odd + +type flow_control = +| Flow_none +| Flow_software +| Flow_hardware + +(* currently this defaults to Eio_linux. idk of a better way to handle this because there's no high + level method to open with O_NOCTTY *) + +let make ~(sw : Switch.t) ?(baudrate=115200) ?(bytesize=8) ?(parity=Parity_none) ?(stopbits=1) + ?(flowctrl=Flow_none) ?(exclusive=false) + (path : _ Eio.Path.t) : t = + (* and here we run into our first problem: how do we wrangle a path into an argument to openat *) + let path = Eio.Path.native_exn path in + let fd = + Eio_linux.Low_level.openat ~sw ~access:`RW ~flags:Uring.Open_flags.(cloexec + noctty) + ~perm:0 Eio_linux.Low_level.Fs path in + (* TODO *) + ignore exclusive; (* acquire lock *) + Switch.on_release sw (fun () -> + (* release lock *) + ignore exclusive; + Eio_unix.Fd.close fd + ); + Eio_unix.Fd.use_exn "tty setup" fd (fun fd -> + let attr = Unix.tcgetattr fd in + let attr = { + attr with + c_clocal = true; + c_cread = true; + c_icanon = false; + c_echo = false; + c_echoe = false; + c_echok = false; + c_echonl = false; + c_isig = false; + c_opost = false; + c_inlcr = false; + c_igncr = false; + c_icrnl = false; + c_ignbrk = false; + c_parmrk = false; + c_inpck = false; + c_istrip = false; + + c_obaud = baudrate; + c_ibaud = baudrate; + c_csize = bytesize; + c_cstopb = stopbits; + c_parenb = (parity != Parity_none); + c_parodd = (parity == Parity_odd); + + c_ixon = (flowctrl == Flow_software); + c_ixoff = (flowctrl == Flow_software); + + (* rtscts is not exposed by ocaml *) + + c_vmin = 0; + c_vtime = 0; + } in + Unix.tcsetattr fd Unix.TCSANOW attr; + (* here we'd also reset rstcts and dsrdtr but again.... ocaml... *) + Unix.tcflush fd Unix.TCIFLUSH); + (* how to convert this into flow...... *) + { fd; } + +let tcflow (port : t) (action : Unix.flow_action) : unit = + Eio_unix.Fd.use_exn "tcflow" port.fd (fun fd -> + Unix.tcflow fd action) diff --git a/lib/eio_serial.mli b/lib/eio_serial.mli new file mode 100644 index 0000000..8115b51 --- /dev/null +++ b/lib/eio_serial.mli @@ -0,0 +1,18 @@ +open Eio.Std + +type t + +type parity = +| Parity_none +| Parity_even +| Parity_odd + +type flow_control = +| Flow_none +| Flow_software +| Flow_hardware + +val make : sw:Switch.t -> ?baudrate:int -> ?bytesize:int -> ?parity:parity -> ?stopbits:int -> + ?flowctrl:flow_control -> ?exclusive:bool -> _ Eio.Path.t -> t + +val tcflow : t -> Unix.flow_action -> unit