⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rawmidi.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait){	struct snd_rawmidi_file *rfile;	struct snd_rawmidi_runtime *runtime;	unsigned int mask;	rfile = file->private_data;	if (rfile->input != NULL) {		runtime = rfile->input->runtime;		snd_rawmidi_input_trigger(rfile->input, 1);		poll_wait(file, &runtime->sleep, wait);	}	if (rfile->output != NULL) {		runtime = rfile->output->runtime;		poll_wait(file, &runtime->sleep, wait);	}	mask = 0;	if (rfile->input != NULL) {		if (snd_rawmidi_ready(rfile->input))			mask |= POLLIN | POLLRDNORM;	}	if (rfile->output != NULL) {		if (snd_rawmidi_ready(rfile->output))			mask |= POLLOUT | POLLWRNORM;	}	return mask;}/* */#ifdef CONFIG_COMPAT#include "rawmidi_compat.c"#else#define snd_rawmidi_ioctl_compat	NULL#endif/* */static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,				       struct snd_info_buffer *buffer){	struct snd_rawmidi *rmidi;	struct snd_rawmidi_substream *substream;	struct snd_rawmidi_runtime *runtime;	rmidi = entry->private_data;	snd_iprintf(buffer, "%s\n\n", rmidi->name);	mutex_lock(&rmidi->open_mutex);	if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) {		list_for_each_entry(substream,				    &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,				    list) {			snd_iprintf(buffer,				    "Output %d\n"				    "  Tx bytes     : %lu\n",				    substream->number,				    (unsigned long) substream->bytes);			if (substream->opened) {				runtime = substream->runtime;				snd_iprintf(buffer,				    "  Mode         : %s\n"				    "  Buffer size  : %lu\n"				    "  Avail        : %lu\n",				    runtime->oss ? "OSS compatible" : "native",				    (unsigned long) runtime->buffer_size,				    (unsigned long) runtime->avail);			}		}	}	if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT) {		list_for_each_entry(substream,				    &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams,				    list) {			snd_iprintf(buffer,				    "Input %d\n"				    "  Rx bytes     : %lu\n",				    substream->number,				    (unsigned long) substream->bytes);			if (substream->opened) {				runtime = substream->runtime;				snd_iprintf(buffer,					    "  Buffer size  : %lu\n"					    "  Avail        : %lu\n"					    "  Overruns     : %lu\n",					    (unsigned long) runtime->buffer_size,					    (unsigned long) runtime->avail,					    (unsigned long) runtime->xruns);			}		}	}	mutex_unlock(&rmidi->open_mutex);}/* *  Register functions */static const struct file_operations snd_rawmidi_f_ops ={	.owner =	THIS_MODULE,	.read =		snd_rawmidi_read,	.write =	snd_rawmidi_write,	.open =		snd_rawmidi_open,	.release =	snd_rawmidi_release,	.poll =		snd_rawmidi_poll,	.unlocked_ioctl =	snd_rawmidi_ioctl,	.compat_ioctl =	snd_rawmidi_ioctl_compat,};static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,					struct snd_rawmidi_str *stream,					int direction,					int count){	struct snd_rawmidi_substream *substream;	int idx;	for (idx = 0; idx < count; idx++) {		substream = kzalloc(sizeof(*substream), GFP_KERNEL);		if (substream == NULL) {			snd_printk(KERN_ERR "rawmidi: cannot allocate substream\n");			return -ENOMEM;		}		substream->stream = direction;		substream->number = idx;		substream->rmidi = rmidi;		substream->pstr = stream;		list_add_tail(&substream->list, &stream->substreams);		stream->substream_count++;	}	return 0;}/** * snd_rawmidi_new - create a rawmidi instance * @card: the card instance * @id: the id string * @device: the device index * @output_count: the number of output streams * @input_count: the number of input streams * @rrawmidi: the pointer to store the new rawmidi instance * * Creates a new rawmidi instance. * Use snd_rawmidi_set_ops() to set the operators to the new instance. * * Returns zero if successful, or a negative error code on failure. */int snd_rawmidi_new(struct snd_card *card, char *id, int device,		    int output_count, int input_count,		    struct snd_rawmidi ** rrawmidi){	struct snd_rawmidi *rmidi;	int err;	static struct snd_device_ops ops = {		.dev_free = snd_rawmidi_dev_free,		.dev_register = snd_rawmidi_dev_register,		.dev_disconnect = snd_rawmidi_dev_disconnect,	};	snd_assert(rrawmidi != NULL, return -EINVAL);	*rrawmidi = NULL;	snd_assert(card != NULL, return -ENXIO);	rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL);	if (rmidi == NULL) {		snd_printk(KERN_ERR "rawmidi: cannot allocate\n");		return -ENOMEM;	}	rmidi->card = card;	rmidi->device = device;	mutex_init(&rmidi->open_mutex);	init_waitqueue_head(&rmidi->open_wait);	INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams);	INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams);	if (id != NULL)		strlcpy(rmidi->id, id, sizeof(rmidi->id));	if ((err = snd_rawmidi_alloc_substreams(rmidi,						&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],						SNDRV_RAWMIDI_STREAM_INPUT,						input_count)) < 0) {		snd_rawmidi_free(rmidi);		return err;	}	if ((err = snd_rawmidi_alloc_substreams(rmidi,						&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT],						SNDRV_RAWMIDI_STREAM_OUTPUT,						output_count)) < 0) {		snd_rawmidi_free(rmidi);		return err;	}	if ((err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops)) < 0) {		snd_rawmidi_free(rmidi);		return err;	}	*rrawmidi = rmidi;	return 0;}static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream){	struct snd_rawmidi_substream *substream;	while (!list_empty(&stream->substreams)) {		substream = list_entry(stream->substreams.next, struct snd_rawmidi_substream, list);		list_del(&substream->list);		kfree(substream);	}}static int snd_rawmidi_free(struct snd_rawmidi *rmidi){	snd_assert(rmidi != NULL, return -ENXIO);		snd_info_free_entry(rmidi->proc_entry);	rmidi->proc_entry = NULL;	mutex_lock(&register_mutex);	if (rmidi->ops && rmidi->ops->dev_unregister)		rmidi->ops->dev_unregister(rmidi);	mutex_unlock(&register_mutex);	snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);	snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);	if (rmidi->private_free)		rmidi->private_free(rmidi);	kfree(rmidi);	return 0;}static int snd_rawmidi_dev_free(struct snd_device *device){	struct snd_rawmidi *rmidi = device->device_data;	return snd_rawmidi_free(rmidi);}#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device){	struct snd_rawmidi *rmidi = device->private_data;	rmidi->seq_dev = NULL;}#endifstatic int snd_rawmidi_dev_register(struct snd_device *device){	int err;	struct snd_info_entry *entry;	char name[16];	struct snd_rawmidi *rmidi = device->device_data;	if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)		return -ENOMEM;	mutex_lock(&register_mutex);	if (snd_rawmidi_search(rmidi->card, rmidi->device)) {		mutex_unlock(&register_mutex);		return -EBUSY;	}	list_add_tail(&rmidi->list, &snd_rawmidi_devices);	sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device);	if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,				       rmidi->card, rmidi->device,				       &snd_rawmidi_f_ops, rmidi, name)) < 0) {		snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device);		list_del(&rmidi->list);		mutex_unlock(&register_mutex);		return err;	}	if (rmidi->ops && rmidi->ops->dev_register &&	    (err = rmidi->ops->dev_register(rmidi)) < 0) {		snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);		list_del(&rmidi->list);		mutex_unlock(&register_mutex);		return err;	}#ifdef CONFIG_SND_OSSEMUL	rmidi->ossreg = 0;	if ((int)rmidi->device == midi_map[rmidi->card->number]) {		if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,					    rmidi->card, 0, &snd_rawmidi_f_ops,					    rmidi, name) < 0) {			snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);		} else {			rmidi->ossreg++;#ifdef SNDRV_OSS_INFO_DEV_MIDI			snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number, rmidi->name);#endif		}	}	if ((int)rmidi->device == amidi_map[rmidi->card->number]) {		if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,					    rmidi->card, 1, &snd_rawmidi_f_ops,					    rmidi, name) < 0) {			snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1);		} else {			rmidi->ossreg++;		}	}#endif /* CONFIG_SND_OSSEMUL */	mutex_unlock(&register_mutex);	sprintf(name, "midi%d", rmidi->device);	entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root);	if (entry) {		entry->private_data = rmidi;		entry->c.text.read = snd_rawmidi_proc_info_read;		if (snd_info_register(entry) < 0) {			snd_info_free_entry(entry);			entry = NULL;		}	}	rmidi->proc_entry = entry;#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))	if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */		if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) {			rmidi->seq_dev->private_data = rmidi;			rmidi->seq_dev->private_free = snd_rawmidi_dev_seq_free;			sprintf(rmidi->seq_dev->name, "MIDI %d-%d", rmidi->card->number, rmidi->device);			snd_device_register(rmidi->card, rmidi->seq_dev);		}	}#endif	return 0;}static int snd_rawmidi_dev_disconnect(struct snd_device *device){	struct snd_rawmidi *rmidi = device->device_data;	mutex_lock(&register_mutex);	list_del_init(&rmidi->list);#ifdef CONFIG_SND_OSSEMUL	if (rmidi->ossreg) {		if ((int)rmidi->device == midi_map[rmidi->card->number]) {			snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 0);#ifdef SNDRV_OSS_INFO_DEV_MIDI			snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number);#endif		}		if ((int)rmidi->device == amidi_map[rmidi->card->number])			snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 1);		rmidi->ossreg = 0;	}#endif /* CONFIG_SND_OSSEMUL */	snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);	mutex_unlock(&register_mutex);	return 0;}/** * snd_rawmidi_set_ops - set the rawmidi operators * @rmidi: the rawmidi instance * @stream: the stream direction, SNDRV_RAWMIDI_STREAM_XXX * @ops: the operator table * * Sets the rawmidi operators for the given stream direction. */void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,			 struct snd_rawmidi_ops *ops){	struct snd_rawmidi_substream *substream;		list_for_each_entry(substream, &rmidi->streams[stream].substreams, list)		substream->ops = ops;}/* *  ENTRY functions */static int __init alsa_rawmidi_init(void){	snd_ctl_register_ioctl(snd_rawmidi_control_ioctl);	snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl);#ifdef CONFIG_SND_OSSEMUL	{ int i;	/* check device map table */	for (i = 0; i < SNDRV_CARDS; i++) {		if (midi_map[i] < 0 || midi_map[i] >= SNDRV_RAWMIDI_DEVICES) {			snd_printk(KERN_ERR "invalid midi_map[%d] = %d\n", i, midi_map[i]);			midi_map[i] = 0;		}		if (amidi_map[i] < 0 || amidi_map[i] >= SNDRV_RAWMIDI_DEVICES) {			snd_printk(KERN_ERR "invalid amidi_map[%d] = %d\n", i, amidi_map[i]);			amidi_map[i] = 1;		}	}	}#endif /* CONFIG_SND_OSSEMUL */	return 0;}static void __exit alsa_rawmidi_exit(void){	snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl);	snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl);}module_init(alsa_rawmidi_init)module_exit(alsa_rawmidi_exit)EXPORT_SYMBOL(snd_rawmidi_output_params);EXPORT_SYMBOL(snd_rawmidi_input_params);EXPORT_SYMBOL(snd_rawmidi_drop_output);EXPORT_SYMBOL(snd_rawmidi_drain_output);EXPORT_SYMBOL(snd_rawmidi_drain_input);EXPORT_SYMBOL(snd_rawmidi_receive);EXPORT_SYMBOL(snd_rawmidi_transmit_empty);EXPORT_SYMBOL(snd_rawmidi_transmit_peek);EXPORT_SYMBOL(snd_rawmidi_transmit_ack);EXPORT_SYMBOL(snd_rawmidi_transmit);EXPORT_SYMBOL(snd_rawmidi_new);EXPORT_SYMBOL(snd_rawmidi_set_ops);EXPORT_SYMBOL(snd_rawmidi_info_select);EXPORT_SYMBOL(snd_rawmidi_kernel_open);EXPORT_SYMBOL(snd_rawmidi_kernel_release);EXPORT_SYMBOL(snd_rawmidi_kernel_read);EXPORT_SYMBOL(snd_rawmidi_kernel_write);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -