Blame view

arch/um/drivers/hostaudio_kern.c 7.62 KB
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
1
2
  /*
   * Copyright (C) 2002 Steve Schmidtke
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
   * Licensed under the GPL
   */
37185b332   Al Viro   um: get rid of po...
5
6
7
8
9
10
11
12
13
  #include <linux/fs.h>
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/sound.h>
  #include <linux/soundcard.h>
  #include <linux/mutex.h>
  #include <asm/uaccess.h>
  #include <init.h>
  #include <os.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
  
  struct hostaudio_state {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
16
  	int fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
  };
  
  struct hostmixer_state {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
20
  	int fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
  };
  
  #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
  #define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
25
26
  /*
   * Changed either at boot time or module load time.  At boot, this is
b612e475e   Jeff Dike   [PATCH] uml: audi...
27
28
29
30
31
   * single-threaded; at module load, multiple modules would each have
   * their own copy of these variables.
   */
  static char *dsp = HOSTAUDIO_DEV_DSP;
  static char *mixer = HOSTAUDIO_DEV_MIXER;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  
  #define DSP_HELP \
  "    This is used to specify the host dsp device to the hostaudio driver.
  " \
  "    The default is \"" HOSTAUDIO_DEV_DSP "\".
  
  "
  
  #define MIXER_HELP \
  "    This is used to specify the host mixer device to the hostaudio driver.
  "\
  "    The default is \"" HOSTAUDIO_DEV_MIXER "\".
  
  "
