diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2022-05-04 17:18:29 +0900 |
---|---|---|
committer | 坂本 貴史 <o-takashi@sakamocchi.jp> | 2022-05-05 08:10:07 +0900 |
commit | 697bb2d6bcbde2125f7089d3a723241c619a6bdc (patch) | |
tree | 19404eca249e45d83001600e1e48cf7ff4575a8a | |
parent | 67a775fd51cf2c689090e4d2d5ec6304c54b8bd7 (diff) | |
download | libhinoko-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.c | 37 | ||||
-rw-r--r-- | src/fw_iso_ctx_private.h | 15 | ||||
-rw-r--r-- | src/fw_iso_rx_multiple.c | 218 | ||||
-rw-r--r-- | src/fw_iso_rx_single.c | 75 | ||||
-rw-r--r-- | src/fw_iso_tx.c | 32 |
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); -} |