diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2023-07-16 17:13:47 +0900 |
---|---|---|
committer | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2023-07-16 17:13:47 +0900 |
commit | cde82311a1b300ce634234ef5acd0c3ed3a8b2bc (patch) | |
tree | 5f5314ac6cae48cde75b48147644838d1cda3990 | |
parent | d76688665d25007ee56a18958f574a6bc1891fee (diff) | |
download | hinawa-rs-cde82311a1b300ce634234ef5acd0c3ed3a8b2bc.tar.gz |
hinawa: regenerate crate
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
-rw-r--r-- | hinawa/examples/read-quadlet.rs | 19 | ||||
-rw-r--r-- | hinawa/src/auto/cycle_time.rs | 105 | ||||
-rw-r--r-- | hinawa/src/auto/mod.rs | 3 | ||||
-rw-r--r-- | hinawa/src/auto/versions.txt | 2 | ||||
-rw-r--r-- | hinawa/src/cycle_time.rs | 72 | ||||
-rw-r--r-- | hinawa/src/fw_fcp.rs | 211 | ||||
-rw-r--r-- | hinawa/src/fw_node.rs | 40 | ||||
-rw-r--r-- | hinawa/src/fw_req.rs | 214 | ||||
-rw-r--r-- | hinawa/src/fw_resp.rs | 78 | ||||
-rw-r--r-- | hinawa/src/lib.rs | 1 | ||||
-rw-r--r-- | hinawa/src/subclass/fw_fcp.rs | 37 | ||||
-rw-r--r-- | hinawa/src/subclass/fw_req.rs | 65 | ||||
-rw-r--r-- | hinawa/src/subclass/fw_resp.rs | 91 |
13 files changed, 906 insertions, 32 deletions
diff --git a/hinawa/examples/read-quadlet.rs b/hinawa/examples/read-quadlet.rs index 7510739..f42415e 100644 --- a/hinawa/examples/read-quadlet.rs +++ b/hinawa/examples/read-quadlet.rs @@ -23,15 +23,16 @@ fn main() { let req = hinawa::FwReq::new(); let mut frames = [0; 4]; - req.transaction_sync( - &node, - FwTcode::ReadQuadletRequest, - OFFSET, - 4, - &mut frames, - 100, - ) - .unwrap(); + let _ = req + .transaction_with_tstamp( + &node, + FwTcode::ReadQuadletRequest, + OFFSET, + 4, + &mut frames, + 100, + ) + .unwrap(); assert_eq!(0x31333934, u32::from_be_bytes(frames)); diff --git a/hinawa/src/auto/cycle_time.rs b/hinawa/src/auto/cycle_time.rs new file mode 100644 index 0000000..a03e4ef --- /dev/null +++ b/hinawa/src/auto/cycle_time.rs @@ -0,0 +1,105 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from +// from gir-files (https://github.com/gtk-rs/gir-files) +// DO NOT EDIT + +use glib::translate::*; +use std::mem; + +glib::wrapper! { + /// A boxed object to express data of cycle time. + /// A [`CycleTime`][crate::CycleTime] expresses the value of cycle time of 1394 OHCI as well as Linux system + /// time referring to clock_id. + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct CycleTime(Boxed<ffi::HinawaCycleTime>); + + match fn { + copy => |ptr| glib::gobject_ffi::g_boxed_copy(ffi::hinawa_cycle_time_get_type(), ptr as *mut _) as *mut ffi::HinawaCycleTime, + free => |ptr| glib::gobject_ffi::g_boxed_free(ffi::hinawa_cycle_time_get_type(), ptr as *mut _), + type_ => || ffi::hinawa_cycle_time_get_type(), + } +} + +impl CycleTime { + /// Allocate and return an instance of [`CycleTime`][crate::CycleTime]. + /// + /// # Returns + /// + /// An instance of [`CycleTime`][crate::CycleTime]. + #[doc(alias = "hinawa_cycle_time_new")] + pub fn new() -> CycleTime { + unsafe { from_glib_full(ffi::hinawa_cycle_time_new()) } + } + + /// Get the ID of clock for timestamp. + /// + /// # Returns + /// + /// + /// ## `clock_id` + /// The numeric ID of clock source for the reference timestamp. + /// One of CLOCK_REALTIME(0), CLOCK_MONOTONIC(1), and CLOCK_MONOTONIC_RAW(4) is available + /// UAPI of Linux kernel. + #[doc(alias = "hinawa_cycle_time_get_clock_id")] + #[doc(alias = "get_clock_id")] + pub fn clock_id(&self) -> i32 { + unsafe { + let mut clock_id = mem::MaybeUninit::uninit(); + ffi::hinawa_cycle_time_get_clock_id(self.to_glib_none().0, clock_id.as_mut_ptr()); + let clock_id = clock_id.assume_init(); + clock_id + } + } + + /// Get the value of cycle time in 1394 OHCI controller. + /// + /// # Returns + /// + /// + /// ## `raw` + /// The raw value for CYCLE_TIME register. + #[doc(alias = "hinawa_cycle_time_get_raw")] + #[doc(alias = "get_raw")] + pub fn raw(&self) -> u32 { + unsafe { + let mut raw = mem::MaybeUninit::uninit(); + ffi::hinawa_cycle_time_get_raw(self.to_glib_none().0, raw.as_mut_ptr()); + let raw = raw.assume_init(); + raw + } + } + + /// Get system time with enough size of strorage. The timestamp refers to clock_id available by + /// [`clock_id()`][Self::clock_id()]. + /// + /// # Returns + /// + /// + /// ## `tv_sec` + /// The second part of timestamp. + /// + /// ## `tv_nsec` + /// The nanosecond part of timestamp. + #[doc(alias = "hinawa_cycle_time_get_system_time")] + #[doc(alias = "get_system_time")] + pub fn system_time(&self) -> (i64, i32) { + unsafe { + let mut tv_sec = mem::MaybeUninit::uninit(); + let mut tv_nsec = mem::MaybeUninit::uninit(); + ffi::hinawa_cycle_time_get_system_time( + self.to_glib_none().0, + tv_sec.as_mut_ptr(), + tv_nsec.as_mut_ptr(), + ); + let tv_sec = tv_sec.assume_init(); + let tv_nsec = tv_nsec.assume_init(); + (tv_sec, tv_nsec) + } + } +} + +impl Default for CycleTime { + fn default() -> Self { + Self::new() + } +} diff --git a/hinawa/src/auto/mod.rs b/hinawa/src/auto/mod.rs index e0b9a32..d67f108 100644 --- a/hinawa/src/auto/mod.rs +++ b/hinawa/src/auto/mod.rs @@ -15,6 +15,9 @@ pub use self::fw_req::FwReq; mod fw_resp; pub use self::fw_resp::FwResp; +mod cycle_time; +pub use self::cycle_time::CycleTime; + mod enums; pub use self::enums::FwFcpError; pub use self::enums::FwNodeError; diff --git a/hinawa/src/auto/versions.txt b/hinawa/src/auto/versions.txt index 1313169..4bb7a0b 100644 --- a/hinawa/src/auto/versions.txt +++ b/hinawa/src/auto/versions.txt @@ -1,3 +1,3 @@ Generated by gir (https://github.com/gtk-rs/gir @ c8a7a13d2c4d) from -from gir-files (https://github.com/gtk-rs/gir-files @ 7ebd4478b4a5) +from gir-files (https://github.com/gtk-rs/gir-files @ faebfb303ca6) diff --git a/hinawa/src/cycle_time.rs b/hinawa/src/cycle_time.rs new file mode 100644 index 0000000..2806eea --- /dev/null +++ b/hinawa/src/cycle_time.rs @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +use crate::*; + +impl CycleTime { + /// Get the value of cycle time in 1394 OHCI controller. The first element of array expresses the + /// value of sec field, up to 127. The second element of array expresses the value of cycle field, + /// up to 7999. The third element of array expresses the value of offset field, up to 3071. + /// + /// # Returns + /// + /// + /// ## `fields` + /// The value of cycle time register of 1394 + /// OHCI, including three elements; second, cycle, and offset in its order. + #[doc(alias = "hinawa_cycle_time_get_fields")] + pub fn fields(&mut self) -> [u16; 3] { + let mut fields = [0; 3]; + unsafe { + ffi::hinawa_cycle_time_get_fields(self.to_glib_none_mut().0, &mut fields); + } + fields + } + + /// Compute second count and cycle count from unsigned 16 bit integer value retrieved by Asynchronous + /// Transmit (AT), Asynchronous Receive(AR), Isochronous Transmit (IT), and Isochronous Receive (IR) + /// contexts of 1394 OHCI. The second count is completed with the internal value read from the + /// CYCLE_TIME register. For the precise computation, the method should be called in the condition + /// that the timing between receipt of time stamp and access to CYCLE_TIME register is within 8 + /// seconds. + /// ## `tstamp` + /// The value of time stamp retrieved from each context of 1394 OHCI. + /// + /// # Returns + /// + /// + /// ## `isoc_cycle` + /// The result to parse the time stamp. The + /// first element is for 7 bits of second field in the format of IEEE 1394 CYCLE_TIME + /// register, up to 127. The second element is for 13 bits of cycle field in the format, + /// up to 7,999. + #[doc(alias = "hinawa_cycle_time_compute_tstamp")] + pub fn compute_tstamp(&self, tstamp: u32) -> [u32; 2] { + let mut isoc_cycle = [0; 2]; + unsafe { + ffi::hinawa_cycle_time_compute_tstamp(self.to_glib_none().0, tstamp, &mut isoc_cycle); + } + isoc_cycle + } + + /// Parse second count and cycle count from unsigned 16 bit integer value retrieved by Asynchronous + /// Transmit (AT), Asynchronous Receive(AR), Isochronous Transmit (IT), and Isochronous Receive (IR) + /// contexts of 1394 OHCI. + /// ## `tstamp` + /// The value of time stamp retrieved from each context of 1394 OHCI. + /// + /// # Returns + /// + /// + /// ## `isoc_cycle` + /// The result to parse the time stamp. The + /// first element is for three order bits of second field in the format of IEEE 1394 + /// CYCLE_TIME register, up to 7. The second element is for 13 bits of cycle field in + /// the format, up to 7,999. + #[doc(alias = "hinawa_cycle_time_parse_tstamp")] + pub fn parse_tstamp(tstamp: u32) -> [u32; 2] { + let mut isoc_cycle = [0; 2]; + unsafe { + ffi::hinawa_cycle_time_parse_tstamp(tstamp, &mut isoc_cycle); + } + isoc_cycle + } +} diff --git a/hinawa/src/fw_fcp.rs b/hinawa/src/fw_fcp.rs index ef52200..f345acf 100644 --- a/hinawa/src/fw_fcp.rs +++ b/hinawa/src/fw_fcp.rs @@ -7,43 +7,165 @@ use crate::*; /// /// [`FwFcp`][struct@crate::FwFcp] pub trait FwFcpExtManual { + /// Transfer command frame for FCP. When receiving response frame for FCP, `signal::FwFcp::responded` + /// signal is emitted. + /// + /// Each value of @tstamp is unsigned 16 bit integer including higher 3 bits for three low order bits + /// of second field and the rest 13 bits for cycle field in the format of IEEE 1394 CYCLE_TIMER register. + /// + /// If the version of kernel ABI for Linux FireWire subsystem is less than 6, each element of @tstamp + /// has invalid value (=G_MAXUINT16). + /// ## `cmd_frame` + /// An array with elements for request byte data. The value of this + /// argument should point to the array and immutable. + /// ## `timeout_ms` + /// The timeout to wait for response subaction of transaction for command frame. + /// + /// # Returns + /// + /// TRUE if the overall operation finishes successfully, otherwise FALSE. + /// + /// ## `tstamp` + /// The array with two elements for time stamps. + /// The first element is for the isochronous cycle at which the request arrived. The second + /// element is for the isochronous cycle at which the response was sent. + #[doc(alias = "hinawa_fw_fcp_command_with_tstamp")] + fn command_with_tstamp( + &self, + cmd_frame: &[u8], + timeout_ms: u32, + ) -> Result<[u32; 2], glib::Error>; + /// Finish the pair of asynchronous transaction for AV/C command and response transactions. The - /// timeout_ms parameter is used to wait for response transaction since the command transaction is - /// initiated, ignoring `property::FwFcp::timeout` property of instance. The timeout is not expanded in - /// the case that AV/C INTERIM status is arrived, thus the caller should expand the timeout in - /// advance for the case. - /// ## `cmd` + /// timeout_ms parameter is used to wait for response transaction since the command transaction + /// is initiated, ignoring [property@FwFcp:timeout] property of instance. The timeout is not + /// expanded in the case that AV/C INTERIM status is arrived, thus the caller should expand the + /// timeout in advance for the case. + /// + /// ## `cmd_frame` /// An array with elements for request byte data. The value of /// this argument should point to the array and immutable. - /// ## `resp` + /// ## `resp_frame` /// An array with elements for response byte data. Callers /// should give it for buffer with enough space against the request since this library /// performs no reallocation. Due to the reason, the value of this argument should point to /// the pointer to the array and immutable. The content of array is mutable. /// ## `timeout_ms` /// The timeout to wait for response transaction since command transactions finishes. + /// + /// # Returns + /// + /// TRUE if the overall operation finishes successfully, otherwise FALSE. + /// + /// ## `resp_size` + /// The size of response buffer consumed for response frame. + /// #[doc(alias = "hinawa_fw_fcp_avc_transaction")] fn avc_transaction( &self, - req_frame: &[u8], + cmd_frame: &[u8], resp_frame: &mut [u8], timeout_ms: u32, ) -> Result<usize, glib::Error>; + + /// Finish the pair of asynchronous transaction for AV/C command and response transactions. The + /// timeout_ms parameter is used to wait for response transaction since the command transaction is + /// initiated, ignoring `property::FwFcp::timeout` property of instance. The timeout is not expanded in + /// the case that AV/C INTERIM status is arrived, thus the caller should expand the timeout in + /// advance for the case. + /// ## `cmd_frame` + /// An array with elements for request byte data. The value of + /// this argument should point to the array and immutable. + /// ## `resp_frame` + /// An array with elements for response byte data. Callers + /// should give it for buffer with enough space against the request since this library + /// performs no reallocation. Due to the reason, the value of this argument should point to + /// the pointer to the array and immutable. The content of array is mutable. + /// ## `timeout_ms` + /// The timeout to wait for response transaction since command transactions finishes. + /// + /// # Returns + /// + /// TRUE if the overall operation finishes successfully, otherwise FALSE. + /// + /// ## `tstamp` + /// The array with three elements for time + /// stamps. The first element is for the isochronous cycle at which the request was sent + /// for the command of FCP transaction. The second element is for the isochronous cycle at + /// which the response arrived for the command of FCP transaction. The third element is for + /// the isochronous cycle at which the request was sent for the response of FCP transaction. + #[doc(alias = "hinawa_fw_fcp_avc_transaction_with_tstamp")] + fn avc_transaction_with_tstamp( + &self, + cmd_frame: &[u8], + resp_frame: &mut Vec<u8>, + timeout_ms: u32, + ) -> Result<[u32; 3], glib::Error>; + /// Emitted when the node transfers asynchronous packet as response for FCP and the process - /// successfully read the content of packet. + /// successfully read the content of packet, except for the case that `signal@FwFcp::responded2` + /// signal handler is already assigned. + /// /// ## `frame` /// The array with elements for byte - /// data of response for FCP. + /// data of response for FCP. #[doc(alias = "responded")] fn connect_responded<F>(&self, f: F) -> SignalHandlerId where F: Fn(&Self, &[u8]) + 'static; + + /// Emitted when the node transfers asynchronous packet as response for FCP and the process + /// successfully read the content of packet. + /// + /// The values of @tstamp is unsigned 16 bit integer including higher 3 bits for three low + /// order bits of second field and the rest 13 bits for cycle field in the format of IEEE + /// 1394 CYCLE_TIMER register. + /// + /// If the version of kernel ABI for Linux FireWire subsystem is less than 6, the value of + /// @tstamp argument has invalid value (=G_MAXUINT). + /// + /// ## `tstamp` + /// The time stamp at which the request arrived for the response of FCP + /// transaction. + /// ## `frame` + /// The array with elements for byte + /// data of response for FCP. + #[doc(alias = "responded2")] + fn connect_responded2<F>(&self, f: F) -> SignalHandlerId + where + F: Fn(&Self, u32, &[u8]) + 'static; } impl<O: IsA<FwFcp>> FwFcpExtManual for O { + fn command_with_tstamp( + &self, + cmd_frame: &[u8], + timeout_ms: u32, + ) -> Result<[u32; 2], glib::Error> { + unsafe { + let mut tstamp = [0; 2]; + let mut error = std::ptr::null_mut(); + + let _ = ffi::hinawa_fw_fcp_command_with_tstamp( + self.as_ref().to_glib_none().0, + cmd_frame.as_ptr(), + cmd_frame.len(), + &mut tstamp, + timeout_ms, + &mut error, + ); + + if error.is_null() { + Ok(tstamp) + } else { + Err(from_glib_full(error)) + } + } + } + fn avc_transaction( &self, - req_frame: &[u8], + cmd_frame: &[u8], resp_frame: &mut [u8], timeout_ms: u32, ) -> Result<usize, glib::Error> { @@ -53,8 +175,8 @@ impl<O: IsA<FwFcp>> FwFcpExtManual for O { ffi::hinawa_fw_fcp_avc_transaction( self.as_ref().to_glib_none().0, - req_frame.as_ptr(), - req_frame.len(), + cmd_frame.as_ptr(), + cmd_frame.len(), &mut resp_frame.as_mut_ptr(), &mut resp_frame_size, timeout_ms, @@ -69,6 +191,37 @@ impl<O: IsA<FwFcp>> FwFcpExtManual for O { } } + fn avc_transaction_with_tstamp( + &self, + cmd_frame: &[u8], + resp_frame: &mut Vec<u8>, + timeout_ms: u32, + ) -> Result<[u32; 3], glib::Error> { + unsafe { + let mut resp_frame_size = resp_frame.len(); + let mut tstamp = [0; 3]; + let mut error = std::ptr::null_mut(); + + let _ = ffi::hinawa_fw_fcp_avc_transaction_with_tstamp( + self.as_ref().to_glib_none().0, + cmd_frame.as_ptr(), + cmd_frame.len(), + &mut resp_frame.as_mut_ptr(), + &mut resp_frame_size, + &mut tstamp, + timeout_ms, + &mut error, + ); + + if error.is_null() { + resp_frame.truncate(resp_frame_size); + Ok(tstamp) + } else { + Err(from_glib_full(error)) + } + } + } + fn connect_responded<F>(&self, f: F) -> SignalHandlerId where F: Fn(&Self, &[u8]) + 'static, @@ -100,4 +253,38 @@ impl<O: IsA<FwFcp>> FwFcpExtManual for O { ) } } + + fn connect_responded2<F>(&self, f: F) -> SignalHandlerId + where + F: Fn(&Self, u32, &[u8]) + 'static, + { + unsafe extern "C" fn responded2_trampoline<P, F>( + this: *mut ffi::HinawaFwFcp, + tstamp: libc::c_uint, + frame: *const u8, + length: libc::c_uint, + f: glib::ffi::gpointer, + ) where + P: IsA<FwFcp>, + F: Fn(&P, u32, &[u8]) + 'static, + { + let f: &F = &*(f as *const F); + f( + &FwFcp::from_glib_borrow(this).unsafe_cast_ref(), + tstamp, + std::slice::from_raw_parts(frame, length as usize), + ) + } + unsafe { + let f: std::boxed::Box<F> = std::boxed::Box::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"responded2\0".as_ptr() as *const _, + Some(std::mem::transmute::<_, unsafe extern "C" fn()>( + responded2_trampoline::<Self, F> as *const (), + )), + std::boxed::Box::into_raw(f), + ) + } + } } diff --git a/hinawa/src/fw_node.rs b/hinawa/src/fw_node.rs index 8e5927d..6a48d2d 100644 --- a/hinawa/src/fw_node.rs +++ b/hinawa/src/fw_node.rs @@ -10,10 +10,27 @@ pub trait FwNodeExtManual { /// Get cached content of configuration ROM aligned to big-endian. /// /// # Returns + /// + /// + /// ## `image` /// The content of configuration ROM. #[doc(alias = "hinawa_fw_node_get_config_rom")] #[doc(alias = "get_config_rom")] fn config_rom(&self) -> Result<&[u8], glib::Error>; + + /// Read current value of CYCLE_TIME register in 1394 OHCI controller. + /// ## `clock_id` + /// The numeric ID of clock source for the reference timestamp. One of CLOCK_REALTIME(0), + /// CLOCK_MONOTONIC(1), and CLOCK_MONOTONIC_RAW(4) is available in UAPI of Linux kernel. + /// ## `cycle_time` + /// A [`CycleTime`][crate::CycleTime]. + /// + /// # Returns + /// + /// TRUE if the overall operation finishes successfully, otherwise FALSE. + #[doc(alias = "hinawa_fw_node_read_cycle_time")] + fn read_cycle_time(&self, clock_id: i32, cycle_time: &mut CycleTime) + -> Result<(), glib::Error>; } impl<O: IsA<FwNode>> FwNodeExtManual for O { @@ -37,4 +54,27 @@ impl<O: IsA<FwNode>> FwNodeExtManual for O { } } } + + fn read_cycle_time( + &self, + clock_id: i32, + cycle_time: &mut CycleTime, + ) -> Result<(), glib::Error> { + unsafe { + let mut error = std::ptr::null_mut(); + + let _ = ffi::hinawa_fw_node_read_cycle_time( + self.as_ref().to_glib_none().0, + clock_id, + &cycle_time.to_glib_none_mut().0, + &mut error, + ); + + if error.is_null() { + Ok(()) + } else { + Err(from_glib_full(error)) + } + } + } } diff --git a/hinawa/src/fw_req.rs b/hinawa/src/fw_req.rs index 4700197..fe7d34e 100644 --- a/hinawa/src/fw_req.rs +++ b/hinawa/src/fw_req.rs @@ -33,6 +33,7 @@ pub trait FwReqExtManual { length: usize, frame: &mut [u8], ) -> Result<(), glib::Error>; + /// Execute request subaction of transaction to the given node according to given code, then wait /// for response subaction within the given timeout. The `property::FwReq::timeout` property of /// instance is ignored. @@ -63,18 +64,121 @@ pub trait FwReqExtManual { frame: &mut [u8], timeout_ms: u32, ) -> Result<(), glib::Error>; + + /// Execute request subaction of transactions to the given node according to given code. When the + /// response subaction arrives and running event dispatcher reads the contents, + /// `signal::FwReq::responded` signal handler is called. + /// ## `node` + /// A [`FwNode`][crate::FwNode]. + /// ## `tcode` + /// A transaction code of [`FwTcode`][crate::FwTcode]. + /// ## `addr` + /// A destination address of target device + /// ## `length` + /// The range of address in byte unit. + /// ## `frame` + /// An array with elements for byte data. Callers should + /// give it for buffer with enough space against the request since this library performs no + /// reallocation. Due to the reason, the value of this argument should point to the pointer + /// to the array and immutable. The content of array is mutable for read and lock + /// transaction. + /// + /// # Returns + /// + /// TRUE if the overall operation finishes successfully, otherwise FALSE. + #[doc(alias = "hinawa_fw_req_request")] + fn request<P: IsA<FwNode>>( + &self, + node: &P, + tcode: FwTcode, + addr: u64, + length: usize, + frame: &mut [u8], + ) -> Result<(), glib::Error>; + + /// Execute request subaction of transaction to the given node according to given code, then wait + /// for response subaction within the given timeout. The `property::FwReq::timeout` property of + /// instance is ignored. + /// + /// Each value of @tstamp is unsigned 16 bit integer including higher 3 bits for three low order bits + /// of second field and the rest 13 bits for cycle field in the format of IEEE 1394 CYCLE_TIMER register. + /// + /// If the version of kernel ABI for Linux FireWire subsystem is less than 6, each element of @tstamp + /// has invalid value (=G_MAXUINT). + /// ## `node` + /// A [`FwNode`][crate::FwNode]. + /// ## `tcode` + /// A transaction code of [`FwTcode`][crate::FwTcode]. + /// ## `addr` + /// A destination address of target device + /// ## `length` + /// The range of address in byte unit. + /// ## `frame` + /// An array with elements for byte data. Callers should + /// give it for buffer with enough space against the request since this library performs no + /// reallocation. Due to the reason, the value of this argument should point to the pointer + /// to the array and immutable. The content of array is mutable for read and lock + /// transaction. + /// ## `timeout_ms` + /// The timeout to wait for response subaction of the transaction since request + /// subaction is initiated, in milliseconds. + /// + /// # Returns + /// + /// TRUE if the overall operation finishes successfully, otherwise FALSE. + /// + /// ## `tstamp` + /// The array with two elements for time stamps. + /// The first element is for the isochronous cycle at which the request was sent. The second + /// element is for the isochronous cycle at which the response arrived. + #[doc(alias = "hinawa_fw_req_transaction_with_tstamp")] + fn transaction_with_tstamp<P: IsA<FwNode>>( + &self, + node: &P, + tcode: FwTcode, + addr: u64, + length: usize, + frame: &mut [u8], + timeout_ms: u32, + ) -> Result<[u32; 2], glib::Error>; + /// Emitted when the unit transfers asynchronous packet as response subaction for the /// transaction and the process successfully reads the content of packet from Linux firewire - /// subsystem. + /// subsystem, except for the case that `signal@FwReq::responded2` signal handler is already + /// assigned. + /// /// ## `rcode` /// One of [`FwRcode`][crate::FwRcode]. /// ## `frame` - /// The array with elements for - /// byte data of response subaction for transaction. + /// The array with elements for byte data of response subaction for transaction. #[doc(alias = "responded")] fn connect_responded<F>(&self, f: F) -> SignalHandlerId where F: Fn(&Self, FwRcode, &[u8]) + 'static; + + /// Emitted when the unit transfers asynchronous packet as response subaction for the + /// transaction and the process successfully reads the content of packet from Linux firewire + /// subsystem. + /// + /// The values of @request_tstamp and @response_tstamp are unsigned 16 bit integer including + /// higher 3 bits for three low order bits of second field and the rest 13 bits for cycle + /// field in the format of IEEE 1394 CYCLE_TIMER register. + /// + /// If the version of kernel ABI for Linux FireWire subsystem is less than 6, the + /// @request_tstamp and @response_tstamp argument has invalid value (=G_MAXUINT). + /// + /// ## `rcode` + /// One of [`FwRcode`][crate::FwRcode]. + /// ## `request_tstamp` + /// The isochronous cycle at which the request was sent. + /// ## `response_tstamp` + /// The isochronous cycle at which the response arrived. + /// ## `frame` + /// The array with elements for byte data of response subaction for transaction. + #[doc(alias = "responded2")] + fn connect_responded2<F>(&self, f: F) -> SignalHandlerId + where + F: Fn(&Self, FwRcode, u32, u32, &[u8]) + 'static; } impl<O: IsA<FwReq>> FwReqExtManual for O { @@ -142,6 +246,72 @@ impl<O: IsA<FwReq>> FwReqExtManual for O { } } + fn request<P: IsA<FwNode>>( + &self, + node: &P, + tcode: FwTcode, + addr: u64, + length: usize, + frame: &mut [u8], + ) -> Result<(), glib::Error> { + unsafe { + let mut frame_size = frame.len(); + let mut error = std::ptr::null_mut(); + + let _ = ffi::hinawa_fw_req_request( + self.as_ref().to_glib_none().0, + node.as_ref().to_glib_none().0, + tcode.into_glib(), + addr, + length, + &mut frame.as_mut_ptr(), + &mut frame_size, + &mut error, + ); + + if error.is_null() { + Ok(()) + } else { + Err(from_glib_full(error)) + } + } + } + + fn transaction_with_tstamp<P: IsA<FwNode>>( + &self, + node: &P, + tcode: FwTcode, + addr: u64, + length: usize, + frame: &mut [u8], + timeout_ms: u32, + ) -> Result<[u32; 2], glib::Error> { + unsafe { + let mut frame_size = frame.len(); + let mut tstamp = [0; 2]; + let mut error = std::ptr::null_mut(); + + let _ = ffi::hinawa_fw_req_transaction_with_tstamp( + self.as_ref().to_glib_none().0, + node.as_ref().to_glib_none().0, + tcode.into_glib(), + addr, + length, + &mut frame.as_mut_ptr(), + &mut frame_size, + &mut tstamp, + timeout_ms, + &mut error, + ); + + if error.is_null() { + Ok(tstamp) + } else { + Err(from_glib_full(error)) + } + } + } + fn connect_responded<F>(&self, f: F) -> SignalHandlerId where F: Fn(&Self, FwRcode, &[u8]) + 'static, @@ -175,4 +345,42 @@ impl<O: IsA<FwReq>> FwReqExtManual for O { ) } } + + fn connect_responded2<F>(&self, f: F) -> SignalHandlerId + where + F: Fn(&Self, FwRcode, u32, u32, &[u8]) + 'static, + { + unsafe extern "C" fn responded2_trampoline<P, F>( + this: *mut ffi::HinawaFwReq, + rcode: ffi::HinawaFwRcode, + request_tstamp: libc::c_uint, + response_tstamp: libc::c_uint, + frame: *const u8, + length: libc::c_uint, + f: glib::ffi::gpointer, + ) where + P: IsA<FwReq>, + F: Fn(&P, FwRcode, u32, u32, &[u8]) + 'static, + { + let f: &F = &*(f as *const F); + f( + &FwReq::from_glib_borrow(this).unsafe_cast_ref(), + from_glib(rcode), + request_tstamp, + response_tstamp, + std::slice::from_raw_parts(frame, length as usize), + ) + } + unsafe { + let f: std::boxed::Box<F> = std::boxed::Box::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"responded2\0".as_ptr() as *const _, + Some(std::mem::transmute::<_, unsafe extern "C" fn()>( + responded2_trampoline::<Self, F> as *const (), + )), + std::boxed::Box::into_raw(f), + ) + } + } } diff --git a/hinawa/src/fw_resp.rs b/hinawa/src/fw_resp.rs index 6e924d0..afdf9ac 100644 --- a/hinawa/src/fw_resp.rs +++ b/hinawa/src/fw_resp.rs @@ -7,10 +7,24 @@ use crate::*; /// /// [`FwResp`][struct@crate::FwResp] pub trait FwRespExtManual { - /// Emitted when any node transfers request subaction to the range of address to which this - /// object listening, the `signal::FwResp::requested` signal handler is called with arrived - /// frame for the subaction. The handler is expected to call [`FwRespExt::set_resp_frame()`][crate::prelude::FwRespExt::set_resp_frame()] - /// with frame and return [`FwRcode`][crate::FwRcode] for response subaction. + #[doc(alias = "requested2")] + fn connect_requested2<F>(&self, f: F) -> SignalHandlerId + where + F: Fn(&Self, FwTcode, u64, u32, u32, u32, u32, &[u8]) -> FwRcode + 'static; + + /// Emitted when any node transfers request subaction to the range of address in 1394 OHCI + /// controller to which this object listening. + /// + /// The handler is expected to call [`FwRespExt::set_resp_frame()`][crate::prelude::FwRespExt::set_resp_frame()] with frame and return + /// [`FwRcode`][crate::FwRcode] for response subaction. + /// + /// The value of @tstamp is unsigned 16 bit integer including higher 3 bits for three low + /// order bits of second field and the rest 13 bits for cycle field in the format of IEEE + /// 1394 CYCLE_TIMER register. + /// + /// If the version of kernel ABI for Linux FireWire subsystem is less than 6, the value of + /// tstamp argument has invalid value (=G_MAXUINT). Furthermore, if the version is less than + /// 4, the src, dst, card, generation arguments have invalid value (=G_MAXUINT). /// ## `tcode` /// One of [`FwTcode`][crate::FwTcode] enumerations /// ## `offset` @@ -23,6 +37,8 @@ pub trait FwRespExtManual { /// The index of card corresponding to 1394 OHCI controller. /// ## `generation` /// The generation of bus when the transaction is transferred. + /// ## `tstamp` + /// The isochronous cycle at which the request arrived. /// ## `frame` /// The array with elements for byte /// data. @@ -31,10 +47,10 @@ pub trait FwRespExtManual { /// /// One of [`FwRcode`][crate::FwRcode] enumerations corresponding to rcodes defined in IEEE 1394 /// specification. - #[doc(alias = "requested")] - fn connect_requested2<F>(&self, f: F) -> SignalHandlerId + #[doc(alias = "requested3")] + fn connect_requested3<F>(&self, f: F) -> SignalHandlerId where - F: Fn(&Self, FwTcode, u64, u32, u32, u32, u32, &[u8]) -> FwRcode + 'static; + F: Fn(&Self, FwTcode, u64, u32, u32, u32, u32, u32, &[u8]) -> FwRcode + 'static; } impl<O: IsA<FwResp>> FwRespExtManual for O { @@ -83,4 +99,52 @@ impl<O: IsA<FwResp>> FwRespExtManual for O { ) } } + + fn connect_requested3<F>(&self, f: F) -> SignalHandlerId + where + F: Fn(&Self, FwTcode, u64, u32, u32, u32, u32, u32, &[u8]) -> FwRcode + 'static, + { + unsafe extern "C" fn requested3_trampoline<P, F>( + this: *mut ffi::HinawaFwResp, + tcode: ffi::HinawaFwTcode, + offset: u64, + src: libc::c_uint, + dst: libc::c_uint, + card: libc::c_uint, + generation: libc::c_uint, + tstamp: libc::c_uint, + frame: *const u8, + length: libc::c_uint, + f: glib::ffi::gpointer, + ) -> ffi::HinawaFwRcode + where + P: IsA<FwResp>, + F: Fn(&P, FwTcode, u64, u32, u32, u32, u32, u32, &[u8]) -> FwRcode + 'static, + { + let f: &F = &*(f as *const F); + f( + &FwResp::from_glib_borrow(this).unsafe_cast_ref(), + from_glib(tcode), + offset, + src, + dst, + card, + generation, + tstamp, + std::slice::from_raw_parts(frame, length as usize), + ) + .into_glib() + } + unsafe { + let f: std::boxed::Box<F> = std::boxed::Box::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"requested3\0".as_ptr() as *const _, + Some(std::mem::transmute::<_, unsafe extern "C" fn()>( + requested3_trampoline::<Self, F> as *const (), + )), + std::boxed::Box::into_raw(f), + ) + } + } } diff --git a/hinawa/src/lib.rs b/hinawa/src/lib.rs index ecf2f56..90d6e59 100644 --- a/hinawa/src/lib.rs +++ b/hinawa/src/lib.rs @@ -3,6 +3,7 @@ #![doc = include_str!("../README.md")] mod auto; +mod cycle_time; mod fw_fcp; mod fw_node; mod fw_req; diff --git a/hinawa/src/subclass/fw_fcp.rs b/hinawa/src/subclass/fw_fcp.rs index 18842b4..af76cca 100644 --- a/hinawa/src/subclass/fw_fcp.rs +++ b/hinawa/src/subclass/fw_fcp.rs @@ -7,11 +7,15 @@ pub trait FwFcpImpl: ObjectImpl + FwRespImpl { fn responded(&self, fcp: &Self::Type, frame: &[u8]) { self.parent_responded(fcp, frame) } + fn responded2(&self, fcp: &Self::Type, tstamp: u32, frame: &[u8]) { + self.parent_responded2(fcp, tstamp, frame) + } } /// Trait which is automatically implemented to implementator of [`FwFcpImpl`][self::FwFcpImpl]. pub trait FwFcpImplExt: ObjectSubclass { fn parent_responded(&self, fcp: &Self::Type, frame: &[u8]); + fn parent_responded2(&self, fcp: &Self::Type, tstamp: u32, frame: &[u8]); } impl<T: FwFcpImpl> FwFcpImplExt for T { @@ -29,6 +33,21 @@ impl<T: FwFcpImpl> FwFcpImplExt for T { ) } } + fn parent_responded2(&self, fcp: &Self::Type, tstamp: u32, frame: &[u8]) { + unsafe { + let data = T::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::HinawaFwFcpClass; + let f = (*parent_class) + .responded2 + .expect("No parent class implementation for \"responded2\""); + f( + fcp.unsafe_cast_ref::<FwFcp>().to_glib_none().0, + tstamp, + frame.as_ptr(), + frame.len() as u32, + ) + } + } } unsafe impl<T: FwFcpImpl> IsSubclassable<T> for FwFcp { @@ -37,6 +56,7 @@ unsafe impl<T: FwFcpImpl> IsSubclassable<T> for FwFcp { let klass = class.as_mut(); klass.responded = Some(fw_fcp_responded::<T>); + klass.responded2 = Some(fw_fcp_responded2::<T>); } } @@ -54,3 +74,20 @@ unsafe extern "C" fn fw_fcp_responded<T: FwFcpImpl>( std::slice::from_raw_parts(frame, length as usize), ) } + +unsafe extern "C" fn fw_fcp_responded2<T: FwFcpImpl>( + ptr: *mut ffi::HinawaFwFcp, + tstamp: c_uint, + frame: *const u8, + length: c_uint, +) { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.imp(); + let wrap: Borrowed<FwFcp> = from_glib_borrow(ptr); + + imp.responded2( + wrap.unsafe_cast_ref(), + tstamp, + std::slice::from_raw_parts(frame, length as usize), + ) +} diff --git a/hinawa/src/subclass/fw_req.rs b/hinawa/src/subclass/fw_req.rs index 6acf1f6..21c3a8f 100644 --- a/hinawa/src/subclass/fw_req.rs +++ b/hinawa/src/subclass/fw_req.rs @@ -7,11 +7,29 @@ pub trait FwReqImpl: ObjectImpl { fn responded(&self, req: &Self::Type, rcode: FwRcode, frame: &[u8]) { self.parent_responded(req, rcode, frame) } + fn responded2( + &self, + req: &Self::Type, + rcode: FwRcode, + request_tstamp: u32, + response_tstamp: u32, + frame: &[u8], + ) { + self.parent_responded2(req, rcode, request_tstamp, response_tstamp, frame) + } } /// Trait which is automatically implemented to implementator of [`FwReqImpl`][self::FwReqImpl]. pub trait FwReqImplExt: ObjectSubclass { fn parent_responded(&self, req: &Self::Type, rcode: FwRcode, frame: &[u8]); + fn parent_responded2( + &self, + req: &Self::Type, + rcode: FwRcode, + request_tstamp: u32, + response_tstamp: u32, + frame: &[u8], + ); } impl<T: FwReqImpl> FwReqImplExt for T { @@ -30,6 +48,31 @@ impl<T: FwReqImpl> FwReqImplExt for T { ) } } + + fn parent_responded2( + &self, + req: &Self::Type, + rcode: FwRcode, + request_tstamp: u32, + response_tstamp: u32, + frame: &[u8], + ) { + unsafe { + let data = T::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::HinawaFwReqClass; + let f = (*parent_class) + .responded2 + .expect("No parent class implementation for \"responded2\""); + f( + req.unsafe_cast_ref::<FwReq>().to_glib_none().0, + rcode.into_glib(), + request_tstamp, + response_tstamp, + frame.as_ptr(), + frame.len() as u32, + ) + } + } } unsafe impl<T: FwReqImpl> IsSubclassable<T> for FwReq { @@ -38,6 +81,7 @@ unsafe impl<T: FwReqImpl> IsSubclassable<T> for FwReq { let klass = class.as_mut(); klass.responded = Some(fw_req_responded::<T>); + klass.responded2 = Some(fw_req_responded2::<T>); } } @@ -57,3 +101,24 @@ unsafe extern "C" fn fw_req_responded<T: FwReqImpl>( std::slice::from_raw_parts(frame, length as usize), ) } + +unsafe extern "C" fn fw_req_responded2<T: FwReqImpl>( + ptr: *mut ffi::HinawaFwReq, + rcode: ffi::HinawaFwRcode, + request_tstamp: c_uint, + response_tstamp: c_uint, + frame: *const u8, + length: c_uint, +) { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.imp(); + let wrap: Borrowed<FwReq> = from_glib_borrow(ptr); + + imp.responded2( + wrap.unsafe_cast_ref(), + from_glib(rcode), + request_tstamp, + response_tstamp, + std::slice::from_raw_parts(frame, length as usize), + ) +} diff --git a/hinawa/src/subclass/fw_resp.rs b/hinawa/src/subclass/fw_resp.rs index 76f7e82..997db3a 100644 --- a/hinawa/src/subclass/fw_resp.rs +++ b/hinawa/src/subclass/fw_resp.rs @@ -17,6 +17,22 @@ pub trait FwRespImpl: ObjectImpl { ) -> FwRcode { self.parent_requested2(resp, tcode, offset, src, dst, card, generation, frame) } + fn requested3( + &self, + resp: &Self::Type, + tcode: FwTcode, + offset: u64, + src: u32, + dst: u32, + card: u32, + generation: u32, + tstamp: u32, + frame: &[u8], + ) -> FwRcode { + self.parent_requested3( + resp, tcode, offset, src, dst, card, generation, tstamp, frame, + ) + } } /// Trait which is automatically implemented to implementator of [`FwRespImpl`][self::FwRespImpl]. @@ -32,6 +48,18 @@ pub trait FwRespImplExt: ObjectSubclass { generation: u32, frame: &[u8], ) -> FwRcode; + fn parent_requested3( + &self, + resp: &Self::Type, + tcode: FwTcode, + offset: u64, + src: u32, + dst: u32, + card: u32, + generation: u32, + tstamp: u32, + frame: &[u8], + ) -> FwRcode; } impl<T: FwRespImpl> FwRespImplExt for T { @@ -65,6 +93,38 @@ impl<T: FwRespImpl> FwRespImplExt for T { )) } } + fn parent_requested3( + &self, + resp: &Self::Type, + tcode: FwTcode, + offset: u64, + src: u32, + dst: u32, + card: u32, + generation: u32, + tstamp: u32, + frame: &[u8], + ) -> FwRcode { + unsafe { + let data = T::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::HinawaFwRespClass; + let f = (*parent_class) + .requested3 + .expect("No parent class implementation for \"requested3\""); + from_glib(f( + resp.unsafe_cast_ref::<FwResp>().to_glib_none().0, + tcode.into_glib(), + offset, + src, + dst, + card, + generation, + tstamp, + frame.as_ptr(), + frame.len() as u32, + )) + } + } } unsafe impl<T: FwRespImpl> IsSubclassable<T> for FwResp { @@ -73,6 +133,7 @@ unsafe impl<T: FwRespImpl> IsSubclassable<T> for FwResp { let klass = class.as_mut(); klass.requested2 = Some(fw_resp_requested2::<T>); + klass.requested3 = Some(fw_resp_requested3::<T>); } } @@ -103,3 +164,33 @@ unsafe extern "C" fn fw_resp_requested2<T: FwRespImpl>( ) .into_glib() } + +unsafe extern "C" fn fw_resp_requested3<T: FwRespImpl>( + ptr: *mut ffi::HinawaFwResp, + tcode: ffi::HinawaFwTcode, + offset: u64, + src: u32, + dst: u32, + card: u32, + generation: u32, + tstamp: u32, + frame: *const u8, + length: c_uint, +) -> ffi::HinawaFwRcode { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.imp(); + let wrap: Borrowed<FwResp> = from_glib_borrow(ptr); + + imp.requested3( + wrap.unsafe_cast_ref(), + from_glib(tcode), + offset, + src, + dst, + card, + generation, + tstamp, + std::slice::from_raw_parts(frame, length as usize), + ) + .into_glib() +} |