Skip to content

Commit 634ec0b

Browse files
takaswietiwai
authored andcommitted
ALSA: firewire-motu: notify event for parameter change in register DSP model
This commit copies queued event for change of register DSP into userspace when application operates ALSA hwdep character device. The notification occurs only when packet streaming is running. Signed-off-by: Takashi Sakamoto <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 4c9eda8 commit 634ec0b

File tree

4 files changed

+86
-9
lines changed

4 files changed

+86
-9
lines changed

include/uapi/sound/firewire.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c
1414
#define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION 0x64776479
1515
#define SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL 0x7473636d
16+
#define SNDRV_FIREWIRE_EVENT_MOTU_REGISTER_DSP_CHANGE 0x4d545244
1617

1718
struct snd_firewire_event_common {
1819
unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */
@@ -65,6 +66,12 @@ struct snd_firewire_event_tascam_control {
6566
struct snd_firewire_tascam_change changes[0];
6667
};
6768

69+
struct snd_firewire_event_motu_register_dsp_change {
70+
unsigned int type;
71+
__u32 count; // The number of changes.
72+
__u32 changes[]; // Encoded event for change of register DSP.
73+
};
74+
6875
union snd_firewire_event {
6976
struct snd_firewire_event_common common;
7077
struct snd_firewire_event_lock_status lock_status;
@@ -73,6 +80,7 @@ union snd_firewire_event {
7380
struct snd_firewire_event_digi00x_message digi00x_message;
7481
struct snd_firewire_event_tascam_control tascam_control;
7582
struct snd_firewire_event_motu_notification motu_notification;
83+
struct snd_firewire_event_motu_register_dsp_change motu_register_dsp_change;
7684
};
7785

7886

sound/firewire/motu/motu-hwdep.c

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
2525

2626
spin_lock_irq(&motu->lock);
2727

28-
while (!motu->dev_lock_changed && motu->msg == 0) {
28+
while (!motu->dev_lock_changed && motu->msg == 0 &&
29+
snd_motu_register_dsp_message_parser_count_event(motu) == 0) {
2930
prepare_to_wait(&motu->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
3031
spin_unlock_irq(&motu->lock);
3132
schedule();
@@ -40,20 +41,46 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
4041
event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
4142
event.lock_status.status = (motu->dev_lock_count > 0);
4243
motu->dev_lock_changed = false;
44+
spin_unlock_irq(&motu->lock);
4345

44-
count = min_t(long, count, sizeof(event.lock_status));
45-
} else {
46+
count = min_t(long, count, sizeof(event));
47+
if (copy_to_user(buf, &event, count))
48+
return -EFAULT;
49+
} else if (motu->msg > 0) {
4650
event.motu_notification.type = SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION;
4751
event.motu_notification.message = motu->msg;
4852
motu->msg = 0;
53+
spin_unlock_irq(&motu->lock);
4954

50-
count = min_t(long, count, sizeof(event.motu_notification));
51-
}
55+
count = min_t(long, count, sizeof(event));
56+
if (copy_to_user(buf, &event, count))
57+
return -EFAULT;
58+
} else if (snd_motu_register_dsp_message_parser_count_event(motu) > 0) {
59+
size_t consumed = 0;
60+
u32 __user *ptr;
61+
u32 ev;
5262

53-
spin_unlock_irq(&motu->lock);
63+
spin_unlock_irq(&motu->lock);
5464

55-
if (copy_to_user(buf, &event, count))
56-
return -EFAULT;
65+
// Header is filled later.
66+
consumed += sizeof(event.motu_register_dsp_change);
67+
68+
while (consumed < count &&
69+
snd_motu_register_dsp_message_parser_copy_event(motu, &ev)) {
70+
ptr = (u32 __user *)(buf + consumed);
71+
if (put_user(ev, ptr))
72+
return -EFAULT;
73+
consumed += sizeof(ev);
74+
}
75+
76+
event.motu_register_dsp_change.type = SNDRV_FIREWIRE_EVENT_MOTU_REGISTER_DSP_CHANGE;
77+
event.motu_register_dsp_change.count =
78+
(consumed - sizeof(event.motu_register_dsp_change)) / 4;
79+
if (copy_to_user(buf, &event, sizeof(event.motu_register_dsp_change)))
80+
return -EFAULT;
81+
82+
count = consumed;
83+
}
5784

5885
return count;
5986
}
@@ -67,7 +94,8 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file,
6794
poll_wait(file, &motu->hwdep_wait, wait);
6895

6996
spin_lock_irq(&motu->lock);
70-
if (motu->dev_lock_changed || motu->msg)
97+
if (motu->dev_lock_changed || motu->msg ||
98+
snd_motu_register_dsp_message_parser_count_event(motu) > 0)
7199
events = EPOLLIN | EPOLLRDNORM;
72100
else
73101
events = 0;

sound/firewire/motu/motu-register-dsp-message-parser.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ struct msg_parser {
9595

9696
u32 event_queue[EVENT_QUEUE_SIZE];
9797
unsigned int push_pos;
98+
unsigned int pull_pos;
9899
};
99100

100101
int snd_motu_register_dsp_message_parser_new(struct snd_motu *motu)
@@ -122,6 +123,7 @@ int snd_motu_register_dsp_message_parser_init(struct snd_motu *motu)
122123
return 0;
123124
}
124125

126+
// Rough implementaion of queue without overrun check.
125127
static void queue_event(struct snd_motu *motu, u8 msg_type, u8 identifier0, u8 identifier1, u8 val)
126128
{
127129
struct msg_parser *parser = motu->message_parser;
@@ -145,6 +147,7 @@ void snd_motu_register_dsp_message_parser_parse(struct snd_motu *motu, const str
145147
{
146148
struct msg_parser *parser = motu->message_parser;
147149
bool meter_pos_quirk = parser->meter_pos_quirk;
150+
unsigned int pos = parser->push_pos;
148151
unsigned long flags;
149152
int i;
150153

@@ -351,6 +354,9 @@ void snd_motu_register_dsp_message_parser_parse(struct snd_motu *motu, const str
351354
}
352355
}
353356

357+
if (pos != parser->push_pos)
358+
wake_up(&motu->hwdep_wait);
359+
354360
spin_unlock_irqrestore(&parser->lock, flags);
355361
}
356362

@@ -375,3 +381,36 @@ void snd_motu_register_dsp_message_parser_copy_parameter(struct snd_motu *motu,
375381
memcpy(param, &parser->param, sizeof(*param));
376382
spin_unlock_irqrestore(&parser->lock, flags);
377383
}
384+
385+
unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *motu)
386+
{
387+
struct msg_parser *parser = motu->message_parser;
388+
389+
if (parser->pull_pos > parser->push_pos)
390+
return EVENT_QUEUE_SIZE - parser->pull_pos + parser->push_pos;
391+
else
392+
return parser->push_pos - parser->pull_pos;
393+
}
394+
395+
bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event)
396+
{
397+
struct msg_parser *parser = motu->message_parser;
398+
unsigned int pos = parser->pull_pos;
399+
unsigned long flags;
400+
401+
if (pos == parser->push_pos)
402+
return false;
403+
404+
spin_lock_irqsave(&parser->lock, flags);
405+
406+
*event = parser->event_queue[pos];
407+
408+
++pos;
409+
if (pos >= EVENT_QUEUE_SIZE)
410+
pos = 0;
411+
parser->pull_pos = pos;
412+
413+
spin_unlock_irqrestore(&parser->lock, flags);
414+
415+
return true;
416+
}

sound/firewire/motu/motu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ void snd_motu_register_dsp_message_parser_copy_meter(struct snd_motu *motu,
283283
struct snd_firewire_motu_register_dsp_meter *meter);
284284
void snd_motu_register_dsp_message_parser_copy_parameter(struct snd_motu *motu,
285285
struct snd_firewire_motu_register_dsp_parameter *params);
286+
unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *motu);
287+
bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event);
286288

287289
int snd_motu_command_dsp_message_parser_new(struct snd_motu *motu);
288290
int snd_motu_command_dsp_message_parser_init(struct snd_motu *motu, enum cip_sfc sfc);

0 commit comments

Comments
 (0)