e3c6cf618   FUJITA Tomonori   uml: fix build
46
47
48
49
  module_param(dsp, charp, 0644);
  MODULE_PARM_DESC(dsp, DSP_HELP);
  module_param(mixer, charp, 0644);
  MODULE_PARM_DESC(mixer, MIXER_HELP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
  #ifndef MODULE
  static int set_dsp(char *name, int *add)
  {
  	dsp = name;
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
54
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
58
59
60
61
62
  }
  
  __uml_setup("dsp=", set_dsp, "dsp=<dsp device>
  " DSP_HELP);
  
  static int set_mixer(char *name, int *add)
  {
  	mixer = name;
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
63
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
  }
  
  __uml_setup("mixer=", set_mixer, "mixer=<mixer device>
  " MIXER_HELP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  #endif
9a181c586   Arnd Bergmann   uml: kill big ker...
69
  static DEFINE_MUTEX(hostaudio_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  /* /dev/dsp file operations */
4d338e1ac   Al Viro   [PATCH] uml: spar...
71
72
  static ssize_t hostaudio_read(struct file *file, char __user *buffer,
  			      size_t count, loff_t *ppos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
74
  	struct hostaudio_state *state = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
  	void *kbuf;
  	int err;
  
  #ifdef DEBUG
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
79
80
  	printk(KERN_DEBUG "hostaudio: read called, count = %d
  ", count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
  #endif
  
  	kbuf = kmalloc(count, GFP_KERNEL);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
84
85
  	if (kbuf == NULL)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86

a6ea4ccee   Jeff Dike   uml: rename os_{r...
87
  	err = os_read_file(state->fd, kbuf, count);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
88
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  		goto out;
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
90
  	if (copy_to_user(buffer, kbuf, err))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  		err = -EFAULT;
d471c0fca   Jeff Dike   [PATCH] uml: audi...
92
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
  	kfree(kbuf);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
94
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  }
4d338e1ac   Al Viro   [PATCH] uml: spar...
96
  static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
  			       size_t count, loff_t *ppos)
  {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
99
  	struct hostaudio_state *state = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
  	void *kbuf;
  	int err;
  
  #ifdef DEBUG
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
104
105
  	printk(KERN_DEBUG "hostaudio: write called, count = %d
  ", count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
  #endif
  
  	kbuf = kmalloc(count, GFP_KERNEL);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
109
110
  	if (kbuf == NULL)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
  
  	err = -EFAULT;
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
113
  	if (copy_from_user(kbuf, buffer, count))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  		goto out;
a6ea4ccee   Jeff Dike   uml: rename os_{r...
115
  	err = os_write_file(state->fd, kbuf, count);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
116
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
119
120
121
  		goto out;
  	*ppos += err;
  
   out:
  	kfree(kbuf);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
122
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  }
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
124
  static unsigned int hostaudio_poll(struct file *file,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
  				   struct poll_table_struct *wait)
  {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
127
  	unsigned int mask = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
  
  #ifdef DEBUG
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
130
131
  	printk(KERN_DEBUG "hostaudio: poll called (unimplemented)
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  #endif
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
133
  	return mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  }
d6c89d9ac   John Kacur   uml: Convert to u...
135
  static long hostaudio_ioctl(struct file *file,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
  			   unsigned int cmd, unsigned long arg)
  {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
138
  	struct hostaudio_state *state = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
  	unsigned long data = 0;
  	int err;
  
  #ifdef DEBUG
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
143
144
  	printk(KERN_DEBUG "hostaudio: ioctl called, cmd = %u
  ", cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
147
148
149
150
151
152
  #endif
  	switch(cmd){
  	case SNDCTL_DSP_SPEED:
  	case SNDCTL_DSP_STEREO:
  	case SNDCTL_DSP_GETBLKSIZE:
  	case SNDCTL_DSP_CHANNELS:
  	case SNDCTL_DSP_SUBDIVIDE:
  	case SNDCTL_DSP_SETFRAGMENT:
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
153
  		if (get_user(data, (int __user *) arg))
484f1e2c1   Johann Felix Soden   uml: fix errno re...
154
  			return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  		break;
  	default:
  		break;
  	}
  
  	err = os_ioctl_generic(state->fd, cmd, (unsigned long) &data);
  
  	switch(cmd){
  	case SNDCTL_DSP_SPEED:
  	case SNDCTL_DSP_STEREO:
  	case SNDCTL_DSP_GETBLKSIZE:
  	case SNDCTL_DSP_CHANNELS:
  	case SNDCTL_DSP_SUBDIVIDE:
  	case SNDCTL_DSP_SETFRAGMENT:
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
169
170
  		if (put_user(data, (int __user *) arg))
  			return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
173
174
  		break;
  	default:
  		break;
  	}
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
175
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
  }
  
  static int hostaudio_open(struct inode *inode, struct file *file)
  {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
180
181
182
  	struct hostaudio_state *state;
  	int r = 0, w = 0;
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
  
  #ifdef DEBUG
d6d1b650a   Rusty Russell   param: simple loc...
185
  	kparam_block_sysfs_write(dsp);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
186
187
  	printk(KERN_DEBUG "hostaudio: open called (host: %s)
  ", dsp);
d6d1b650a   Rusty Russell   param: simple loc...
188
  	kparam_unblock_sysfs_write(dsp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  #endif
d471c0fca   Jeff Dike   [PATCH] uml: audi...
190
  	state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
191
192
  	if (state == NULL)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193

cb8fa61c2   Jeff Dike   uml: arch/um/driv...
194
195
196
197
  	if (file->f_mode & FMODE_READ)
  		r = 1;
  	if (file->f_mode & FMODE_WRITE)
  		w = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198

d6d1b650a   Rusty Russell   param: simple loc...
199
  	kparam_block_sysfs_write(dsp);
9a181c586   Arnd Bergmann   uml: kill big ker...
200
  	mutex_lock(&hostaudio_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
9a181c586   Arnd Bergmann   uml: kill big ker...
202
  	mutex_unlock(&hostaudio_mutex);
d6d1b650a   Rusty Russell   param: simple loc...
203
  	kparam_unblock_sysfs_write(dsp);
90dc763fe   Arnd Bergmann   sound: push BKL i...
204

cb8fa61c2   Jeff Dike   uml: arch/um/driv...
205
  	if (ret < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  		kfree(state);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
207
  		return ret;
d471c0fca   Jeff Dike   [PATCH] uml: audi...
208
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
  	state->fd = ret;
d471c0fca   Jeff Dike   [PATCH] uml: audi...
210
  	file->private_data = state;
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
211
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
214
215
  }
  
  static int hostaudio_release(struct inode *inode, struct file *file)
  {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
216
  	struct hostaudio_state *state = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
  
  #ifdef DEBUG
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
219
220
  	printk(KERN_DEBUG "hostaudio: release called
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  #endif
d471c0fca   Jeff Dike   [PATCH] uml: audi...
222
223
  	os_close_file(state->fd);
  	kfree(state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224

cb8fa61c2   Jeff Dike   uml: arch/um/driv...
225
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
228
  }
  
  /* /dev/mixer file operations */
d6c89d9ac   John Kacur   uml: Convert to u...
229
  static long hostmixer_ioctl_mixdev(struct file *file,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
  				  unsigned int cmd, unsigned long arg)
  {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
232
  	struct hostmixer_state *state = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
  
  #ifdef DEBUG
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
235
236
  	printk(KERN_DEBUG "hostmixer: ioctl called
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  #endif
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
238
  	return os_ioctl_generic(state->fd, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
242
  }
  
  static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
  {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
243
244
245
  	struct hostmixer_state *state;
  	int r = 0, w = 0;
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
  
  #ifdef DEBUG
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
248
249
  	printk(KERN_DEBUG "hostmixer: open called (host: %s)
  ", mixer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  #endif
d471c0fca   Jeff Dike   [PATCH] uml: audi...
251
  	state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
252
253
  	if (state == NULL)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254

cb8fa61c2   Jeff Dike   uml: arch/um/driv...
255
256
257
258
  	if (file->f_mode & FMODE_READ)
  		r = 1;
  	if (file->f_mode & FMODE_WRITE)
  		w = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259

d6d1b650a   Rusty Russell   param: simple loc...
260
  	kparam_block_sysfs_write(mixer);
9a181c586   Arnd Bergmann   uml: kill big ker...
261
  	mutex_lock(&hostaudio_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
  	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
9a181c586   Arnd Bergmann   uml: kill big ker...
263
  	mutex_unlock(&hostaudio_mutex);
d6d1b650a   Rusty Russell   param: simple loc...
264
  	kparam_unblock_sysfs_write(mixer);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
265
266
  
  	if (ret < 0) {
d6d1b650a   Rusty Russell   param: simple loc...
267
  		kparam_block_sysfs_write(dsp);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
268
269
270
  		printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', "
  		       "err = %d
  ", dsp, -ret);
d6d1b650a   Rusty Russell   param: simple loc...
271
  		kparam_unblock_sysfs_write(dsp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
  		kfree(state);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
273
  		return ret;
d471c0fca   Jeff Dike   [PATCH] uml: audi...
274
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275

d471c0fca   Jeff Dike   [PATCH] uml: audi...
276
  	file->private_data = state;
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
277
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
280
281
  }
  
  static int hostmixer_release(struct inode *inode, struct file *file)
  {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
282
  	struct hostmixer_state *state = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
  
  #ifdef DEBUG
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
285
286
  	printk(KERN_DEBUG "hostmixer: release called
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  #endif
d471c0fca   Jeff Dike   [PATCH] uml: audi...
288
289
  	os_close_file(state->fd);
  	kfree(state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290

cb8fa61c2   Jeff Dike   uml: arch/um/driv...
291
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  /* kernel module operations */
5e7672ec3   Jeff Dike   [PATCH] uml: cons...
294
  static const struct file_operations hostaudio_fops = {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
295
296
297
298
299
  	.owner          = THIS_MODULE,
  	.llseek         = no_llseek,
  	.read           = hostaudio_read,
  	.write          = hostaudio_write,
  	.poll           = hostaudio_poll,
d6c89d9ac   John Kacur   uml: Convert to u...
300
  	.unlocked_ioctl	= hostaudio_ioctl,
d471c0fca   Jeff Dike   [PATCH] uml: audi...
301
302
303
  	.mmap           = NULL,
  	.open           = hostaudio_open,
  	.release        = hostaudio_release,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
  };
5e7672ec3   Jeff Dike   [PATCH] uml: cons...
305
  static const struct file_operations hostmixer_fops = {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
306
307
  	.owner          = THIS_MODULE,
  	.llseek         = no_llseek,
d6c89d9ac   John Kacur   uml: Convert to u...
308
  	.unlocked_ioctl	= hostmixer_ioctl_mixdev,
d471c0fca   Jeff Dike   [PATCH] uml: audi...
309
310
  	.open           = hostmixer_open_mixdev,
  	.release        = hostmixer_release,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
312
313
314
315
316
317
318
319
320
321
322
323
  };
  
  struct {
  	int dev_audio;
  	int dev_mixer;
  } module_data;
  
  MODULE_AUTHOR("Steve Schmidtke");
  MODULE_DESCRIPTION("UML Audio Relay");
  MODULE_LICENSE("GPL");
  
  static int __init hostaudio_init_module(void)
  {
d6d1b650a   Rusty Russell   param: simple loc...
324
  	__kernel_param_lock();
d471c0fca   Jeff Dike   [PATCH] uml: audi...
325
326
  	printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  	       dsp, mixer);
d6d1b650a   Rusty Russell   param: simple loc...
328
  	__kernel_param_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
  
  	module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
331
  	if (module_data.dev_audio < 0) {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
332
333
334
335
  		printk(KERN_ERR "hostaudio: couldn't register DSP device!
  ");
  		return -ENODEV;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
  
  	module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1);
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
338
  	if (module_data.dev_mixer < 0) {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
339
  		printk(KERN_ERR "hostmixer: couldn't register mixer "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
  		       "device!
  ");
d471c0fca   Jeff Dike   [PATCH] uml: audi...
342
343
344
  		unregister_sound_dsp(module_data.dev_audio);
  		return -ENODEV;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345

d471c0fca   Jeff Dike   [PATCH] uml: audi...
346
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
349
350
  }
  
  static void __exit hostaudio_cleanup_module (void)
  {
d471c0fca   Jeff Dike   [PATCH] uml: audi...
351
352
  	unregister_sound_mixer(module_data.dev_mixer);
  	unregister_sound_dsp(module_data.dev_audio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
355
356
  }
  
  module_init(hostaudio_init_module);
  module_exit(hostaudio_cleanup_module);