firewire_tascam_protocols/
asynch.rs1pub mod fe8;
10
11use {
12 super::*,
13 glib::{
14 subclass::{object::*, types::*},
15 *,
16 },
17 hinawa::{prelude::*, subclass::prelude::*, *},
18 hitaki::{prelude::*, subclass::prelude::*, *},
19 std::{cell::RefCell, sync::Mutex},
20};
21
22const ASYNCH_IMAGE_QUADLET_COUNT: usize = TascamExpander::QUADLET_COUNT;
23
24glib::wrapper! {
25 pub struct TascamExpander(ObjectSubclass<imp::TascamExpanderPrivate>)
29 @extends FwResp, @implements TascamProtocol;
30}
31
32impl TascamExpander {
33 pub const QUADLET_COUNT: usize = imp::RESPONSE_FRAME_SIZE / 4;
34
35 pub fn new() -> Self {
36 Object::new(&[]).expect("Failed to create TascamExpander")
37 }
38
39 fn node(&self) -> FwNode {
40 self.property::<FwNode>("node")
41 }
42
43 pub fn bind(&self, node: &FwNode) -> Result<(), Error> {
44 self.reserve_within_region(
45 node,
46 imp::RESPONSE_REGION_START,
47 imp::RESPONSE_REGION_END,
48 imp::RESPONSE_FRAME_SIZE as u32,
49 )?;
50
51 let mut addr = self.offset();
52 addr |= (node.local_node_id() as u64) << 48;
53
54 let mut req = FwReq::new();
55
56 let mut addr_hi = ((addr >> 32) as u32).to_be_bytes();
57 write_quadlet(&mut req, node, imp::ADDR_HIGH_OFFSET, &mut addr_hi, 100)?;
58
59 let mut addr_lo = ((addr & 0xffffffff) as u32).to_be_bytes();
60 write_quadlet(&mut req, node, imp::ADDR_LOW_OFFSET, &mut addr_lo, 100)?;
61
62 self.set_property("node", node);
63
64 Ok(())
65 }
66
67 pub fn listen(&self) -> Result<(), Error> {
68 let mut frames = 1u32.to_be_bytes();
69 let mut req = FwReq::new();
70 write_quadlet(
71 &mut req,
72 &self.node(),
73 imp::ENABLE_NOTIFICATION,
74 &mut frames,
75 100,
76 )
77 }
78
79 pub fn unlisten(&self) {
80 let mut frames = 0u32.to_be_bytes();
81 let mut req = FwReq::new();
82 let _ = write_quadlet(
83 &mut req,
84 &self.node(),
85 imp::ENABLE_NOTIFICATION,
86 &mut frames,
87 100,
88 );
89 }
90
91 pub fn unbind(&self) {
92 self.release();
93
94 let mut req = FwReq::new();
95 let _ = write_quadlet(
96 &mut req,
97 &self.node(),
98 imp::ADDR_HIGH_OFFSET,
99 &mut [0; 4],
100 100,
101 );
102 let _ = write_quadlet(
103 &mut req,
104 &self.node(),
105 imp::ADDR_LOW_OFFSET,
106 &mut [0; 4],
107 100,
108 );
109
110 let private = imp::TascamExpanderPrivate::from_instance(self);
111 *private.0.borrow_mut() = None;
112 }
113}
114
115mod imp {
116 use {super::*, once_cell::sync::Lazy};
117
118 pub const RESPONSE_REGION_START: u64 = 0xffffe0000000;
119 pub const RESPONSE_REGION_END: u64 = 0xfffff0000000;
120 pub const RESPONSE_FRAME_SIZE: usize = 0x80;
121
122 pub const ENABLE_NOTIFICATION: u64 = 0x0310;
123 pub const ADDR_HIGH_OFFSET: u64 = 0x0314;
124 pub const ADDR_LOW_OFFSET: u64 = 0x0318;
125
126 #[derive(Default)]
127 pub struct TascamExpanderPrivate(
128 pub RefCell<Option<FwNode>>,
129 RefCell<Mutex<[u32; super::TascamExpander::QUADLET_COUNT]>>,
130 );
131
132 #[glib::object_subclass]
133 impl ObjectSubclass for TascamExpanderPrivate {
134 const NAME: &'static str = "TascamExpander";
135 type Type = super::TascamExpander;
136 type ParentType = FwResp;
137 type Interfaces = (TascamProtocol,);
138
139 fn new() -> Self {
140 Self::default()
141 }
142 }
143
144 impl ObjectImpl for TascamExpanderPrivate {
145 fn properties() -> &'static [ParamSpec] {
146 static PROPERTIES: Lazy<Vec<ParamSpec>> = Lazy::new(|| {
147 vec![ParamSpecObject::new(
148 "node",
149 "node",
150 "An instance of FwNode",
151 FwNode::static_type(),
152 ParamFlags::READWRITE,
153 )]
154 });
155
156 PROPERTIES.as_ref()
157 }
158
159 fn property(&self, _obj: &Self::Type, _id: usize, pspec: &ParamSpec) -> Value {
160 match pspec.name() {
161 "node" => self.0.borrow().as_ref().unwrap().to_value(),
162 _ => unimplemented!(),
163 }
164 }
165
166 fn set_property(&self, _unit: &Self::Type, _id: usize, value: &Value, pspec: &ParamSpec) {
167 match pspec.name() {
168 "node" => {
169 let node = value
170 .get()
171 .expect("type conformity checked by `Object::set_property`");
172 *self.0.borrow_mut() = node;
173 }
174 _ => unimplemented!(),
175 }
176 }
177 }
178
179 fn parse_notification(
180 image: &mut [u32],
181 events: &mut Vec<(u32, u32, u32)>,
182 tcode: FwTcode,
183 frame: &[u8],
184 ) -> FwRcode {
185 if tcode == FwTcode::WriteQuadletRequest || tcode == FwTcode::WriteBlockRequest {
186 let mut quadlet = [0; 4];
187 (0..frame.len()).step_by(4).for_each(|pos| {
188 quadlet.copy_from_slice(&frame[pos..(pos + 4)]);
189 let value = u32::from_be_bytes(quadlet);
190 let index = ((value & 0x00ff0000) >> 16) as usize;
191 let state = value & 0x0000ffff;
192 if index < image.len() && image[index] != state {
193 events.push((index as u32, image[index], state));
194 image[index] = state;
195 }
196 });
197 FwRcode::Complete
198 } else {
199 FwRcode::TypeError
200 }
201 }
202
203 impl FwRespImpl for TascamExpanderPrivate {
204 fn requested2(
205 &self,
206 resp: &Self::Type,
207 tcode: FwTcode,
208 offset: u64,
209 src: u32,
210 _dst: u32,
211 _card: u32,
212 _generation: u32,
213 frame: &[u8],
214 ) -> FwRcode {
215 if !resp.is_reserved() {
216 return FwRcode::DataError;
217 }
218
219 let inst = match resp.downcast_ref::<super::TascamExpander>() {
220 Some(inst) => inst,
221 None => return FwRcode::DataError,
222 };
223
224 match self.0.borrow().as_ref() {
225 Some(node) => {
226 if src != node.node_id() || offset != resp.offset() {
227 return FwRcode::AddressError;
228 }
229 }
230 None => return FwRcode::DataError,
231 }
232
233 let mut events = Vec::<(u32, u32, u32)>::new();
234
235 let rcode = self
236 .1
237 .borrow_mut()
238 .lock()
239 .map(|mut image| {
240 parse_notification(&mut image[..], &mut events, tcode, frame);
241 FwRcode::Complete
242 })
243 .unwrap_or(FwRcode::DataError);
244
245 events
246 .iter()
247 .for_each(|ev| inst.emit_changed(ev.0, ev.1, ev.2));
248
249 rcode
250 }
251 }
252
253 impl TascamProtocolImpl for TascamExpanderPrivate {
254 fn read_state(&self, _unit: &Self::Type, state: &mut Vec<u32>) -> Result<(), Error> {
255 if state.len() < super::TascamExpander::QUADLET_COUNT {
256 let msg = format!(
257 "The size of buffer should be greater than 32 but {}",
258 state.len()
259 );
260 Err(Error::new(FileError::Inval, &msg))
261 } else {
262 self.1
263 .borrow()
264 .lock()
265 .map(|image| {
266 state.copy_from_slice(&image[..]);
267 state.truncate(super::TascamExpander::QUADLET_COUNT);
268 })
269 .map_err(|e| {
270 let msg = format!("{:?}", e);
271 Error::new(FileError::Io, &msg)
272 })
273 }
274 }
275
276 fn changed(&self, _unit: &Self::Type, _index: u32, _before: u32, _after: u32) {}
277 }
278}