usbip_device/
lib.rs

1pub(crate) mod cmd;
2pub(crate) mod debug;
3pub(crate) mod handler;
4pub(crate) mod op;
5pub(crate) mod request;
6pub(crate) mod response;
7
8use crate::{cmd::UsbIpHeader, handler::SocketHandler, request::UsbIpCmdSubmit};
9use std::{
10    collections::VecDeque,
11    sync::{Arc, Mutex, MutexGuard},
12};
13use usb_device::{
14    Result as UsbResult, UsbDirection, UsbError,
15    {
16        bus::{PollResult, UsbBus},
17        endpoint::{EndpointAddress, EndpointType},
18    },
19};
20
21#[derive(Debug, Clone)]
22/// The error type, used by this crate.
23pub enum UsbIpError {
24    /// The connection closed unexpectedly.
25    ConnectionClosed,
26
27    /// A packet was received but it was shorter than the 48 bytes required to parse the header.
28    PkgTooShort(usize),
29
30    /// A received packet contained a command, that is unknown to the USBIP specification.
31    InvalidCommand(u16),
32
33    /// A received packet had a status field set to an unknown status value.
34    StatusNotOk(u32),
35}
36
37impl std::fmt::Display for UsbIpError {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        match self {
40            Self::ConnectionClosed => write!(f, "connection no longer exsists"),
41            Self::PkgTooShort(len) => write!(f, "packet of length {} is to short to parse", len),
42            Self::InvalidCommand(cmd) => write!(f, "unknown command: {}", cmd),
43            Self::StatusNotOk(status) => write!(f, "received invalid status: {}", status),
44        }
45    }
46}
47
48impl std::error::Error for UsbIpError {}
49
50const NUM_ENDPOINTS: usize = 8;
51
52#[derive(Debug, Clone)]
53pub(crate) struct Pipe {
54    pub data: VecDeque<Vec<u8>>,
55    pub ty: EndpointType,
56    pub max_packet_size: u16,
57    #[allow(dead_code)]
58    pub interval: u8,
59}
60
61impl Pipe {
62    /// Checks, whether the endpoint contains a full transaction
63    /// (terminated by a short packet) and is ready to send it.
64    pub fn is_rts(&self) -> bool {
65        match self.data.back() {
66            // If there is no data pending, we are not ready to send
67            None => false,
68            Some(val) => {
69                if self.ty != EndpointType::Control {
70                    true
71                } else {
72                    // Control Endpoint use packet transactions.
73                    // Therefore, we must wait until a transaction is complete before we return the packets
74                    val.len() < self.max_packet_size as usize
75                }
76            }
77        }
78    }
79}
80
81#[derive(Debug, Clone)]
82struct Endpoint {
83    pub(crate) pipe_in: Option<Pipe>,
84    pub(crate) pipe_out: Option<Pipe>,
85    pub(crate) pending_ins: VecDeque<(UsbIpHeader, UsbIpCmdSubmit, Vec<u8>)>,
86    pub(crate) stalled: bool,
87    pub(crate) setup_flag: bool,
88    pub(crate) in_complete_flag: bool,
89}
90
91impl Default for Endpoint {
92    fn default() -> Self {
93        Self {
94            pipe_in: None,
95            pipe_out: None,
96            pending_ins: VecDeque::new(),
97            stalled: true,
98            setup_flag: false,
99            in_complete_flag: false,
100        }
101    }
102}
103
104impl Endpoint {
105    /// Returns the input pipe of this endpoint
106    fn get_in(&mut self) -> UsbResult<&mut Pipe> {
107        self.pipe_in.as_mut().ok_or(UsbError::InvalidEndpoint)
108    }
109
110    /// Returns the output pipe of this endpoint
111    fn get_out(&mut self) -> UsbResult<&mut Pipe> {
112        self.pipe_out.as_mut().ok_or(UsbError::InvalidEndpoint)
113    }
114
115    /// Checks, whether the input pipe is ready to send data back to the host.
116    fn is_rts(&self) -> bool {
117        match self.pipe_in {
118            None => false,
119            Some(ref pipe) => pipe.is_rts(),
120        }
121    }
122
123    /// Processes an unlink and removes the pending packet on this endpoint.
124    ///
125    /// # Returns
126    /// - `true` if pending urb was removed
127    /// - `false` if it was not found
128    // NOTE: This is super inefficient, use linked lists, as soon as linked_list_remove stabilizes
129    fn unlink(&mut self, seqnum: u32) -> bool {
130        let old_len = self.pending_ins.len();
131
132        self.pending_ins = self
133            .pending_ins
134            .drain(..)
135            .filter(|(header, _, _)| header.seqnum != seqnum)
136            .collect();
137
138        // If the length is the same as before, we have not changed anything
139        // and return false
140        old_len != self.pending_ins.len()
141    }
142}
143
144#[derive(Debug)]
145pub(crate) struct UsbIpBusInner {
146    pub handler: SocketHandler,
147    pub endpoint: [Endpoint; NUM_ENDPOINTS],
148    pub device_address: u8,
149    pub reset: bool,
150    pub suspended: bool,
151}
152
153impl UsbIpBusInner {
154    /// Creates a new UsbIpBusInner
155    fn new() -> Self {
156        Self {
157            handler: SocketHandler::new(),
158            endpoint: <[Endpoint; NUM_ENDPOINTS]>::default(),
159            device_address: 0,
160            reset: true,
161            suspended: false,
162        }
163    }
164
165    /// Resets the handler to the state, in which it acts like it is new
166    fn reset(&mut self) {
167        self.endpoint = <[Endpoint; NUM_ENDPOINTS]>::default();
168        self.reset = true;
169        self.suspended = false;
170    }
171
172    /// Returns the first enpoint, that is not already initialized or `None`,
173    /// if all are already in use.
174    fn next_available_endpoint(&self, direction: UsbDirection) -> Option<usize> {
175        match direction {
176            UsbDirection::In => {
177                for i in 1..NUM_ENDPOINTS {
178                    if self.endpoint[i].pipe_in.is_none() {
179                        return Some(i);
180                    }
181                }
182            }
183            UsbDirection::Out => {
184                for i in 1..NUM_ENDPOINTS {
185                    if self.endpoint[i].pipe_out.is_none() {
186                        return Some(i);
187                    }
188                }
189            }
190        }
191
192        None
193    }
194
195    /// Returns the requested endpoint if it exists and
196    /// [`UsbError::InvalidEndpoint`] otherwise.
197    fn get_endpoint(&mut self, ep: usize) -> UsbResult<&mut Endpoint> {
198        //let ep_addr = ep.index();
199
200        if ep >= NUM_ENDPOINTS {
201            log::error!("attempt to access out-of-bounds endpoint {:?}", ep);
202            return Err(UsbError::InvalidEndpoint);
203        }
204
205        Ok(&mut self.endpoint[ep])
206    }
207
208    /// Processes an unlink and removes the pending packet.
209    ///
210    /// # Returns
211    /// - `true` if pending urb was removed
212    /// - `false` if it was not found
213    fn unlink(&mut self, seqnum: u32) -> bool {
214        for i in 0..NUM_ENDPOINTS {
215            if self.endpoint[i].unlink(seqnum) {
216                return true;
217            }
218        }
219
220        false
221    }
222}
223
224#[derive(Debug, Clone)]
225/// An implementation of [`UsbBus`](https://docs.rs/usb-device/0.2.7/usb_device/bus/trait.UsbBus.html),
226/// based on the Linux USBIP protocol.
227pub struct UsbIpBus(Arc<Mutex<UsbIpBusInner>>);
228
229impl UsbIpBus {
230    /// Create a new [`UsbIpBus`].
231    ///
232    /// # Note
233    /// There can only ever be one bus [`UsbIpBus`] device on the system, since
234    /// it is blocking port 3240.
235    ///
236    /// # Panics
237    /// If port 3240 is already in use.
238    pub fn new() -> Self {
239        Self(Arc::new(Mutex::new(UsbIpBusInner::new())))
240    }
241
242    fn lock(&self) -> MutexGuard<UsbIpBusInner> {
243        self.0.lock().unwrap()
244    }
245}
246
247impl Default for UsbIpBus {
248    fn default() -> Self {
249        Self::new()
250    }
251}
252
253impl UsbBus for UsbIpBus {
254    fn alloc_ep(
255        &mut self,
256        ep_dir: UsbDirection,
257        ep_addr: Option<EndpointAddress>,
258        ep_type: EndpointType,
259        max_packet_size: u16,
260        interval: u8,
261    ) -> UsbResult<EndpointAddress> {
262        let mut inner = self.lock();
263
264        // Get the endpoint to initialize
265        let endpoint_index = match ep_addr {
266            Some(addr) => {
267                if addr.index() < NUM_ENDPOINTS {
268                    addr.index()
269                } else {
270                    return Err(UsbError::InvalidEndpoint);
271                }
272            }
273            None => inner
274                .next_available_endpoint(ep_dir)
275                .ok_or(UsbError::EndpointMemoryOverflow)?,
276        };
277
278        let endpoint = &mut inner.endpoint[endpoint_index as usize];
279
280        // check endpoint allocation here
281        let maybe_pipe = match ep_dir {
282            UsbDirection::In => endpoint.get_in(),
283            UsbDirection::Out => endpoint.get_out(),
284        };
285
286        // we want to get an invalid enpoint, otherwise the requested endpoint
287        // was already allocated
288        match maybe_pipe {
289            Err(UsbError::InvalidEndpoint) => (),
290            Ok(_) => return Err(UsbError::InvalidEndpoint),
291            Err(_) => return Err(UsbError::InvalidEndpoint),
292        }
293
294        // initialize the endpoint
295        let pipe = Pipe {
296            data: VecDeque::new(),
297            ty: ep_type,
298            max_packet_size,
299            interval,
300        };
301        match ep_dir {
302            UsbDirection::In => endpoint.pipe_in = Some(pipe),
303            UsbDirection::Out => endpoint.pipe_out = Some(pipe),
304        }
305
306        log::debug!(
307            "initialized new endpoint {:?} as address {:?}",
308            endpoint,
309            endpoint_index
310        );
311
312        Ok(EndpointAddress::from_parts(endpoint_index as usize, ep_dir))
313    }
314
315    fn enable(&mut self) {
316        log::info!("usb device is being enabled");
317    }
318
319    fn reset(&self) {
320        let mut inner = self.lock();
321
322        // Skip if we are already in reset state
323        if inner.reset {
324            return;
325        }
326
327        inner.reset();
328        log::debug!("usb device is being reset");
329    }
330
331    fn set_device_address(&self, addr: u8) {
332        let mut inner = self.lock();
333
334        log::info!("setting device address to {}", addr);
335        inner.device_address = addr;
336    }
337
338    fn write(&self, ep_addr: EndpointAddress, buf: &[u8]) -> UsbResult<usize> {
339        log::trace!("write request at endpoint {}", ep_addr.index());
340        let mut inner = self.lock();
341
342        // We can not write anything, as long as there is no connection
343        if !inner.handler.is_connected() {
344            return Err(UsbError::WouldBlock);
345        }
346
347        // Get the endpoint
348        let ep = inner.get_endpoint(ep_addr.index())?;
349
350        // NOTE: This is a hack to allow driving the setup packets in a transactional way
351        // while the rest of the packets use packet logic
352        if ep_addr.index() == 0 {
353            ep.in_complete_flag = true;
354        }
355
356        let pipe = ep.get_in()?;
357
358        // If there is data waiting in the output buffer, we need to wait
359        if pipe.is_rts() {
360            if ep_addr.index() == 0 {
361                ep.in_complete_flag = false;
362            }
363            return Err(UsbError::WouldBlock);
364        }
365
366        pipe.data.push_back(buf.to_vec());
367
368        // we attempt to service in packets, if we have them available
369        if pipe.is_rts() {
370            inner.try_send_pending(ep_addr.index());
371        }
372
373        Ok(buf.len())
374    }
375
376    fn read(&self, ep_addr: EndpointAddress, buf: &mut [u8]) -> UsbResult<usize> {
377        log::trace!("read request at endpoint {}", ep_addr.index());
378        let mut inner = self.lock();
379        let ep = inner.get_endpoint(ep_addr.index())?;
380        let pipe = ep.get_out()?;
381
382        // Try to get data
383        let data = match pipe.data.pop_front() {
384            None => {
385                log::trace!("no data available at endpoint");
386                return Err(UsbError::WouldBlock);
387            }
388            Some(data) => data,
389        };
390
391        if buf.len() < data.len() {
392            buf.copy_from_slice(&data[..buf.len()]);
393        } else {
394            buf[..data.len()].copy_from_slice(&data);
395        }
396        Ok(data.len())
397    }
398
399    fn set_stalled(&self, ep_addr: EndpointAddress, stalled: bool) {
400        let mut inner = self.lock();
401
402        let endpoint = match inner.get_endpoint(ep_addr.index()) {
403            Ok(endpoint) => endpoint,
404            _ => return,
405        };
406
407        if endpoint.stalled != stalled {
408            log::debug!(
409                "setting endpoint {:?} to stalled state {}",
410                ep_addr,
411                stalled
412            );
413        }
414        endpoint.stalled = stalled;
415    }
416
417    fn is_stalled(&self, ep_addr: EndpointAddress) -> bool {
418        let mut inner = self.lock();
419
420        let endpoint = match inner.get_endpoint(ep_addr.index()) {
421            Ok(endpoint) => endpoint,
422            _ => return false,
423        };
424
425        endpoint.stalled
426    }
427
428    fn suspend(&self) {
429        let mut inner = self.lock();
430
431        log::info!("suspending device");
432        if inner.suspended {
433            log::warn!("supending already suspended device");
434        }
435
436        inner.suspended = true;
437    }
438
439    fn resume(&self) {
440        let mut inner = self.lock();
441
442        log::info!("resuming device");
443        if !inner.suspended {
444            log::warn!("resuming already active device");
445        }
446
447        inner.suspended = false;
448    }
449
450    fn poll(&self) -> PollResult {
451        let mut inner = self.lock();
452        log::trace!("usb device is being polled");
453
454        inner.handle_socket();
455
456        if inner.reset {
457            log::trace!("device is in reset state");
458            return PollResult::Reset;
459        }
460
461        if inner.suspended {
462            log::trace!("device is suspended");
463            return PollResult::Suspend;
464        }
465
466        let mut ep_in: u16 = 0;
467        let mut ep_out: u16 = 0;
468        let mut ep_setup: u16 = 0;
469
470        for i in (0..NUM_ENDPOINTS).into_iter().rev() {
471            ep_in <<= 1;
472            ep_out <<= 1;
473            ep_setup <<= 1;
474
475            let ep = &mut inner.endpoint[i];
476
477            // Check for pending output
478            if let Some(ref pipe) = ep.pipe_out {
479                if !pipe.data.is_empty() {
480                    ep_out |= 1;
481                }
482            }
483
484            if ep.in_complete_flag {
485                ep.in_complete_flag = false;
486                ep_in |= 1;
487            }
488
489            if ep.setup_flag {
490                ep.setup_flag = false;
491                ep_setup |= 1;
492            }
493        }
494
495        PollResult::Data {
496            ep_out,
497            ep_in_complete: ep_in,
498            ep_setup,
499        }
500    }
501}