Loading include/sound/rawmidi.h +0 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ #define SNDRV_RAWMIDI_LFLG_INPUT (1<<1) #define SNDRV_RAWMIDI_LFLG_OPEN (3<<0) #define SNDRV_RAWMIDI_LFLG_APPEND (1<<2) #define SNDRV_RAWMIDI_LFLG_NOOPENLOCK (1<<3) struct snd_rawmidi; struct snd_rawmidi_substream; Loading sound/core/rawmidi.c +194 −183 Original line number Diff line number Diff line Loading @@ -224,155 +224,142 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream) return 0; } int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, int mode, struct snd_rawmidi_file * rfile) /* look for an available substream for the given stream direction; * if a specific subdevice is given, try to assign it */ static int assign_substream(struct snd_rawmidi *rmidi, int subdevice, int stream, int mode, struct snd_rawmidi_substream **sub_ret) { struct snd_rawmidi *rmidi; struct list_head *list1, *list2; struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL; struct snd_rawmidi_runtime *input = NULL, *output = NULL; int err; struct snd_rawmidi_substream *substream; struct snd_rawmidi_str *s = &rmidi->streams[stream]; static unsigned int info_flags[2] = { [SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT, [SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT, }; if (rfile) rfile->input = rfile->output = NULL; mutex_lock(®ister_mutex); rmidi = snd_rawmidi_search(card, device); if (rmidi == NULL) { mutex_unlock(®ister_mutex); return -ENODEV; } if (!try_module_get(rmidi->card->module)) { mutex_unlock(®ister_mutex); if (!(rmidi->info_flags & info_flags[stream])) return -ENXIO; } mutex_unlock(®ister_mutex); if (subdevice >= 0 && subdevice >= s->substream_count) return -ENODEV; if (s->substream_opened >= s->substream_count) return -EAGAIN; if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) mutex_lock(&rmidi->open_mutex); if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT)) { err = -ENXIO; goto __error; } if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) { err = -ENODEV; goto __error; } if (rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened >= rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) { err = -EAGAIN; goto __error; } list_for_each_entry(substream, &s->substreams, list) { if (substream->opened) { if (stream == SNDRV_RAWMIDI_STREAM_INPUT || !(mode & SNDRV_RAWMIDI_LFLG_APPEND)) continue; } if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT)) { err = -ENXIO; goto __error; if (subdevice < 0 || subdevice == substream->number) { *sub_ret = substream; return 0; } if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) { err = -ENODEV; goto __error; } if (rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened >= rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) { err = -EAGAIN; goto __error; return -EAGAIN; } /* open and do ref-counting for the given substream */ static int open_substream(struct snd_rawmidi *rmidi, struct snd_rawmidi_substream *substream, int mode) { int err; err = snd_rawmidi_runtime_create(substream); if (err < 0) return err; err = substream->ops->open(substream); if (err < 0) return err; substream->opened = 1; if (substream->use_count++ == 0) substream->active_sensing = 1; if (mode & SNDRV_RAWMIDI_LFLG_APPEND) substream->append = 1; rmidi->streams[substream->stream].substream_opened++; return 0; } list1 = rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams.next; while (1) { if (list1 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { sinput = NULL; static void close_substream(struct snd_rawmidi *rmidi, struct snd_rawmidi_substream *substream, int cleanup); static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, struct snd_rawmidi_file *rfile) { struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL; int err; rfile->input = rfile->output = NULL; if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { err = -EAGAIN; goto __error; } break; } sinput = list_entry(list1, struct snd_rawmidi_substream, list); if ((mode & SNDRV_RAWMIDI_LFLG_INPUT) && sinput->opened) goto __nexti; if (subdevice < 0 || (subdevice >= 0 && subdevice == sinput->number)) break; __nexti: list1 = list1->next; } list2 = rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams.next; while (1) { if (list2 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { soutput = NULL; if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { err = -EAGAIN; err = assign_substream(rmidi, subdevice, SNDRV_RAWMIDI_STREAM_INPUT, mode, &sinput); if (err < 0) goto __error; } break; } soutput = list_entry(list2, struct snd_rawmidi_substream, list); if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { if (mode & SNDRV_RAWMIDI_LFLG_APPEND) { if (soutput->opened && !soutput->append) goto __nexto; } else { if (soutput->opened) goto __nexto; } } if (subdevice < 0 || (subdevice >= 0 && subdevice == soutput->number)) break; __nexto: list2 = list2->next; } if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { if ((err = snd_rawmidi_runtime_create(sinput)) < 0) goto __error; input = sinput->runtime; if ((err = sinput->ops->open(sinput)) < 0) err = assign_substream(rmidi, subdevice, SNDRV_RAWMIDI_STREAM_OUTPUT, mode, &soutput); if (err < 0) goto __error; sinput->opened = 1; rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened++; } else { sinput = NULL; } if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { if (soutput->opened) goto __skip_output; if ((err = snd_rawmidi_runtime_create(soutput)) < 0) { if (mode & SNDRV_RAWMIDI_LFLG_INPUT) sinput->ops->close(sinput); if (sinput) { err = open_substream(rmidi, sinput, mode); if (err < 0) goto __error; } output = soutput->runtime; if ((err = soutput->ops->open(soutput)) < 0) { if (mode & SNDRV_RAWMIDI_LFLG_INPUT) sinput->ops->close(sinput); if (soutput) { err = open_substream(rmidi, soutput, mode); if (err < 0) { if (sinput) close_substream(rmidi, sinput, 0); goto __error; } __skip_output: soutput->opened = 1; if (mode & SNDRV_RAWMIDI_LFLG_APPEND) soutput->append = 1; if (soutput->use_count++ == 0) soutput->active_sensing = 1; rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened++; } else { soutput = NULL; } if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) mutex_unlock(&rmidi->open_mutex); if (rfile) { rfile->rmidi = rmidi; rfile->input = sinput; rfile->output = soutput; } return 0; __error: if (input != NULL) if (sinput && sinput->runtime) snd_rawmidi_runtime_free(sinput); if (output != NULL) if (soutput && soutput->runtime) snd_rawmidi_runtime_free(soutput); if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) return err; } /* called from sound/core/seq/seq_midi.c */ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, int mode, struct snd_rawmidi_file * rfile) { struct snd_rawmidi *rmidi; int err; if (snd_BUG_ON(!rfile)) return -EINVAL; mutex_lock(®ister_mutex); rmidi = snd_rawmidi_search(card, device); if (rmidi == NULL) { mutex_unlock(®ister_mutex); return -ENODEV; } if (!try_module_get(rmidi->card->module)) { mutex_unlock(®ister_mutex); return -ENXIO; } mutex_unlock(®ister_mutex); mutex_lock(&rmidi->open_mutex); err = rawmidi_open_priv(rmidi, subdevice, mode, rfile); mutex_unlock(&rmidi->open_mutex); if (err < 0) module_put(rmidi->card->module); return err; } Loading @@ -385,10 +372,13 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) unsigned short fflags; int err; struct snd_rawmidi *rmidi; struct snd_rawmidi_file *rawmidi_file; struct snd_rawmidi_file *rawmidi_file = NULL; wait_queue_t wait; struct snd_ctl_file *kctl; if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) return -EINVAL; /* invalid combination */ if (maj == snd_major) { rmidi = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_RAWMIDI); Loading @@ -402,24 +392,25 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) if (rmidi == NULL) return -ENODEV; if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) return -EINVAL; /* invalid combination */ if (!try_module_get(rmidi->card->module)) return -ENXIO; mutex_lock(&rmidi->open_mutex); card = rmidi->card; err = snd_card_file_add(card, file); if (err < 0) return -ENODEV; goto __error_card; fflags = snd_rawmidi_file_flags(file); if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */ fflags |= SNDRV_RAWMIDI_LFLG_APPEND; fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK; rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL); if (rawmidi_file == NULL) { snd_card_file_remove(card, file); return -ENOMEM; err = -ENOMEM; goto __error; } init_waitqueue_entry(&wait, current); add_wait_queue(&rmidi->open_wait, &wait); mutex_lock(&rmidi->open_mutex); while (1) { subdevice = -1; read_lock(&card->ctl_files_rwlock); Loading @@ -431,8 +422,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) } } read_unlock(&card->ctl_files_rwlock); err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device, subdevice, fflags, rawmidi_file); err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file); if (err >= 0) break; if (err == -EAGAIN) { Loading @@ -451,67 +441,89 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) break; } } remove_wait_queue(&rmidi->open_wait, &wait); if (err < 0) { kfree(rawmidi_file); goto __error; } #ifdef CONFIG_SND_OSSEMUL if (rawmidi_file->input && rawmidi_file->input->runtime) rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR); if (rawmidi_file->output && rawmidi_file->output->runtime) rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR); #endif remove_wait_queue(&rmidi->open_wait, &wait); if (err >= 0) { file->private_data = rawmidi_file; } else { mutex_unlock(&rmidi->open_mutex); return 0; __error: snd_card_file_remove(card, file); kfree(rawmidi_file); } __error_card: mutex_unlock(&rmidi->open_mutex); module_put(rmidi->card->module); return err; } int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile) static void close_substream(struct snd_rawmidi *rmidi, struct snd_rawmidi_substream *substream, int cleanup) { struct snd_rawmidi *rmidi; struct snd_rawmidi_substream *substream; struct snd_rawmidi_runtime *runtime; rmidi->streams[substream->stream].substream_opened--; if (--substream->use_count) return; if (snd_BUG_ON(!rfile)) return -ENXIO; rmidi = rfile->rmidi; mutex_lock(&rmidi->open_mutex); if (rfile->input != NULL) { substream = rfile->input; rfile->input = NULL; runtime = substream->runtime; if (cleanup) { if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT) snd_rawmidi_input_trigger(substream, 0); substream->ops->close(substream); if (runtime->private_free != NULL) runtime->private_free(substream); snd_rawmidi_runtime_free(substream); substream->opened = 0; rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened--; } if (rfile->output != NULL) { substream = rfile->output; rfile->output = NULL; if (--substream->use_count == 0) { runtime = substream->runtime; else { if (substream->active_sensing) { unsigned char buf = 0xfe; /* sending single active sensing message to shut the device up */ /* sending single active sensing message * to shut the device up */ snd_rawmidi_kernel_write(substream, &buf, 1); } if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS) snd_rawmidi_output_trigger(substream, 0); } } substream->ops->close(substream); if (runtime->private_free != NULL) runtime->private_free(substream); if (substream->runtime->private_free) substream->runtime->private_free(substream); snd_rawmidi_runtime_free(substream); substream->opened = 0; substream->append = 0; } rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened--; static void rawmidi_release_priv(struct snd_rawmidi_file *rfile) { struct snd_rawmidi *rmidi; rmidi = rfile->rmidi; mutex_lock(&rmidi->open_mutex); if (rfile->input) { close_substream(rmidi, rfile->input, 1); rfile->input = NULL; } if (rfile->output) { close_substream(rmidi, rfile->output, 1); rfile->output = NULL; } rfile->rmidi = NULL; mutex_unlock(&rmidi->open_mutex); wake_up(&rmidi->open_wait); } /* called from sound/core/seq/seq_midi.c */ int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile) { struct snd_rawmidi *rmidi; if (snd_BUG_ON(!rfile)) return -ENXIO; rmidi = rfile->rmidi; rawmidi_release_priv(rfile); module_put(rmidi->card->module); return 0; } Loading @@ -520,15 +532,14 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file) { struct snd_rawmidi_file *rfile; struct snd_rawmidi *rmidi; int err; rfile = file->private_data; err = snd_rawmidi_kernel_release(rfile); rmidi = rfile->rmidi; wake_up(&rmidi->open_wait); rawmidi_release_priv(rfile); kfree(rfile); snd_card_file_remove(rmidi->card, file); return err; module_put(rmidi->card->module); return 0; } static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, Loading Loading
include/sound/rawmidi.h +0 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ #define SNDRV_RAWMIDI_LFLG_INPUT (1<<1) #define SNDRV_RAWMIDI_LFLG_OPEN (3<<0) #define SNDRV_RAWMIDI_LFLG_APPEND (1<<2) #define SNDRV_RAWMIDI_LFLG_NOOPENLOCK (1<<3) struct snd_rawmidi; struct snd_rawmidi_substream; Loading
sound/core/rawmidi.c +194 −183 Original line number Diff line number Diff line Loading @@ -224,155 +224,142 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream) return 0; } int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, int mode, struct snd_rawmidi_file * rfile) /* look for an available substream for the given stream direction; * if a specific subdevice is given, try to assign it */ static int assign_substream(struct snd_rawmidi *rmidi, int subdevice, int stream, int mode, struct snd_rawmidi_substream **sub_ret) { struct snd_rawmidi *rmidi; struct list_head *list1, *list2; struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL; struct snd_rawmidi_runtime *input = NULL, *output = NULL; int err; struct snd_rawmidi_substream *substream; struct snd_rawmidi_str *s = &rmidi->streams[stream]; static unsigned int info_flags[2] = { [SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT, [SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT, }; if (rfile) rfile->input = rfile->output = NULL; mutex_lock(®ister_mutex); rmidi = snd_rawmidi_search(card, device); if (rmidi == NULL) { mutex_unlock(®ister_mutex); return -ENODEV; } if (!try_module_get(rmidi->card->module)) { mutex_unlock(®ister_mutex); if (!(rmidi->info_flags & info_flags[stream])) return -ENXIO; } mutex_unlock(®ister_mutex); if (subdevice >= 0 && subdevice >= s->substream_count) return -ENODEV; if (s->substream_opened >= s->substream_count) return -EAGAIN; if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) mutex_lock(&rmidi->open_mutex); if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT)) { err = -ENXIO; goto __error; } if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) { err = -ENODEV; goto __error; } if (rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened >= rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) { err = -EAGAIN; goto __error; } list_for_each_entry(substream, &s->substreams, list) { if (substream->opened) { if (stream == SNDRV_RAWMIDI_STREAM_INPUT || !(mode & SNDRV_RAWMIDI_LFLG_APPEND)) continue; } if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT)) { err = -ENXIO; goto __error; if (subdevice < 0 || subdevice == substream->number) { *sub_ret = substream; return 0; } if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) { err = -ENODEV; goto __error; } if (rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened >= rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) { err = -EAGAIN; goto __error; return -EAGAIN; } /* open and do ref-counting for the given substream */ static int open_substream(struct snd_rawmidi *rmidi, struct snd_rawmidi_substream *substream, int mode) { int err; err = snd_rawmidi_runtime_create(substream); if (err < 0) return err; err = substream->ops->open(substream); if (err < 0) return err; substream->opened = 1; if (substream->use_count++ == 0) substream->active_sensing = 1; if (mode & SNDRV_RAWMIDI_LFLG_APPEND) substream->append = 1; rmidi->streams[substream->stream].substream_opened++; return 0; } list1 = rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams.next; while (1) { if (list1 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { sinput = NULL; static void close_substream(struct snd_rawmidi *rmidi, struct snd_rawmidi_substream *substream, int cleanup); static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, struct snd_rawmidi_file *rfile) { struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL; int err; rfile->input = rfile->output = NULL; if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { err = -EAGAIN; goto __error; } break; } sinput = list_entry(list1, struct snd_rawmidi_substream, list); if ((mode & SNDRV_RAWMIDI_LFLG_INPUT) && sinput->opened) goto __nexti; if (subdevice < 0 || (subdevice >= 0 && subdevice == sinput->number)) break; __nexti: list1 = list1->next; } list2 = rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams.next; while (1) { if (list2 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { soutput = NULL; if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { err = -EAGAIN; err = assign_substream(rmidi, subdevice, SNDRV_RAWMIDI_STREAM_INPUT, mode, &sinput); if (err < 0) goto __error; } break; } soutput = list_entry(list2, struct snd_rawmidi_substream, list); if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { if (mode & SNDRV_RAWMIDI_LFLG_APPEND) { if (soutput->opened && !soutput->append) goto __nexto; } else { if (soutput->opened) goto __nexto; } } if (subdevice < 0 || (subdevice >= 0 && subdevice == soutput->number)) break; __nexto: list2 = list2->next; } if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { if ((err = snd_rawmidi_runtime_create(sinput)) < 0) goto __error; input = sinput->runtime; if ((err = sinput->ops->open(sinput)) < 0) err = assign_substream(rmidi, subdevice, SNDRV_RAWMIDI_STREAM_OUTPUT, mode, &soutput); if (err < 0) goto __error; sinput->opened = 1; rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened++; } else { sinput = NULL; } if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { if (soutput->opened) goto __skip_output; if ((err = snd_rawmidi_runtime_create(soutput)) < 0) { if (mode & SNDRV_RAWMIDI_LFLG_INPUT) sinput->ops->close(sinput); if (sinput) { err = open_substream(rmidi, sinput, mode); if (err < 0) goto __error; } output = soutput->runtime; if ((err = soutput->ops->open(soutput)) < 0) { if (mode & SNDRV_RAWMIDI_LFLG_INPUT) sinput->ops->close(sinput); if (soutput) { err = open_substream(rmidi, soutput, mode); if (err < 0) { if (sinput) close_substream(rmidi, sinput, 0); goto __error; } __skip_output: soutput->opened = 1; if (mode & SNDRV_RAWMIDI_LFLG_APPEND) soutput->append = 1; if (soutput->use_count++ == 0) soutput->active_sensing = 1; rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened++; } else { soutput = NULL; } if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) mutex_unlock(&rmidi->open_mutex); if (rfile) { rfile->rmidi = rmidi; rfile->input = sinput; rfile->output = soutput; } return 0; __error: if (input != NULL) if (sinput && sinput->runtime) snd_rawmidi_runtime_free(sinput); if (output != NULL) if (soutput && soutput->runtime) snd_rawmidi_runtime_free(soutput); if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) return err; } /* called from sound/core/seq/seq_midi.c */ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, int mode, struct snd_rawmidi_file * rfile) { struct snd_rawmidi *rmidi; int err; if (snd_BUG_ON(!rfile)) return -EINVAL; mutex_lock(®ister_mutex); rmidi = snd_rawmidi_search(card, device); if (rmidi == NULL) { mutex_unlock(®ister_mutex); return -ENODEV; } if (!try_module_get(rmidi->card->module)) { mutex_unlock(®ister_mutex); return -ENXIO; } mutex_unlock(®ister_mutex); mutex_lock(&rmidi->open_mutex); err = rawmidi_open_priv(rmidi, subdevice, mode, rfile); mutex_unlock(&rmidi->open_mutex); if (err < 0) module_put(rmidi->card->module); return err; } Loading @@ -385,10 +372,13 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) unsigned short fflags; int err; struct snd_rawmidi *rmidi; struct snd_rawmidi_file *rawmidi_file; struct snd_rawmidi_file *rawmidi_file = NULL; wait_queue_t wait; struct snd_ctl_file *kctl; if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) return -EINVAL; /* invalid combination */ if (maj == snd_major) { rmidi = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_RAWMIDI); Loading @@ -402,24 +392,25 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) if (rmidi == NULL) return -ENODEV; if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) return -EINVAL; /* invalid combination */ if (!try_module_get(rmidi->card->module)) return -ENXIO; mutex_lock(&rmidi->open_mutex); card = rmidi->card; err = snd_card_file_add(card, file); if (err < 0) return -ENODEV; goto __error_card; fflags = snd_rawmidi_file_flags(file); if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */ fflags |= SNDRV_RAWMIDI_LFLG_APPEND; fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK; rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL); if (rawmidi_file == NULL) { snd_card_file_remove(card, file); return -ENOMEM; err = -ENOMEM; goto __error; } init_waitqueue_entry(&wait, current); add_wait_queue(&rmidi->open_wait, &wait); mutex_lock(&rmidi->open_mutex); while (1) { subdevice = -1; read_lock(&card->ctl_files_rwlock); Loading @@ -431,8 +422,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) } } read_unlock(&card->ctl_files_rwlock); err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device, subdevice, fflags, rawmidi_file); err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file); if (err >= 0) break; if (err == -EAGAIN) { Loading @@ -451,67 +441,89 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) break; } } remove_wait_queue(&rmidi->open_wait, &wait); if (err < 0) { kfree(rawmidi_file); goto __error; } #ifdef CONFIG_SND_OSSEMUL if (rawmidi_file->input && rawmidi_file->input->runtime) rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR); if (rawmidi_file->output && rawmidi_file->output->runtime) rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR); #endif remove_wait_queue(&rmidi->open_wait, &wait); if (err >= 0) { file->private_data = rawmidi_file; } else { mutex_unlock(&rmidi->open_mutex); return 0; __error: snd_card_file_remove(card, file); kfree(rawmidi_file); } __error_card: mutex_unlock(&rmidi->open_mutex); module_put(rmidi->card->module); return err; } int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile) static void close_substream(struct snd_rawmidi *rmidi, struct snd_rawmidi_substream *substream, int cleanup) { struct snd_rawmidi *rmidi; struct snd_rawmidi_substream *substream; struct snd_rawmidi_runtime *runtime; rmidi->streams[substream->stream].substream_opened--; if (--substream->use_count) return; if (snd_BUG_ON(!rfile)) return -ENXIO; rmidi = rfile->rmidi; mutex_lock(&rmidi->open_mutex); if (rfile->input != NULL) { substream = rfile->input; rfile->input = NULL; runtime = substream->runtime; if (cleanup) { if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT) snd_rawmidi_input_trigger(substream, 0); substream->ops->close(substream); if (runtime->private_free != NULL) runtime->private_free(substream); snd_rawmidi_runtime_free(substream); substream->opened = 0; rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened--; } if (rfile->output != NULL) { substream = rfile->output; rfile->output = NULL; if (--substream->use_count == 0) { runtime = substream->runtime; else { if (substream->active_sensing) { unsigned char buf = 0xfe; /* sending single active sensing message to shut the device up */ /* sending single active sensing message * to shut the device up */ snd_rawmidi_kernel_write(substream, &buf, 1); } if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS) snd_rawmidi_output_trigger(substream, 0); } } substream->ops->close(substream); if (runtime->private_free != NULL) runtime->private_free(substream); if (substream->runtime->private_free) substream->runtime->private_free(substream); snd_rawmidi_runtime_free(substream); substream->opened = 0; substream->append = 0; } rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened--; static void rawmidi_release_priv(struct snd_rawmidi_file *rfile) { struct snd_rawmidi *rmidi; rmidi = rfile->rmidi; mutex_lock(&rmidi->open_mutex); if (rfile->input) { close_substream(rmidi, rfile->input, 1); rfile->input = NULL; } if (rfile->output) { close_substream(rmidi, rfile->output, 1); rfile->output = NULL; } rfile->rmidi = NULL; mutex_unlock(&rmidi->open_mutex); wake_up(&rmidi->open_wait); } /* called from sound/core/seq/seq_midi.c */ int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile) { struct snd_rawmidi *rmidi; if (snd_BUG_ON(!rfile)) return -ENXIO; rmidi = rfile->rmidi; rawmidi_release_priv(rfile); module_put(rmidi->card->module); return 0; } Loading @@ -520,15 +532,14 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file) { struct snd_rawmidi_file *rfile; struct snd_rawmidi *rmidi; int err; rfile = file->private_data; err = snd_rawmidi_kernel_release(rfile); rmidi = rfile->rmidi; wake_up(&rmidi->open_wait); rawmidi_release_priv(rfile); kfree(rfile); snd_card_file_remove(rmidi->card, file); return err; module_put(rmidi->card->module); return 0; } static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, Loading