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
12#define SNDRV_FIREWIRE_EVENT_EFW_RESPONSE 0x4e61747512#define SNDRV_FIREWIRE_EVENT_EFW_RESPONSE 0x4e617475
13#define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c13#define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c
14#define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION 0x6477647914#define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION 0x64776479
15#define SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL 0x7473636d
15 16
16struct snd_firewire_event_common {17struct snd_firewire_event_common {
17 unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */18 unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */
@@ -59,12 +60,18 @@ struct snd_firewire_tascam_change { · 41 unmodified lines
59 __be32 after;60 __be32 after;
60};61};
61 62
63struct snd_firewire_event_tascam_control {
64 unsigned int type;
65 struct snd_firewire_tascam_change changes[0];
66};
67
62union snd_firewire_event {68union snd_firewire_event {
63 struct snd_firewire_event_common common;69 struct snd_firewire_event_common common;
64 struct snd_firewire_event_lock_status lock_status;70 struct snd_firewire_event_lock_status lock_status;
65 struct snd_firewire_event_dice_notification dice_notification;71 struct snd_firewire_event_dice_notification dice_notification;
66 struct snd_firewire_event_efw_response efw_response;72 struct snd_firewire_event_efw_response efw_response;
67 struct snd_firewire_event_digi00x_message digi00x_message;73 struct snd_firewire_event_digi00x_message digi00x_message;
74 struct snd_firewire_event_tascam_control tascam_control;
68 struct snd_firewire_event_motu_notification motu_notification;75 struct snd_firewire_event_motu_notification motu_notification;
69};76};
70 77
sound/firewire/tascam/amdtp-tascam.c+2−0
@@ -156,6 +156,8 @@ static void read_status_messages(struct amdtp_stream *s, · 155 unmodified lines
156 if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT)156 if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT)
157 tscm->push_pos = 0;157 tscm->push_pos = 0;
158 spin_unlock_irq(&tscm->lock);158 spin_unlock_irq(&tscm->lock);
159
160 wake_up(&tscm->hwdep_wait);
159 }161 }
160 }162 }
161 163
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
35 return count;35 return count;
36}36}
37 37
38static 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
38static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,97static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
39 loff_t *offset)98 loff_t *offset)
40{99{
@@ -43,7 +102,7 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, · 2 unmodified lines
43 102
44 spin_lock_irq(&tscm->lock);103 spin_lock_irq(&tscm->lock);
45 104
46 while (!tscm->dev_lock_changed) {105 while (!tscm->dev_lock_changed && tscm->push_pos == tscm->pull_pos) {
47 prepare_to_wait(&tscm->hwdep_wait, &wait, TASK_INTERRUPTIBLE);106 prepare_to_wait(&tscm->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
48 spin_unlock_irq(&tscm->lock);107 spin_unlock_irq(&tscm->lock);
49 schedule();108 schedule();
@@ -56,6 +115,8 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, · 6 unmodified lines
56 // NOTE: The acquired lock should be released in callee side.115 // NOTE: The acquired lock should be released in callee side.
57 if (tscm->dev_lock_changed) {116 if (tscm->dev_lock_changed) {
58 count = tscm_hwdep_read_locked(tscm, buf, count, offset);117 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);
59 } else {120 } else {
60 spin_unlock_irq(&tscm->lock);121 spin_unlock_irq(&tscm->lock);
61 count = 0;122 count = 0;
@@ -73,7 +134,7 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, · 11 unmodified lines
73 poll_wait(file, &tscm->hwdep_wait, wait);134 poll_wait(file, &tscm->hwdep_wait, wait);
74 135
75 spin_lock_irq(&tscm->lock);136 spin_lock_irq(&tscm->lock);
76 if (tscm->dev_lock_changed)137 if (tscm->dev_lock_changed || tscm->push_pos != tscm->pull_pos)
77 events = EPOLLIN | EPOLLRDNORM;138 events = EPOLLIN | EPOLLRDNORM;
78 else139 else
79 events = 0;140 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