libobsbot_core/transport/
usb.rs1#![cfg(target_os = "linux")]
13
14use std::fs::File;
15
16use crate::discovery::DeviceInfo;
17use crate::transport::Transport;
18use crate::uvc::UvcGet;
19use crate::Result;
20
21const SET_CUR: u8 = 0x01;
23
24pub(crate) struct UsbTransport {
27 vendor_id: u16,
28 product_id: u16,
29 v4l2: File,
30}
31
32impl UsbTransport {
33 pub(crate) fn open(info: &DeviceInfo) -> Result<Self> {
34 let v4l2 = super::uvcvideo::open_for(info.busnum, info.devnum)?;
35 tracing::debug!(
36 vid = format_args!("{:04x}", info.vendor_id),
37 pid = format_args!("{:04x}", info.product_id),
38 busnum = info.busnum,
39 devnum = info.devnum,
40 "opened uvcvideo transport",
41 );
42 Ok(Self {
43 vendor_id: info.vendor_id,
44 product_id: info.product_id,
45 v4l2,
46 })
47 }
48}
49
50impl Transport for UsbTransport {
51 fn uvc_set(&self, entity: u8, selector: u8, payload: &[u8]) -> Result<()> {
52 tracing::trace!(
53 vid = format_args!("{:04x}", self.vendor_id),
54 pid = format_args!("{:04x}", self.product_id),
55 entity,
56 selector = format_args!("{selector:#04x}"),
57 len = payload.len(),
58 "uvc_set",
59 );
60 if let Some(result) = super::uvcvideo::v4l2_set(&self.v4l2, entity, selector, payload) {
61 return result;
62 }
63 let mut buf = payload.to_vec();
66 super::uvcvideo::xu_query(&self.v4l2, entity, selector, SET_CUR, &mut buf).map(|_| ())
67 }
68
69 fn uvc_get(&self, req: UvcGet, entity: u8, selector: u8, out: &mut [u8]) -> Result<usize> {
70 tracing::trace!(
71 vid = format_args!("{:04x}", self.vendor_id),
72 pid = format_args!("{:04x}", self.product_id),
73 entity,
74 selector = format_args!("{selector:#04x}"),
75 req = ?req,
76 length = out.len(),
77 "uvc_get",
78 );
79 if let Some(result) = super::uvcvideo::v4l2_get(&self.v4l2, req, entity, selector, out) {
80 return result;
81 }
82 super::uvcvideo::xu_query(&self.v4l2, entity, selector, req as u8, out)
83 }
84}