| // SPDX-License-Identifier: LGPL-2.1-or-later |
| #include "internal.h" |
| |
| /** |
| * HinawaCycleTime: |
| * A boxed object to express data of cycle time. |
| * |
| * A [struct@CycleTime] expresses the value of cycle time of 1394 OHCI as well as Linux system |
| * time referring to clock_id. |
| */ |
| HinawaCycleTime *hinawa_cycle_time_copy(const HinawaCycleTime *self) |
| { |
| #ifdef g_memdup2 |
| return g_memdup2(self, sizeof(*self)); |
| #else |
| // GLib v2.68 deprecated g_memdup() with concern about overflow by narrow conversion from |
| // size_t to unsigned int in ABI for LP64 data model. |
| gpointer ptr = g_malloc(sizeof(*self)); |
| memcpy(ptr, self, sizeof(*self)); |
| return ptr; |
| #endif |
| } |
| |
| G_DEFINE_BOXED_TYPE(HinawaCycleTime, hinawa_cycle_time, hinawa_cycle_time_copy, g_free) |
| |
| /** |
| * hinawa_cycle_time_new: |
| * |
| * Allocate and return an instance of [struct@CycleTime]. |
| * |
| * Returns: (transfer full): An instance of [struct@CycleTime]. |
| * |
| * Since: 2.6 |
| */ |
| HinawaCycleTime *hinawa_cycle_time_new() |
| { |
| return g_malloc0(sizeof(HinawaCycleTime)); |
| } |
| |
| /** |
| * hinawa_cycle_time_get_system_time: |
| * @self: A [struct@CycleTime]. |
| * @tv_sec: (out caller-allocates): The second part of timestamp. |
| * @tv_nsec: (out caller-allocates): The nanosecond part of timestamp. |
| * |
| * Get system time with enough size of strorage. The timestamp refers to clock_id available by |
| * [method@CycleTime.get_clock_id]. |
| * |
| * Since: 2.6 |
| */ |
| void hinawa_cycle_time_get_system_time(const HinawaCycleTime *self, gint64 *tv_sec, gint32 *tv_nsec) |
| { |
| *tv_sec = self->tv_sec; |
| *tv_nsec = self->tv_nsec; |
| } |
| |
| /** |
| * hinawa_cycle_time_get_clock_id: |
| * @self: A [struct@CycleTime]. |
| * @clock_id: (out caller-allocates): 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. |
| * |
| * Get the ID of clock for timestamp. |
| * |
| * Since: 2.6 |
| */ |
| void hinawa_cycle_time_get_clock_id(const HinawaCycleTime *self, gint *clock_id) |
| { |
| *clock_id = self->clk_id; |
| } |
| |
| #define IEEE1394_CYCLE_TIME_SEC_MASK 0xfe000000 |
| #define IEEE1394_CYCLE_TIME_SEC_SHIFT 25 |
| #define IEEE1394_CYCLE_TIME_CYCLE_MASK 0x01fff000 |
| #define IEEE1394_CYCLE_TIME_CYCLE_SHIFT 12 |
| #define IEEE1394_CYCLE_TIME_OFFSET_MASK 0x00000fff |
| |
| static guint ieee1394_cycle_time_to_sec(guint32 cycle_time) |
| { |
| return (cycle_time & IEEE1394_CYCLE_TIME_SEC_MASK) >> IEEE1394_CYCLE_TIME_SEC_SHIFT; |
| } |
| |
| static guint ieee1394_cycle_time_to_cycle(guint32 cycle_time) |
| { |
| return (cycle_time & IEEE1394_CYCLE_TIME_CYCLE_MASK) >> IEEE1394_CYCLE_TIME_CYCLE_SHIFT; |
| } |
| |
| static guint ieee1394_cycle_time_to_offset(guint32 cycle_time) |
| { |
| return cycle_time & IEEE1394_CYCLE_TIME_OFFSET_MASK; |
| } |
| |
| /** |
| * hinawa_cycle_time_get_fields: |
| * @self: A [struct@CycleTime]. |
| * @fields: (array fixed-size=3) (out caller-allocates): The value of cycle time register of 1394 |
| * OHCI hardware, including three elements; second, cycle, and offset in its order. |
| * |
| * Get the value of cycle time in 1394 OHCI hardware. 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. |
| * |
| * Since: 2.6 |
| */ |
| void hinawa_cycle_time_get_fields(const HinawaCycleTime *self, guint16 fields[3]) |
| { |
| fields[0] = ieee1394_cycle_time_to_sec(self->cycle_timer); |
| fields[1] = ieee1394_cycle_time_to_cycle(self->cycle_timer); |
| fields[2] = ieee1394_cycle_time_to_offset(self->cycle_timer); |
| } |
| |
| /** |
| * hinawa_cycle_time_get_raw: |
| * @self: A [struct@CycleTime]. |
| * @raw: (out caller-allocates): The raw value for CYCLE_TIME register. |
| * |
| * Get the value of cycle time in 1394 OHCI hardware. |
| * |
| * Since: 2.6 |
| */ |
| void hinawa_cycle_time_get_raw(const HinawaCycleTime *self, guint32 *raw) |
| { |
| *raw = self->cycle_timer; |
| } |
| |
| #define OHCI1394_TSTAMP_SEC_MASK 0x0000e000 |
| #define OHCI1394_TSTAMP_SEC_SHIFT 13 |
| #define OHCI1394_TSTAMP_CYCLE_MASK 0x00001fff |
| #define OHCI1394_TSTAMP_CYCLE_SHIFT 0 |
| |
| #define IEEE1394_SEC_MAX 128 |
| #define OHCI1394_SEC_MAX 8 |
| |
| /** |
| * hinawa_cycle_time_compute_tstamp: |
| * @self: A [struct@CycleTime]. |
| * @tstamp: The value of time stamp retrieved from each context of 1394 OHCI. |
| * @isoc_cycle: (array fixed-size=2)(out caller-allocates): 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. |
| * |
| * 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. |
| * |
| * Since: 2.6 |
| */ |
| void hinawa_cycle_time_compute_tstamp(const HinawaCycleTime *self, guint tstamp, guint isoc_cycle[2]) |
| { |
| guint tstamp_sec_low = (tstamp & OHCI1394_TSTAMP_SEC_MASK) >> OHCI1394_TSTAMP_SEC_SHIFT; |
| guint curr_sec_low = ieee1394_cycle_time_to_sec(self->cycle_timer) & 0x7; |
| guint sec = ieee1394_cycle_time_to_sec(self->cycle_timer); |
| |
| // Round up. |
| if (tstamp_sec_low < curr_sec_low) |
| sec += OHCI1394_SEC_MAX; |
| sec |= tstamp_sec_low; |
| sec %= IEEE1394_SEC_MAX; |
| |
| isoc_cycle[0] = sec; |
| isoc_cycle[1] = (tstamp & OHCI1394_TSTAMP_CYCLE_MASK) >> OHCI1394_TSTAMP_CYCLE_SHIFT; |
| } |
| |
| /** |
| * hinawa_cycle_time_parse_tstamp: |
| * @tstamp: The value of time stamp retrieved from each context of 1394 OHCI. |
| * @isoc_cycle: (array fixed-size=2)(out caller-allocates): 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. |
| * |
| * 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. |
| * |
| * Since: 2.6 |
| */ |
| void hinawa_cycle_time_parse_tstamp(guint tstamp, guint isoc_cycle[2]) |
| { |
| isoc_cycle[0] = (tstamp & OHCI1394_TSTAMP_SEC_MASK) >> OHCI1394_TSTAMP_SEC_SHIFT; |
| isoc_cycle[1] = (tstamp & OHCI1394_TSTAMP_CYCLE_MASK) >> OHCI1394_TSTAMP_CYCLE_SHIFT; |
| } |