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 linux_gpib_sys::Addr4882_t;
7use std::default::Default;
8use std::os::raw::{c_int, c_short, c_void};
9
10pub fn FindLstn(board_desc: c_int, padList: Vec<Addr4882>) -> Result<Vec<Addr4882>, GpibError> {
21 let mut result: Vec<Addr4882_t> = Vec::new();
22 result.resize_with(31, || linux_gpib_sys::NOADDR);
23 let mut padList = padList
24 .into_iter()
25 .map(|a| a.addr)
26 .collect::<Vec<Addr4882_t>>();
27 padList.push(linux_gpib_sys::NOADDR);
28 log::debug!("FindLstn({}, {:?})", board_desc, padList);
29 unsafe {
30 linux_gpib_sys::FindLstn(
31 board_desc,
32 padList.as_ptr(),
33 result.as_mut_ptr(),
34 padList.len().try_into()?,
35 )
36 };
37 let status = IbStatus::current_thread_local_status();
38 if status.err {
39 let error = IbError::current_thread_local_error()?;
40 match error {
41 IbError::EARG => {
42 log::error!(
43 "Invalid primary address at index {} in padlist",
44 ThreadIbcnt()
45 );
46 }
47 IbError::EBUS => {
48 log::error!("No devices are connected to the GPIB.");
49 }
50 IbError::ETAB => {
51 log::error!("The number of devices found on the GPIB exceed limit.");
52 }
53 _ => {}
54 }
55 log::debug!("-> {:?}", error);
56 Err(GpibError::DriverError(status, error))
57 } else {
58 let n_values: usize = ThreadIbcntl().try_into()?;
59 result.truncate(n_values);
60 log::debug!("-> {:?}", result);
61 Ok(result.into_iter().map(|a| Addr4882 { addr: a }).collect())
62 }
63}
64
65pub fn FindAllLstn(board_desc: c_int) -> Result<Vec<Addr4882>, GpibError> {
67 let padList = (1..31)
68 .into_iter()
69 .map(|pad| Addr4882::new(PrimaryAddress::new(pad)?, SecondaryAddress::default()))
70 .collect::<Result<Vec<Addr4882>, GpibError>>()?;
71 FindLstn(board_desc, padList)
72}
73
74pub fn DevClear(board: c_int, address: Addr4882) -> Result<(), GpibError> {
78 log::debug!("DevClear({}, {})", board, address);
79 unsafe {
80 linux_gpib_sys::DevClear(board, address.addr);
81 }
82 let status = IbStatus::current_thread_local_status();
83 if status.err {
84 log::debug!("-> {:?}", status);
85 Err(GpibError::DriverError(
86 status,
87 IbError::current_thread_local_error()?,
88 ))
89 } else {
90 log::debug!("-> {:?}", status);
91 Ok(())
92 }
93}
94
95pub fn DevClearList(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
99 let mut instruments = addresses
100 .iter()
101 .map(|a| a.addr)
102 .collect::<Vec<Addr4882_t>>();
103 instruments.push(linux_gpib_sys::NOADDR);
104 log::debug!("DevClearList({:?}, {:?})", board, addresses);
105 unsafe {
106 linux_gpib_sys::DevClearList(board, instruments.as_ptr());
107 }
108 let status = IbStatus::current_thread_local_status();
109 log::debug!("-> {:?}", status);
110 if status.err {
111 Err(GpibError::DriverError(
112 status,
113 IbError::current_thread_local_error()?,
114 ))
115 } else {
116 Ok(())
117 }
118}
119
120pub fn EnableLocal(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
128 let mut instruments = addresses
129 .iter()
130 .map(|a| a.addr)
131 .collect::<Vec<Addr4882_t>>();
132 instruments.push(linux_gpib_sys::NOADDR);
133 unsafe {
134 linux_gpib_sys::EnableLocal(board, instruments.as_ptr());
135 }
136 let status = IbStatus::current_thread_local_status();
137 if status.err {
138 Err(GpibError::DriverError(
139 status,
140 IbError::current_thread_local_error()?,
141 ))
142 } else {
143 Ok(())
144 }
145}
146
147pub fn EnableRemote(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
153 let mut instruments = addresses
154 .iter()
155 .map(|a| a.addr)
156 .collect::<Vec<Addr4882_t>>();
157 instruments.push(linux_gpib_sys::NOADDR);
158 unsafe {
159 linux_gpib_sys::EnableRemote(board, instruments.as_ptr());
160 }
161 let status = IbStatus::current_thread_local_status();
162 if status.err {
163 Err(GpibError::DriverError(
164 status,
165 IbError::current_thread_local_error()?,
166 ))
167 } else {
168 Ok(())
169 }
170}
171
172pub fn FindRQS(board: c_int, addresses: &Vec<Addr4882>) -> Result<(Addr4882, c_short), GpibError> {
178 let mut instruments = addresses
179 .iter()
180 .map(|a| a.addr)
181 .collect::<Vec<Addr4882_t>>();
182 instruments.push(linux_gpib_sys::NOADDR);
183 let mut status_byte: c_short = 0;
184 unsafe {
185 linux_gpib_sys::FindRQS(board, instruments.as_ptr(), &mut status_byte);
186 }
187 let status = IbStatus::current_thread_local_status();
188 if status.err {
189 Err(GpibError::DriverError(
190 status,
191 IbError::current_thread_local_error()?,
192 ))
193 } else {
194 let index: usize = ThreadIbcnt().try_into()?;
195 if index >= addresses.len() {
196 Err(GpibError::ValueError(
197 "index stored in Ibcnt is larger than addresses array length".to_owned(),
198 ))
199 } else {
200 Ok((addresses[index], status_byte))
201 }
202 }
203}
204
205pub fn PassControl(board: c_int, address: Addr4882) -> Result<(), GpibError> {
211 unsafe {
212 linux_gpib_sys::PassControl(board, address.addr);
213 }
214 let status = IbStatus::current_thread_local_status();
215 if status.err {
216 Err(GpibError::DriverError(
217 status,
218 IbError::current_thread_local_error()?,
219 ))
220 } else {
221 Ok(())
222 }
223}
224
225pub fn PPoll(board: c_int) -> Result<c_short, GpibError> {
231 let mut result: c_short = 0;
232 unsafe {
233 linux_gpib_sys::PPoll(board, &mut result);
234 }
235 let status = IbStatus::current_thread_local_status();
236 if status.err {
237 Err(GpibError::DriverError(
238 status,
239 IbError::current_thread_local_error()?,
240 ))
241 } else {
242 Ok(result)
243 }
244}
245
246pub fn PPollConfig(
252 board: c_int,
253 address: Addr4882,
254 dio_line: c_int,
255 line_sense: c_int,
256) -> Result<(), GpibError> {
257 unsafe {
258 linux_gpib_sys::PPollConfig(board, address.addr, dio_line, line_sense);
259 }
260 let status = IbStatus::current_thread_local_status();
261 if status.err {
262 Err(GpibError::DriverError(
263 status,
264 IbError::current_thread_local_error()?,
265 ))
266 } else {
267 Ok(())
268 }
269}
270
271pub fn PPollUnconfig(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
275 let mut instruments = addresses
276 .iter()
277 .map(|a| a.addr)
278 .collect::<Vec<Addr4882_t>>();
279 instruments.push(linux_gpib_sys::NOADDR);
280 unsafe {
281 linux_gpib_sys::PPollUnconfig(board, instruments.as_ptr());
282 }
283 let status = IbStatus::current_thread_local_status();
284 if status.err {
285 Err(GpibError::DriverError(
286 status,
287 IbError::current_thread_local_error()?,
288 ))
289 } else {
290 Ok(())
291 }
292}
293
294pub fn RcvRespMsg(board: c_int, buffer: &mut [u8], termination: c_int) -> Result<(), GpibError> {
304 unsafe {
305 linux_gpib_sys::RcvRespMsg(
306 board,
307 buffer.as_mut_ptr() as *mut c_void,
308 buffer.len().try_into()?,
309 termination,
310 );
311 }
312 let status = IbStatus::current_thread_local_status();
313 if status.err {
314 Err(GpibError::DriverError(
315 status,
316 IbError::current_thread_local_error()?,
317 ))
318 } else {
319 Ok(())
320 }
321}
322
323pub fn ReadStatusByte(board: c_int, address: Addr4882) -> Result<c_short, GpibError> {
329 let mut result: c_short = 0;
330 unsafe {
331 linux_gpib_sys::ReadStatusByte(board, address.addr, &mut result);
332 }
333 let status = IbStatus::current_thread_local_status();
334 if status.err {
335 Err(GpibError::DriverError(
336 status,
337 IbError::current_thread_local_error()?,
338 ))
339 } else {
340 Ok(result)
341 }
342}
343
344pub fn Receive(
350 board: c_int,
351 address: Addr4882,
352 buffer: &mut [u8],
353 termination: c_int,
354) -> Result<(IbStatus, usize), GpibError> {
355 log::debug!("Receive({:?}, {:?})", board, address);
356 unsafe {
357 linux_gpib_sys::Receive(
358 board,
359 address.addr,
360 buffer.as_mut_ptr() as *mut c_void,
361 buffer.len().try_into()?,
362 termination,
363 );
364 }
365 let status = IbStatus::current_thread_local_status();
366 if status.err {
367 log::debug!("-> {:?}", status);
368 Err(GpibError::DriverError(
369 status,
370 IbError::current_thread_local_error()?,
371 ))
372 } else {
373 let n_read = ThreadIbcntl().try_into()?;
374 log::debug!(
375 "Receive({:?}, {:?}) -> Read {} bytes",
376 board,
377 address,
378 n_read
379 );
380 Ok((status, n_read))
381 }
382}
383
384pub fn ReceiveSetup(board: c_int, address: Addr4882) -> Result<(), GpibError> {
392 unsafe {
393 linux_gpib_sys::ReceiveSetup(board, address.addr);
394 }
395 let status = IbStatus::current_thread_local_status();
396 if status.err {
397 Err(GpibError::DriverError(
398 status,
399 IbError::current_thread_local_error()?,
400 ))
401 } else {
402 Ok(())
403 }
404}
405
406pub fn ResetSys(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
417 let mut instruments = addresses
418 .iter()
419 .map(|a| a.addr)
420 .collect::<Vec<Addr4882_t>>();
421 instruments.push(linux_gpib_sys::NOADDR);
422 unsafe {
423 linux_gpib_sys::ResetSys(board, instruments.as_ptr());
424 }
425 let status = IbStatus::current_thread_local_status();
426 if status.err {
427 Err(GpibError::DriverError(
428 status,
429 IbError::current_thread_local_error()?,
430 ))
431 } else {
432 Ok(())
433 }
434}
435
436pub fn Send(
442 board: c_int,
443 address: Addr4882,
444 buffer: &[u8],
445 eot_mode: IbSendEOI,
446) -> Result<(), GpibError> {
447 log::debug!("Send({:?}, {:?}, {:?})", board, address, buffer);
448 unsafe {
449 linux_gpib_sys::Send(
450 board,
451 address.addr,
452 buffer.as_ptr() as *const c_void,
453 buffer.len().try_into()?,
454 eot_mode.as_eot(),
455 );
456 }
457 let status = IbStatus::current_thread_local_status();
458 log::debug!(
459 "Send({:?}, {:?}, {:?}) -> {:?}",
460 board,
461 address,
462 buffer,
463 status
464 );
465 if status.err {
466 Err(GpibError::DriverError(
467 status,
468 IbError::current_thread_local_error()?,
469 ))
470 } else {
471 Ok(())
472 }
473}
474
475pub fn SendIFC(board: c_int) -> Result<(), GpibError> {
479 log::debug!("SendIFC({})", board);
480 unsafe {
481 linux_gpib_sys::SendIFC(board);
482 }
483 let status = IbStatus::current_thread_local_status();
484 log::debug!("endIFC({}) -> {:?}", board, status);
485 if status.err {
486 Err(GpibError::DriverError(
487 status,
488 IbError::current_thread_local_error()?,
489 ))
490 } else {
491 Ok(())
492 }
493}
494
495pub fn SendList(
499 board: c_int,
500 addresses: &Vec<Addr4882>,
501 buffer: &[u8],
502 eot_mode: IbSendEOI,
503) -> Result<(), GpibError> {
504 log::debug!("SendList({:?}, {:?}, {:?})", board, addresses, buffer);
505 let mut instruments = addresses
506 .iter()
507 .map(|a| a.addr)
508 .collect::<Vec<Addr4882_t>>();
509 instruments.push(linux_gpib_sys::NOADDR);
510 unsafe {
511 linux_gpib_sys::SendList(
512 board,
513 instruments.as_ptr(),
514 buffer.as_ptr() as *const c_void,
515 buffer.len().try_into()?,
516 eot_mode.as_eot(),
517 );
518 }
519 let status = IbStatus::current_thread_local_status();
520 log::debug!(
521 "SendList({:?}, {:?}, {:?}) -> {:?}",
522 board,
523 addresses,
524 buffer,
525 status
526 );
527 if status.err {
528 Err(GpibError::DriverError(
529 status,
530 IbError::current_thread_local_error()?,
531 ))
532 } else {
533 Ok(())
534 }
535}
536
537pub fn SendLLO(board: c_int) -> Result<(), GpibError> {
541 unsafe {
542 linux_gpib_sys::SendLLO(board);
543 }
544 let status = IbStatus::current_thread_local_status();
545 if status.err {
546 Err(GpibError::DriverError(
547 status,
548 IbError::current_thread_local_error()?,
549 ))
550 } else {
551 Ok(())
552 }
553}
554
555pub fn SetRWLS(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
559 let mut instruments = addresses
560 .iter()
561 .map(|a| a.addr)
562 .collect::<Vec<Addr4882_t>>();
563 instruments.push(linux_gpib_sys::NOADDR);
564 unsafe {
565 linux_gpib_sys::SetRWLS(board, instruments.as_ptr());
566 }
567 let status = IbStatus::current_thread_local_status();
568 if status.err {
569 Err(GpibError::DriverError(
570 status,
571 IbError::current_thread_local_error()?,
572 ))
573 } else {
574 Ok(())
575 }
576}
577
578pub fn TestSRQ(board: c_int) -> Result<bool, GpibError> {
584 let mut result: c_short = 10;
585 unsafe {
586 linux_gpib_sys::TestSRQ(board, &mut result);
587 }
588 let status = IbStatus::current_thread_local_status();
589 if status.err {
590 Err(GpibError::DriverError(
591 status,
592 IbError::current_thread_local_error()?,
593 ))
594 } else {
595 match result {
596 0 => Ok(false),
597 1 => Ok(true),
598 other => Err(GpibError::ValueError(format!("Unexpected value {}", other))),
599 }
600 }
601}
602
603pub fn TestSys(board: c_int, addresses: &Vec<Addr4882>) -> Result<Vec<c_short>, GpibError> {
607 let mut instruments = addresses
608 .iter()
609 .map(|a| a.addr)
610 .collect::<Vec<Addr4882_t>>();
611 instruments.push(linux_gpib_sys::NOADDR);
612 let mut results: Vec<c_short> = Vec::with_capacity(addresses.len());
613 results.resize(addresses.len(), 0);
614 unsafe {
615 linux_gpib_sys::TestSys(board, instruments.as_ptr(), results.as_mut_ptr());
616 }
617 let status = IbStatus::current_thread_local_status();
618 if status.err {
619 Err(GpibError::DriverError(
620 status,
621 IbError::current_thread_local_error()?,
622 ))
623 } else {
624 Ok(results)
625 }
626}
627
628pub fn Trigger(board: c_int, address: Addr4882) -> Result<(), GpibError> {
632 unsafe {
633 linux_gpib_sys::Trigger(board, address.addr);
634 }
635 let status = IbStatus::current_thread_local_status();
636 if status.err {
637 Err(GpibError::DriverError(
638 status,
639 IbError::current_thread_local_error()?,
640 ))
641 } else {
642 Ok(())
643 }
644}
645
646pub fn TriggerList(board: c_int, addresses: &Vec<Addr4882>) -> Result<(), GpibError> {
650 let mut instruments = addresses
651 .iter()
652 .map(|a| a.addr)
653 .collect::<Vec<Addr4882_t>>();
654 instruments.push(linux_gpib_sys::NOADDR);
655 unsafe {
656 linux_gpib_sys::TriggerList(board, instruments.as_ptr());
657 }
658 let status = IbStatus::current_thread_local_status();
659 if status.err {
660 Err(GpibError::DriverError(
661 status,
662 IbError::current_thread_local_error()?,
663 ))
664 } else {
665 Ok(())
666 }
667}
668
669#[cfg(feature = "async-tokio")]
670pub async fn WaitSRQ(board: c_int) -> Result<c_short, GpibError> {
674 tokio::task::spawn_blocking(move || {
675 let mut result: c_short = 0;
676 unsafe {
677 linux_gpib_sys::WaitSRQ(board, &mut result);
678 }
679 let status = IbStatus::current_thread_local_status();
680 if status.err {
681 Err(GpibError::DriverError(
682 status,
683 IbError::current_thread_local_error()?,
684 ))
685 } else {
686 Ok(result)
687 }
688 })
689 .await?
690}