*/
G_DEFINE_QUARK(alsactl-card-error-quark, alsactl_card_error)
+static const char *const err_msgs[] = {
+ [ALSACTL_CARD_ERROR_DISCONNECTED] = "The card associated to the instance is in disconnect state",
+};
+
+#define generate_local_error(exception, code) \
+ g_set_error_literal(exception, ALSACTL_CARD_ERROR, code, err_msgs[code])
+
#define generate_syscall_error(exception, errno, fmt, arg) \
g_set_error(exception, ALSACTL_CARD_ERROR, ALSACTL_CARD_ERROR_FAILED, \
fmt" %d(%s)", arg, errno, strerror(errno))
open_flag |= O_RDONLY;
priv->fd = open(devnode, open_flag);
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)", devnode);
- else
- generate_syscall_error(error, errno, "open(%s)", devnode);
+ if (errno == ENODEV) {
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ } else {
+ GFileError code = g_file_error_from_errno(errno);
+
+ if (code != G_FILE_ERROR_FAILED)
+ generate_file_error(error, code, "open(%s)", devnode);
+ else
+ generate_syscall_error(error, errno, "open(%s)", devnode);
+ }
g_free(devnode);
return;
// Remember the version of protocol currently used.
if (ioctl(priv->fd, SNDRV_CTL_IOCTL_PVERSION, &proto_ver) < 0) {
- generate_syscall_error(error, errno, "ioctl(%s)", "PVERSION");
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "PVERSION");
close(priv->fd);
priv->fd = -1;
g_free(devnode);
ctl_card_info_refer_private(*card_info, &info);
if (ioctl(priv->fd, SNDRV_CTL_IOCTL_CARD_INFO, info) < 0) {
- generate_syscall_error(error, errno, "ioctl(%s)", "CARD_INFO");
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "CARD_INFO");
g_object_unref(*card_info);
}
}
// Get the number of elements in this control device.
if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, list) < 0) {
- generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_LIST");
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_LIST");
return;
}
// Get the IDs of elements in this control device.
if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, list) < 0) {
- generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_LIST");
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_LIST");
free(ids);
list->pids = NULL;
return;
}
ret = ioctl(priv->fd, req, elem_id);
- if (ret < 0)
- generate_syscall_error(error, errno, "ioctl(%s)", req_name);
+ if (ret < 0) {
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", req_name);
+ }
}
static void parse_enum_names(ALSACtlCardPrivate *priv,
for (i = 0; i < count; ++i) {
info->value.enumerated.item = i;
if (ioctl(priv->fd, SNDRV_CTL_IOCTL_ELEM_INFO, info)) {
- generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_INFO");
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_INFO");
goto error;
}
info->id = *elem_id;
if (ioctl(priv->fd, SNDRV_CTL_IOCTL_ELEM_INFO, info)) {
- generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_INFO");
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_INFO");
return;
}
packet->length = container_size;
memcpy(packet->tlv, container, container_size);
- if (ioctl(priv->fd, SNDRV_CTL_IOCTL_TLV_WRITE, packet) < 0)
- generate_syscall_error(error, errno, "ioctl(%s)", "TLV_WRITE");
+ if (ioctl(priv->fd, SNDRV_CTL_IOCTL_TLV_WRITE, packet) < 0) {
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "TLV_WRITE");
+ }
g_free(packet);
}
packet->numid = elem_id->numid;
packet->length = container_size;
- if (ioctl(priv->fd, SNDRV_CTL_IOCTL_TLV_READ, packet) < 0)
- generate_syscall_error(error, errno, "ioctl(%s)", "TLV_READ");
+ if (ioctl(priv->fd, SNDRV_CTL_IOCTL_TLV_READ, packet) < 0) {
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "TLV_READ");
+ }
memcpy(*container, packet->tlv, packet->length);
*container_count = packet->length / sizeof(**container);
packet->length = container_size;
memcpy(packet->tlv, *container, container_size);
- if (ioctl(priv->fd, SNDRV_CTL_IOCTL_TLV_COMMAND, packet) < 0)
- generate_syscall_error(error, errno, "ioctl(%s)", "TLV_COMMAND");
+ if (ioctl(priv->fd, SNDRV_CTL_IOCTL_TLV_COMMAND, packet) < 0) {
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "TLV_COMMAND");
+ }
memcpy(*container, packet->tlv, packet->length);
*container_count = packet->length / sizeof(**container);
}
info->owner = (__kernel_pid_t)elem_count;
- if (ioctl(fd, request, info) < 0)
- generate_syscall_error(error, errno, "ioctl(%s)", req_name);
+ if (ioctl(fd, request, info) < 0) {
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", req_name);
+ }
g_free((void *)info->value.enumerated.names_ptr);
if (*error != NULL)
return;
g_return_if_fail(elem_id != NULL);
g_return_if_fail(error == NULL || *error == NULL);
- if (ioctl(priv->fd, SNDRV_CTL_IOCTL_ELEM_REMOVE, elem_id) < 0)
- generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_REMOVE");
+ if (ioctl(priv->fd, SNDRV_CTL_IOCTL_ELEM_REMOVE, elem_id) < 0) {
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_REMOVE");
+ }
}
/**
ctl_elem_value_refer_private((ALSACtlElemValue *)elem_value, &value);
value->id = *elem_id;
- if (ioctl(priv->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, value) < 0)
- generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_WRITE");
+ if (ioctl(priv->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, value) < 0) {
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_WRITE");
+ }
}
/**
ctl_elem_value_refer_private(*elem_value, &value);
value->id = *elem_id;
- if (ioctl(priv->fd, SNDRV_CTL_IOCTL_ELEM_READ, value) < 0)
- generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_READ");
+ if (ioctl(priv->fd, SNDRV_CTL_IOCTL_ELEM_READ, value) < 0) {
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "ELEM_READ");
+ }
}
static void handle_elem_event(CtlCardSource *src, struct snd_ctl_event *ev)
g_atomic_int_inc(&priv->subscribers);
if (ioctl(priv->fd, SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS, &subscribe)) {
- generate_syscall_error(error, errno, "ioctl(%s)", "SUBSCRIBE_EVENTS");
+ if (errno == ENODEV)
+ generate_local_error(error, ALSACTL_CARD_ERROR_DISCONNECTED);
+ else
+ generate_syscall_error(error, errno, "ioctl(%s)", "SUBSCRIBE_EVENTS");
g_source_unref(*gsrc);
}
}