aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2022-05-04 17:18:29 +0900
committer坂本 貴史 <o-takashi@sakamocchi.jp>2022-05-05 08:10:07 +0900
commit697bb2d6bcbde2125f7089d3a723241c619a6bdc (patch)
tree19404eca249e45d83001600e1e48cf7ff4575a8a
parent67a775fd51cf2c689090e4d2d5ec6304c54b8bd7 (diff)
downloadlibhinoko-697bb2d6bcbde2125f7089d3a723241c619a6bdc.tar.gz
fw_iso_ctx: code refactoring to dispatch iso interrupt events
This commit moves the position of current implementation of event handler and changes the way to call them. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
-rw-r--r--src/fw_iso_ctx.c37
-rw-r--r--src/fw_iso_ctx_private.h15
-rw-r--r--src/fw_iso_rx_multiple.c218
-rw-r--r--src/fw_iso_rx_single.c75
-rw-r--r--src/fw_iso_tx.c32
5 files changed, 194 insertions, 183 deletions
diff --git a/src/fw_iso_ctx.c b/src/fw_iso_ctx.c
index 8be5410..ca91c11 100644
--- a/src/fw_iso_ctx.c
+++ b/src/fw_iso_ctx.c
@@ -270,7 +270,6 @@ void hinoko_fw_iso_ctx_allocate(HinokoFwIsoCtx *self, const char *path,
create.type = mode;
create.channel = channel;
create.speed = scode;
- create.closure = (__u64)self;
create.header_size = header_size;
if (ioctl(priv->fd, FW_CDEV_IOC_CREATE_ISO_CONTEXT, &create) < 0) {
@@ -667,42 +666,34 @@ static gboolean check_src(GSource *source)
return !!(condition & (G_IO_IN | G_IO_ERR));
}
-static void handle_irq_event(const struct fw_cdev_event_iso_interrupt *ev,
+static void handle_irq_event(HinokoFwIsoCtx *self, const union fw_cdev_event *event,
GError **error)
{
- if (HINOKO_IS_FW_ISO_RX_SINGLE((gpointer)ev->closure)) {
- HinokoFwIsoRxSingle *ctx = HINOKO_FW_ISO_RX_SINGLE((gpointer)ev->closure);
-
- hinoko_fw_iso_rx_single_handle_event(ctx, ev, error);
- } else if (HINOKO_IS_FW_ISO_TX((gpointer)ev->closure)) {
- HinokoFwIsoTx *ctx = HINOKO_FW_ISO_TX((gpointer)ev->closure);
-
- hinoko_fw_iso_tx_handle_event(ctx, ev, error);
- } else {
+ if (HINOKO_IS_FW_ISO_RX_SINGLE(self))
+ (void)fw_iso_rx_single_handle_event(self, event, error);
+ else if (HINOKO_IS_FW_ISO_TX(self))
+ (void)fw_iso_tx_handle_event(self, event, error);
+ else
return;
- }
if (*error != NULL)
return;
- fw_iso_ctx_queue_chunks(HINOKO_FW_ISO_CTX((gpointer)ev->closure), error);
+ fw_iso_ctx_queue_chunks(self, error);
}
-static void handle_irq_mc_event(const struct fw_cdev_event_iso_interrupt_mc *ev,
+static void handle_irq_mc_event(HinokoFwIsoCtx *self, const union fw_cdev_event *event,
GError **error)
{
- if (HINOKO_IS_FW_ISO_RX_MULTIPLE((gpointer)ev->closure)) {
- HinokoFwIsoRxMultiple *ctx = HINOKO_FW_ISO_RX_MULTIPLE((gpointer)ev->closure);
-
- hinoko_fw_iso_rx_multiple_handle_event(ctx, ev, error);
- } else {
+ if (HINOKO_IS_FW_ISO_RX_MULTIPLE(self))
+ (void)fw_iso_rx_multiple_handle_event(self, event, error);
+ else
return;
- }
if (*error != NULL)
return;
- fw_iso_ctx_queue_chunks(HINOKO_FW_ISO_CTX((gpointer)ev->closure), error);
+ fw_iso_ctx_queue_chunks(self, error);
}
static gboolean dispatch_src(GSource *source, GSourceFunc cb, gpointer user_data)
@@ -732,12 +723,12 @@ static gboolean dispatch_src(GSource *source, GSourceFunc cb, gpointer user_data
event = (const union fw_cdev_event *)src->buf;
switch (event->common.type) {
case FW_CDEV_EVENT_ISO_INTERRUPT:
- handle_irq_event(&event->iso_interrupt, &error);
+ handle_irq_event(src->self, event, &error);
if (error != NULL)
goto error;
break;
case FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL:
- handle_irq_mc_event(&event->iso_interrupt_mc, &error);
+ handle_irq_mc_event(src->self, event, &error);
if (error != NULL)
goto error;
break;
diff --git a/src/fw_iso_ctx_private.h b/src/fw_iso_ctx_private.h
index 3797993..a8e7997 100644
--- a/src/fw_iso_ctx_private.h
+++ b/src/fw_iso_ctx_private.h
@@ -32,16 +32,13 @@ void hinoko_fw_iso_ctx_read_frames(HinokoFwIsoCtx *self, guint offset,
guint length, const guint8 **frames,
guint *frame_size);
-void hinoko_fw_iso_rx_single_handle_event(HinokoFwIsoRxSingle *self,
- const struct fw_cdev_event_iso_interrupt *event,
- GError **error);
+gboolean fw_iso_rx_single_handle_event(HinokoFwIsoCtx *inst, const union fw_cdev_event *event,
+ GError **error);
-void hinoko_fw_iso_rx_multiple_handle_event(HinokoFwIsoRxMultiple *self,
- const struct fw_cdev_event_iso_interrupt_mc *event,
- GError **error);
+gboolean fw_iso_rx_multiple_handle_event(HinokoFwIsoCtx *inst, const union fw_cdev_event *event,
+ GError **error);
-void hinoko_fw_iso_tx_handle_event(HinokoFwIsoTx *self,
- const struct fw_cdev_event_iso_interrupt *event,
- GError **error);
+gboolean fw_iso_tx_handle_event(HinokoFwIsoCtx *inst, const union fw_cdev_event *event,
+ GError **error);
#endif
diff --git a/src/fw_iso_rx_multiple.c b/src/fw_iso_rx_multiple.c
index c435fb0..bbe8e91 100644
--- a/src/fw_iso_rx_multiple.c
+++ b/src/fw_iso_rx_multiple.c
@@ -120,6 +120,118 @@ static void hinoko_fw_iso_rx_multiple_init(HinokoFwIsoRxMultiple *self)
return;
}
+static gboolean fw_iso_rx_multiple_register_chunk(HinokoFwIsoRxMultiple *self, GError **error)
+{
+ HinokoFwIsoRxMultiplePrivate *priv = hinoko_fw_iso_rx_multiple_get_instance_private(self);
+ gboolean schedule_irq = FALSE;
+
+ if (priv->chunks_per_irq > 0) {
+ if (++priv->accumulated_chunk_count % priv->chunks_per_irq == 0)
+ schedule_irq = TRUE;
+ if (priv->accumulated_chunk_count >= G_MAXINT)
+ priv->accumulated_chunk_count %= priv->chunks_per_irq;
+ }
+
+ hinoko_fw_iso_ctx_register_chunk(HINOKO_FW_ISO_CTX(self), FALSE, 0, 0, NULL, 0, 0,
+ schedule_irq, error);
+
+ return TRUE;
+}
+
+gboolean fw_iso_rx_multiple_handle_event(HinokoFwIsoCtx *inst, const union fw_cdev_event *event,
+ GError **error)
+{
+ HinokoFwIsoRxMultiple *self;
+ HinokoFwIsoRxMultiplePrivate *priv;
+
+ const struct fw_cdev_event_iso_interrupt_mc *ev;
+ unsigned int bytes_per_chunk;
+ unsigned int chunks_per_buffer;
+ unsigned int bytes_per_buffer;
+ unsigned int accum_end;
+ unsigned int accum_length;
+ unsigned int chunk_pos;
+ unsigned int chunk_end;
+ struct ctx_payload *ctx_payload;
+
+ g_return_val_if_fail(HINOKO_IS_FW_ISO_RX_MULTIPLE(inst), FALSE);
+ g_return_val_if_fail(event->common.type == FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL, FALSE);
+
+ self = HINOKO_FW_ISO_RX_MULTIPLE(inst);
+ priv = hinoko_fw_iso_rx_multiple_get_instance_private(self);
+
+ ev = &event->iso_interrupt_mc;
+
+ g_object_get(G_OBJECT(self),
+ "bytes-per-chunk", &bytes_per_chunk,
+ "chunks-per-buffer", &chunks_per_buffer, NULL);
+
+ bytes_per_buffer = bytes_per_chunk * chunks_per_buffer;
+
+ accum_end = ev->completed;
+ if (accum_end < priv->prev_offset)
+ accum_end += bytes_per_buffer;
+
+ accum_length = 0;
+ ctx_payload = priv->ctx_payloads;
+ priv->ctx_payload_count = 0;
+ while (TRUE) {
+ unsigned int avail = accum_end - priv->prev_offset - accum_length;
+ guint offset;
+ const guint8 *frames;
+ const guint32 *buf;
+ guint32 iso_header;
+ guint frame_size;
+ unsigned int length;
+
+ if (avail < 4)
+ break;
+
+ offset = (priv->prev_offset + accum_length) % bytes_per_buffer;
+ hinoko_fw_iso_ctx_read_frames(HINOKO_FW_ISO_CTX(self), offset,
+ 4, &frames, &frame_size);
+
+ buf = (const guint32 *)frames;
+ iso_header = GUINT32_FROM_LE(buf[0]);
+ length = (iso_header & 0xffff0000) >> 16;
+
+ // In buffer-fill mode, payload is sandwitched by heading
+ // isochronous header and trailing timestamp.
+ length += 8;
+
+ if (avail < length)
+ break;
+
+ g_debug("%3d: %6d %4d %6d",
+ priv->ctx_payload_count, offset, length,
+ ev->completed);
+
+ ctx_payload->offset = offset;
+ ctx_payload->length = length;
+ ++ctx_payload;
+ ++priv->ctx_payload_count;
+
+ // For next position.
+ accum_length += length;
+ }
+
+ g_signal_emit(self,
+ fw_iso_rx_multiple_sigs[FW_ISO_RX_MULTIPLE_SIG_TYPE_IRQ],
+ 0, priv->ctx_payload_count);
+
+ chunk_pos = priv->prev_offset / bytes_per_chunk;
+ chunk_end = (priv->prev_offset + accum_length) / bytes_per_chunk;
+ for (; chunk_pos < chunk_end; ++chunk_pos) {
+ if (!fw_iso_rx_multiple_register_chunk(self, error))
+ return FALSE;
+ }
+
+ priv->prev_offset += accum_length;
+ priv->prev_offset %= bytes_per_buffer;
+
+ return TRUE;
+}
+
/**
* hinoko_fw_iso_rx_multiple_new:
*
@@ -288,23 +400,6 @@ void hinoko_fw_iso_rx_multiple_unmap_buffer(HinokoFwIsoRxMultiple *self)
priv->concat_frames = NULL;
}
-static void fw_iso_rx_multiple_register_chunk(HinokoFwIsoRxMultiple *self,
- GError **error)
-{
- HinokoFwIsoRxMultiplePrivate *priv = hinoko_fw_iso_rx_multiple_get_instance_private(self);
- gboolean schedule_irq = FALSE;
-
- if (priv->chunks_per_irq > 0) {
- if (++priv->accumulated_chunk_count % priv->chunks_per_irq == 0)
- schedule_irq = TRUE;
- if (priv->accumulated_chunk_count >= G_MAXINT)
- priv->accumulated_chunk_count %= priv->chunks_per_irq;
- }
-
- hinoko_fw_iso_ctx_register_chunk(HINOKO_FW_ISO_CTX(self), FALSE, 0, 0, NULL, 0, 0,
- schedule_irq, error);
-}
-
/**
* hinoko_fw_iso_rx_multiple_start:
* @self: A [class@FwIsoRxMultiple].
@@ -342,8 +437,7 @@ void hinoko_fw_iso_rx_multiple_start(HinokoFwIsoRxMultiple *self,
priv->accumulated_chunk_count = 0;
for (i = 0; i < chunks_per_buffer; ++i) {
- fw_iso_rx_multiple_register_chunk(self, error);
- if (*error != NULL)
+ if (!fw_iso_rx_multiple_register_chunk(self, error))
return;
}
@@ -364,92 +458,6 @@ void hinoko_fw_iso_rx_multiple_stop(HinokoFwIsoRxMultiple *self)
hinoko_fw_iso_ctx_stop(HINOKO_FW_ISO_CTX(self));
}
-void hinoko_fw_iso_rx_multiple_handle_event(HinokoFwIsoRxMultiple *self,
- const struct fw_cdev_event_iso_interrupt_mc *event,
- GError **error)
-{
- HinokoFwIsoRxMultiplePrivate *priv;
- unsigned int bytes_per_chunk;
- unsigned int chunks_per_buffer;
- unsigned int bytes_per_buffer;
- unsigned int accum_end;
- unsigned int accum_length;
- unsigned int chunk_pos;
- unsigned int chunk_end;
- struct ctx_payload *ctx_payload;
-
- g_return_if_fail(HINOKO_IS_FW_ISO_RX_MULTIPLE(self));
- priv = hinoko_fw_iso_rx_multiple_get_instance_private(self);
-
- g_object_get(G_OBJECT(self),
- "bytes-per-chunk", &bytes_per_chunk,
- "chunks-per-buffer", &chunks_per_buffer, NULL);
-
- bytes_per_buffer = bytes_per_chunk * chunks_per_buffer;
-
- accum_end = event->completed;
- if (accum_end < priv->prev_offset)
- accum_end += bytes_per_buffer;
-
- accum_length = 0;
- ctx_payload = priv->ctx_payloads;
- priv->ctx_payload_count = 0;
- while (TRUE) {
- unsigned int avail = accum_end - priv->prev_offset - accum_length;
- guint offset;
- const guint8 *frames;
- const guint32 *buf;
- guint32 iso_header;
- guint frame_size;
- unsigned int length;
-
- if (avail < 4)
- break;
-
- offset = (priv->prev_offset + accum_length) % bytes_per_buffer;
- hinoko_fw_iso_ctx_read_frames(HINOKO_FW_ISO_CTX(self), offset,
- 4, &frames, &frame_size);
-
- buf = (const guint32 *)frames;
- iso_header = GUINT32_FROM_LE(buf[0]);
- length = (iso_header & 0xffff0000) >> 16;
-
- // In buffer-fill mode, payload is sandwitched by heading
- // isochronous header and trailing timestamp.
- length += 8;
-
- if (avail < length)
- break;
-
- g_debug("%3d: %6d %4d %6d",
- priv->ctx_payload_count, offset, length,
- event->completed);
-
- ctx_payload->offset = offset;
- ctx_payload->length = length;
- ++ctx_payload;
- ++priv->ctx_payload_count;
-
- // For next position.
- accum_length += length;
- }
-
- g_signal_emit(self,
- fw_iso_rx_multiple_sigs[FW_ISO_RX_MULTIPLE_SIG_TYPE_IRQ],
- 0, priv->ctx_payload_count);
-
- chunk_pos = priv->prev_offset / bytes_per_chunk;
- chunk_end = (priv->prev_offset + accum_length) / bytes_per_chunk;
- for (; chunk_pos < chunk_end; ++chunk_pos) {
- fw_iso_rx_multiple_register_chunk(self, error);
- if (*error != NULL)
- return;
- }
-
- priv->prev_offset += accum_length;
- priv->prev_offset %= bytes_per_buffer;
-}
-
/**
* hinoko_fw_iso_rx_multiple_get_payload:
* @self: A [class@FwIsoRxMultiple].
diff --git a/src/fw_iso_rx_single.c b/src/fw_iso_rx_single.c
index e4ff9f8..7642a1e 100644
--- a/src/fw_iso_rx_single.c
+++ b/src/fw_iso_rx_single.c
@@ -79,6 +79,47 @@ static void hinoko_fw_iso_rx_single_init(HinokoFwIsoRxSingle *self)
return;
}
+gboolean fw_iso_rx_single_handle_event(HinokoFwIsoCtx *inst, const union fw_cdev_event *event,
+ GError **error)
+{
+ HinokoFwIsoRxSingle *self;
+ HinokoFwIsoRxSinglePrivate *priv;
+
+ const struct fw_cdev_event_iso_interrupt *ev;
+ guint sec;
+ guint cycle;
+ guint count;
+
+ g_return_val_if_fail(HINOKO_IS_FW_ISO_RX_SINGLE(inst), FALSE);
+ g_return_val_if_fail(event->common.type == FW_CDEV_EVENT_ISO_INTERRUPT, FALSE);
+
+ self = HINOKO_FW_ISO_RX_SINGLE(inst);
+ priv = hinoko_fw_iso_rx_single_get_instance_private(self);
+
+ ev = &event->iso_interrupt;
+ sec = (ev->cycle & 0x0000e000) >> 13;
+ cycle = ev->cycle & 0x00001fff;
+ count = ev->header_length / priv->header_size;
+
+ // TODO; handling error?
+ priv->ev = ev;
+ g_signal_emit(self, fw_iso_rx_single_sigs[FW_ISO_RX_SINGLE_SIG_TYPE_IRQ], 0,
+ sec, cycle, ev->header, ev->header_length, count);
+ priv->ev = NULL;
+
+ priv->chunk_cursor += count;
+ if (priv->chunk_cursor >= G_MAXINT) {
+ guint chunks_per_buffer;
+
+ g_object_get(G_OBJECT(self),
+ "chunks-per-buffer", &chunks_per_buffer, NULL);
+
+ priv->chunk_cursor %= chunks_per_buffer;
+ }
+
+ return TRUE;
+}
+
/**
* hinoko_fw_iso_rx_single_new:
*
@@ -236,40 +277,6 @@ void hinoko_fw_iso_rx_single_stop(HinokoFwIsoRxSingle *self)
hinoko_fw_iso_ctx_stop(HINOKO_FW_ISO_CTX(self));
}
-void hinoko_fw_iso_rx_single_handle_event(HinokoFwIsoRxSingle *self,
- const struct fw_cdev_event_iso_interrupt *event,
- GError **error)
-{
- HinokoFwIsoRxSinglePrivate *priv;
- guint sec;
- guint cycle;
- guint count;
-
- g_return_if_fail(HINOKO_IS_FW_ISO_RX_SINGLE(self));
- priv = hinoko_fw_iso_rx_single_get_instance_private(self);
-
- sec = (event->cycle & 0x0000e000) >> 13;
- cycle = event->cycle & 0x00001fff;
- count = event->header_length / priv->header_size;
-
- // TODO; handling error?
- priv->ev = event;
- g_signal_emit(self,
- fw_iso_rx_single_sigs[FW_ISO_RX_SINGLE_SIG_TYPE_IRQ],
- 0, sec, cycle, event->header, event->header_length, count);
- priv->ev = NULL;
-
- priv->chunk_cursor += count;
- if (priv->chunk_cursor >= G_MAXINT) {
- guint chunks_per_buffer;
-
- g_object_get(G_OBJECT(self),
- "chunks-per-buffer", &chunks_per_buffer, NULL);
-
- priv->chunk_cursor %= chunks_per_buffer;
- }
-}
-
/**
* hinoko_fw_iso_rx_single_get_payload:
* @self: A [class@FwIsoRxSingle].
diff --git a/src/fw_iso_tx.c b/src/fw_iso_tx.c
index 254ac59..4f0d4f1 100644
--- a/src/fw_iso_tx.c
+++ b/src/fw_iso_tx.c
@@ -71,6 +71,26 @@ static void hinoko_fw_iso_tx_init(HinokoFwIsoTx *self)
return;
}
+gboolean fw_iso_tx_handle_event(HinokoFwIsoCtx *inst, const union fw_cdev_event *event,
+ GError **error)
+{
+ const struct fw_cdev_event_iso_interrupt *ev;
+
+ g_return_val_if_fail(HINOKO_FW_ISO_TX(inst), FALSE);
+ g_return_val_if_fail(event->common.type == FW_CDEV_EVENT_ISO_INTERRUPT, FALSE);
+
+ ev = &event->iso_interrupt;
+
+ guint sec = (ev->cycle & 0x0000e000) >> 13;
+ guint cycle = ev->cycle & 0x00001fff;
+ unsigned int pkt_count = ev->header_length / 4;
+
+ g_signal_emit(inst, fw_iso_tx_sigs[FW_ISO_TX_SIG_TYPE_IRQ], 0, sec, cycle, ev->header,
+ ev->header_length, pkt_count);
+
+ return TRUE;
+}
+
/**
* hinoko_fw_iso_tx_new:
*
@@ -270,15 +290,3 @@ void hinoko_fw_iso_tx_register_packet(HinokoFwIsoTx *self,
priv->offset = frame_size;
}
}
-
-void hinoko_fw_iso_tx_handle_event(HinokoFwIsoTx *self,
- const struct fw_cdev_event_iso_interrupt *event,
- GError **error)
-{
- guint sec = (event->cycle & 0x0000e000) >> 13;
- guint cycle = event->cycle & 0x00001fff;
- unsigned int pkt_count = event->header_length / 4;
-
- g_signal_emit(self, fw_iso_tx_sigs[FW_ISO_TX_SIG_TYPE_IRQ], 0, sec, cycle, event->header,
- event->header_length, pkt_count);
-}