Skip to main content

usb_gadget/function/
printer.rs

1//! Printer function.
2//!
3//! The Linux kernel configuration option `CONFIG_USB_CONFIGFS_F_PRINTER` must be enabled.
4//!
5//! A device file at `/dev/g_printerN` will be created for each instance of the function, where N
6//! instance number. See `examples/printer.rs` for an example.
7
8use bitflags::bitflags;
9use std::{ffi::OsString, io::Result};
10
11use super::{
12    util::{FunctionDir, Status},
13    Function, Handle,
14};
15
16/// Get printer status ioctrl ID
17pub const GADGET_GET_PRINTER_STATUS: u8 = 0x21;
18/// Set printer status ioctrl ID
19pub const GADGET_SET_PRINTER_STATUS: u8 = 0x22;
20
21bitflags! {
22    #[derive(Clone, Copy, Debug)]
23    #[non_exhaustive]
24    /// [Printer status flags](https://www.usb.org/sites/default/files/usbprint11a021811.pdf)
25    pub struct StatusFlags: u8 {
26        /// Printer not in error state
27        const NOT_ERROR = (1 << 3);
28        /// Printer selected
29        const SELECTED = (1 << 4);
30        /// Printer out of paper
31        const PAPER_EMPTY = (1 << 5);
32    }
33}
34
35/// Builder for USB printer function.
36#[derive(Debug, Clone)]
37#[non_exhaustive]
38pub struct PrinterBuilder {
39    /// The PNP ID string used for this printer.
40    pub pnp_string: Option<String>,
41    /// The number of 8k buffers to use per endpoint. The default is 10.
42    pub qlen: Option<u8>,
43}
44
45impl PrinterBuilder {
46    /// Build the USB function.
47    ///
48    /// The returned handle must be added to a USB gadget configuration.
49    #[must_use]
50    pub fn build(self) -> (Printer, Handle) {
51        let dir = FunctionDir::new();
52        (Printer { dir: dir.clone() }, Handle::new(PrinterFunction { builder: self, dir }))
53    }
54}
55
56#[derive(Debug)]
57struct PrinterFunction {
58    builder: PrinterBuilder,
59    dir: FunctionDir,
60}
61
62impl Function for PrinterFunction {
63    fn driver(&self) -> OsString {
64        "printer".into()
65    }
66
67    fn dir(&self) -> FunctionDir {
68        self.dir.clone()
69    }
70
71    fn register(&self) -> Result<()> {
72        if let Some(pnp_string) = &self.builder.pnp_string {
73            self.dir.write("pnp_string", pnp_string)?;
74        }
75        if let Some(qlen) = self.builder.qlen {
76            self.dir.write("q_len", qlen.to_string())?;
77        }
78
79        Ok(())
80    }
81}
82
83/// USB printer function.
84#[derive(Debug)]
85pub struct Printer {
86    dir: FunctionDir,
87}
88
89impl Printer {
90    /// Creates a new USB printer builder.
91    pub fn builder() -> PrinterBuilder {
92        PrinterBuilder { pnp_string: None, qlen: None }
93    }
94
95    /// Creates a new USB printer function and handle with f_printer defaults
96    #[must_use]
97    pub fn new(self) -> (Printer, Handle) {
98        Self::builder().build()
99    }
100
101    /// Access to registration status.
102    pub fn status(&self) -> Status {
103        self.dir.status()
104    }
105}