cameleon_device/u3v/
channel.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::time;
6
7use crate::u3v::Result;
8
9use super::device::LibUsbDeviceHandle;
10
11pub struct ControlChannel {
12    pub(super) device_handle: LibUsbDeviceHandle,
13    pub iface_info: ControlIfaceInfo,
14    pub is_opened: bool,
15}
16
17impl ControlChannel {
18    pub fn open(&mut self) -> Result<()> {
19        if !self.is_opened() {
20            self.device_handle
21                .claim_interface(self.iface_info.iface_number)?;
22            self.is_opened = true;
23        }
24
25        Ok(())
26    }
27
28    pub fn close(&mut self) -> Result<()> {
29        if self.is_opened() {
30            self.device_handle
31                .release_interface(self.iface_info.iface_number)?;
32            self.is_opened = false;
33        }
34
35        Ok(())
36    }
37
38    #[must_use]
39    pub fn is_opened(&self) -> bool {
40        self.is_opened
41    }
42
43    pub fn send(&self, buf: &[u8], timeout: time::Duration) -> Result<usize> {
44        Ok(self
45            .device_handle
46            .write_bulk(self.iface_info.bulk_out_ep, buf, timeout)?)
47    }
48
49    pub fn recv(&self, buf: &mut [u8], timeout: time::Duration) -> Result<usize> {
50        Ok(self
51            .device_handle
52            .read_bulk(self.iface_info.bulk_in_ep, buf, timeout)?)
53    }
54
55    pub fn set_halt(&self, timeout: time::Duration) -> Result<()> {
56        set_halt(&self.device_handle, self.iface_info.bulk_in_ep, timeout)?;
57        set_halt(&self.device_handle, self.iface_info.bulk_out_ep, timeout)?;
58
59        Ok(())
60    }
61
62    pub fn clear_halt(&mut self) -> Result<()> {
63        self.device_handle.clear_halt(self.iface_info.bulk_in_ep)?;
64        self.device_handle.clear_halt(self.iface_info.bulk_out_ep)?;
65        Ok(())
66    }
67
68    pub(super) fn new(device_handle: LibUsbDeviceHandle, iface_info: ControlIfaceInfo) -> Self {
69        Self {
70            device_handle,
71            iface_info,
72            is_opened: false,
73        }
74    }
75}
76
77pub struct ReceiveChannel {
78    pub(super) device_handle: LibUsbDeviceHandle,
79    pub iface_info: ReceiveIfaceInfo,
80    pub is_opened: bool,
81}
82
83impl ReceiveChannel {
84    pub fn open(&mut self) -> Result<()> {
85        if !self.is_opened() {
86            self.device_handle
87                .claim_interface(self.iface_info.iface_number)?;
88            self.is_opened = true;
89        }
90
91        Ok(())
92    }
93
94    pub fn close(&mut self) -> Result<()> {
95        if self.is_opened() {
96            self.device_handle
97                .release_interface(self.iface_info.iface_number)?;
98        }
99
100        self.is_opened = false;
101        Ok(())
102    }
103
104    #[must_use]
105    pub fn is_opened(&self) -> bool {
106        self.is_opened
107    }
108
109    pub fn recv(&self, buf: &mut [u8], timeout: time::Duration) -> Result<usize> {
110        Ok(self
111            .device_handle
112            .read_bulk(self.iface_info.bulk_in_ep, buf, timeout)?)
113    }
114
115    pub fn set_halt(&self, timeout: time::Duration) -> Result<()> {
116        set_halt(&self.device_handle, self.iface_info.bulk_in_ep, timeout)?;
117
118        Ok(())
119    }
120
121    pub fn clear_halt(&mut self) -> Result<()> {
122        self.device_handle.clear_halt(self.iface_info.bulk_in_ep)?;
123        Ok(())
124    }
125
126    pub(super) fn new(device_handle: LibUsbDeviceHandle, iface_info: ReceiveIfaceInfo) -> Self {
127        Self {
128            device_handle,
129            iface_info,
130            is_opened: false,
131        }
132    }
133}
134
135#[derive(Clone, Debug)]
136pub struct ControlIfaceInfo {
137    pub iface_number: u8,
138    pub bulk_in_ep: u8,
139    pub bulk_out_ep: u8,
140}
141
142#[derive(Clone, Debug)]
143pub struct ReceiveIfaceInfo {
144    pub iface_number: u8,
145    pub bulk_in_ep: u8,
146}
147
148fn set_halt(
149    handle: &LibUsbDeviceHandle,
150    endpoint_number: u8,
151    timeout: time::Duration,
152) -> Result<()> {
153    let request_type = rusb::request_type(
154        rusb::Direction::Out,
155        rusb::RequestType::Standard,
156        rusb::Recipient::Endpoint,
157    );
158    let request = 0x03; // SET_FEATURE.
159    let value = 0x00; // ENDPOINT_HALT.
160    let buf = vec![]; // NO DATA.
161
162    handle.write_control(
163        request_type,
164        request,
165        value,
166        u16::from(endpoint_number),
167        &buf,
168        timeout,
169    )?;
170
171    Ok(())
172}