package serialport

  1. Overview
  2. Docs

Source file serialport_lwt.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
open Lwt.Syntax

type t = {
  fd : Lwt_unix.file_descr;
  oc : Lwt_io.output_channel;
  ic : Lwt_io.input_channel;
  port_name : string;
}

let make ~port_name fd =
  let oc = Lwt_io.of_fd ~mode:Output fd in
  let ic = Lwt_io.of_fd ~mode:Input fd in

  { fd; oc; ic; port_name }

exception Not_found_port of string

let open_communication ?switch ?(exclusive = true) ~opts:port_opts port_name =
  let* _ =
    if not (Sys.file_exists port_name) then Lwt.fail (Not_found_port port_name)
    else Lwt.return_unit
  in

  let* fd =
    Lwt_unix.openfile port_name [ O_RDWR; O_NOCTTY; O_NONBLOCK ] 0o000
  in

  Lwt_switch.add_hook switch (fun () -> Lwt_unix.close fd);

  let unix_fd = Lwt_unix.unix_file_descr fd in

  Serialport.Native.flush_serial_port unix_fd;
  Serialport.Native.initialize_serial_port_by_port_opts unix_fd port_opts;
  Serialport.Native.set_serial_port_exclusive unix_fd exclusive;

  Lwt.return @@ make ~port_name fd

let close_communication { oc; _ } = Lwt_io.close oc

let with_open_communication ?(exclusive = true) ~opts port_name f =
  Lwt_switch.with_switch @@ fun switch ->
  Lwt.Infix.(open_communication ~switch ~exclusive ~opts port_name >>= f)

let to_channels { ic; oc; _ } = (ic, oc)
let[@inline] to_unix_fd { fd; _ } = Lwt_unix.unix_file_descr fd

module Modem = struct
  let set_request_to_send ser_port level =
    Serialport.Modem.set_request_to_send (to_unix_fd ser_port) level

  and set_data_terminal_ready ser_port level =
    Serialport.Modem.set_data_terminal_ready (to_unix_fd ser_port) level
end

let set_exclusive ser_port enable =
  Serialport.Native.set_serial_port_exclusive (to_unix_fd ser_port) enable

let pp fmt { port_name; _ } = Lwt_fmt.fprintf fmt "SerialPort(%s)" port_name