aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2022-05-05 11:37:24 +0900
committer坂本 貴史 <o-takashi@sakamocchi.jp>2022-05-05 16:09:50 +0900
commit99934c517b6a98002bc55ac05ded03f2fd43236a (patch)
treee4e49034ca92f9698094a6fc88dedd0ac073d1ae
parentb4a12cf1e57e224cfa8f2fe141be11bb6cc17e96 (diff)
downloadlibhinoko-99934c517b6a98002bc55ac05ded03f2fd43236a.tar.gz
fw_iso_ctx: code refactoring to split allocate function
It's planned to make Hinoko.FwIsoCtx as interface. It's convenient for derived object to use private helper function instead of instance method. This commit splits current implementaion of Hinoko.FwIsoCtx.allocate() into internal API part and private implementation. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
-rw-r--r--src/fw_iso_ctx.c110
-rw-r--r--src/fw_iso_ctx_private.c102
-rw-r--r--src/fw_iso_ctx_private.h39
-rw-r--r--src/meson.build1
4 files changed, 145 insertions, 107 deletions
diff --git a/src/fw_iso_ctx.c b/src/fw_iso_ctx.c
index 286c19a..39e47d1 100644
--- a/src/fw_iso_ctx.c
+++ b/src/fw_iso_ctx.c
@@ -1,10 +1,6 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "fw_iso_ctx_private.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
#include <sys/mman.h>
/**
@@ -16,25 +12,8 @@
* subsystem specific request commands. This object is designed for internal
* use, therefore a few method and properties are available for applications.
*/
-typedef struct {
- int fd;
- guint handle;
-
- HinokoFwIsoCtxMode mode;
- guint header_size;
- guchar *addr;
- guint bytes_per_chunk;
- guint chunks_per_buffer;
-
- // The number of entries equals to the value of chunks_per_buffer.
- guint8 *data;
- guint data_length;
- guint alloc_data_length;
- guint registered_chunk_count;
+typedef struct fw_iso_ctx_state HinokoFwIsoCtxPrivate;
- guint curr_offset;
- gboolean running;
-} HinokoFwIsoCtxPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(HinokoFwIsoCtx, hinoko_fw_iso_ctx, G_TYPE_OBJECT)
/**
@@ -47,7 +26,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(HinokoFwIsoCtx, hinoko_fw_iso_ctx, G_TYPE_OB
*/
G_DEFINE_QUARK(hinoko-fw-iso-ctx-error-quark, hinoko_fw_iso_ctx_error)
-static const char *const err_msgs[] = {
+const char *const fw_iso_ctx_err_msgs[7] = {
[HINOKO_FW_ISO_CTX_ERROR_ALLOCATED] =
"The instance is already associated to any firewire character device",
[HINOKO_FW_ISO_CTX_ERROR_NOT_ALLOCATED] =
@@ -59,17 +38,6 @@ static const char *const err_msgs[] = {
[HINOKO_FW_ISO_CTX_ERROR_CHUNK_UNREGISTERED] = "No chunk registered before starting",
};
-#define generate_local_error(error, code) \
- g_set_error_literal(error, HINOKO_FW_ISO_CTX_ERROR, code, err_msgs[code])
-
-#define generate_syscall_error(error, errno, format, arg) \
- g_set_error(error, HINOKO_FW_ISO_CTX_ERROR, \
- HINOKO_FW_ISO_CTX_ERROR_FAILED, \
- format " %d(%s)", arg, 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;
gpointer tag;
@@ -213,83 +181,11 @@ void hinoko_fw_iso_ctx_allocate(HinokoFwIsoCtx *self, const char *path,
GError **error)
{
HinokoFwIsoCtxPrivate *priv;
- struct fw_cdev_get_info info = {0};
- struct fw_cdev_create_iso_context create = {0};
g_return_if_fail(HINOKO_IS_FW_ISO_CTX(self));
- g_return_if_fail(path != NULL && strlen(path) > 0);
- g_return_if_fail(error == NULL || *error == NULL);
-
- // Linux firewire stack supports three types of isochronous context
- // described in 1394 OHCI specification.
- g_return_if_fail(mode == HINOKO_FW_ISO_CTX_MODE_TX ||
- mode == HINOKO_FW_ISO_CTX_MODE_RX_SINGLE ||
- mode == HINOKO_FW_ISO_CTX_MODE_RX_MULTIPLE);
-
- g_return_if_fail(scode == HINOKO_FW_SCODE_S100 ||
- scode == HINOKO_FW_SCODE_S200 ||
- scode == HINOKO_FW_SCODE_S400 ||
- scode == HINOKO_FW_SCODE_S800 ||
- scode == HINOKO_FW_SCODE_S1600 ||
- scode == HINOKO_FW_SCODE_S3200);
-
- // IEEE 1394 specification supports isochronous channel up to 64.
- g_return_if_fail(channel < 64);
-
- // Headers should be aligned to quadlet.
- g_return_if_fail(header_size % 4 == 0);
-
- if (mode == HINOKO_FW_ISO_CTX_MODE_RX_SINGLE) {
- // At least, 1 quadlet is required for iso_header.
- g_return_if_fail(header_size >= 4);
- g_return_if_fail(channel < 64);
- } else if (mode == HINOKO_FW_ISO_CTX_MODE_RX_MULTIPLE) {
- // Needless.
- g_return_if_fail(header_size == 0);
- g_return_if_fail(channel == 0);
- }
-
priv = hinoko_fw_iso_ctx_get_instance_private(self);
- if (priv->fd >= 0) {
- generate_local_error(error, HINOKO_FW_ISO_CTX_ERROR_ALLOCATED);
- return;
- }
-
- priv->fd = open(path, O_RDWR);
- if (priv->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;
- }
-
- // Support FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW.
- info.version = 5;
- if (ioctl(priv->fd, FW_CDEV_IOC_GET_INFO, &info) < 0) {
- generate_syscall_error(error, errno, "ioctl(%s)", "FW_CDEV_IOC_GET_INFO");
- close(priv->fd);
- priv->fd = -1;
- return;
- }
-
- create.type = mode;
- create.channel = channel;
- create.speed = scode;
- create.header_size = header_size;
-
- if (ioctl(priv->fd, FW_CDEV_IOC_CREATE_ISO_CONTEXT, &create) < 0) {
- generate_syscall_error(error, errno, "ioctl(%s)", "FW_CDEV_IOC_CREATE_ISO_CONTEXT");
- close(priv->fd);
- priv->fd = -1;
- return;
- }
-
- priv->handle = create.handle;
- priv->mode = mode;
- priv->header_size = header_size;
+ (void)fw_iso_ctx_state_allocate(priv, path, mode, scode, channel, header_size, error);
}
/**
diff --git a/src/fw_iso_ctx_private.c b/src/fw_iso_ctx_private.c
new file mode 100644
index 0000000..7c1fc9c
--- /dev/null
+++ b/src/fw_iso_ctx_private.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+#include "fw_iso_ctx_private.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/**
+ * fw_iso_ctx_state_allocate:
+ * @state: A [struct@FwIsoCtxState].
+ * @path: A path to any Linux FireWire character device.
+ * @mode: The mode of context, one of [enum@FwIsoCtxMode] enumerations.
+ * @scode: The speed of context, one of [enum@FwScode] enumerations.
+ * @channel: The numeric channel of context up to 64.
+ * @header_size: The number of bytes for header of isochronous context.
+ * @error: A [struct@GLib.Error].
+ *
+ * Allocate a isochronous context to 1394 OHCI controller. A local node of the
+ * node corresponding to the given path is used as the controller, thus any
+ * path is accepted as long as process has enough permission for the path.
+ */
+gboolean fw_iso_ctx_state_allocate(struct fw_iso_ctx_state *state, const char *path,
+ HinokoFwIsoCtxMode mode, HinokoFwScode scode, guint channel,
+ guint header_size, GError **error)
+{
+ struct fw_cdev_get_info info = {0};
+ struct fw_cdev_create_iso_context create = {0};
+
+ g_return_val_if_fail(path != NULL && strlen(path) > 0, FALSE);
+ g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
+
+ // Linux firewire stack supports three types of isochronous context
+ // described in 1394 OHCI specification.
+ g_return_val_if_fail(mode == HINOKO_FW_ISO_CTX_MODE_TX ||
+ mode == HINOKO_FW_ISO_CTX_MODE_RX_SINGLE ||
+ mode == HINOKO_FW_ISO_CTX_MODE_RX_MULTIPLE, FALSE);
+
+ g_return_val_if_fail(scode == HINOKO_FW_SCODE_S100 ||
+ scode == HINOKO_FW_SCODE_S200 ||
+ scode == HINOKO_FW_SCODE_S400 ||
+ scode == HINOKO_FW_SCODE_S800 ||
+ scode == HINOKO_FW_SCODE_S1600 ||
+ scode == HINOKO_FW_SCODE_S3200, FALSE);
+
+ // IEEE 1394 specification supports isochronous channel up to 64.
+ g_return_val_if_fail(channel < 64, FALSE);
+
+ // Headers should be aligned to quadlet.
+ g_return_val_if_fail(header_size % 4 == 0, FALSE);
+
+ if (mode == HINOKO_FW_ISO_CTX_MODE_RX_SINGLE) {
+ // At least, 1 quadlet is required for iso_header.
+ g_return_val_if_fail(header_size >= 4, FALSE);
+ g_return_val_if_fail(channel < 64, FALSE);
+ } else if (mode == HINOKO_FW_ISO_CTX_MODE_RX_MULTIPLE) {
+ // Needless.
+ g_return_val_if_fail(header_size == 0, FALSE);
+ g_return_val_if_fail(channel == 0, FALSE);
+ }
+
+ if (state->fd >= 0) {
+ generate_local_error(error, HINOKO_FW_ISO_CTX_ERROR_ALLOCATED);
+ return FALSE;
+ }
+
+ state->fd = open(path, O_RDWR);
+ if (state->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;
+ }
+
+ // Support FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW.
+ info.version = 5;
+ if (ioctl(state->fd, FW_CDEV_IOC_GET_INFO, &info) < 0) {
+ generate_syscall_error(error, errno, "ioctl(%s)", "FW_CDEV_IOC_GET_INFO");
+ close(state->fd);
+ state->fd = -1;
+ return FALSE;
+ }
+
+ create.type = mode;
+ create.channel = channel;
+ create.speed = scode;
+ create.header_size = header_size;
+
+ if (ioctl(state->fd, FW_CDEV_IOC_CREATE_ISO_CONTEXT, &create) < 0) {
+ generate_syscall_error(error, errno, "ioctl(%s)", "FW_CDEV_IOC_CREATE_ISO_CONTEXT");
+ close(state->fd);
+ state->fd = -1;
+ return FALSE;
+ }
+
+ state->handle = create.handle;
+ state->mode = mode;
+ state->header_size = header_size;
+
+ return TRUE;
+}
diff --git a/src/fw_iso_ctx_private.h b/src/fw_iso_ctx_private.h
index a8e7997..03135f2 100644
--- a/src/fw_iso_ctx_private.h
+++ b/src/fw_iso_ctx_private.h
@@ -6,6 +6,45 @@
#include <unistd.h>
#include <errno.h>
+#include <sys/ioctl.h>
+
+extern const char *const fw_iso_ctx_err_msgs[7];
+
+#define generate_local_error(error, code) \
+ g_set_error_literal(error, HINOKO_FW_ISO_CTX_ERROR, code, fw_iso_ctx_err_msgs[code])
+
+#define generate_syscall_error(error, errno, format, arg) \
+ g_set_error(error, HINOKO_FW_ISO_CTX_ERROR, \
+ HINOKO_FW_ISO_CTX_ERROR_FAILED, \
+ format " %d(%s)", arg, errno, strerror(errno))
+
+#define generate_file_error(error, code, format, arg) \
+ g_set_error(error, G_FILE_ERROR, code, format, arg)
+
+struct fw_iso_ctx_state {
+ int fd;
+ guint handle;
+
+ HinokoFwIsoCtxMode mode;
+ guint header_size;
+ guchar *addr;
+ guint bytes_per_chunk;
+ guint chunks_per_buffer;
+
+ // The number of entries equals to the value of chunks_per_buffer.
+ guint8 *data;
+ guint data_length;
+ guint alloc_data_length;
+ guint registered_chunk_count;
+
+ guint curr_offset;
+ gboolean running;
+};
+
+
+gboolean fw_iso_ctx_state_allocate(struct fw_iso_ctx_state *state, const char *path,
+ HinokoFwIsoCtxMode mode, HinokoFwScode scode, guint channel,
+ guint header_size, GError **error);
#define STOPPED_SIGNAL_NEME "stopped"
diff --git a/src/meson.build b/src/meson.build
index 1a991e4..6f78b77 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -32,6 +32,7 @@ headers = [
privates = [
'fw_iso_ctx_private.h',
+ 'fw_iso_ctx_private.c',
'fw_iso_resource_private.h',
'fw_iso_resource_private.c',
]