[alsa-devel] [PATCH 0/5] ALSA: firewire-tascam: support notification of
Hi,
Units of TASCAM FireWire series transfer its state in tx isochronous packets. The way to handle change of the state is a longstanding issue since I firstly reveal the mechanism in this list[1].
In this time, Scott Bahling dedicates for further investigation to seek better implementation[2][3][4]. Finally, we identified meaning of the most of bits in the image of state, and decided which changes are worth for userspace applications to handle as events.
This commit adds support notification of the events. Userspace applications can handle the notification via ALSA hwdep interface. Furthermore, they can retrieve image of the latest states via the interface.
Changes from the initial proposal[5]: - obsolete usage of mmap(2) due to several disadvantages. Instead, use event queue for change notification, and add ioctl command to retrieve image of states.
Changes from the latest work[6]: - To reduce time in an interrupt context in which tx isochronous packets are handled, data in the event and the image is passed to userspace in big-endian order. Additionally, image of the states are passed to userspace in big-endian order as well. Userspace applications are responsible to convert the data in host-endianness order. - improve efficiency to copy batch of events to userspace in hwdep interface - rename structure and macro name.
This patchset is also available in my remote branch for backport purpose to Linux v4.17 or later[7].
I've already prepare userspace implementation; libhinwa. A 'topic/firewire-tascam-pr' remote branch includes patchset for the additional feature[8]. This library produces GObject class to handle the event notification and emits GObject signal, and has a method 'HinawaSndTscm.get_state()', with enough consideration to endianness. Developers can process change of state with these two APIs.
Scott
As the above, I changed method name from 'HinawaSndTscm.get_status()'. I'd like you to change your local implementation for 'hinawa-utils'. Sorry to add further work to you.
[1] http://mailman.alsa-project.org/pipermail/alsa-devel/2015-July/094817.html [2] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-September/140051.h... [3] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-October/140593.htm... [4] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-November/141395.ht... [5] https://github.com/takaswie/snd-firewire-improve/tree/topic/tascam-userspace [6] https://github.com/takaswie/snd-firewire-improve/tree/topic/tascam-userspace... [7] https://github.com/takaswie/snd-firewire-improve/tree/topic/tascam-userspace... [8] https://github.com/takaswie/libhinawa/tree/topic/tascam-userspace-pr
Regards
Takashi Sakamoto (5): ALSA: firewire-tascam: pick up data of state from tx isochronous pakcets ALSA: firewire-tascam: add new hwdep ioctl command to get state image ALSA: firewire-tascam: queue events for change of control surface ALSA: firewire-tascam: apply small refactoring to handle several type of event for hwdep interface ALSA: firewire-tascam: notify events of change of state for userspace applications
include/uapi/sound/firewire.h | 20 +++++ sound/firewire/tascam/amdtp-tascam.c | 51 +++++++++++- sound/firewire/tascam/tascam-hwdep.c | 115 +++++++++++++++++++++++---- sound/firewire/tascam/tascam.h | 9 +++ 4 files changed, 180 insertions(+), 15 deletions(-)
Units of TASCAM FireWire series multiplex PCM frames and state of control surface into the same tx isochronous packets. One isochronous packet includes a part of the state in a quadlet data. An image of the state consists of 64 quadlet data.
This commit demultiplexes the state from tx isochronous packets.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- include/uapi/sound/firewire.h | 2 ++ sound/firewire/tascam/amdtp-tascam.c | 17 ++++++++++++++++- sound/firewire/tascam/tascam.h | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h index f0a547d86679..b9bc4bb1756b 100644 --- a/include/uapi/sound/firewire.h +++ b/include/uapi/sound/firewire.h @@ -88,4 +88,6 @@ struct snd_firewire_get_info { * Returns -EBUSY if the driver is already streaming. */
+#define SNDRV_FIREWIRE_TASCAM_STATE_COUNT 64 + #endif /* _UAPI_SOUND_FIREWIRE_H_INCLUDED */ diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index ab482423c165..516cb931fd5e 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -117,6 +117,21 @@ int amdtp_tscm_add_pcm_hw_constraints(struct amdtp_stream *s, return amdtp_stream_add_pcm_hw_constraints(s, runtime); }
+static void read_status_messages(struct amdtp_stream *s, + __be32 *buffer, unsigned int data_blocks) +{ + struct snd_tscm *tscm = container_of(s, struct snd_tscm, tx_stream); + int i; + + for (i = 0; i < data_blocks; i++) { + unsigned int index; + + index = be32_to_cpu(buffer[0]) % SNDRV_FIREWIRE_TASCAM_STATE_COUNT; + tscm->state[index] = buffer[s->data_block_quadlets - 1]; + buffer += s->data_block_quadlets; + } +} + static unsigned int process_tx_data_blocks(struct amdtp_stream *s, __be32 *buffer, unsigned int data_blocks, @@ -128,7 +143,7 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, if (data_blocks > 0 && pcm) read_pcm_s32(s, pcm, buffer, data_blocks);
- /* A place holder for control messages. */ + read_status_messages(s, buffer, data_blocks);
return data_blocks; } diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index a5bd167eb5d9..c710496a99cf 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -89,6 +89,9 @@ struct snd_tscm {
/* For MIDI message outgoing transactions. */ struct snd_fw_async_midi_port out_ports[TSCM_MIDI_OUT_PORT_MAX]; + + // A cache of status information in tx isoc packets. + __be32 state[SNDRV_FIREWIRE_TASCAM_STATE_COUNT]; };
#define TSCM_ADDR_BASE 0xffff00000000ull
In a previous commit, ALSA firewire-tascam driver stores state image from tx isochronous packets. This image includes states of knob, fader, button of control surface, level of gain/volume of each physical inputs/outputs, and so on. It's useful for userspace applications to read whole of the image.
This commit adds a unique ioctl command for ALSA hwdep interface for the purpose. For actual meaning of each bits in this image, please refer to discussion in alsa-devel[1].
[1] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-October/140785.htm...
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- include/uapi/sound/firewire.h | 5 +++++ sound/firewire/tascam/tascam-hwdep.c | 10 ++++++++++ 2 files changed, 15 insertions(+)
diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h index b9bc4bb1756b..012f81bf4750 100644 --- a/include/uapi/sound/firewire.h +++ b/include/uapi/sound/firewire.h @@ -66,6 +66,7 @@ union snd_firewire_event { #define SNDRV_FIREWIRE_IOCTL_GET_INFO _IOR('H', 0xf8, struct snd_firewire_get_info) #define SNDRV_FIREWIRE_IOCTL_LOCK _IO('H', 0xf9) #define SNDRV_FIREWIRE_IOCTL_UNLOCK _IO('H', 0xfa) +#define SNDRV_FIREWIRE_IOCTL_TASCAM_STATE _IOR('H', 0xfb, struct snd_firewire_tascam_state)
#define SNDRV_FIREWIRE_TYPE_DICE 1 #define SNDRV_FIREWIRE_TYPE_FIREWORKS 2 @@ -90,4 +91,8 @@ struct snd_firewire_get_info {
#define SNDRV_FIREWIRE_TASCAM_STATE_COUNT 64
+struct snd_firewire_tascam_state { + __be32 data[SNDRV_FIREWIRE_TASCAM_STATE_COUNT]; +}; + #endif /* _UAPI_SOUND_FIREWIRE_H_INCLUDED */ diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 4e4c1e9020e8..a80397116c48 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -123,6 +123,14 @@ static int hwdep_unlock(struct snd_tscm *tscm) return err; }
+static int tscm_hwdep_state(struct snd_tscm *tscm, void __user *arg) +{ + if (copy_to_user(arg, tscm->state, sizeof(tscm->state))) + return -EFAULT; + + return 0; +} + static int hwdep_release(struct snd_hwdep *hwdep, struct file *file) { struct snd_tscm *tscm = hwdep->private_data; @@ -147,6 +155,8 @@ static int hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file, return hwdep_lock(tscm); case SNDRV_FIREWIRE_IOCTL_UNLOCK: return hwdep_unlock(tscm); + case SNDRV_FIREWIRE_IOCTL_TASCAM_STATE: + return tscm_hwdep_state(tscm, (void __user *)arg); default: return -ENOIOCTLCMD; }
Units of TASCAM FireWire series transfer image of states of the unit in tx isochronous packets. Demultiplexing of the states from the packets is done in software interrupt context regardless of any process context. In a view of userspace applications, it needs to have notification mechanism to catch change of the states.
This commit implements a queue to store events for the notification. The image of states includes fluctuating data such as level of gain/volume for physical input/output and position of knobs. Therefore the events are queued corresponding to some control features only.
Furthermore, the queued events are planned to be consumed by userspace applications via ALSA hwdep interface. This commit suppresses event queueing when no applications open the hwdep interface.
However, the queue is maintained in an optimistic scenario, thus without any care against overrrun. This is reasonable because target events are useless just to handle PCM frames. It starts queueing when an usespace application opens hwdep interface, thus it's expected to read the queued events steadily.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- include/uapi/sound/firewire.h | 6 +++++ sound/firewire/tascam/amdtp-tascam.c | 34 +++++++++++++++++++++++++++- sound/firewire/tascam/tascam-hwdep.c | 2 ++ sound/firewire/tascam/tascam.h | 6 +++++ 4 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h index 012f81bf4750..bb067efb09c6 100644 --- a/include/uapi/sound/firewire.h +++ b/include/uapi/sound/firewire.h @@ -53,6 +53,12 @@ struct snd_firewire_event_motu_notification { __u32 message; /* MOTU-specific bits. */ };
+struct snd_firewire_tascam_change { + unsigned int index; + __be32 before; + __be32 after; +}; + union snd_firewire_event { struct snd_firewire_event_common common; struct snd_firewire_event_lock_status lock_status; diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 516cb931fd5e..0e8088c9ada9 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -121,13 +121,45 @@ static void read_status_messages(struct amdtp_stream *s, __be32 *buffer, unsigned int data_blocks) { struct snd_tscm *tscm = container_of(s, struct snd_tscm, tx_stream); + bool used = READ_ONCE(tscm->hwdep->used); int i;
for (i = 0; i < data_blocks; i++) { unsigned int index; + __be32 before; + __be32 after;
index = be32_to_cpu(buffer[0]) % SNDRV_FIREWIRE_TASCAM_STATE_COUNT; - tscm->state[index] = buffer[s->data_block_quadlets - 1]; + before = tscm->state[index]; + after = buffer[s->data_block_quadlets - 1]; + + if (used && index > 4 && index < 16) { + __be32 mask; + + if (index == 5) + mask = cpu_to_be32(~0x0000ffff); + else if (index == 6) + mask = cpu_to_be32(~0x0000ffff); + else if (index == 8) + mask = cpu_to_be32(~0x000f0f00); + else + mask = cpu_to_be32(~0x00000000); + + if ((before ^ after) & mask) { + struct snd_firewire_tascam_change *entry = + &tscm->queue[tscm->push_pos]; + + spin_lock_irq(&tscm->lock); + entry->index = index; + entry->before = before; + entry->after = after; + if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT) + tscm->push_pos = 0; + spin_unlock_irq(&tscm->lock); + } + } + + tscm->state[index] = after; buffer += s->data_block_quadlets; } } diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index a80397116c48..9afa827af05d 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -195,5 +195,7 @@ int snd_tscm_create_hwdep_device(struct snd_tscm *tscm) hwdep->private_data = tscm; hwdep->exclusive = true;
+ tscm->hwdep = hwdep; + return err; } diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index c710496a99cf..6a411ee0dcf1 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -62,6 +62,8 @@ struct snd_fw_async_midi_port { int consume_bytes; };
+#define SND_TSCM_QUEUE_COUNT 16 + struct snd_tscm { struct snd_card *card; struct fw_unit *unit; @@ -92,6 +94,10 @@ struct snd_tscm {
// A cache of status information in tx isoc packets. __be32 state[SNDRV_FIREWIRE_TASCAM_STATE_COUNT]; + struct snd_hwdep *hwdep; + struct snd_firewire_tascam_change queue[SND_TSCM_QUEUE_COUNT]; + unsigned int pull_pos; + unsigned int push_pos; };
#define TSCM_ADDR_BASE 0xffff00000000ull
In later commits, ALSA firewire-tascam driver will allow userspace applications to receive notifications about changes of device state, transferred in tx isochronous packet. At present, all of drivers in ALSA firewire stack have mechanism to notify change of status of packet streaming, thus it needs to distinguish these two types of notification.
This commit is a preparation for the above.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/tascam/tascam-hwdep.c | 38 +++++++++++++++++++--------- 1 file changed, 26 insertions(+), 12 deletions(-)
diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 9afa827af05d..8f34cede2e9f 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -16,14 +16,30 @@
#include "tascam.h"
+static long tscm_hwdep_read_locked(struct snd_tscm *tscm, char __user *buf, + long count, loff_t *offset) +{ + struct snd_firewire_event_lock_status event = { + .type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS, + }; + + event.status = (tscm->dev_lock_count > 0); + tscm->dev_lock_changed = false; + count = min_t(long, count, sizeof(event)); + + spin_unlock_irq(&tscm->lock); + + if (copy_to_user(buf, &event, count)) + return -EFAULT; + + return count; +} + static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, loff_t *offset) { struct snd_tscm *tscm = hwdep->private_data; DEFINE_WAIT(wait); - union snd_firewire_event event = { - .lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS, - };
spin_lock_irq(&tscm->lock);
@@ -37,15 +53,13 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, spin_lock_irq(&tscm->lock); }
- event.lock_status.status = (tscm->dev_lock_count > 0); - tscm->dev_lock_changed = false; - - spin_unlock_irq(&tscm->lock); - - count = min_t(long, count, sizeof(event.lock_status)); - - if (copy_to_user(buf, &event, count)) - return -EFAULT; + // NOTE: The acquired lock should be released in callee side. + if (tscm->dev_lock_changed) { + count = tscm_hwdep_read_locked(tscm, buf, count, offset); + } else { + spin_unlock_irq(&tscm->lock); + count = 0; + }
return count; }
In former commits, ALSA firewire-tascam driver queues events to notify change of state of control surface to userspace via ALSA hwdep interface.
This commit implements actual notification of the events. The events are not governed by real time, thus no need to care underrun.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- include/uapi/sound/firewire.h | 7 +++ sound/firewire/tascam/amdtp-tascam.c | 2 + sound/firewire/tascam/tascam-hwdep.c | 65 +++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h index bb067efb09c6..ae12826ed641 100644 --- a/include/uapi/sound/firewire.h +++ b/include/uapi/sound/firewire.h @@ -12,6 +12,7 @@ #define SNDRV_FIREWIRE_EVENT_EFW_RESPONSE 0x4e617475 #define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c #define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION 0x64776479 +#define SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL 0x7473636d
struct snd_firewire_event_common { unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */ @@ -59,12 +60,18 @@ struct snd_firewire_tascam_change { __be32 after; };
+struct snd_firewire_event_tascam_control { + unsigned int type; + struct snd_firewire_tascam_change changes[0]; +}; + union snd_firewire_event { struct snd_firewire_event_common common; struct snd_firewire_event_lock_status lock_status; struct snd_firewire_event_dice_notification dice_notification; struct snd_firewire_event_efw_response efw_response; struct snd_firewire_event_digi00x_message digi00x_message; + struct snd_firewire_event_tascam_control tascam_control; struct snd_firewire_event_motu_notification motu_notification; };
diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 0e8088c9ada9..a52d1f76c610 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -156,6 +156,8 @@ static void read_status_messages(struct amdtp_stream *s, if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT) tscm->push_pos = 0; spin_unlock_irq(&tscm->lock); + + wake_up(&tscm->hwdep_wait); } }
diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 8f34cede2e9f..0414abf5daa8 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -35,6 +35,65 @@ static long tscm_hwdep_read_locked(struct snd_tscm *tscm, char __user *buf, return count; }
+static long tscm_hwdep_read_queue(struct snd_tscm *tscm, char __user *buf, + long remained, loff_t *offset) +{ + char __user *pos = buf; + unsigned int type = SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL; + struct snd_firewire_tascam_change *entries = tscm->queue; + long count; + + // At least, one control event can be copied. + if (remained < sizeof(type) + sizeof(*entries)) { + spin_unlock_irq(&tscm->lock); + return -EINVAL; + } + + // Copy the type field later. + count = sizeof(type); + remained -= sizeof(type); + pos += sizeof(type); + + while (true) { + unsigned int head_pos; + unsigned int tail_pos; + unsigned int length; + + if (tscm->pull_pos == tscm->push_pos) + break; + else if (tscm->pull_pos < tscm->push_pos) + tail_pos = tscm->push_pos; + else + tail_pos = SND_TSCM_QUEUE_COUNT; + head_pos = tscm->pull_pos; + + length = (tail_pos - head_pos) * sizeof(*entries); + if (remained < length) + length = rounddown(remained, sizeof(*entries)); + if (length == 0) + break; + + spin_unlock_irq(&tscm->lock); + if (copy_to_user(pos, &entries[head_pos], length)) + return -EFAULT; + + spin_lock_irq(&tscm->lock); + + tscm->pull_pos = tail_pos % SND_TSCM_QUEUE_COUNT; + + count += length; + remained -= length; + pos += length; + } + + spin_unlock_irq(&tscm->lock); + + if (copy_to_user(buf, &type, sizeof(type))) + return -EFAULT; + + return count; +} + static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, loff_t *offset) { @@ -43,7 +102,7 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
spin_lock_irq(&tscm->lock);
- while (!tscm->dev_lock_changed) { + while (!tscm->dev_lock_changed && tscm->push_pos == tscm->pull_pos) { prepare_to_wait(&tscm->hwdep_wait, &wait, TASK_INTERRUPTIBLE); spin_unlock_irq(&tscm->lock); schedule(); @@ -56,6 +115,8 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, // NOTE: The acquired lock should be released in callee side. if (tscm->dev_lock_changed) { count = tscm_hwdep_read_locked(tscm, buf, count, offset); + } else if (tscm->push_pos != tscm->pull_pos) { + count = tscm_hwdep_read_queue(tscm, buf, count, offset); } else { spin_unlock_irq(&tscm->lock); count = 0; @@ -73,7 +134,7 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_wait(file, &tscm->hwdep_wait, wait);
spin_lock_irq(&tscm->lock); - if (tscm->dev_lock_changed) + if (tscm->dev_lock_changed || tscm->push_pos != tscm->pull_pos) events = EPOLLIN | EPOLLRDNORM; else events = 0;
Oops, the subject line is truncated... It should be "ALSA: firewire-tascam: support notification of change of state for control surface". (My text editor works for the surplus.)
On Fri, Nov 23, 2018 at 01:13:02PM +0900, Takashi Sakamoto wrote:
Hi,
Units of TASCAM FireWire series transfer its state in tx isochronous packets. The way to handle change of the state is a longstanding issue since I firstly reveal the mechanism in this list[1].
In this time, Scott Bahling dedicates for further investigation to seek better implementation[2][3][4]. Finally, we identified meaning of the most of bits in the image of state, and decided which changes are worth for userspace applications to handle as events.
This commit adds support notification of the events. Userspace applications can handle the notification via ALSA hwdep interface. Furthermore, they can retrieve image of the latest states via the interface.
Changes from the initial proposal[5]:
- obsolete usage of mmap(2) due to several disadvantages. Instead, use event queue for change notification, and add ioctl command to retrieve image of states.
Changes from the latest work[6]:
- To reduce time in an interrupt context in which tx isochronous packets are handled, data in the event and the image is passed to userspace in big-endian order. Additionally, image of the states are passed to userspace in big-endian order as well. Userspace applications are responsible to convert the data in host-endianness order.
- improve efficiency to copy batch of events to userspace in hwdep interface
- rename structure and macro name.
This patchset is also available in my remote branch for backport purpose to Linux v4.17 or later[7].
I've already prepare userspace implementation; libhinwa. A 'topic/firewire-tascam-pr' remote branch includes patchset for the additional feature[8]. This library produces GObject class to handle the event notification and emits GObject signal, and has a method 'HinawaSndTscm.get_state()', with enough consideration to endianness. Developers can process change of state with these two APIs.
Scott
As the above, I changed method name from 'HinawaSndTscm.get_status()'. I'd like you to change your local implementation for 'hinawa-utils'. Sorry to add further work to you.
[1] http://mailman.alsa-project.org/pipermail/alsa-devel/2015-July/094817.html [2] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-September/140051.h... [3] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-October/140593.htm... [4] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-November/141395.ht... [5] https://github.com/takaswie/snd-firewire-improve/tree/topic/tascam-userspace [6] https://github.com/takaswie/snd-firewire-improve/tree/topic/tascam-userspace... [7] https://github.com/takaswie/snd-firewire-improve/tree/topic/tascam-userspace... [8] https://github.com/takaswie/libhinawa/tree/topic/tascam-userspace-pr
Regards
Takashi Sakamoto (5): ALSA: firewire-tascam: pick up data of state from tx isochronous pakcets ALSA: firewire-tascam: add new hwdep ioctl command to get state image ALSA: firewire-tascam: queue events for change of control surface ALSA: firewire-tascam: apply small refactoring to handle several type of event for hwdep interface ALSA: firewire-tascam: notify events of change of state for userspace applications
include/uapi/sound/firewire.h | 20 +++++ sound/firewire/tascam/amdtp-tascam.c | 51 +++++++++++- sound/firewire/tascam/tascam-hwdep.c | 115 +++++++++++++++++++++++---- sound/firewire/tascam/tascam.h | 9 +++ 4 files changed, 180 insertions(+), 15 deletions(-)
-- 2.19.1
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
On Fri, 23 Nov 2018 05:13:02 +0100, Takashi Sakamoto wrote:
Hi,
Units of TASCAM FireWire series transfer its state in tx isochronous packets. The way to handle change of the state is a longstanding issue since I firstly reveal the mechanism in this list[1].
In this time, Scott Bahling dedicates for further investigation to seek better implementation[2][3][4]. Finally, we identified meaning of the most of bits in the image of state, and decided which changes are worth for userspace applications to handle as events.
This commit adds support notification of the events. Userspace applications can handle the notification via ALSA hwdep interface. Furthermore, they can retrieve image of the latest states via the interface.
Changes from the initial proposal[5]:
- obsolete usage of mmap(2) due to several disadvantages. Instead, use event queue for change notification, and add ioctl command to retrieve image of states.
Changes from the latest work[6]:
- To reduce time in an interrupt context in which tx isochronous packets are handled, data in the event and the image is passed to userspace in big-endian order. Additionally, image of the states are passed to userspace in big-endian order as well. Userspace applications are responsible to convert the data in host-endianness order.
- improve efficiency to copy batch of events to userspace in hwdep interface
- rename structure and macro name.
This patchset is also available in my remote branch for backport purpose to Linux v4.17 or later[7].
I've already prepare userspace implementation; libhinwa. A 'topic/firewire-tascam-pr' remote branch includes patchset for the additional feature[8]. This library produces GObject class to handle the event notification and emits GObject signal, and has a method 'HinawaSndTscm.get_state()', with enough consideration to endianness. Developers can process change of state with these two APIs.
Scott
As the above, I changed method name from 'HinawaSndTscm.get_status()'. I'd like you to change your local implementation for 'hinawa-utils'. Sorry to add further work to you.
[1] http://mailman.alsa-project.org/pipermail/alsa-devel/2015-July/094817.html [2] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-September/140051.h... [3] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-October/140593.htm... [4] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-November/141395.ht... [5] https://github.com/takaswie/snd-firewire-improve/tree/topic/tascam-userspace [6] https://github.com/takaswie/snd-firewire-improve/tree/topic/tascam-userspace... [7] https://github.com/takaswie/snd-firewire-improve/tree/topic/tascam-userspace... [8] https://github.com/takaswie/libhinawa/tree/topic/tascam-userspace-pr
Regards
Takashi Sakamoto (5): ALSA: firewire-tascam: pick up data of state from tx isochronous pakcets ALSA: firewire-tascam: add new hwdep ioctl command to get state image ALSA: firewire-tascam: queue events for change of control surface ALSA: firewire-tascam: apply small refactoring to handle several type of event for hwdep interface ALSA: firewire-tascam: notify events of change of state for userspace applications
Applied all five patches now. Thanks.
Takashi
participants (2)
-
Takashi Iwai
-
Takashi Sakamoto