History

ALSA: firewire-tascam: notify events of change of state for userspace applications

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.

Takashi Sakamoto committed 7 years ago

Commit a8c0d131 parent afb8e2d3 files · +72 −2Browse files

Unified · Split

3 files
  1. include/uapi/sound/firewire.h +7 −0
  2. sound/firewire/tascam/amdtp-tascam.c +2 −0
  3. sound/firewire/tascam/tascam-hwdep.c +63 −2
include/uapi/sound/firewire.h+7−0
@@ -12,6 +12,7 @@ · 11 unmodified lines
1212 #define SNDRV_FIREWIRE_EVENT_EFW_RESPONSE 0x4e617475
1313 #define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c
1414 #define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION 0x64776479
15+#define SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL 0x7473636d
1516
1617 struct snd_firewire_event_common {
1718 unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */
@@ -59,12 +60,18 @@ struct snd_firewire_tascam_change { · 41 unmodified lines
5960 __be32 after;
6061 };
6162
63+struct snd_firewire_event_tascam_control {
64+ unsigned int type;
65+ struct snd_firewire_tascam_change changes[0];
66+};
67+
6268 union snd_firewire_event {
6369 struct snd_firewire_event_common common;
6470 struct snd_firewire_event_lock_status lock_status;
6571 struct snd_firewire_event_dice_notification dice_notification;
6672 struct snd_firewire_event_efw_response efw_response;
6773 struct snd_firewire_event_digi00x_message digi00x_message;
74+ struct snd_firewire_event_tascam_control tascam_control;
6875 struct snd_firewire_event_motu_notification motu_notification;
6976 };
7077
sound/firewire/tascam/amdtp-tascam.c+2−0
@@ -156,6 +156,8 @@ static void read_status_messages(struct amdtp_stream *s, · 155 unmodified lines
156156 if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT)
157157 tscm->push_pos = 0;
158158 spin_unlock_irq(&tscm->lock);
159+
160+ wake_up(&tscm->hwdep_wait);
159161 }
160162 }
161163
sound/firewire/tascam/tascam-hwdep.c+63−2
@@ -35,6 +35,65 @@ static long tscm_hwdep_read_locked(struct snd_tscm *tscm, char __user *buf, · 34 unmodified lines
3535 return count;
3636 }
3737
38+static long tscm_hwdep_read_queue(struct snd_tscm *tscm, char __user *buf,
39+ long remained, loff_t *offset)
40+{
41+ char __user *pos = buf;
42+ unsigned int type = SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL;
43+ struct snd_firewire_tascam_change *entries = tscm->queue;
44+ long count;
45+
46+ // At least, one control event can be copied.
47+ if (remained < sizeof(type) + sizeof(*entries)) {
48+ spin_unlock_irq(&tscm->lock);
49+ return -EINVAL;
50+ }
51+
52+ // Copy the type field later.
53+ count = sizeof(type);
54+ remained -= sizeof(type);
55+ pos += sizeof(type);
56+
57+ while (true) {
58+ unsigned int head_pos;
59+ unsigned int tail_pos;
60+ unsigned int length;
61+
62+ if (tscm->pull_pos == tscm->push_pos)
63+ break;
64+ else if (tscm->pull_pos < tscm->push_pos)
65+ tail_pos = tscm->push_pos;
66+ else
67+ tail_pos = SND_TSCM_QUEUE_COUNT;
68+ head_pos = tscm->pull_pos;
69+
70+ length = (tail_pos - head_pos) * sizeof(*entries);
71+ if (remained < length)
72+ length = rounddown(remained, sizeof(*entries));
73+ if (length == 0)
74+ break;
75+
76+ spin_unlock_irq(&tscm->lock);
77+ if (copy_to_user(pos, &entries[head_pos], length))
78+ return -EFAULT;
79+
80+ spin_lock_irq(&tscm->lock);
81+
82+ tscm->pull_pos = tail_pos % SND_TSCM_QUEUE_COUNT;
83+
84+ count += length;
85+ remained -= length;
86+ pos += length;
87+ }
88+
89+ spin_unlock_irq(&tscm->lock);
90+
91+ if (copy_to_user(buf, &type, sizeof(type)))
92+ return -EFAULT;
93+
94+ return count;
95+}
96+
3897 static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
3998 loff_t *offset)
4099 {
@@ -43,7 +102,7 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, · 2 unmodified lines
43102
44103 spin_lock_irq(&tscm->lock);
45104
46− while (!tscm->dev_lock_changed) {
105+ while (!tscm->dev_lock_changed && tscm->push_pos == tscm->pull_pos) {
47106 prepare_to_wait(&tscm->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
48107 spin_unlock_irq(&tscm->lock);
49108 schedule();
@@ -56,6 +115,8 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, · 6 unmodified lines
56115 // NOTE: The acquired lock should be released in callee side.
57116 if (tscm->dev_lock_changed) {
58117 count = tscm_hwdep_read_locked(tscm, buf, count, offset);
118+ } else if (tscm->push_pos != tscm->pull_pos) {
119+ count = tscm_hwdep_read_queue(tscm, buf, count, offset);
59120 } else {
60121 spin_unlock_irq(&tscm->lock);
61122 count = 0;
@@ -73,7 +134,7 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, · 11 unmodified lines
73134 poll_wait(file, &tscm->hwdep_wait, wait);
74135
75136 spin_lock_irq(&tscm->lock);
76− if (tscm->dev_lock_changed)
137+ if (tscm->dev_lock_changed || tscm->push_pos != tscm->pull_pos)
77138 events = EPOLLIN | EPOLLRDNORM;
78139 else
79140 events = 0;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t