/* * look for the identical slot
*/ staticstruct seq_oss_midi *
find_slot(int client, int port)
{ int i; struct seq_oss_midi *mdev; unsignedlong flags;
spin_lock_irqsave(®ister_lock, flags); for (i = 0; i < max_midi_devs; i++) {
mdev = midi_devs[i]; if (mdev && mdev->client == client && mdev->port == port) { /* found! */
snd_use_lock_use(&mdev->use_lock);
spin_unlock_irqrestore(®ister_lock, flags); return mdev;
}
}
spin_unlock_irqrestore(®ister_lock, flags); return NULL;
}
#define PERM_WRITE (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE) #define PERM_READ (SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ) /* * register a new port if it doesn't exist yet
*/ int
snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
{ int i; struct seq_oss_midi *mdev; unsignedlong flags;
/* the port must include generic midi */ if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC)) return 0; /* either read or write subscribable */ if ((pinfo->capability & PERM_WRITE) != PERM_WRITE &&
(pinfo->capability & PERM_READ) != PERM_READ) return 0;
/* * look for the identical slot
*/
mdev = find_slot(pinfo->addr.client, pinfo->addr.port); if (mdev) { /* already exists */
snd_use_lock_free(&mdev->use_lock); return 0;
}
/* * allocate midi info record
*/
mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); if (!mdev) return -ENOMEM;
/* copy the port information */
mdev->client = pinfo->addr.client;
mdev->port = pinfo->addr.port;
mdev->flags = pinfo->capability;
mdev->opened = 0;
snd_use_lock_init(&mdev->use_lock);
mutex_init(&mdev->open_mutex);
/* copy and truncate the name of synth device */
strscpy(mdev->name, pinfo->name, sizeof(mdev->name));
/* create MIDI coder */ if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
pr_err("ALSA: seq_oss: can't malloc midi coder\n");
kfree(mdev); return -ENOMEM;
} /* OSS sequencer adds running status to all sequences */
snd_midi_event_no_status(mdev->coder, 1);
/* * look for en empty slot
*/
spin_lock_irqsave(®ister_lock, flags); for (i = 0; i < max_midi_devs; i++) { if (midi_devs[i] == NULL) break;
} if (i >= max_midi_devs) { if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) {
spin_unlock_irqrestore(®ister_lock, flags);
snd_midi_event_free(mdev->coder);
kfree(mdev); return -ENOMEM;
}
max_midi_devs++;
}
mdev->seq_device = i;
midi_devs[mdev->seq_device] = mdev;
spin_unlock_irqrestore(®ister_lock, flags);
return 0;
}
/* * release the midi device if it was registered
*/ int
snd_seq_oss_midi_check_exit_port(int client, int port)
{ struct seq_oss_midi *mdev; unsignedlong flags; int index;
mdev = find_slot(client, port); if (mdev) {
spin_lock_irqsave(®ister_lock, flags);
midi_devs[mdev->seq_device] = NULL;
spin_unlock_irqrestore(®ister_lock, flags);
snd_use_lock_free(&mdev->use_lock);
snd_use_lock_sync(&mdev->use_lock);
snd_midi_event_free(mdev->coder);
kfree(mdev);
}
spin_lock_irqsave(®ister_lock, flags); for (index = max_midi_devs - 1; index >= 0; index--) { if (midi_devs[index]) break;
}
max_midi_devs = index + 1;
spin_unlock_irqrestore(®ister_lock, flags); return 0;
}
/* * release the midi device if it was registered
*/ void
snd_seq_oss_midi_clear_all(void)
{ int i; struct seq_oss_midi *mdev; unsignedlong flags;
spin_lock_irqsave(®ister_lock, flags); for (i = 0; i < max_midi_devs; i++) {
mdev = midi_devs[i]; if (mdev) {
snd_midi_event_free(mdev->coder);
kfree(mdev);
midi_devs[i] = NULL;
}
}
max_midi_devs = 0;
spin_unlock_irqrestore(®ister_lock, flags);
}
/* * set up midi tables
*/ void
snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
{
spin_lock_irq(®ister_lock);
dp->max_mididev = max_midi_devs;
spin_unlock_irq(®ister_lock);
}
/* * clean up midi tables
*/ void
snd_seq_oss_midi_cleanup(struct seq_oss_devinfo *dp)
{ int i; for (i = 0; i < dp->max_mididev; i++)
snd_seq_oss_midi_close(dp, i);
dp->max_mididev = 0;
}
/* * open all midi devices. ignore errors.
*/ void
snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode)
{ int i; for (i = 0; i < dp->max_mididev; i++)
snd_seq_oss_midi_open(dp, i, file_mode);
}
/* * get the midi device information
*/ staticstruct seq_oss_midi *
get_mididev(struct seq_oss_devinfo *dp, int dev)
{ if (dev < 0 || dev >= dp->max_mididev) return NULL;
dev = array_index_nospec(dev, dp->max_mididev); return get_mdev(dev);
}
/* * open the midi device if not opened yet
*/ int
snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
{ int perm; struct seq_oss_midi *mdev; struct snd_seq_port_subscribe subs; int err;
mdev = get_mididev(dp, dev); if (!mdev) return -ENODEV;
/* * close the midi device if already opened
*/ int
snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
{ struct seq_oss_midi *mdev; struct snd_seq_port_subscribe subs;
mdev = get_mididev(dp, dev); if (!mdev) return -ENODEV;
mutex_lock(&mdev->open_mutex); if (!mdev->opened || mdev->devinfo != dp) goto unlock;
/* * reset the midi device and close it: * so far, only close the device.
*/ void
snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
{ struct seq_oss_midi *mdev;
mdev = get_mididev(dp, dev); if (!mdev) return; if (! mdev->opened) {
snd_use_lock_free(&mdev->use_lock); return;
}
if (mdev->opened & PERM_WRITE) { struct snd_seq_event ev; int c;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.