Initial commit: telfax - Rust Fax Server

- Modem driver (serialport) with AT command interface
- Class 1 fax protocol (T.30 session, HDLC framing)
- T.4/T.6 image codec (fax crate integration)
- Document conversion (image to fax, TIFF-F output)
- REST API (axum) for fax job management
- SQLite/InMemory job queue
- CLI interface (detect/serve/send/test)
- Integration tests passing
This commit is contained in:
Warren
2026-07-01 09:06:41 +08:00
commit 13438289fe
28 changed files with 4615 additions and 0 deletions
+91
View File
@@ -0,0 +1,91 @@
#[derive(Debug, Clone)]
pub struct FaxCapabilities {
pub resolution: Resolution,
pub page_width: PageWidth,
pub page_length: PageLength,
pub data_rate: DataRate,
pub ecm: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Resolution {
Standard, // 98 lpi, 204 dpi
Fine, // 196 lpi, 204 dpi
SuperFine, // 392 lpi, 204 dpi
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PageWidth {
A4, // 1728 pels
A3, // 2432 pels
B4, // 2048 pels
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PageLength {
A4, // 297mm
Unlimited,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DataRate {
V27ter2400,
V27ter4800,
V29_7200,
V29_9600,
V17_7200,
V17_9600,
V17_12000,
V17_14400,
}
impl DataRate {
pub fn to_modulation_value(&self) -> u32 {
match self {
DataRate::V27ter2400 => 24,
DataRate::V27ter4800 => 48,
DataRate::V29_7200 => 72,
DataRate::V29_9600 => 96,
DataRate::V17_7200 => 73,
DataRate::V17_9600 => 97,
DataRate::V17_12000 => 121,
DataRate::V17_14400 => 145,
}
}
pub fn from_modulation_value(val: u32) -> Option<Self> {
match val {
24 => Some(DataRate::V27ter2400),
48 => Some(DataRate::V27ter4800),
72 => Some(DataRate::V29_7200),
96 => Some(DataRate::V29_9600),
73 => Some(DataRate::V17_7200),
97 => Some(DataRate::V17_9600),
121 => Some(DataRate::V17_12000),
145 => Some(DataRate::V17_14400),
_ => None,
}
}
pub fn max_for_modem(supported_rates: &[u32]) -> Option<Self> {
let priority = [145, 121, 97, 73, 96, 72, 48, 24];
for rate in &priority {
if supported_rates.contains(rate) {
return Self::from_modulation_value(*rate);
}
}
None
}
}
impl Default for FaxCapabilities {
fn default() -> Self {
Self {
resolution: Resolution::Fine,
page_width: PageWidth::A4,
page_length: PageLength::A4,
data_rate: DataRate::V17_14400,
ecm: true,
}
}
}