1#![allow(non_snake_case)]
2use crate::error::{GpibError, IbError};
3use crate::lowlevel::utility::{Addr4882, ThreadIbcnt, ThreadIbcntl};
4use crate::status::IbStatus;
5use crate::types::{IbSendEOI, PrimaryAddress, SecondaryAddress};
6use crate::DEBUG;
7use linux_gpib_sys::Addr4882_t;
8use std::default::Default;
9use std::os::raw::{c_int, c_short, c_void};
10
11pub fn FindLstn(board_desc: c_int, padList: Vec<Addr4882>) -> Result<Vec<Addr4882>, GpibError> {
22 let mut result: Vec<Addr4882_t> = Vec::new();
23 result.resize_with(31, || linux_gpib_sys::NOADDR);
24 let mut padList = padList
25 .into_iter()
26 .map(|a| a.addr)
27 .collect::<Vec<Addr4882_t>>();
28 padList.push(linux_gpib_sys::NOADDR);
29 if DEBUG {
30 println!("FindLstn({}, {:?})", board_desc, padList);
31 }
32 unsafe {
33 linux_gpib_sys::FindLstn(
34 board_desc,
35 padList.as_ptr(),
36 result.as_mut_ptr(),
37 padList.len().try_into()?,
38 )
39 };
40 let status = IbStatus::current_thread_local_status();
41 if status.err {
42 let error = IbError::current_thread_local_error()?;
43 match error {
44 IbError::EARG => {
45 eprintln!(
46 "Invalid primary address at index {} in padlist",
47 ThreadIbcnt()
48 );
49 }
50 IbError::EBUS => {
51 eprintln!("No devices are connected to the GPIB.");
52 }
53 IbError::ETAB => {
54 eprintln!("The number of devices found on the GPIB exceed limit.");
55 }
56 _ => {}
57 }
58 if DEBUG {
59 println!("-> {:?}", error);
60 }
61 Err(GpibError::DriverError(status, error))
62 } else {
63 let n_values: usize = ThreadIbcntl().try_into()?;
64 result.truncate(n_values);
65 if DEBUG {
66 println!("-> {:?}", result);
67 }
68 Ok(result.into_iter().map(|a| Addr4882 { addr: a }).collect())
69 }
70}
71
72pub fn FindAllLstn(board_desc: c_int) -> Result<Vec<Addr4882>, GpibError> {
74 let padList = (1..31)
75 .into_iter()
76 .map(|pad| Addr4882::new(PrimaryAddress::new(pad)?, SecondaryAddress::default()))
77 .collect::<Result<Vec<Addr4882>, GpibError>>()?;
78 FindLstn(board_desc, padList)
79}
80
81pub fn DevClear(board: c_int, address: Addr4882) -> Result<(), GpibError> {
85 if DEBUG {
86 println!("DevClear({}, {})", board, address);
87 }
88 unsafe {
89 linux_gpib_sys::DevClear(board, address.addr);
90 }
91 let status = IbStatus::current_thread_local_status();
92 if status.err {
93 if DEBUG {
94 println!("-> {:?}", status);
95 }
96 Err(GpibError::DriverError(
97 status,
98 IbError::current_thread_local_error()?,
99 ))
100 } else {
101 if DEBUG {
102 println!("-> {:?}", status);
103 }
104 Ok(())
105 }
106}
107
108pub fn DevClearList(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
112 let mut instruments = addresses
113 .iter()
114 .map(|a| a.addr)
115 .collect::<Vec<Addr4882_t>>();
116 instruments.push(linux_gpib_sys::NOADDR);
117 if DEBUG {
118 println!("DevClearList({:?}, {:?})", board, addresses);
119 }
120 unsafe {
121 linux_gpib_sys::DevClearList(board, instruments.as_ptr());
122 }
123 let status = IbStatus::current_thread_local_status();
124 if DEBUG {
125 println!("-> {:?}", status);
126 }
127 if status.err {
128 Err(GpibError::DriverError(
129 status,
130 IbError::current_thread_local_error()?,
131 ))
132 } else {
133 Ok(())
134 }
135}
136
137pub fn EnableLocal(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
145 let mut instruments = addresses
146 .iter()
147 .map(|a| a.addr)
148 .collect::<Vec<Addr4882_t>>();
149 instruments.push(linux_gpib_sys::NOADDR);
150 unsafe {
151 linux_gpib_sys::EnableLocal(board, instruments.as_ptr());
152 }
153 let status = IbStatus::current_thread_local_status();
154 if status.err {
155 Err(GpibError::DriverError(
156 status,
157 IbError::current_thread_local_error()?,
158 ))
159 } else {
160 Ok(())
161 }
162}
163
164pub fn EnableRemote(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
170 let mut instruments = addresses
171 .iter()
172 .map(|a| a.addr)
173 .collect::<Vec<Addr4882_t>>();
174 instruments.push(linux_gpib_sys::NOADDR);
175 unsafe {
176 linux_gpib_sys::EnableRemote(board, instruments.as_ptr());
177 }
178 let status = IbStatus::current_thread_local_status();
179 if status.err {
180 Err(GpibError::DriverError(
181 status,
182 IbError::current_thread_local_error()?,
183 ))
184 } else {
185 Ok(())
186 }
187}
188
189pub fn FindRQS(board: c_int, addresses: &Vec<Addr4882>) -> Result<(Addr4882, c_short), GpibError> {
195 let mut instruments = addresses
196 .iter()
197 .map(|a| a.addr)
198 .collect::<Vec<Addr4882_t>>();
199 instruments.push(linux_gpib_sys::NOADDR);
200 let mut status_byte: c_short = 0;
201 unsafe {
202 linux_gpib_sys::FindRQS(board, instruments.as_ptr(), &mut status_byte);
203 }
204 let status = IbStatus::current_thread_local_status();
205 if status.err {
206 Err(GpibError::DriverError(
207 status,
208 IbError::current_thread_local_error()?,
209 ))
210 } else {
211 let index: usize = ThreadIbcnt().try_into()?;
212 if index >= addresses.len() {
213 Err(GpibError::ValueError(
214 "index stored in Ibcnt is larger than addresses array length".to_owned(),
215 ))
216 } else {
217 Ok((addresses[index], status_byte))
218 }
219 }
220}
221
222pub fn PassControl(board: c_int, address: Addr4882) -> Result<(), GpibError> {
228 unsafe {
229 linux_gpib_sys::PassControl(board, address.addr);
230 }
231 let status = IbStatus::current_thread_local_status();
232 if status.err {
233 Err(GpibError::DriverError(
234 status,
235 IbError::current_thread_local_error()?,
236 ))
237 } else {
238 Ok(())
239 }
240}
241
242pub fn PPoll(board: c_int) -> Result<c_short, GpibError> {
248 let mut result: c_short = 0;
249 unsafe {
250 linux_gpib_sys::PPoll(board, &mut result);
251 }
252 let status = IbStatus::current_thread_local_status();
253 if status.err {
254 Err(GpibError::DriverError(
255 status,
256 IbError::current_thread_local_error()?,
257 ))
258 } else {
259 Ok(result)
260 }
261}
262
263pub fn PPollConfig(
269 board: c_int,
270 address: Addr4882,
271 dio_line: c_int,
272 line_sense: c_int,
273) -> Result<(), GpibError> {
274 unsafe {
275 linux_gpib_sys::PPollConfig(board, address.addr, dio_line, line_sense);
276 }
277 let status = IbStatus::current_thread_local_status();
278 if status.err {
279 Err(GpibError::DriverError(
280 status,
281 IbError::current_thread_local_error()?,
282 ))
283 } else {
284 Ok(())
285 }
286}
287
288pub fn PPollUnconfig(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
292 let mut instruments = addresses
293 .iter()
294 .map(|a| a.addr)
295 .collect::<Vec<Addr4882_t>>();
296 instruments.push(linux_gpib_sys::NOADDR);
297 unsafe {
298 linux_gpib_sys::PPollUnconfig(board, instruments.as_ptr());
299 }
300 let status = IbStatus::current_thread_local_status();
301 if status.err {
302 Err(GpibError::DriverError(
303 status,
304 IbError::current_thread_local_error()?,
305 ))
306 } else {
307 Ok(())
308 }
309}
310
311pub fn RcvRespMsg(board: c_int, buffer: &mut [u8], termination: c_int) -> Result<(), GpibError> {
321 unsafe {
322 linux_gpib_sys::RcvRespMsg(
323 board,
324 buffer.as_mut_ptr() as *mut c_void,
325 buffer.len().try_into()?,
326 termination,
327 );
328 }
329 let status = IbStatus::current_thread_local_status();
330 if status.err {
331 Err(GpibError::DriverError(
332 status,
333 IbError::current_thread_local_error()?,
334 ))
335 } else {
336 Ok(())
337 }
338}
339
340pub fn ReadStatusByte(board: c_int, address: Addr4882) -> Result<c_short, GpibError> {
346 let mut result: c_short = 0;
347 unsafe {
348 linux_gpib_sys::ReadStatusByte(board, address.addr, &mut result);
349 }
350 let status = IbStatus::current_thread_local_status();
351 if status.err {
352 Err(GpibError::DriverError(
353 status,
354 IbError::current_thread_local_error()?,
355 ))
356 } else {
357 Ok(result)
358 }
359}
360
361pub fn Receive(
367 board: c_int,
368 address: Addr4882,
369 buffer: &mut [u8],
370 termination: c_int,
371) -> Result<(IbStatus, usize), GpibError> {
372 if DEBUG {
373 println!("Receive({:?}, {:?})", board, address);
374 }
375 unsafe {
376 linux_gpib_sys::Receive(
377 board,
378 address.addr,
379 buffer.as_mut_ptr() as *mut c_void,
380 buffer.len().try_into()?,
381 termination,
382 );
383 }
384 let status = IbStatus::current_thread_local_status();
385 if status.err {
386 if DEBUG {
387 println!("-> {:?}", status);
388 }
389 Err(GpibError::DriverError(
390 status,
391 IbError::current_thread_local_error()?,
392 ))
393 } else {
394 let n_read = ThreadIbcntl().try_into()?;
395 if DEBUG {
396 println!(
397 "Receive({:?}, {:?}) -> Read {} bytes",
398 board, address, n_read
399 );
400 }
401 Ok((status, n_read))
402 }
403}
404
405pub fn ReceiveSetup(board: c_int, address: Addr4882) -> Result<(), GpibError> {
413 unsafe {
414 linux_gpib_sys::ReceiveSetup(board, address.addr);
415 }
416 let status = IbStatus::current_thread_local_status();
417 if status.err {
418 Err(GpibError::DriverError(
419 status,
420 IbError::current_thread_local_error()?,
421 ))
422 } else {
423 Ok(())
424 }
425}
426
427pub fn ResetSys(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
438 let mut instruments = addresses
439 .iter()
440 .map(|a| a.addr)
441 .collect::<Vec<Addr4882_t>>();
442 instruments.push(linux_gpib_sys::NOADDR);
443 unsafe {
444 linux_gpib_sys::ResetSys(board, instruments.as_ptr());
445 }
446 let status = IbStatus::current_thread_local_status();
447 if status.err {
448 Err(GpibError::DriverError(
449 status,
450 IbError::current_thread_local_error()?,
451 ))
452 } else {
453 Ok(())
454 }
455}
456
457pub fn Send(
463 board: c_int,
464 address: Addr4882,
465 buffer: &[u8],
466 eot_mode: IbSendEOI,
467) -> Result<(), GpibError> {
468 if DEBUG {
469 println!("Send({:?}, {:?}, {:?})", board, address, buffer);
470 }
471 unsafe {
472 linux_gpib_sys::Send(
473 board,
474 address.addr,
475 buffer.as_ptr() as *const c_void,
476 buffer.len().try_into()?,
477 eot_mode.as_eot(),
478 );
479 }
480 let status = IbStatus::current_thread_local_status();
481 if DEBUG {
482 println!(
483 "Send({:?}, {:?}, {:?}) -> {:?}",
484 board, address, buffer, status
485 );
486 }
487 if status.err {
488 Err(GpibError::DriverError(
489 status,
490 IbError::current_thread_local_error()?,
491 ))
492 } else {
493 Ok(())
494 }
495}
496
497pub fn SendIFC(board: c_int) -> Result<(), GpibError> {
501 if DEBUG {
502 println!("SendIFC({})", board);
503 }
504 unsafe {
505 linux_gpib_sys::SendIFC(board);
506 }
507 let status = IbStatus::current_thread_local_status();
508 if DEBUG {
509 println!("endIFC({}) -> {:?}", board, status);
510 }
511 if status.err {
512 Err(GpibError::DriverError(
513 status,
514 IbError::current_thread_local_error()?,
515 ))
516 } else {
517 Ok(())
518 }
519}
520
521pub fn SendList(
525 board: c_int,
526 addresses: &Vec<Addr4882>,
527 buffer: &[u8],
528 eot_mode: IbSendEOI,
529) -> Result<(), GpibError> {
530 if DEBUG {
531 println!("SendList({:?}, {:?}, {:?})", board, addresses, buffer);
532 }
533 let mut instruments = addresses
534 .iter()
535 .map(|a| a.addr)
536 .collect::<Vec<Addr4882_t>>();
537 instruments.push(linux_gpib_sys::NOADDR);
538 unsafe {
539 linux_gpib_sys::SendList(
540 board,
541 instruments.as_ptr(),
542 buffer.as_ptr() as *const c_void,
543 buffer.len().try_into()?,
544 eot_mode.as_eot(),
545 );
546 }
547 let status = IbStatus::current_thread_local_status();
548 if DEBUG {
549 println!(
550 "SendList({:?}, {:?}, {:?}) -> {:?}",
551 board, addresses, buffer, status
552 );
553 }
554 if status.err {
555 Err(GpibError::DriverError(
556 status,
557 IbError::current_thread_local_error()?,
558 ))
559 } else {
560 Ok(())
561 }
562}
563
564pub fn SendLLO(board: c_int) -> Result<(), GpibError> {
568 unsafe {
569 linux_gpib_sys::SendLLO(board);
570 }
571 let status = IbStatus::current_thread_local_status();
572 if status.err {
573 Err(GpibError::DriverError(
574 status,
575 IbError::current_thread_local_error()?,
576 ))
577 } else {
578 Ok(())
579 }
580}
581
582pub fn SetRWLS(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
586 let mut instruments = addresses
587 .iter()
588 .map(|a| a.addr)
589 .collect::<Vec<Addr4882_t>>();
590 instruments.push(linux_gpib_sys::NOADDR);
591 unsafe {
592 linux_gpib_sys::SetRWLS(board, instruments.as_ptr());
593 }
594 let status = IbStatus::current_thread_local_status();
595 if status.err {
596 Err(GpibError::DriverError(
597 status,
598 IbError::current_thread_local_error()?,
599 ))
600 } else {
601 Ok(())
602 }
603}
604
605pub fn TestSRQ(board: c_int) -> Result<bool, GpibError> {
611 let mut result: c_short = 10;
612 unsafe {
613 linux_gpib_sys::TestSRQ(board, &mut result);
614 }
615 let status = IbStatus::current_thread_local_status();
616 if status.err {
617 Err(GpibError::DriverError(
618 status,
619 IbError::current_thread_local_error()?,
620 ))
621 } else {
622 match result {
623 0 => Ok(false),
624 1 => Ok(true),
625 other => Err(GpibError::ValueError(format!("Unexpected value {}", other))),
626 }
627 }
628}
629
630pub fn TestSys(board: c_int, addresses: &Vec<Addr4882>) -> Result<Vec<c_short>, GpibError> {
634 let mut instruments = addresses
635 .iter()
636 .map(|a| a.addr)
637 .collect::<Vec<Addr4882_t>>();
638 instruments.push(linux_gpib_sys::NOADDR);
639 let mut results: Vec<c_short> = Vec::with_capacity(addresses.len());
640 results.resize(addresses.len(), 0);
641 unsafe {
642 linux_gpib_sys::TestSys(board, instruments.as_ptr(), results.as_mut_ptr());
643 }
644 let status = IbStatus::current_thread_local_status();
645 if status.err {
646 Err(GpibError::DriverError(
647 status,
648 IbError::current_thread_local_error()?,
649 ))
650 } else {
651 Ok(results)
652 }
653}
654
655pub fn Trigger(board: c_int, address: Addr4882) -> Result<(), GpibError> {
659 unsafe {
660 linux_gpib_sys::Trigger(board, address.addr);
661 }
662 let status = IbStatus::current_thread_local_status();
663 if status.err {
664 Err(GpibError::DriverError(
665 status,
666 IbError::current_thread_local_error()?,
667 ))
668 } else {
669 Ok(())
670 }
671}
672
673pub fn TriggerList(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
677 let mut instruments = addresses
678 .iter()
679 .map(|a| a.addr)
680 .collect::<Vec<Addr4882_t>>();
681 instruments.push(linux_gpib_sys::NOADDR);
682 unsafe {
683 linux_gpib_sys::TriggerList(board, instruments.as_ptr());
684 }
685 let status = IbStatus::current_thread_local_status();
686 if status.err {
687 Err(GpibError::DriverError(
688 status,
689 IbError::current_thread_local_error()?,
690 ))
691 } else {
692 Ok(())
693 }
694}
695
696#[cfg(feature = "async-tokio")]
697pub async fn WaitSRQ(board: c_int) -> Result<c_short, GpibError> {
701 tokio::task::spawn_blocking(move || {
702 let mut result: c_short = 0;
703 unsafe {
704 linux_gpib_sys::WaitSRQ(board, &mut result);
705 }
706 let status = IbStatus::current_thread_local_status();
707 if status.err {
708 Err(GpibError::DriverError(
709 status,
710 IbError::current_thread_local_error()?,
711 ))
712 } else {
713 Ok(result)
714 }
715 })
716 .await?
717}