#define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c
#define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION 0x64776479
#define SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL 0x7473636d
+#define SNDRV_FIREWIRE_EVENT_MOTU_REGISTER_DSP_CHANGE 0x4d545244
struct snd_firewire_event_common {
unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */
struct snd_firewire_tascam_change changes[0];
};
+struct snd_firewire_event_motu_register_dsp_change {
+ unsigned int type;
+ __u32 count; // The number of changes.
+ __u32 changes[]; // Encoded event for change of register DSP.
+};
+
union snd_firewire_event {
struct snd_firewire_event_common common;
struct snd_firewire_event_lock_status lock_status;
struct snd_firewire_event_digi00x_message digi00x_message;
struct snd_firewire_event_tascam_control tascam_control;
struct snd_firewire_event_motu_notification motu_notification;
+ struct snd_firewire_event_motu_register_dsp_change motu_register_dsp_change;
};
spin_lock_irq(&motu->lock);
- while (!motu->dev_lock_changed && motu->msg == 0) {
+ while (!motu->dev_lock_changed && motu->msg == 0 &&
+ snd_motu_register_dsp_message_parser_count_event(motu) == 0) {
prepare_to_wait(&motu->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
spin_unlock_irq(&motu->lock);
schedule();
event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
event.lock_status.status = (motu->dev_lock_count > 0);
motu->dev_lock_changed = false;
+ spin_unlock_irq(&motu->lock);
- count = min_t(long, count, sizeof(event.lock_status));
- } else {
+ count = min_t(long, count, sizeof(event));
+ if (copy_to_user(buf, &event, count))
+ return -EFAULT;
+ } else if (motu->msg > 0) {
event.motu_notification.type = SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION;
event.motu_notification.message = motu->msg;
motu->msg = 0;
+ spin_unlock_irq(&motu->lock);
- count = min_t(long, count, sizeof(event.motu_notification));
- }
+ count = min_t(long, count, sizeof(event));
+ if (copy_to_user(buf, &event, count))
+ return -EFAULT;
+ } else if (snd_motu_register_dsp_message_parser_count_event(motu) > 0) {
+ size_t consumed = 0;
+ u32 __user *ptr;
+ u32 ev;
- spin_unlock_irq(&motu->lock);
+ spin_unlock_irq(&motu->lock);
- if (copy_to_user(buf, &event, count))
- return -EFAULT;
+ // Header is filled later.
+ consumed += sizeof(event.motu_register_dsp_change);
+
+ while (consumed < count &&
+ snd_motu_register_dsp_message_parser_copy_event(motu, &ev)) {
+ ptr = (u32 __user *)(buf + consumed);
+ if (put_user(ev, ptr))
+ return -EFAULT;
+ consumed += sizeof(ev);
+ }
+
+ event.motu_register_dsp_change.type = SNDRV_FIREWIRE_EVENT_MOTU_REGISTER_DSP_CHANGE;
+ event.motu_register_dsp_change.count =
+ (consumed - sizeof(event.motu_register_dsp_change)) / 4;
+ if (copy_to_user(buf, &event, sizeof(event.motu_register_dsp_change)))
+ return -EFAULT;
+
+ count = consumed;
+ }
return count;
}
poll_wait(file, &motu->hwdep_wait, wait);
spin_lock_irq(&motu->lock);
- if (motu->dev_lock_changed || motu->msg)
+ if (motu->dev_lock_changed || motu->msg ||
+ snd_motu_register_dsp_message_parser_count_event(motu) > 0)
events = EPOLLIN | EPOLLRDNORM;
else
events = 0;
u32 event_queue[EVENT_QUEUE_SIZE];
unsigned int push_pos;
+ unsigned int pull_pos;
};
int snd_motu_register_dsp_message_parser_new(struct snd_motu *motu)
return 0;
}
+// Rough implementaion of queue without overrun check.
static void queue_event(struct snd_motu *motu, u8 msg_type, u8 identifier0, u8 identifier1, u8 val)
{
struct msg_parser *parser = motu->message_parser;
{
struct msg_parser *parser = motu->message_parser;
bool meter_pos_quirk = parser->meter_pos_quirk;
+ unsigned int pos = parser->push_pos;
unsigned long flags;
int i;
}
}
+ if (pos != parser->push_pos)
+ wake_up(&motu->hwdep_wait);
+
spin_unlock_irqrestore(&parser->lock, flags);
}
memcpy(param, &parser->param, sizeof(*param));
spin_unlock_irqrestore(&parser->lock, flags);
}
+
+unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *motu)
+{
+ struct msg_parser *parser = motu->message_parser;
+
+ if (parser->pull_pos > parser->push_pos)
+ return EVENT_QUEUE_SIZE - parser->pull_pos + parser->push_pos;
+ else
+ return parser->push_pos - parser->pull_pos;
+}
+
+bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event)
+{
+ struct msg_parser *parser = motu->message_parser;
+ unsigned int pos = parser->pull_pos;
+ unsigned long flags;
+
+ if (pos == parser->push_pos)
+ return false;
+
+ spin_lock_irqsave(&parser->lock, flags);
+
+ *event = parser->event_queue[pos];
+
+ ++pos;
+ if (pos >= EVENT_QUEUE_SIZE)
+ pos = 0;
+ parser->pull_pos = pos;
+
+ spin_unlock_irqrestore(&parser->lock, flags);
+
+ return true;
+}
struct snd_firewire_motu_register_dsp_meter *meter);
void snd_motu_register_dsp_message_parser_copy_parameter(struct snd_motu *motu,
struct snd_firewire_motu_register_dsp_parameter *params);
+unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *motu);
+bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event);
int snd_motu_command_dsp_message_parser_new(struct snd_motu *motu);
int snd_motu_command_dsp_message_parser_init(struct snd_motu *motu, enum cip_sfc sfc);