1use std::collections::HashMap;
17use std::sync::Arc;
18use std::time::SystemTime;
19
20use std::any::Any;
21
22#[derive(Debug, Clone)]
24pub struct DeviceState {
25 pub connected: bool,
26 pub enabled: bool,
27 pub auto_connect: bool,
28}
29
30impl Default for DeviceState {
31 fn default() -> Self {
32 Self {
33 connected: true,
34 enabled: true,
35 auto_connect: true,
36 }
37 }
38}
39
40use crate::error::{AsynError, AsynResult, AsynStatus};
41use crate::exception::{AsynException, ExceptionEvent, ExceptionManager};
42use crate::interpose::{OctetInterpose, OctetInterposeStack};
43use crate::interrupt::{InterruptManager, InterruptValue};
44use crate::param::{EnumEntry, ParamList, ParamType};
45use crate::trace::TraceManager;
46use crate::user::AsynUser;
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
52pub enum QueuePriority {
53 Low = 0,
54 #[default]
55 Medium = 1,
56 High = 2,
57 Connect = 3,
59}
60
61#[derive(Debug, Clone, Copy)]
63pub struct PortFlags {
64 pub multi_device: bool,
66 pub can_block: bool,
75 pub destructible: bool,
77}
78
79impl Default for PortFlags {
80 fn default() -> Self {
81 Self {
82 multi_device: false,
83 can_block: false,
84 destructible: true,
85 }
86 }
87}
88
89pub struct PortDriverBase {
101 pub port_name: String,
102 pub max_addr: usize,
103 pub flags: PortFlags,
104 pub params: ParamList,
105 pub interrupts: InterruptManager,
106 pub connected: bool,
107 pub enabled: bool,
108 pub auto_connect: bool,
109 pub exception_sink: Option<Arc<ExceptionManager>>,
111 pub options: HashMap<String, String>,
112 pub input_eos: Vec<u8>,
114 pub output_eos: Vec<u8>,
116 pub interpose_octet: OctetInterposeStack,
117 pub trace: Option<Arc<TraceManager>>,
118 pub device_states: HashMap<i32, DeviceState>,
120 pub timestamp_source: Option<Arc<dyn Fn() -> SystemTime + Send + Sync>>,
122}
123
124impl PortDriverBase {
125 pub fn new(port_name: &str, max_addr: usize, flags: PortFlags) -> Self {
126 Self {
127 port_name: port_name.to_string(),
128 max_addr: max_addr.max(1),
129 flags,
130 params: ParamList::new(max_addr, flags.multi_device),
131 interrupts: InterruptManager::new(256),
132 connected: true,
133 enabled: true,
134 auto_connect: true,
135 exception_sink: None,
136 options: HashMap::new(),
137 input_eos: Vec::new(),
138 output_eos: Vec::new(),
139 interpose_octet: OctetInterposeStack::new(),
140 trace: None,
141 device_states: HashMap::new(),
142 timestamp_source: None,
143 }
144 }
145
146 pub fn announce_exception(&self, exception: AsynException, addr: i32) {
148 if let Some(ref sink) = self.exception_sink {
149 sink.announce(&ExceptionEvent {
150 port_name: self.port_name.clone(),
151 exception,
152 addr,
153 });
154 }
155 }
156
157 pub fn is_connected(&self) -> bool {
159 self.connected
160 }
161
162 pub fn is_enabled(&self) -> bool {
164 self.enabled
165 }
166
167 pub fn is_auto_connect(&self) -> bool {
169 self.auto_connect
170 }
171
172 pub fn check_ready(&self) -> AsynResult<()> {
175 if !self.enabled {
176 return Err(AsynError::Status {
177 status: AsynStatus::Disabled,
178 message: format!("port {} is disabled", self.port_name),
179 });
180 }
181 if !self.connected {
182 return Err(AsynError::Status {
183 status: AsynStatus::Disconnected,
184 message: format!("port {} is disconnected", self.port_name),
185 });
186 }
187 Ok(())
188 }
189
190 pub fn check_ready_addr(&self, addr: i32) -> AsynResult<()> {
193 self.check_ready()?;
194 if self.flags.multi_device {
195 if let Some(ds) = self.device_states.get(&addr) {
196 if !ds.enabled {
197 return Err(AsynError::Status {
198 status: AsynStatus::Disabled,
199 message: format!("port {} addr {} is disabled", self.port_name, addr),
200 });
201 }
202 if !ds.connected {
203 return Err(AsynError::Status {
204 status: AsynStatus::Disconnected,
205 message: format!("port {} addr {} is disconnected", self.port_name, addr),
206 });
207 }
208 }
209 }
210 Ok(())
211 }
212
213 pub fn device_state(&mut self, addr: i32) -> &mut DeviceState {
215 self.device_states.entry(addr).or_default()
216 }
217
218 pub fn is_device_connected(&self, addr: i32) -> bool {
220 self.device_states
221 .get(&addr)
222 .map_or(true, |ds| ds.connected)
223 }
224
225 pub fn connect_addr(&mut self, addr: i32) {
227 self.device_state(addr).connected = true;
228 self.announce_exception(AsynException::Connect, addr);
229 }
230
231 pub fn disconnect_addr(&mut self, addr: i32) {
233 self.device_state(addr).connected = false;
234 self.announce_exception(AsynException::Connect, addr);
235 }
236
237 pub fn enable_addr(&mut self, addr: i32) {
239 self.device_state(addr).enabled = true;
240 self.announce_exception(AsynException::Enable, addr);
241 }
242
243 pub fn disable_addr(&mut self, addr: i32) {
245 self.device_state(addr).enabled = false;
246 self.announce_exception(AsynException::Enable, addr);
247 }
248
249 pub fn register_timestamp_source<F>(&mut self, source: F)
251 where
252 F: Fn() -> SystemTime + Send + Sync + 'static,
253 {
254 self.timestamp_source = Some(Arc::new(source));
255 }
256
257 pub fn current_timestamp(&self) -> SystemTime {
259 self.timestamp_source
260 .as_ref()
261 .map_or_else(SystemTime::now, |f| f())
262 }
263
264 pub fn create_param(&mut self, name: &str, param_type: ParamType) -> AsynResult<usize> {
265 self.params.create_param(name, param_type)
266 }
267
268 pub fn find_param(&self, name: &str) -> Option<usize> {
269 self.params.find_param(name)
270 }
271
272 pub fn set_int32_param(&mut self, index: usize, addr: i32, value: i32) -> AsynResult<()> {
275 self.params.set_int32(index, addr, value)
276 }
277
278 pub fn get_int32_param(&self, index: usize, addr: i32) -> AsynResult<i32> {
279 self.params.get_int32(index, addr)
280 }
281
282 pub fn set_int64_param(&mut self, index: usize, addr: i32, value: i64) -> AsynResult<()> {
283 self.params.set_int64(index, addr, value)
284 }
285
286 pub fn get_int64_param(&self, index: usize, addr: i32) -> AsynResult<i64> {
287 self.params.get_int64(index, addr)
288 }
289
290 pub fn set_float64_param(&mut self, index: usize, addr: i32, value: f64) -> AsynResult<()> {
291 self.params.set_float64(index, addr, value)
292 }
293
294 pub fn get_float64_param(&self, index: usize, addr: i32) -> AsynResult<f64> {
295 self.params.get_float64(index, addr)
296 }
297
298 pub fn set_string_param(&mut self, index: usize, addr: i32, value: String) -> AsynResult<()> {
299 self.params.set_string(index, addr, value)
300 }
301
302 pub fn get_string_param(&self, index: usize, addr: i32) -> AsynResult<&str> {
303 self.params.get_string(index, addr)
304 }
305
306 pub fn set_uint32_param(
307 &mut self,
308 index: usize,
309 addr: i32,
310 value: u32,
311 mask: u32,
312 ) -> AsynResult<()> {
313 self.params.set_uint32(index, addr, value, mask)
314 }
315
316 pub fn get_uint32_param(&self, index: usize, addr: i32) -> AsynResult<u32> {
317 self.params.get_uint32(index, addr)
318 }
319
320 pub fn get_enum_param(&self, index: usize, addr: i32) -> AsynResult<(usize, Arc<[EnumEntry]>)> {
321 self.params.get_enum(index, addr)
322 }
323
324 pub fn set_enum_index_param(
325 &mut self,
326 index: usize,
327 addr: i32,
328 value: usize,
329 ) -> AsynResult<()> {
330 self.params.set_enum_index(index, addr, value)
331 }
332
333 pub fn set_enum_choices_param(
334 &mut self,
335 index: usize,
336 addr: i32,
337 choices: Arc<[EnumEntry]>,
338 ) -> AsynResult<()> {
339 self.params.set_enum_choices(index, addr, choices)
340 }
341
342 pub fn get_generic_pointer_param(
343 &self,
344 index: usize,
345 addr: i32,
346 ) -> AsynResult<Arc<dyn Any + Send + Sync>> {
347 self.params.get_generic_pointer(index, addr)
348 }
349
350 pub fn set_generic_pointer_param(
351 &mut self,
352 index: usize,
353 addr: i32,
354 value: Arc<dyn Any + Send + Sync>,
355 ) -> AsynResult<()> {
356 self.params.set_generic_pointer(index, addr, value)
357 }
358
359 pub fn set_param_timestamp(
360 &mut self,
361 index: usize,
362 addr: i32,
363 ts: SystemTime,
364 ) -> AsynResult<()> {
365 self.params.set_timestamp(index, addr, ts)
366 }
367
368 pub fn set_param_status(
369 &mut self,
370 index: usize,
371 addr: i32,
372 status: AsynStatus,
373 alarm_status: u16,
374 alarm_severity: u16,
375 ) -> AsynResult<()> {
376 self.params
377 .set_param_status(index, addr, status, alarm_status, alarm_severity)
378 }
379
380 pub fn get_param_status(&self, index: usize, addr: i32) -> AsynResult<(AsynStatus, u16, u16)> {
381 self.params.get_param_status(index, addr)
382 }
383
384 pub fn report_params(&self, level: i32) {
386 eprintln!(" Number of parameters is {}", self.params.len());
387 if level < 1 {
388 return;
389 }
390 for i in 0..self.params.len() {
391 let name = self.params.param_name(i).unwrap_or("?");
392 let ptype = self
393 .params
394 .param_type(i)
395 .map(|t| format!("{t:?}"))
396 .unwrap_or("?".into());
397 if level >= 2 {
398 for addr in 0..self.max_addr.max(1) {
399 let val = self
400 .params
401 .get_value(i, addr as i32)
402 .map(|v| format!("{v:?}"))
403 .unwrap_or("undefined".into());
404 let (status, alarm_st, alarm_sev) = self
405 .params
406 .get_param_status(i, addr as i32)
407 .unwrap_or((AsynStatus::Success, 0, 0));
408 eprintln!(
409 " param[{i}] name={name} type={ptype} addr={addr} val={val} status={status:?} alarm=({alarm_st},{alarm_sev})"
410 );
411 }
412 } else {
413 eprintln!(" param[{i}] name={name} type={ptype}");
414 }
415 }
416 }
417
418 pub fn push_octet_interpose(&mut self, layer: Box<dyn OctetInterpose>) {
424 self.interpose_octet.push(layer);
425 }
426
427 pub fn call_param_callbacks(&mut self, addr: i32) -> AsynResult<()> {
430 let changed = self.params.take_changed(addr)?;
431 let now = self.current_timestamp();
432 for reason in changed {
433 let value = self.params.get_value(reason, addr)?.clone();
434 let ts = self.params.get_timestamp(reason, addr)?.unwrap_or(now);
435 let uint32_mask = self
436 .params
437 .get_uint32_interrupt_mask(reason, addr)
438 .unwrap_or(0);
439 self.interrupts.notify(InterruptValue {
440 reason,
441 addr,
442 value,
443 timestamp: ts,
444 uint32_changed_mask: uint32_mask,
445 });
446 }
447 Ok(())
448 }
449
450 pub fn call_param_callback(&mut self, addr: i32, reason: usize) -> AsynResult<()> {
454 if self.params.take_changed_single(reason, addr)? {
455 let now = self.current_timestamp();
456 let value = self.params.get_value(reason, addr)?.clone();
457 let ts = self.params.get_timestamp(reason, addr)?.unwrap_or(now);
458 let uint32_mask = self
459 .params
460 .get_uint32_interrupt_mask(reason, addr)
461 .unwrap_or(0);
462 self.interrupts.notify(InterruptValue {
463 reason,
464 addr,
465 value,
466 timestamp: ts,
467 uint32_changed_mask: uint32_mask,
468 });
469 }
470 Ok(())
471 }
472
473 pub fn mark_param_changed(&mut self, index: usize, addr: i32) -> AsynResult<()> {
478 self.params.mark_changed(index, addr)
479 }
480}
481
482pub trait PortDriver: Send + Sync + 'static {
497 fn base(&self) -> &PortDriverBase;
498 fn base_mut(&mut self) -> &mut PortDriverBase;
499
500 fn connect(&mut self, _user: &AsynUser) -> AsynResult<()> {
503 self.base_mut().connected = true;
504 self.base().announce_exception(AsynException::Connect, -1);
505 Ok(())
506 }
507
508 fn disconnect(&mut self, _user: &AsynUser) -> AsynResult<()> {
509 self.base_mut().connected = false;
510 self.base().announce_exception(AsynException::Connect, -1);
511 Ok(())
512 }
513
514 fn enable(&mut self, _user: &AsynUser) -> AsynResult<()> {
515 self.base_mut().enabled = true;
516 self.base().announce_exception(AsynException::Enable, -1);
517 Ok(())
518 }
519
520 fn disable(&mut self, _user: &AsynUser) -> AsynResult<()> {
521 self.base_mut().enabled = false;
522 self.base().announce_exception(AsynException::Enable, -1);
523 Ok(())
524 }
525
526 fn connect_addr(&mut self, user: &AsynUser) -> AsynResult<()> {
527 self.base_mut().connect_addr(user.addr);
528 Ok(())
529 }
530
531 fn disconnect_addr(&mut self, user: &AsynUser) -> AsynResult<()> {
532 self.base_mut().disconnect_addr(user.addr);
533 Ok(())
534 }
535
536 fn enable_addr(&mut self, user: &AsynUser) -> AsynResult<()> {
537 self.base_mut().enable_addr(user.addr);
538 Ok(())
539 }
540
541 fn disable_addr(&mut self, user: &AsynUser) -> AsynResult<()> {
542 self.base_mut().disable_addr(user.addr);
543 Ok(())
544 }
545
546 fn get_option(&self, key: &str) -> AsynResult<String> {
547 self.base()
548 .options
549 .get(key)
550 .cloned()
551 .ok_or_else(|| AsynError::OptionNotFound(key.to_string()))
552 }
553
554 fn set_option(&mut self, key: &str, value: &str) -> AsynResult<()> {
555 self.base_mut()
556 .options
557 .insert(key.to_string(), value.to_string());
558 Ok(())
559 }
560
561 fn report(&self, level: i32) {
562 let base = self.base();
563 eprintln!("Port: {}", base.port_name);
564 eprintln!(
565 " connected: {}, max_addr: {}, params: {}, options: {}",
566 base.connected,
567 base.max_addr,
568 base.params.len(),
569 base.options.len()
570 );
571 if level >= 1 {
572 base.report_params(level.saturating_sub(1));
573 }
574 if level >= 2 {
575 for (k, v) in &base.options {
576 eprintln!(" option: {k} = {v}");
577 }
578 }
579 }
580
581 fn read_int32(&mut self, user: &AsynUser) -> AsynResult<i32> {
588 self.base().params.get_int32(user.reason, user.addr)
589 }
590
591 fn write_int32(&mut self, user: &mut AsynUser, value: i32) -> AsynResult<()> {
592 self.base_mut()
593 .params
594 .set_int32(user.reason, user.addr, value)?;
595 self.base_mut().call_param_callbacks(user.addr)
596 }
597
598 fn read_int64(&mut self, user: &AsynUser) -> AsynResult<i64> {
599 self.base().params.get_int64(user.reason, user.addr)
600 }
601
602 fn write_int64(&mut self, user: &mut AsynUser, value: i64) -> AsynResult<()> {
603 self.base_mut()
604 .params
605 .set_int64(user.reason, user.addr, value)?;
606 self.base_mut().call_param_callbacks(user.addr)
607 }
608
609 fn get_bounds_int32(&self, _user: &AsynUser) -> AsynResult<(i32, i32)> {
610 Ok((i32::MIN, i32::MAX))
611 }
612
613 fn get_bounds_int64(&self, _user: &AsynUser) -> AsynResult<(i64, i64)> {
614 Ok((i64::MIN, i64::MAX))
615 }
616
617 fn read_float64(&mut self, user: &AsynUser) -> AsynResult<f64> {
618 self.base().params.get_float64(user.reason, user.addr)
619 }
620
621 fn write_float64(&mut self, user: &mut AsynUser, value: f64) -> AsynResult<()> {
622 self.base_mut()
623 .params
624 .set_float64(user.reason, user.addr, value)?;
625 self.base_mut().call_param_callbacks(user.addr)
626 }
627
628 fn read_octet(&mut self, user: &AsynUser, buf: &mut [u8]) -> AsynResult<usize> {
629 let s = self.base().params.get_string(user.reason, user.addr)?;
630 let bytes = s.as_bytes();
631 let n = bytes.len().min(buf.len());
632 buf[..n].copy_from_slice(&bytes[..n]);
633 Ok(n)
634 }
635
636 fn write_octet(&mut self, user: &mut AsynUser, data: &[u8]) -> AsynResult<()> {
637 let s = String::from_utf8_lossy(data).into_owned();
638 self.base_mut()
639 .params
640 .set_string(user.reason, user.addr, s)?;
641 self.base_mut().call_param_callbacks(user.addr)
642 }
643
644 fn read_uint32_digital(&mut self, user: &AsynUser, mask: u32) -> AsynResult<u32> {
645 let val = self.base().params.get_uint32(user.reason, user.addr)?;
646 Ok(val & mask)
647 }
648
649 fn write_uint32_digital(
650 &mut self,
651 user: &mut AsynUser,
652 value: u32,
653 mask: u32,
654 ) -> AsynResult<()> {
655 self.base_mut()
656 .params
657 .set_uint32(user.reason, user.addr, value, mask)?;
658 self.base_mut().call_param_callbacks(user.addr)
659 }
660
661 fn read_enum(&mut self, user: &AsynUser) -> AsynResult<(usize, Arc<[EnumEntry]>)> {
664 self.base().params.get_enum(user.reason, user.addr)
665 }
666
667 fn write_enum(&mut self, user: &mut AsynUser, index: usize) -> AsynResult<()> {
668 self.base_mut()
669 .params
670 .set_enum_index(user.reason, user.addr, index)?;
671 self.base_mut().call_param_callbacks(user.addr)
672 }
673
674 fn write_enum_choices(
675 &mut self,
676 user: &mut AsynUser,
677 choices: Arc<[EnumEntry]>,
678 ) -> AsynResult<()> {
679 self.base_mut()
680 .params
681 .set_enum_choices(user.reason, user.addr, choices)?;
682 self.base_mut().call_param_callbacks(user.addr)
683 }
684
685 fn read_generic_pointer(&mut self, user: &AsynUser) -> AsynResult<Arc<dyn Any + Send + Sync>> {
688 self.base()
689 .params
690 .get_generic_pointer(user.reason, user.addr)
691 }
692
693 fn write_generic_pointer(
694 &mut self,
695 user: &mut AsynUser,
696 value: Arc<dyn Any + Send + Sync>,
697 ) -> AsynResult<()> {
698 self.base_mut()
699 .params
700 .set_generic_pointer(user.reason, user.addr, value)?;
701 self.base_mut().call_param_callbacks(user.addr)
702 }
703
704 fn read_float64_array(&mut self, _user: &AsynUser, _buf: &mut [f64]) -> AsynResult<usize> {
707 Err(AsynError::InterfaceNotSupported("asynFloat64Array".into()))
708 }
709
710 fn write_float64_array(&mut self, user: &AsynUser, data: &[f64]) -> AsynResult<()> {
711 self.base_mut()
712 .params
713 .set_float64_array(user.reason, user.addr, data.to_vec())?;
714 self.base_mut().call_param_callbacks(user.addr)
715 }
716
717 fn read_int32_array(&mut self, _user: &AsynUser, _buf: &mut [i32]) -> AsynResult<usize> {
718 Err(AsynError::InterfaceNotSupported("asynInt32Array".into()))
719 }
720
721 fn write_int32_array(&mut self, user: &AsynUser, data: &[i32]) -> AsynResult<()> {
722 self.base_mut()
723 .params
724 .set_int32_array(user.reason, user.addr, data.to_vec())?;
725 self.base_mut().call_param_callbacks(user.addr)
726 }
727
728 fn read_int8_array(&mut self, _user: &AsynUser, _buf: &mut [i8]) -> AsynResult<usize> {
729 Err(AsynError::InterfaceNotSupported("asynInt8Array".into()))
730 }
731
732 fn write_int8_array(&mut self, user: &AsynUser, data: &[i8]) -> AsynResult<()> {
733 self.base_mut()
734 .params
735 .set_int8_array(user.reason, user.addr, data.to_vec())?;
736 self.base_mut().call_param_callbacks(user.addr)
737 }
738
739 fn read_int16_array(&mut self, _user: &AsynUser, _buf: &mut [i16]) -> AsynResult<usize> {
740 Err(AsynError::InterfaceNotSupported("asynInt16Array".into()))
741 }
742
743 fn write_int16_array(&mut self, user: &AsynUser, data: &[i16]) -> AsynResult<()> {
744 self.base_mut()
745 .params
746 .set_int16_array(user.reason, user.addr, data.to_vec())?;
747 self.base_mut().call_param_callbacks(user.addr)
748 }
749
750 fn read_int64_array(&mut self, _user: &AsynUser, _buf: &mut [i64]) -> AsynResult<usize> {
751 Err(AsynError::InterfaceNotSupported("asynInt64Array".into()))
752 }
753
754 fn write_int64_array(&mut self, user: &AsynUser, data: &[i64]) -> AsynResult<()> {
755 self.base_mut()
756 .params
757 .set_int64_array(user.reason, user.addr, data.to_vec())?;
758 self.base_mut().call_param_callbacks(user.addr)
759 }
760
761 fn read_float32_array(&mut self, _user: &AsynUser, _buf: &mut [f32]) -> AsynResult<usize> {
762 Err(AsynError::InterfaceNotSupported("asynFloat32Array".into()))
763 }
764
765 fn write_float32_array(&mut self, user: &AsynUser, data: &[f32]) -> AsynResult<()> {
766 self.base_mut()
767 .params
768 .set_float32_array(user.reason, user.addr, data.to_vec())?;
769 self.base_mut().call_param_callbacks(user.addr)
770 }
771
772 fn io_read_octet(&mut self, user: &AsynUser, buf: &mut [u8]) -> AsynResult<usize> {
777 self.read_octet(user, buf)
778 }
779
780 fn io_write_octet(&mut self, user: &mut AsynUser, data: &[u8]) -> AsynResult<()> {
781 self.write_octet(user, data)
782 }
783
784 fn io_read_int32(&mut self, user: &AsynUser) -> AsynResult<i32> {
785 self.read_int32(user)
786 }
787
788 fn io_write_int32(&mut self, user: &mut AsynUser, value: i32) -> AsynResult<()> {
789 self.write_int32(user, value)
790 }
791
792 fn io_read_int64(&mut self, user: &AsynUser) -> AsynResult<i64> {
793 self.read_int64(user)
794 }
795
796 fn io_write_int64(&mut self, user: &mut AsynUser, value: i64) -> AsynResult<()> {
797 self.write_int64(user, value)
798 }
799
800 fn io_read_float64(&mut self, user: &AsynUser) -> AsynResult<f64> {
801 self.read_float64(user)
802 }
803
804 fn io_write_float64(&mut self, user: &mut AsynUser, value: f64) -> AsynResult<()> {
805 self.write_float64(user, value)
806 }
807
808 fn io_read_uint32_digital(&mut self, user: &AsynUser, mask: u32) -> AsynResult<u32> {
809 self.read_uint32_digital(user, mask)
810 }
811
812 fn io_write_uint32_digital(
813 &mut self,
814 user: &mut AsynUser,
815 value: u32,
816 mask: u32,
817 ) -> AsynResult<()> {
818 self.write_uint32_digital(user, value, mask)
819 }
820
821 fn io_flush(&mut self, _user: &mut AsynUser) -> AsynResult<()> {
822 Ok(())
823 }
824
825 fn set_input_eos(&mut self, eos: &[u8]) -> AsynResult<()> {
828 if eos.len() > 2 {
829 return Err(AsynError::Status {
830 status: AsynStatus::Error,
831 message: format!("illegal eoslen {}", eos.len()),
832 });
833 }
834 self.base_mut().input_eos = eos.to_vec();
835 Ok(())
836 }
837
838 fn get_input_eos(&self) -> Vec<u8> {
839 self.base().input_eos.clone()
840 }
841
842 fn set_output_eos(&mut self, eos: &[u8]) -> AsynResult<()> {
843 if eos.len() > 2 {
844 return Err(AsynError::Status {
845 status: AsynStatus::Error,
846 message: format!("illegal eoslen {}", eos.len()),
847 });
848 }
849 self.base_mut().output_eos = eos.to_vec();
850 Ok(())
851 }
852
853 fn get_output_eos(&self) -> Vec<u8> {
854 self.base().output_eos.clone()
855 }
856
857 fn shutdown(&mut self) -> AsynResult<()> {
862 Ok(())
863 }
864
865 fn drv_user_create(&self, drv_info: &str) -> AsynResult<usize> {
870 self.base()
871 .params
872 .find_param(drv_info)
873 .ok_or_else(|| AsynError::ParamNotFound(drv_info.to_string()))
874 }
875
876 fn capabilities(&self) -> Vec<crate::interfaces::Capability> {
881 crate::interfaces::default_capabilities()
882 }
883
884 fn supports(&self, cap: crate::interfaces::Capability) -> bool {
886 self.capabilities().contains(&cap)
887 }
888
889 fn init(&mut self) -> AsynResult<()> {
890 Ok(())
891 }
892}
893
894#[cfg(test)]
895mod tests {
896 use super::*;
897 struct TestDriver {
898 base: PortDriverBase,
899 }
900
901 impl TestDriver {
902 fn new() -> Self {
903 let mut base = PortDriverBase::new("test", 1, PortFlags::default());
904 base.create_param("VAL", ParamType::Int32).unwrap();
905 base.create_param("TEMP", ParamType::Float64).unwrap();
906 base.create_param("MSG", ParamType::Octet).unwrap();
907 base.create_param("BITS", ParamType::UInt32Digital).unwrap();
908 Self { base }
909 }
910 }
911
912 impl PortDriver for TestDriver {
913 fn base(&self) -> &PortDriverBase {
914 &self.base
915 }
916 fn base_mut(&mut self) -> &mut PortDriverBase {
917 &mut self.base
918 }
919 }
920
921 #[test]
922 fn test_default_read_write_int32() {
923 let mut drv = TestDriver::new();
924 let mut user = AsynUser::new(0);
925 drv.write_int32(&mut user, 42).unwrap();
926 let user = AsynUser::new(0);
927 assert_eq!(drv.read_int32(&user).unwrap(), 42);
928 }
929
930 #[test]
931 fn test_default_read_write_float64() {
932 let mut drv = TestDriver::new();
933 let mut user = AsynUser::new(1);
934 drv.write_float64(&mut user, 3.14).unwrap();
935 let user = AsynUser::new(1);
936 assert!((drv.read_float64(&user).unwrap() - 3.14).abs() < 1e-10);
937 }
938
939 #[test]
940 fn test_default_read_write_octet() {
941 let mut drv = TestDriver::new();
942 let mut user = AsynUser::new(2);
943 drv.write_octet(&mut user, b"hello").unwrap();
944 let user = AsynUser::new(2);
945 let mut buf = [0u8; 32];
946 let n = drv.read_octet(&user, &mut buf).unwrap();
947 assert_eq!(&buf[..n], b"hello");
948 }
949
950 #[test]
951 fn test_default_read_write_uint32() {
952 let mut drv = TestDriver::new();
953 let mut user = AsynUser::new(3);
954 drv.write_uint32_digital(&mut user, 0xFF, 0x0F).unwrap();
955 let user = AsynUser::new(3);
956 assert_eq!(drv.read_uint32_digital(&user, 0xFF).unwrap(), 0x0F);
957 }
958
959 #[test]
960 fn test_connect_disconnect() {
961 let mut drv = TestDriver::new();
962 let user = AsynUser::default();
963 assert!(drv.base().connected);
964 drv.disconnect(&user).unwrap();
965 assert!(!drv.base().connected);
966 drv.connect(&user).unwrap();
967 assert!(drv.base().connected);
968 }
969
970 #[test]
971 fn test_drv_user_create() {
972 let drv = TestDriver::new();
973 assert_eq!(drv.drv_user_create("VAL").unwrap(), 0);
974 assert_eq!(drv.drv_user_create("TEMP").unwrap(), 1);
975 assert!(drv.drv_user_create("NOPE").is_err());
976 }
977
978 #[test]
979 fn test_call_param_callbacks() {
980 let mut drv = TestDriver::new();
981 let mut rx = drv.base_mut().interrupts.subscribe_async();
982
983 drv.base_mut().set_int32_param(0, 0, 100).unwrap();
984 drv.base_mut().set_float64_param(1, 0, 2.0).unwrap();
985 drv.base_mut().call_param_callbacks(0).unwrap();
986
987 let v1 = rx.try_recv().unwrap();
988 assert_eq!(v1.reason, 0);
989 let v2 = rx.try_recv().unwrap();
990 assert_eq!(v2.reason, 1);
991 assert!(rx.try_recv().is_err());
992 }
993
994 #[test]
995 fn test_no_callback_for_unchanged() {
996 let mut drv = TestDriver::new();
997 let mut rx = drv.base_mut().interrupts.subscribe_async();
998
999 drv.base_mut().set_int32_param(0, 0, 5).unwrap();
1000 drv.base_mut().call_param_callbacks(0).unwrap();
1001 let _ = rx.try_recv().unwrap(); drv.base_mut().set_int32_param(0, 0, 5).unwrap();
1005 drv.base_mut().call_param_callbacks(0).unwrap();
1006 assert!(rx.try_recv().is_err());
1007 }
1008
1009 #[test]
1010 fn test_array_not_supported_by_default() {
1011 let mut drv = TestDriver::new();
1012 let user = AsynUser::new(0);
1013 let mut buf = [0f64; 10];
1014 assert!(drv.read_float64_array(&user, &mut buf).is_err());
1015 assert!(drv.write_float64_array(&user, &[1.0]).is_err());
1016 }
1017
1018 #[test]
1019 fn test_option_set_get() {
1020 let mut drv = TestDriver::new();
1021 drv.set_option("baud", "9600").unwrap();
1022 assert_eq!(drv.get_option("baud").unwrap(), "9600");
1023 drv.set_option("baud", "115200").unwrap();
1024 assert_eq!(drv.get_option("baud").unwrap(), "115200");
1025 }
1026
1027 #[test]
1028 fn test_option_not_found() {
1029 let drv = TestDriver::new();
1030 let err = drv.get_option("nonexistent").unwrap_err();
1031 assert!(matches!(err, AsynError::OptionNotFound(_)));
1032 }
1033
1034 #[test]
1035 fn test_report_no_panic() {
1036 let mut drv = TestDriver::new();
1037 drv.set_option("testkey", "testval").unwrap();
1038 drv.base_mut().set_int32_param(0, 0, 42).unwrap();
1039 for level in 0..=3 {
1040 drv.report(level);
1041 }
1042 }
1043
1044 #[test]
1045 fn test_callback_uses_param_timestamp() {
1046 let mut drv = TestDriver::new();
1047 let mut rx = drv.base_mut().interrupts.subscribe_async();
1048
1049 let custom_ts = SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(1_000_000);
1050 drv.base_mut().set_int32_param(0, 0, 77).unwrap();
1051 drv.base_mut().set_param_timestamp(0, 0, custom_ts).unwrap();
1052 drv.base_mut().call_param_callbacks(0).unwrap();
1053
1054 let v = rx.try_recv().unwrap();
1055 assert_eq!(v.reason, 0);
1056 assert_eq!(v.timestamp, custom_ts);
1057 }
1058
1059 #[test]
1060 fn test_default_read_write_enum() {
1061 use crate::param::EnumEntry;
1062
1063 let mut base = PortDriverBase::new("test_enum", 1, PortFlags::default());
1064 base.create_param("MODE", ParamType::Enum).unwrap();
1065
1066 struct EnumDriver {
1067 base: PortDriverBase,
1068 }
1069 impl PortDriver for EnumDriver {
1070 fn base(&self) -> &PortDriverBase {
1071 &self.base
1072 }
1073 fn base_mut(&mut self) -> &mut PortDriverBase {
1074 &mut self.base
1075 }
1076 }
1077
1078 let mut drv = EnumDriver { base };
1079 let choices: Arc<[EnumEntry]> = Arc::from(vec![
1080 EnumEntry {
1081 string: "Off".into(),
1082 value: 0,
1083 severity: 0,
1084 },
1085 EnumEntry {
1086 string: "On".into(),
1087 value: 1,
1088 severity: 0,
1089 },
1090 ]);
1091 let mut user = AsynUser::new(0);
1092 drv.write_enum_choices(&mut user, choices).unwrap();
1093 drv.write_enum(&mut user, 1).unwrap();
1094 let (idx, ch) = drv.read_enum(&AsynUser::new(0)).unwrap();
1095 assert_eq!(idx, 1);
1096 assert_eq!(ch[1].string, "On");
1097 }
1098
1099 #[test]
1100 fn test_enum_callback() {
1101 use crate::param::{EnumEntry, ParamValue};
1102
1103 let mut base = PortDriverBase::new("test_enum_cb", 1, PortFlags::default());
1104 base.create_param("MODE", ParamType::Enum).unwrap();
1105 let mut rx = base.interrupts.subscribe_async();
1106
1107 struct EnumDriver {
1108 base: PortDriverBase,
1109 }
1110 impl PortDriver for EnumDriver {
1111 fn base(&self) -> &PortDriverBase {
1112 &self.base
1113 }
1114 fn base_mut(&mut self) -> &mut PortDriverBase {
1115 &mut self.base
1116 }
1117 }
1118
1119 let mut drv = EnumDriver { base };
1120 let choices: Arc<[EnumEntry]> = Arc::from(vec![
1121 EnumEntry {
1122 string: "A".into(),
1123 value: 0,
1124 severity: 0,
1125 },
1126 EnumEntry {
1127 string: "B".into(),
1128 value: 1,
1129 severity: 0,
1130 },
1131 ]);
1132 drv.base_mut()
1133 .set_enum_choices_param(0, 0, choices)
1134 .unwrap();
1135 drv.base_mut().set_enum_index_param(0, 0, 1).unwrap();
1136 drv.base_mut().call_param_callbacks(0).unwrap();
1137
1138 let v = rx.try_recv().unwrap();
1139 assert_eq!(v.reason, 0);
1140 assert!(matches!(v.value, ParamValue::Enum { index: 1, .. }));
1141 }
1142
1143 #[test]
1144 fn test_default_read_write_generic_pointer() {
1145 let mut base = PortDriverBase::new("test_gp", 1, PortFlags::default());
1146 base.create_param("PTR", ParamType::GenericPointer).unwrap();
1147
1148 struct GpDriver {
1149 base: PortDriverBase,
1150 }
1151 impl PortDriver for GpDriver {
1152 fn base(&self) -> &PortDriverBase {
1153 &self.base
1154 }
1155 fn base_mut(&mut self) -> &mut PortDriverBase {
1156 &mut self.base
1157 }
1158 }
1159
1160 let mut drv = GpDriver { base };
1161 let data: Arc<dyn std::any::Any + Send + Sync> = Arc::new(99i32);
1162 let mut user = AsynUser::new(0);
1163 drv.write_generic_pointer(&mut user, data).unwrap();
1164 let val = drv.read_generic_pointer(&AsynUser::new(0)).unwrap();
1165 assert_eq!(*val.downcast_ref::<i32>().unwrap(), 99);
1166 }
1167
1168 #[test]
1169 fn test_generic_pointer_callback() {
1170 use crate::param::ParamValue;
1171
1172 let mut base = PortDriverBase::new("test_gp_cb", 1, PortFlags::default());
1173 base.create_param("PTR", ParamType::GenericPointer).unwrap();
1174 let mut rx = base.interrupts.subscribe_async();
1175
1176 struct GpDriver {
1177 base: PortDriverBase,
1178 }
1179 impl PortDriver for GpDriver {
1180 fn base(&self) -> &PortDriverBase {
1181 &self.base
1182 }
1183 fn base_mut(&mut self) -> &mut PortDriverBase {
1184 &mut self.base
1185 }
1186 }
1187
1188 let mut drv = GpDriver { base };
1189 let data: Arc<dyn std::any::Any + Send + Sync> = Arc::new(vec![1, 2, 3]);
1190 drv.base_mut()
1191 .set_generic_pointer_param(0, 0, data)
1192 .unwrap();
1193 drv.base_mut().call_param_callbacks(0).unwrap();
1194
1195 let v = rx.try_recv().unwrap();
1196 assert_eq!(v.reason, 0);
1197 assert!(matches!(v.value, ParamValue::GenericPointer(_)));
1198 }
1199
1200 #[test]
1201 fn test_interpose_push_requires_lock() {
1202 use crate::interpose::{OctetInterpose, OctetNext, OctetReadResult};
1203 use parking_lot::Mutex;
1204 use std::sync::Arc;
1205
1206 struct NoopInterpose;
1207 impl OctetInterpose for NoopInterpose {
1208 fn read(
1209 &mut self,
1210 user: &AsynUser,
1211 buf: &mut [u8],
1212 next: &mut dyn OctetNext,
1213 ) -> AsynResult<OctetReadResult> {
1214 next.read(user, buf)
1215 }
1216 fn write(
1217 &mut self,
1218 user: &mut AsynUser,
1219 data: &[u8],
1220 next: &mut dyn OctetNext,
1221 ) -> AsynResult<usize> {
1222 next.write(user, data)
1223 }
1224 fn flush(&mut self, user: &mut AsynUser, next: &mut dyn OctetNext) -> AsynResult<()> {
1225 next.flush(user)
1226 }
1227 }
1228
1229 let port: Arc<Mutex<dyn PortDriver>> = Arc::new(Mutex::new(TestDriver::new()));
1230
1231 {
1232 let mut guard = port.lock();
1233 guard
1234 .base_mut()
1235 .push_octet_interpose(Box::new(NoopInterpose));
1236 assert_eq!(guard.base().interpose_octet.len(), 1);
1237 }
1238 }
1239
1240 #[test]
1241 fn test_default_read_write_int64() {
1242 let mut base = PortDriverBase::new("test_i64", 1, PortFlags::default());
1243 base.create_param("BIG", ParamType::Int64).unwrap();
1244
1245 struct I64Driver {
1246 base: PortDriverBase,
1247 }
1248 impl PortDriver for I64Driver {
1249 fn base(&self) -> &PortDriverBase {
1250 &self.base
1251 }
1252 fn base_mut(&mut self) -> &mut PortDriverBase {
1253 &mut self.base
1254 }
1255 }
1256
1257 let mut drv = I64Driver { base };
1258 let mut user = AsynUser::new(0);
1259 drv.write_int64(&mut user, i64::MAX).unwrap();
1260 assert_eq!(drv.read_int64(&AsynUser::new(0)).unwrap(), i64::MAX);
1261 }
1262
1263 #[test]
1264 fn test_get_bounds_int64_default() {
1265 let base = PortDriverBase::new("test_bounds", 1, PortFlags::default());
1266 struct BoundsDriver {
1267 base: PortDriverBase,
1268 }
1269 impl PortDriver for BoundsDriver {
1270 fn base(&self) -> &PortDriverBase {
1271 &self.base
1272 }
1273 fn base_mut(&mut self) -> &mut PortDriverBase {
1274 &mut self.base
1275 }
1276 }
1277 let drv = BoundsDriver { base };
1278 let (lo, hi) = drv.get_bounds_int64(&AsynUser::default()).unwrap();
1279 assert_eq!(lo, i64::MIN);
1280 assert_eq!(hi, i64::MAX);
1281 }
1282
1283 #[test]
1284 fn test_per_addr_device_state() {
1285 let mut base = PortDriverBase::new(
1286 "multi",
1287 4,
1288 PortFlags {
1289 multi_device: true,
1290 can_block: false,
1291 destructible: true,
1292 },
1293 );
1294 base.create_param("V", ParamType::Int32).unwrap();
1295
1296 assert!(base.is_device_connected(0));
1298 assert!(base.is_device_connected(1));
1299
1300 base.device_state(1).enabled = false;
1302 assert!(base.check_ready_addr(0).is_ok());
1303 let err = base.check_ready_addr(1).unwrap_err();
1304 assert!(format!("{err}").contains("disabled"));
1305
1306 base.device_state(2).connected = false;
1308 let err = base.check_ready_addr(2).unwrap_err();
1309 assert!(format!("{err}").contains("disconnected"));
1310 }
1311
1312 #[test]
1313 fn test_per_addr_single_device_ignored() {
1314 let mut base = PortDriverBase::new("single", 1, PortFlags::default());
1315 base.create_param("V", ParamType::Int32).unwrap();
1316 assert!(base.check_ready_addr(0).is_ok());
1318 }
1319
1320 #[test]
1321 fn test_timestamp_source() {
1322 let mut base = PortDriverBase::new("ts_test", 1, PortFlags::default());
1323 base.create_param("V", ParamType::Int32).unwrap();
1324
1325 let fixed_ts = SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(999999);
1326 base.register_timestamp_source(move || fixed_ts);
1327
1328 assert_eq!(base.current_timestamp(), fixed_ts);
1329 }
1330
1331 #[test]
1332 fn test_timestamp_source_in_callbacks() {
1333 let mut base = PortDriverBase::new("ts_cb", 1, PortFlags::default());
1334 base.create_param("V", ParamType::Int32).unwrap();
1335 let mut rx = base.interrupts.subscribe_async();
1336
1337 let fixed_ts = SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(123456);
1338 base.register_timestamp_source(move || fixed_ts);
1339
1340 struct TsDriver {
1341 base: PortDriverBase,
1342 }
1343 impl PortDriver for TsDriver {
1344 fn base(&self) -> &PortDriverBase {
1345 &self.base
1346 }
1347 fn base_mut(&mut self) -> &mut PortDriverBase {
1348 &mut self.base
1349 }
1350 }
1351 let mut drv = TsDriver { base };
1352 drv.base_mut().set_int32_param(0, 0, 42).unwrap();
1353 drv.base_mut().call_param_callbacks(0).unwrap();
1354
1355 let v = rx.try_recv().unwrap();
1356 assert_eq!(v.timestamp, fixed_ts);
1358 }
1359
1360 #[test]
1361 fn test_queue_priority_connect() {
1362 assert!(QueuePriority::Connect > QueuePriority::High);
1363 }
1364
1365 #[test]
1366 fn test_port_flags_destructible_default() {
1367 let flags = PortFlags::default();
1368 assert!(flags.destructible);
1369 }
1370
1371 #[test]
1374 fn test_connect_addr() {
1375 let mut base = PortDriverBase::new(
1376 "multi_conn",
1377 4,
1378 PortFlags {
1379 multi_device: true,
1380 can_block: false,
1381 destructible: true,
1382 },
1383 );
1384 base.create_param("V", ParamType::Int32).unwrap();
1385
1386 base.disconnect_addr(1);
1387 assert!(!base.is_device_connected(1));
1388 assert!(base.check_ready_addr(1).is_err());
1389
1390 base.connect_addr(1);
1391 assert!(base.is_device_connected(1));
1392 assert!(base.check_ready_addr(1).is_ok());
1393 }
1394
1395 #[test]
1396 fn test_enable_disable_addr() {
1397 let mut base = PortDriverBase::new(
1398 "multi_en",
1399 4,
1400 PortFlags {
1401 multi_device: true,
1402 can_block: false,
1403 destructible: true,
1404 },
1405 );
1406 base.create_param("V", ParamType::Int32).unwrap();
1407
1408 base.disable_addr(2);
1409 let err = base.check_ready_addr(2).unwrap_err();
1410 assert!(format!("{err}").contains("disabled"));
1411
1412 base.enable_addr(2);
1413 assert!(base.check_ready_addr(2).is_ok());
1414 }
1415
1416 #[test]
1417 fn test_port_level_overrides_addr() {
1418 let mut base = PortDriverBase::new(
1419 "multi_override",
1420 4,
1421 PortFlags {
1422 multi_device: true,
1423 can_block: false,
1424 destructible: true,
1425 },
1426 );
1427 base.create_param("V", ParamType::Int32).unwrap();
1428
1429 base.enabled = false;
1431 base.enable_addr(0); let err = base.check_ready_addr(0).unwrap_err();
1433 assert!(format!("{err}").contains("disabled"));
1434 }
1435
1436 #[test]
1437 fn test_per_addr_exception_announced() {
1438 use std::sync::atomic::{AtomicI32, Ordering};
1439
1440 let mut base = PortDriverBase::new(
1441 "multi_exc",
1442 4,
1443 PortFlags {
1444 multi_device: true,
1445 can_block: false,
1446 destructible: true,
1447 },
1448 );
1449 base.create_param("V", ParamType::Int32).unwrap();
1450
1451 let exc_mgr = Arc::new(crate::exception::ExceptionManager::new());
1452 base.exception_sink = Some(exc_mgr.clone());
1453
1454 let last_addr = Arc::new(AtomicI32::new(-99));
1455 let last_addr2 = last_addr.clone();
1456 exc_mgr.add_callback(move |event| {
1457 last_addr2.store(event.addr, Ordering::Relaxed);
1458 });
1459
1460 base.disconnect_addr(3);
1461 assert_eq!(last_addr.load(Ordering::Relaxed), 3);
1462
1463 base.enable_addr(2);
1464 assert_eq!(last_addr.load(Ordering::Relaxed), 2);
1465 }
1466}