diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2022-05-03 07:57:47 +0900 |
---|---|---|
committer | 坂本 貴史 <o-takashi@sakamocchi.jp> | 2022-05-03 08:31:29 +0900 |
commit | 76dea57853eabd6c86a0382f43d26f869cff009d (patch) | |
tree | ca8b993e3176d9088a6df0f43d9e7105bac6ab54 | |
parent | 2a8eec4921324e1dfaeeed24f49abb4fe531540f (diff) | |
download | libhinoko-76dea57853eabd6c86a0382f43d26f869cff009d.tar.gz |
fw_iso_resource_priviate: split private implementatino into a file
By maintenance POV.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
-rw-r--r-- | src/fw_iso_resource.c | 225 | ||||
-rw-r--r-- | src/fw_iso_resource_auto.c | 8 | ||||
-rw-r--r-- | src/fw_iso_resource_once.c | 8 | ||||
-rw-r--r-- | src/fw_iso_resource_private.c | 226 | ||||
-rw-r--r-- | src/fw_iso_resource_private.h | 4 | ||||
-rw-r--r-- | src/meson.build | 1 |
6 files changed, 237 insertions, 235 deletions
diff --git a/src/fw_iso_resource.c b/src/fw_iso_resource.c index b84b239..df04c18 100644 --- a/src/fw_iso_resource.c +++ b/src/fw_iso_resource.c @@ -1,10 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later #include "fw_iso_resource_private.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - /** * HinokoFwIsoResource: * An interface object to listen events of isochronous resource allocation and deallocation. @@ -27,37 +23,6 @@ G_DEFINE_INTERFACE(HinokoFwIsoResource, hinoko_fw_iso_resource, G_TYPE_OBJECT) */ G_DEFINE_QUARK(hinoko-fw-iso-resource-error-quark, hinoko_fw_iso_resource_error) -static const char *const err_msgs[] = { - [HINOKO_FW_ISO_RESOURCE_ERROR_OPENED] = - "The instance is already associated to any firewire character device", - [HINOKO_FW_ISO_RESOURCE_ERROR_NOT_OPENED] = - "The instance is not associated to any firewire character device", - [HINOKO_FW_ISO_RESOURCE_ERROR_TIMEOUT] = - "No event to the request arrives within timeout.", -}; - -#define generate_local_error(error, code) \ - g_set_error_literal(error, HINOKO_FW_ISO_RESOURCE_ERROR, code, err_msgs[code]) - -#define generate_event_error(error, errno) \ - g_set_error(error, HINOKO_FW_ISO_RESOURCE_ERROR, \ - HINOKO_FW_ISO_RESOURCE_ERROR_EVENT, \ - "%d %s", errno, strerror(errno)) - -#define generate_file_error(error, code, format, arg) \ - g_set_error(error, G_FILE_ERROR, code, format, arg) - -typedef struct { - GSource src; - HinokoFwIsoResource *self; - gpointer tag; - gsize len; - guint8 *buf; - int fd; - void (*handle_event)(HinokoFwIsoResource *self, const char *signal_name, guint channel, - guint bandwidth, const GError *error); -} FwIsoResourceSource; - static void hinoko_fw_iso_resource_default_init(HinokoFwIsoResourceInterface *iface) { /** @@ -103,30 +68,6 @@ static void hinoko_fw_iso_resource_default_init(HinokoFwIsoResourceInterface *if 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_ERROR); } -gboolean fw_iso_resource_open(int *fd, const gchar *path, gint open_flag, GError **error) -{ - g_return_val_if_fail(fd != NULL, FALSE); - g_return_val_if_fail(path != NULL && strlen(path) > 0, FALSE); - g_return_val_if_fail(error == NULL || *error == NULL, FALSE); - - if (*fd >= 0) { - generate_local_error(error, HINOKO_FW_ISO_RESOURCE_ERROR_OPENED); - return FALSE; - } - - open_flag |= O_RDONLY; - *fd = open(path, open_flag); - if (*fd < 0) { - GFileError code = g_file_error_from_errno(errno); - if (code != G_FILE_ERROR_FAILED) - generate_file_error(error, code, "open(%s)", path); - else - generate_syscall_error(error, errno, "open(%s)", path); - return FALSE; - } - - return TRUE; -} /** * hinoko_fw_iso_resource_open: * @self: A [iface@FwIsoResource]. @@ -151,172 +92,6 @@ void hinoko_fw_iso_resource_open(HinokoFwIsoResource *self, const gchar *path, g (void)HINOKO_FW_ISO_RESOURCE_GET_IFACE(self)->open(self, path, open_flag, error); } -static void handle_event_signal(HinokoFwIsoResource *self, guint channel, guint bandwidth, - const GError *error, gpointer user_data) -{ - struct fw_iso_resource_waiter *w = (struct fw_iso_resource_waiter *)user_data; - - g_mutex_lock(&w->mutex); - if (error != NULL) - w->error = g_error_copy(error); - w->handled = TRUE; - g_cond_signal(&w->cond); - g_mutex_unlock(&w->mutex); -} - -// For internal use. -void fw_iso_resource_waiter_init(HinokoFwIsoResource *self, struct fw_iso_resource_waiter *w, - const char *signal_name, guint timeout_ms) -{ - g_mutex_init(&w->mutex); - g_cond_init(&w->cond); - w->error = NULL; - w->handled = FALSE; - w->expiration = g_get_monotonic_time() + timeout_ms * G_TIME_SPAN_MILLISECOND; - w->handler_id = g_signal_connect(self, signal_name, G_CALLBACK(handle_event_signal), w); -} - -// For internal use. -void fw_iso_resource_waiter_wait(HinokoFwIsoResource *self, struct fw_iso_resource_waiter *w, - GError **error) -{ - if (*error != NULL) { - g_signal_handler_disconnect(self, w->handler_id); - return; - } - - g_mutex_lock(&w->mutex); - while (w->handled == FALSE) { - if (!g_cond_wait_until(&w->cond, &w->mutex, w->expiration)) - break; - } - g_signal_handler_disconnect(self, w->handler_id); - g_mutex_unlock(&w->mutex); - - if (w->handled == FALSE) - generate_local_error(error, HINOKO_FW_ISO_RESOURCE_ERROR_TIMEOUT); - else if (w->error != NULL) - *error = w->error; // Delegate ownership. -} - -static void handle_iso_resource_event(FwIsoResourceSource *src, - const struct fw_cdev_event_iso_resource *ev) -{ - guint channel; - guint bandwidth; - const char *signal_name; - GError *error = NULL; - - if (ev->channel >= 0) { - channel = ev->channel; - bandwidth = ev->bandwidth; - } else { - channel = 0; - bandwidth = 0; - generate_event_error(&error, -ev->channel); - } - - if (ev->type == FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED) - signal_name = ALLOCATED_SIGNAL_NAME; - else - signal_name = DEALLOCATED_SIGNAL_NAME; - - src->handle_event(src->self, signal_name, channel, bandwidth, error); - - if (error != NULL) - g_clear_error(&error); -} - -static gboolean check_src(GSource *source) -{ - FwIsoResourceSource *src = (FwIsoResourceSource *)source; - GIOCondition condition; - - // Don't go to dispatch if nothing available. As an error, return - // TRUE for POLLERR to call .dispatch for internal destruction. - condition = g_source_query_unix_fd(source, src->tag); - return !!(condition & (G_IO_IN | G_IO_ERR)); -} - -static gboolean dispatch_src(GSource *source, GSourceFunc cb, gpointer user_data) -{ - FwIsoResourceSource *src = (FwIsoResourceSource *)source; - GIOCondition condition; - ssize_t len; - const union fw_cdev_event *ev; - - if (src->fd < 0) - return G_SOURCE_REMOVE; - - condition = g_source_query_unix_fd(source, src->tag); - if (condition & G_IO_ERR) - return G_SOURCE_REMOVE; - - len = read(src->fd, src->buf, src->len); - if (len <= 0) { - if (errno == EAGAIN) - return G_SOURCE_CONTINUE; - - return G_SOURCE_REMOVE; - } - - ev = (const union fw_cdev_event *)src->buf; - switch (ev->common.type) { - case FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED: - case FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED: - handle_iso_resource_event(src, &ev->iso_resource); - break; - default: - break; - } - - // Just be sure to continue to process this source. - return G_SOURCE_CONTINUE; -} - -static void finalize_src(GSource *source) -{ - FwIsoResourceSource *src = (FwIsoResourceSource *)source; - - g_free(src->buf); - g_object_unref(src->self); -} - -gboolean fw_iso_resource_create_source(int fd, HinokoFwIsoResource *inst, - void (*handle_event)(HinokoFwIsoResource *self, - const char *signal_name, guint channel, - guint bandwidth, const GError *error), - GSource **source, GError **error) -{ - static GSourceFuncs funcs = { - .check = check_src, - .dispatch = dispatch_src, - .finalize = finalize_src, - }; - long page_size = sysconf(_SC_PAGESIZE); - FwIsoResourceSource *src; - - g_return_val_if_fail(HINOKO_IS_FW_ISO_RESOURCE(inst), FALSE); - g_return_val_if_fail(source != NULL, FALSE); - g_return_val_if_fail(error != NULL && *error == NULL, FALSE); - - *source = g_source_new(&funcs, sizeof(FwIsoResourceSource)); - - g_source_set_name(*source, "HinokoFwIsoResource"); - - src = (FwIsoResourceSource *)(*source); - - src->buf = g_malloc0(page_size); - - src->len = (gsize)page_size; - src->tag = g_source_add_unix_fd(*source, fd, G_IO_IN); - src->fd = fd; - src->self = g_object_ref(inst); - src->handle_event = handle_event; - - return TRUE; -} - /** * hinoko_fw_iso_resource_create_source: * @self: A [iface@FwIsoResource]. diff --git a/src/fw_iso_resource_auto.c b/src/fw_iso_resource_auto.c index 83d06ab..ec4f8cd 100644 --- a/src/fw_iso_resource_auto.c +++ b/src/fw_iso_resource_auto.c @@ -329,14 +329,14 @@ void hinoko_fw_iso_resource_auto_allocate_sync(HinokoFwIsoResourceAuto *self, g_return_if_fail(HINOKO_IS_FW_ISO_RESOURCE_AUTO(self)); g_return_if_fail(error == NULL || *error == NULL); - fw_iso_resource_waiter_init(HINOKO_FW_ISO_RESOURCE(self), &w, ALLOCATED_SIGNAL_NAME, + fw_iso_resource_waiter_init(&w, HINOKO_FW_ISO_RESOURCE(self), ALLOCATED_SIGNAL_NAME, timeout_ms); hinoko_fw_iso_resource_auto_allocate_async(self, channel_candidates, channel_candidates_count, bandwidth, error); - fw_iso_resource_waiter_wait(HINOKO_FW_ISO_RESOURCE(self), &w, error); + fw_iso_resource_waiter_wait(&w, HINOKO_FW_ISO_RESOURCE(self), error); } /** @@ -359,10 +359,10 @@ void hinoko_fw_iso_resource_auto_deallocate_sync(HinokoFwIsoResourceAuto *self, g_return_if_fail(HINOKO_IS_FW_ISO_RESOURCE_AUTO(self)); g_return_if_fail(error == NULL || *error == NULL); - fw_iso_resource_waiter_init(HINOKO_FW_ISO_RESOURCE(self), &w, DEALLOCATED_SIGNAL_NAME, + fw_iso_resource_waiter_init(&w, HINOKO_FW_ISO_RESOURCE(self), DEALLOCATED_SIGNAL_NAME, timeout_ms); hinoko_fw_iso_resource_auto_deallocate_async(self, error); - fw_iso_resource_waiter_wait(HINOKO_FW_ISO_RESOURCE(self), &w, error); + fw_iso_resource_waiter_wait(&w, HINOKO_FW_ISO_RESOURCE(self), error); } diff --git a/src/fw_iso_resource_once.c b/src/fw_iso_resource_once.c index 1a3de3c..0983c19 100644 --- a/src/fw_iso_resource_once.c +++ b/src/fw_iso_resource_once.c @@ -209,13 +209,13 @@ void hinoko_fw_iso_resource_once_allocate_sync(HinokoFwIsoResourceOnce *self, g_return_if_fail(HINOKO_IS_FW_ISO_RESOURCE_ONCE(self)); g_return_if_fail(error == NULL || *error == NULL); - fw_iso_resource_waiter_init(HINOKO_FW_ISO_RESOURCE(self), &w, ALLOCATED_SIGNAL_NAME, + fw_iso_resource_waiter_init(&w, HINOKO_FW_ISO_RESOURCE(self), ALLOCATED_SIGNAL_NAME, timeout_ms); hinoko_fw_iso_resource_once_allocate_async(self, channel_candidates, channel_candidates_count, bandwidth, error); - fw_iso_resource_waiter_wait(HINOKO_FW_ISO_RESOURCE(self), &w, error); + fw_iso_resource_waiter_wait(&w, HINOKO_FW_ISO_RESOURCE(self), error); } /** @@ -240,10 +240,10 @@ void hinoko_fw_iso_resource_once_deallocate_sync(HinokoFwIsoResourceOnce *self, g_return_if_fail(HINOKO_IS_FW_ISO_RESOURCE_ONCE(self)); g_return_if_fail(error == NULL || *error == NULL); - fw_iso_resource_waiter_init(HINOKO_FW_ISO_RESOURCE(self), &w, DEALLOCATED_SIGNAL_NAME, + fw_iso_resource_waiter_init(&w, HINOKO_FW_ISO_RESOURCE(self), DEALLOCATED_SIGNAL_NAME, timeout_ms); hinoko_fw_iso_resource_once_deallocate_async(self, channel, bandwidth, error); - fw_iso_resource_waiter_wait(HINOKO_FW_ISO_RESOURCE(self), &w, error); + fw_iso_resource_waiter_wait(&w, HINOKO_FW_ISO_RESOURCE(self), error); } diff --git a/src/fw_iso_resource_private.c b/src/fw_iso_resource_private.c new file mode 100644 index 0000000..a2d6fc3 --- /dev/null +++ b/src/fw_iso_resource_private.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +#include "fw_iso_resource_private.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +static const char *const err_msgs[] = { + [HINOKO_FW_ISO_RESOURCE_ERROR_OPENED] = + "The instance is already associated to any firewire character device", + [HINOKO_FW_ISO_RESOURCE_ERROR_NOT_OPENED] = + "The instance is not associated to any firewire character device", + [HINOKO_FW_ISO_RESOURCE_ERROR_TIMEOUT] = + "No event to the request arrives within timeout.", +}; + +#define generate_local_error(error, code) \ + g_set_error_literal(error, HINOKO_FW_ISO_RESOURCE_ERROR, code, err_msgs[code]) + +#define generate_event_error(error, errno) \ + g_set_error(error, HINOKO_FW_ISO_RESOURCE_ERROR, \ + HINOKO_FW_ISO_RESOURCE_ERROR_EVENT, \ + "%d %s", errno, strerror(errno)) + +#define generate_file_error(error, code, format, arg) \ + g_set_error(error, G_FILE_ERROR, code, format, arg) + +typedef struct { + GSource src; + HinokoFwIsoResource *self; + gpointer tag; + gsize len; + guint8 *buf; + int fd; + void (*handle_event)(HinokoFwIsoResource *self, const char *signal_name, guint channel, + guint bandwidth, const GError *error); +} FwIsoResourceSource; + +gboolean fw_iso_resource_open(int *fd, const gchar *path, gint open_flag, GError **error) +{ + g_return_val_if_fail(fd != NULL, FALSE); + g_return_val_if_fail(path != NULL && strlen(path) > 0, FALSE); + g_return_val_if_fail(error == NULL || *error == NULL, FALSE); + + if (*fd >= 0) { + generate_local_error(error, HINOKO_FW_ISO_RESOURCE_ERROR_OPENED); + return FALSE; + } + + open_flag |= O_RDONLY; + *fd = open(path, open_flag); + if (*fd < 0) { + GFileError code = g_file_error_from_errno(errno); + if (code != G_FILE_ERROR_FAILED) + generate_file_error(error, code, "open(%s)", path); + else + generate_syscall_error(error, errno, "open(%s)", path); + return FALSE; + } + + return TRUE; +} + +static void handle_iso_resource_event(FwIsoResourceSource *src, + const struct fw_cdev_event_iso_resource *ev) +{ + guint channel; + guint bandwidth; + const char *signal_name; + GError *error = NULL; + + if (ev->channel >= 0) { + channel = ev->channel; + bandwidth = ev->bandwidth; + } else { + channel = 0; + bandwidth = 0; + generate_event_error(&error, -ev->channel); + } + + if (ev->type == FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED) + signal_name = ALLOCATED_SIGNAL_NAME; + else + signal_name = DEALLOCATED_SIGNAL_NAME; + + src->handle_event(src->self, signal_name, channel, bandwidth, error); + + if (error != NULL) + g_clear_error(&error); +} + +static gboolean check_src(GSource *source) +{ + FwIsoResourceSource *src = (FwIsoResourceSource *)source; + GIOCondition condition; + + // Don't go to dispatch if nothing available. As an error, return + // TRUE for POLLERR to call .dispatch for internal destruction. + condition = g_source_query_unix_fd(source, src->tag); + return !!(condition & (G_IO_IN | G_IO_ERR)); +} + +static gboolean dispatch_src(GSource *source, GSourceFunc cb, gpointer user_data) +{ + FwIsoResourceSource *src = (FwIsoResourceSource *)source; + GIOCondition condition; + ssize_t len; + const union fw_cdev_event *ev; + + if (src->fd < 0) + return G_SOURCE_REMOVE; + + condition = g_source_query_unix_fd(source, src->tag); + if (condition & G_IO_ERR) + return G_SOURCE_REMOVE; + + len = read(src->fd, src->buf, src->len); + if (len <= 0) { + if (errno == EAGAIN) + return G_SOURCE_CONTINUE; + + return G_SOURCE_REMOVE; + } + + ev = (const union fw_cdev_event *)src->buf; + switch (ev->common.type) { + case FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED: + case FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED: + handle_iso_resource_event(src, &ev->iso_resource); + break; + default: + break; + } + + // Just be sure to continue to process this source. + return G_SOURCE_CONTINUE; +} + +static void finalize_src(GSource *source) +{ + FwIsoResourceSource *src = (FwIsoResourceSource *)source; + + g_free(src->buf); + g_object_unref(src->self); +} + +gboolean fw_iso_resource_create_source(int fd, HinokoFwIsoResource *inst, + void (*handle_event)(HinokoFwIsoResource *self, + const char *signal_name, guint channel, + guint bandwidth, const GError *error), + GSource **source, GError **error) +{ + static GSourceFuncs funcs = { + .check = check_src, + .dispatch = dispatch_src, + .finalize = finalize_src, + }; + long page_size = sysconf(_SC_PAGESIZE); + FwIsoResourceSource *src; + + g_return_val_if_fail(HINOKO_IS_FW_ISO_RESOURCE(inst), FALSE); + g_return_val_if_fail(source != NULL, FALSE); + g_return_val_if_fail(error != NULL && *error == NULL, FALSE); + + *source = g_source_new(&funcs, sizeof(FwIsoResourceSource)); + + g_source_set_name(*source, "HinokoFwIsoResource"); + + src = (FwIsoResourceSource *)(*source); + + src->buf = g_malloc0(page_size); + + src->len = (gsize)page_size; + src->tag = g_source_add_unix_fd(*source, fd, G_IO_IN); + src->fd = fd; + src->self = g_object_ref(inst); + src->handle_event = handle_event; + + return TRUE; +} + +static void handle_event_signal(HinokoFwIsoResource *self, guint channel, guint bandwidth, + const GError *error, gpointer user_data) +{ + struct fw_iso_resource_waiter *w = (struct fw_iso_resource_waiter *)user_data; + + g_mutex_lock(&w->mutex); + if (error != NULL) + w->error = g_error_copy(error); + w->handled = TRUE; + g_cond_signal(&w->cond); + g_mutex_unlock(&w->mutex); +} + +void fw_iso_resource_waiter_init(struct fw_iso_resource_waiter *w, HinokoFwIsoResource *self, + const char *signal_name, guint timeout_ms) +{ + g_mutex_init(&w->mutex); + g_cond_init(&w->cond); + w->error = NULL; + w->handled = FALSE; + w->expiration = g_get_monotonic_time() + timeout_ms * G_TIME_SPAN_MILLISECOND; + w->handler_id = g_signal_connect(self, signal_name, G_CALLBACK(handle_event_signal), w); +} + +void fw_iso_resource_waiter_wait(struct fw_iso_resource_waiter *w, HinokoFwIsoResource *self, + GError **error) +{ + if (*error != NULL) { + g_signal_handler_disconnect(self, w->handler_id); + return; + } + + g_mutex_lock(&w->mutex); + while (w->handled == FALSE) { + if (!g_cond_wait_until(&w->cond, &w->mutex, w->expiration)) + break; + } + g_signal_handler_disconnect(self, w->handler_id); + g_mutex_unlock(&w->mutex); + + if (w->handled == FALSE) + generate_local_error(error, HINOKO_FW_ISO_RESOURCE_ERROR_TIMEOUT); + else if (w->error != NULL) + *error = w->error; // Delegate ownership. +} diff --git a/src/fw_iso_resource_private.h b/src/fw_iso_resource_private.h index 9a7a62c..c839407 100644 --- a/src/fw_iso_resource_private.h +++ b/src/fw_iso_resource_private.h @@ -33,10 +33,10 @@ struct fw_iso_resource_waiter { gulong handler_id; }; -void fw_iso_resource_waiter_init(HinokoFwIsoResource *self, struct fw_iso_resource_waiter *w, +void fw_iso_resource_waiter_init(struct fw_iso_resource_waiter *w, HinokoFwIsoResource *self, const char *signal_name, guint timeout_ms); -void fw_iso_resource_waiter_wait(HinokoFwIsoResource *self, struct fw_iso_resource_waiter *w, +void fw_iso_resource_waiter_wait(struct fw_iso_resource_waiter *w, HinokoFwIsoResource *self, GError **error); #endif diff --git a/src/meson.build b/src/meson.build index 998095c..1a991e4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -33,6 +33,7 @@ headers = [ privates = [ 'fw_iso_ctx_private.h', 'fw_iso_resource_private.h', + 'fw_iso_resource_private.c', ] inc_dir = meson.project_name() |