diff options
Diffstat (limited to 'sound/core/rawmidi.c')
| -rw-r--r-- | sound/core/rawmidi.c | 177 | 
1 files changed, 102 insertions, 75 deletions
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index cbbed0db9e5..6fc71a4c8a5 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -27,7 +27,7 @@  #include <linux/time.h>  #include <linux/wait.h>  #include <linux/mutex.h> -#include <linux/moduleparam.h> +#include <linux/module.h>  #include <linux/delay.h>  #include <sound/rawmidi.h>  #include <sound/info.h> @@ -56,6 +56,13 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device);  static LIST_HEAD(snd_rawmidi_devices);  static DEFINE_MUTEX(register_mutex); +#define rmidi_err(rmidi, fmt, args...) \ +	dev_err((rmidi)->card->dev, fmt, ##args) +#define rmidi_warn(rmidi, fmt, args...) \ +	dev_warn((rmidi)->card->dev, fmt, ##args) +#define rmidi_dbg(rmidi, fmt, args...) \ +	dev_dbg((rmidi)->card->dev, fmt, ##args) +  static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)  {  	struct snd_rawmidi *rawmidi; @@ -92,16 +99,12 @@ static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substre  	       (!substream->append || runtime->avail >= count);  } -static void snd_rawmidi_input_event_tasklet(unsigned long data) -{ -	struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data; -	substream->runtime->event(substream); -} - -static void snd_rawmidi_output_trigger_tasklet(unsigned long data) +static void snd_rawmidi_input_event_work(struct work_struct *work)  { -	struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data; -	substream->ops->trigger(substream, 1); +	struct snd_rawmidi_runtime *runtime = +		container_of(work, struct snd_rawmidi_runtime, event_work); +	if (runtime->event) +		runtime->event(runtime->substream);  }  static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) @@ -110,16 +113,10 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)  	if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL)  		return -ENOMEM; +	runtime->substream = substream;  	spin_lock_init(&runtime->lock);  	init_waitqueue_head(&runtime->sleep); -	if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT) -		tasklet_init(&runtime->tasklet, -			     snd_rawmidi_input_event_tasklet, -			     (unsigned long)substream); -	else -		tasklet_init(&runtime->tasklet, -			     snd_rawmidi_output_trigger_tasklet, -			     (unsigned long)substream); +	INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work);  	runtime->event = NULL;  	runtime->buffer_size = PAGE_SIZE;  	runtime->avail_min = 1; @@ -150,12 +147,7 @@ static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *subs  {  	if (!substream->opened)  		return; -	if (up) { -		tasklet_schedule(&substream->runtime->tasklet); -	} else { -		tasklet_kill(&substream->runtime->tasklet); -		substream->ops->trigger(substream, 0); -	} +	substream->ops->trigger(substream, up);  }  static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) @@ -163,8 +155,8 @@ static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, i  	if (!substream->opened)  		return;  	substream->ops->trigger(substream, up); -	if (!up && substream->runtime->event) -		tasklet_kill(&substream->runtime->tasklet); +	if (!up) +		cancel_work_sync(&substream->runtime->event_work);  }  int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream) @@ -180,6 +172,7 @@ int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream)  	spin_unlock_irqrestore(&runtime->lock, flags);  	return 0;  } +EXPORT_SYMBOL(snd_rawmidi_drop_output);  int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream)  { @@ -195,7 +188,9 @@ int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream)  	if (signal_pending(current))  		err = -ERESTARTSYS;  	if (runtime->avail < runtime->buffer_size && !timeout) { -		snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size); +		rmidi_warn(substream->rmidi, +			   "rawmidi drain error (avail = %li, buffer_size = %li)\n", +			   (long)runtime->avail, (long)runtime->buffer_size);  		err = -EIO;  	}  	runtime->drain = 0; @@ -209,6 +204,7 @@ int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream)  	}  	return err;  } +EXPORT_SYMBOL(snd_rawmidi_drain_output);  int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)  { @@ -223,6 +219,7 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)  	spin_unlock_irqrestore(&runtime->lock, flags);  	return 0;  } +EXPORT_SYMBOL(snd_rawmidi_drain_input);  /* look for an available substream for the given stream direction;   * if a specific subdevice is given, try to assign it @@ -360,6 +357,7 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,  		module_put(rmidi->card->module);  	return err;  } +EXPORT_SYMBOL(snd_rawmidi_kernel_open);  static int snd_rawmidi_open(struct inode *inode, struct file *file)  { @@ -394,8 +392,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  	if (rmidi == NULL)  		return -ENODEV; -	if (!try_module_get(rmidi->card->module)) +	if (!try_module_get(rmidi->card->module)) { +		snd_card_unref(rmidi->card);  		return -ENXIO; +	}  	mutex_lock(&rmidi->open_mutex);  	card = rmidi->card; @@ -437,6 +437,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  		mutex_unlock(&rmidi->open_mutex);  		schedule();  		mutex_lock(&rmidi->open_mutex); +		if (rmidi->card->shutdown) { +			err = -ENODEV; +			break; +		}  		if (signal_pending(current)) {  			err = -ERESTARTSYS;  			break; @@ -455,6 +459,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  #endif  	file->private_data = rawmidi_file;  	mutex_unlock(&rmidi->open_mutex); +	snd_card_unref(rmidi->card);  	return 0;   __error: @@ -462,6 +467,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)   __error_card:  	mutex_unlock(&rmidi->open_mutex);  	module_put(rmidi->card->module); +	snd_card_unref(rmidi->card);  	return err;  } @@ -530,6 +536,7 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile)  	module_put(rmidi->card->module);  	return 0;  } +EXPORT_SYMBOL(snd_rawmidi_kernel_release);  static int snd_rawmidi_release(struct inode *inode, struct file *file)  { @@ -606,6 +613,7 @@ int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info  	}  	return -ENXIO;  } +EXPORT_SYMBOL(snd_rawmidi_info_select);  static int snd_rawmidi_info_select_user(struct snd_card *card,  					struct snd_rawmidi_info __user *_info) @@ -641,10 +649,10 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,  		return -EINVAL;  	}  	if (params->buffer_size != runtime->buffer_size) { -		newbuf = kmalloc(params->buffer_size, GFP_KERNEL); +		newbuf = krealloc(runtime->buffer, params->buffer_size, +				  GFP_KERNEL);  		if (!newbuf)  			return -ENOMEM; -		kfree(runtime->buffer);  		runtime->buffer = newbuf;  		runtime->buffer_size = params->buffer_size;  		runtime->avail = runtime->buffer_size; @@ -653,6 +661,7 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,  	substream->active_sensing = !params->no_active_sensing;  	return 0;  } +EXPORT_SYMBOL(snd_rawmidi_output_params);  int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,  			     struct snd_rawmidi_params * params) @@ -668,16 +677,17 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,  		return -EINVAL;  	}  	if (params->buffer_size != runtime->buffer_size) { -		newbuf = kmalloc(params->buffer_size, GFP_KERNEL); +		newbuf = krealloc(runtime->buffer, params->buffer_size, +				  GFP_KERNEL);  		if (!newbuf)  			return -ENOMEM; -		kfree(runtime->buffer);  		runtime->buffer = newbuf;  		runtime->buffer_size = params->buffer_size;  	}  	runtime->avail_min = params->avail_min;  	return 0;  } +EXPORT_SYMBOL(snd_rawmidi_input_params);  static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,  				     struct snd_rawmidi_status * status) @@ -809,10 +819,9 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long  			return -EINVAL;  		}  	} -#ifdef CONFIG_SND_DEBUG  	default: -		snd_printk(KERN_WARNING "rawmidi: unknown command = 0x%x\n", cmd); -#endif +		rmidi_dbg(rfile->rmidi, +			  "rawmidi: unknown command = 0x%x\n", cmd);  	}  	return -ENOTTY;  } @@ -870,7 +879,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,   *   * Reads the data from the internal buffer.   * - * Returns the size of read data, or a negative error code on failure. + * Return: The size of read data, or a negative error code on failure.   */  int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,  			const unsigned char *buffer, int count) @@ -882,7 +891,8 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,  	if (!substream->opened)  		return -EBADFD;  	if (runtime->buffer == NULL) { -		snd_printd("snd_rawmidi_receive: input is not active!!!\n"); +		rmidi_dbg(substream->rmidi, +			  "snd_rawmidi_receive: input is not active!!!\n");  		return -EINVAL;  	}  	spin_lock_irqsave(&runtime->lock, flags); @@ -926,13 +936,14 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,  	}  	if (result > 0) {  		if (runtime->event) -			tasklet_schedule(&runtime->tasklet); +			schedule_work(&runtime->event_work);  		else if (snd_rawmidi_ready(substream))  			wake_up(&runtime->sleep);  	}  	spin_unlock_irqrestore(&runtime->lock, flags);  	return result;  } +EXPORT_SYMBOL(snd_rawmidi_receive);  static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,  				     unsigned char __user *userbuf, @@ -975,6 +986,7 @@ long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,  	snd_rawmidi_input_trigger(substream, 1);  	return snd_rawmidi_kernel_read1(substream, NULL/*userbuf*/, buf, count);  } +EXPORT_SYMBOL(snd_rawmidi_kernel_read);  static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t count,  				loff_t *offset) @@ -1006,6 +1018,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun  			spin_unlock_irq(&runtime->lock);  			schedule();  			remove_wait_queue(&runtime->sleep, &wait); +			if (rfile->rmidi->card->shutdown) +				return -ENODEV;  			if (signal_pending(current))  				return result > 0 ? result : -ERESTARTSYS;  			if (!runtime->avail) @@ -1029,8 +1043,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun  /**   * snd_rawmidi_transmit_empty - check whether the output buffer is empty   * @substream: the rawmidi substream - *  - * Returns 1 if the internal output buffer is empty, 0 if not. + * + * Return: 1 if the internal output buffer is empty, 0 if not.   */  int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)  { @@ -1039,7 +1053,8 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)  	unsigned long flags;  	if (runtime->buffer == NULL) { -		snd_printd("snd_rawmidi_transmit_empty: output is not active!!!\n"); +		rmidi_dbg(substream->rmidi, +			  "snd_rawmidi_transmit_empty: output is not active!!!\n");  		return 1;  	}  	spin_lock_irqsave(&runtime->lock, flags); @@ -1047,6 +1062,7 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)  	spin_unlock_irqrestore(&runtime->lock, flags);  	return result;		  } +EXPORT_SYMBOL(snd_rawmidi_transmit_empty);  /**   * snd_rawmidi_transmit_peek - copy data from the internal buffer @@ -1060,7 +1076,7 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)   * and call snd_rawmidi_transmit_ack() after the transmission is   * finished.   * - * Returns the size of copied data, or a negative error code on failure. + * Return: The size of copied data, or a negative error code on failure.   */  int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,  			      unsigned char *buffer, int count) @@ -1070,7 +1086,8 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,  	struct snd_rawmidi_runtime *runtime = substream->runtime;  	if (runtime->buffer == NULL) { -		snd_printd("snd_rawmidi_transmit_peek: output is not active!!!\n"); +		rmidi_dbg(substream->rmidi, +			  "snd_rawmidi_transmit_peek: output is not active!!!\n");  		return -EINVAL;  	}  	result = 0; @@ -1102,17 +1119,18 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,  	spin_unlock_irqrestore(&runtime->lock, flags);  	return result;  } +EXPORT_SYMBOL(snd_rawmidi_transmit_peek);  /**   * snd_rawmidi_transmit_ack - acknowledge the transmission   * @substream: the rawmidi substream - * @count: the tranferred count + * @count: the transferred count   *   * Advances the hardware pointer for the internal output buffer with   * the given size and updates the condition.   * Call after the transmission is finished.   * - * Returns the advanced size if successful, or a negative error code on failure. + * Return: The advanced size if successful, or a negative error code on failure.   */  int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)  { @@ -1120,7 +1138,8 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)  	struct snd_rawmidi_runtime *runtime = substream->runtime;  	if (runtime->buffer == NULL) { -		snd_printd("snd_rawmidi_transmit_ack: output is not active!!!\n"); +		rmidi_dbg(substream->rmidi, +			  "snd_rawmidi_transmit_ack: output is not active!!!\n");  		return -EINVAL;  	}  	spin_lock_irqsave(&runtime->lock, flags); @@ -1136,6 +1155,7 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)  	spin_unlock_irqrestore(&runtime->lock, flags);  	return count;  } +EXPORT_SYMBOL(snd_rawmidi_transmit_ack);  /**   * snd_rawmidi_transmit - copy from the buffer to the device @@ -1145,7 +1165,7 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)   *    * Copies data from the buffer to the device and advances the pointer.   * - * Returns the copied size if successful, or a negative error code on failure. + * Return: The copied size if successful, or a negative error code on failure.   */  int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,  			 unsigned char *buffer, int count) @@ -1157,6 +1177,7 @@ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,  		return count;  	return snd_rawmidi_transmit_ack(substream, count);  } +EXPORT_SYMBOL(snd_rawmidi_transmit);  static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,  				      const unsigned char __user *userbuf, @@ -1218,6 +1239,7 @@ long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream,  {  	return snd_rawmidi_kernel_write1(substream, NULL, buf, count);  } +EXPORT_SYMBOL(snd_rawmidi_kernel_write);  static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,  				 size_t count, loff_t *offset) @@ -1249,6 +1271,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,  			spin_unlock_irq(&runtime->lock);  			timeout = schedule_timeout(30 * HZ);  			remove_wait_queue(&runtime->sleep, &wait); +			if (rfile->rmidi->card->shutdown) +				return -ENODEV;  			if (signal_pending(current))  				return result > 0 ? result : -ERESTARTSYS;  			if (!runtime->avail && !timeout) @@ -1416,7 +1440,7 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,  	for (idx = 0; idx < count; idx++) {  		substream = kzalloc(sizeof(*substream), GFP_KERNEL);  		if (substream == NULL) { -			snd_printk(KERN_ERR "rawmidi: cannot allocate substream\n"); +			rmidi_err(rmidi, "rawmidi: cannot allocate substream\n");  			return -ENOMEM;  		}  		substream->stream = direction; @@ -1441,7 +1465,7 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,   * 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. + * Return: 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, @@ -1461,7 +1485,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,  		*rrawmidi = NULL;  	rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL);  	if (rmidi == NULL) { -		snd_printk(KERN_ERR "rawmidi: cannot allocate\n"); +		dev_err(card->dev, "rawmidi: cannot allocate\n");  		return -ENOMEM;  	}  	rmidi->card = card; @@ -1495,6 +1519,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,  		*rrawmidi = rmidi;  	return 0;  } +EXPORT_SYMBOL(snd_rawmidi_new);  static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream)  { @@ -1560,7 +1585,8 @@ static int snd_rawmidi_dev_register(struct snd_device *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); +		rmidi_err(rmidi, "unable to register rawmidi device %i:%i\n", +			  rmidi->card->number, rmidi->device);  		list_del(&rmidi->list);  		mutex_unlock(®ister_mutex);  		return err; @@ -1577,8 +1603,10 @@ static int snd_rawmidi_dev_register(struct snd_device *device)  	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); +					    rmidi) < 0) { +			rmidi_err(rmidi, +				  "unable to register OSS rawmidi device %i:%i\n", +				  rmidi->card->number, 0);  		} else {  			rmidi->ossreg++;  #ifdef SNDRV_OSS_INFO_DEV_MIDI @@ -1589,8 +1617,10 @@ static int snd_rawmidi_dev_register(struct snd_device *device)  	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); +					    rmidi) < 0) { +			rmidi_err(rmidi, +				  "unable to register OSS rawmidi device %i:%i\n", +				  rmidi->card->number, 1);  		} else {  			rmidi->ossreg++;  		} @@ -1624,9 +1654,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)  static int snd_rawmidi_dev_disconnect(struct snd_device *device)  {  	struct snd_rawmidi *rmidi = device->device_data; +	int dir;  	mutex_lock(®ister_mutex); +	mutex_lock(&rmidi->open_mutex); +	wake_up(&rmidi->open_wait);  	list_del_init(&rmidi->list); +	for (dir = 0; dir < 2; dir++) { +		struct snd_rawmidi_substream *s; +		list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { +			if (s->runtime) +				wake_up(&s->runtime->sleep); +		} +	} +  #ifdef CONFIG_SND_OSSEMUL  	if (rmidi->ossreg) {  		if ((int)rmidi->device == midi_map[rmidi->card->number]) { @@ -1641,6 +1682,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)  	}  #endif /* CONFIG_SND_OSSEMUL */  	snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); +	mutex_unlock(&rmidi->open_mutex);  	mutex_unlock(®ister_mutex);  	return 0;  } @@ -1661,6 +1703,7 @@ void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,  	list_for_each_entry(substream, &rmidi->streams[stream].substreams, list)  		substream->ops = ops;  } +EXPORT_SYMBOL(snd_rawmidi_set_ops);  /*   *  ENTRY functions @@ -1676,11 +1719,13 @@ static int __init alsa_rawmidi_init(void)  	/* 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]); +			pr_err("ALSA: rawmidi: 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]); +			pr_err("ALSA: rawmidi: invalid amidi_map[%d] = %d\n", +			       i, amidi_map[i]);  			amidi_map[i] = 1;  		}  	} @@ -1697,21 +1742,3 @@ static void __exit alsa_rawmidi_exit(void)  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);  | 
