Skip to content

Commit

Permalink
Merge branch 'rust'
Browse files Browse the repository at this point in the history
This branch adds initial support for rust programming language. This
change is super experimental at this time and should not be used in any
production system.

Signed-off-by: Siddharth Chandrasekaran <[email protected]>
  • Loading branch information
sidcha committed Nov 1, 2023
2 parents 298576d + 27efc30 commit 0773728
Show file tree
Hide file tree
Showing 21 changed files with 1,803 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ indent_style = tab
indent_size = 8

# 4 space indentation
[*.{py.in,py,md,cmake}]
[*.{py.in,py,md,cmake,rs}]
indent_style = space
indent_size = 4
19 changes: 19 additions & 0 deletions .github/workflows/build-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,22 @@ jobs:
- name: ClangFormatCheck
run: |
./scripts/clang-format-check.sh
Rust:
name: Rust
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- name: Cargo check
uses: actions-rs/cargo@v1
with:
command: check
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,7 @@ config.make
__pycache__/
.cache/
*.pyc

## Rust
/Cargo.lock
/target/
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]
resolver = "2"
members = [
"rust"
]
14 changes: 14 additions & 0 deletions rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
24 changes: 24 additions & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
edition = "2021"
name = "osdp"
version = "0.1.0"
authors = ["Siddharth Chandrasekaran <[email protected]>"]
description = "Library implementation of IEC 60839-11-5 OSDP (Open Supervised Device Protocol)"
documentation = "https://libosdp.sidcha.dev/rust"
homepage = "https://libosdp.sidcha.dev/"
readme = "README.md"
repository = "https://github.com/goToMain/libosdp"
license = "Apache-2.0"
keywords = ["osdp", "libosdp", "protocol", "sia", "osdpctl", "weigand" ]
categories = ["development-tools", "embedded"]

[build-dependencies]
anyhow = "1.0.75"
cc = "1.0.83"
bindgen = "0.68.1"

[dependencies]
anyhow = "1.0.75"
bitflags = "2.4.0"
lazy_static = "1.4.0"
multiqueue = "0.3.2"
18 changes: 18 additions & 0 deletions rust/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# OSDP Rust library

This crate is a rust wrapper for the C library [LibOSDP][1].

## Usage

TODO

### Control panel

TODO

### Peripheral device

TODO


1: https://github.cobm/goToMain/liosdp
66 changes: 66 additions & 0 deletions rust/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use std::path::PathBuf;

use anyhow::Context;
type Result<T> = anyhow::Result<T, anyhow::Error>;

fn main() -> Result<()> {
// Tell Cargo that if the given file changes, to rerun this build script.
// println!("cargo:rerun-if-changed=src/hello.c");
// Use the `cc` crate to build a C file and statically link it.
let repo_root = std::fs::canonicalize("../")?.into_os_string().into_string().unwrap();
let mut build = cc::Build::new();
let builder = build
.include("../src/")
.include("../include/")
.include("../utils/include/")
.define("REPO_ROOT", format!("\"{}\"", repo_root.as_str()).as_str())
.define("CONFIG_NO_GENERATED_HEADERS", None)
.define("PROJECT_VERSION", format!("\"{}\"", "2.2.0").as_str())
.define("PROJECT_NAME", format!("\"{}\"", "libosdp").as_str())
.define("GIT_BRANCH", format!("\"{}\"", "master").as_str())
.define("GIT_REV", format!("\"{}\"", "6dc2621").as_str())
.define("GIT_TAG", "\"\"")
.define("GIT_DIFF", format!("\"{}\"", "+").as_str())
.define("OSDP_PD_SC_RETRY_MS", "600000")
.define("OSDP_PD_POLL_TIMEOUT_MS", "50")
.define("OSDP_PD_SC_TIMEOUT_MS", "800")
.define("OSDP_RESP_TOUT_MS", "200")
.define("OSDP_ONLINE_RETRY_WAIT_MAX_MS", "300000")
.define("OSDP_CMD_RETRY_WAIT_MS", "300")
.define("OSDP_PACKET_BUF_SIZE", "256")
.define("OSDP_RX_RB_SIZE", "512")
.define("OSDP_CP_CMD_POOL_SIZE", "32")
.define("OSDP_FILE_ERROR_RETRY_MAX", "10")
.define("OSDP_PD_MAX", "126")
.define("OSDP_CMD_ID_OFFSET", "5")
.define("OSDP_EXPORT", "")
.define("OSDP_NO_EXPORT", "")
.define("OSDP_DEPRECATED_EXPORT", "")
.warnings(true)
.warnings_into_errors(true)
.file("../utils/src/list.c")
.file("../utils/src/queue.c")
.file("../utils/src/slab.c")
.file("../utils/src/utils.c")
.file("../utils/src/disjoint_set.c")
.file("../utils/src/logger.c")
.file("../src/osdp_common.c")
.file("../src/osdp_phy.c")
.file("../src/osdp_sc.c")
.file("../src/osdp_file.c")
.file("../src/osdp_pd.c")
.file("../src/osdp_cp.c")
.file("../src/crypto/tinyaes_src.c")
.file("../src/crypto/tinyaes.c");

builder.compile("libosdp.a");

let bindings = bindgen::Builder::default()
.header("../include/osdp.h")
.generate()
.context("Unable to generate bindings")?;

let out_path = PathBuf::from(std::env::var("OUT_DIR").unwrap());
bindings.write_to_file(out_path.join("bindings.rs"))
.context("Couldn't write bindings!")
}
78 changes: 78 additions & 0 deletions rust/examples/cp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::{
io::{Read,Write},
path::PathBuf,
os::unix::net::UnixStream,
time::Duration,
thread
};
use osdp::{
cp::ControlPanel,
common::{PdInfo, OsdpFlag, PdId},
channel::{OsdpChannel, Channel}
};

type Result<T> = anyhow::Result<T, anyhow::Error>;

struct UnixChannel {
stream: UnixStream,
}

impl UnixChannel {
pub fn new(path: PathBuf) -> Result<Self> {
let stream = UnixStream::connect(&path)?;
Ok(Self {
stream,
})
}
}

impl Read for UnixChannel {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.stream.read(buf)
}
}

impl Write for UnixChannel {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.stream.write(buf)
}

fn flush(&mut self) -> std::io::Result<()> {
self.stream.flush()
}
}

impl Channel for UnixChannel {
fn get_id(&self) -> i32 {
1
}
}

fn main() -> anyhow::Result<(), anyhow::Error> {
let stream = UnixChannel::new("/tmp/osdp-conn-1".into())?;
let channel: OsdpChannel = OsdpChannel::new::<UnixChannel>(Box::new(stream));
let pd0 = PdInfo::new(
"PD 101", 101,
115200,
OsdpFlag::EnforceSecure,
PdId {
version: 0x01,
model: 0x02,
vendor_code: 0x03,
serial_number: 0x04,
firmware_version: 0x05,
},
vec![],
channel,
[
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
]
);
let mut pd_info = vec![pd0];
let mut cp = ControlPanel::new(&mut pd_info)?;
loop {
cp.refresh();
thread::sleep(Duration::from_millis(50));
}
}
88 changes: 88 additions & 0 deletions rust/examples/pd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use std::{
os::unix::net::{UnixStream, UnixListener},
path::PathBuf,
io::{Read, Write},
time::Duration,
thread
};
use osdp::{
pd::PeripheralDevice,
common::{PdInfo, OsdpFlag, PdId, PdCapability, PdCapEntry},
channel::{OsdpChannel, Channel},
};

type Result<T> = anyhow::Result<T, anyhow::Error>;

struct UnixChannel {
stream: Option<UnixStream>,
}

impl UnixChannel {
pub fn new(path: PathBuf) -> Result<Self> {
let listener = UnixListener::bind(&path)?;
let (stream, _) = listener.accept()?;
Ok(Self {
stream: Some(stream),
})
}
}

impl Read for UnixChannel {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let stream = self.stream.as_mut().unwrap();
stream.read(buf)
}
}

impl Write for UnixChannel {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let stream = self.stream.as_mut().unwrap();
stream.write(buf)
}

fn flush(&mut self) -> std::io::Result<()> {
let stream = self.stream.as_mut().unwrap();
stream.flush()
}
}

impl Channel for UnixChannel {
fn get_id(&self) -> i32 {
1
}
}

fn main() -> anyhow::Result<(), anyhow::Error> {
let stream = UnixChannel::new("/tmp/osdp-conn-1".into())?;
let channel: OsdpChannel = OsdpChannel::new::<UnixChannel>(Box::new(stream));
let mut pd_info = PdInfo::new(
"PD 101",
101,
115200,
OsdpFlag::EnforceSecure,
PdId {
version: 0x01,
model: 0x02,
vendor_code: 0x03,
serial_number: 0x04,
firmware_version: 0x05,
},
vec![
PdCapability::CommunicationSecurity(PdCapEntry { compliance: 1, num_items: 1 }),
],
channel,
[
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
]
);
let mut pd = PeripheralDevice::new(&mut pd_info)?;
pd.set_command_callback(|_| {
println!("Received command!");
0
});
loop {
pd.refresh();
thread::sleep(Duration::from_millis(50));
}
}
Loading

0 comments on commit 0773728

Please sign in to comment.