PageRenderTime 33ms CodeModel.GetById 8ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/um/drivers/hostaudio_kern.c

https://bitbucket.org/evzijst/gittest
C | 352 lines | 260 code | 74 blank | 18 comment | 22 complexity | dcd1e41605d74530d8f2d7a744100b8f MD5 | raw file
  1/* 
  2 * Copyright (C) 2002 Steve Schmidtke 
  3 * Licensed under the GPL
  4 */
  5
  6#include "linux/config.h"
  7#include "linux/module.h"
  8#include "linux/init.h"
  9#include "linux/slab.h"
 10#include "linux/fs.h"
 11#include "linux/sound.h"
 12#include "linux/soundcard.h"
 13#include "asm/uaccess.h"
 14#include "kern_util.h"
 15#include "init.h"
 16#include "os.h"
 17
 18struct hostaudio_state {
 19  int fd;
 20};
 21
 22struct hostmixer_state {
 23  int fd;
 24};
 25
 26#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
 27#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
 28
 29/* Only changed from linux_main at boot time */
 30char *dsp = HOSTAUDIO_DEV_DSP;
 31char *mixer = HOSTAUDIO_DEV_MIXER;
 32
 33#define DSP_HELP \
 34"    This is used to specify the host dsp device to the hostaudio driver.\n" \
 35"    The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
 36
 37#define MIXER_HELP \
 38"    This is used to specify the host mixer device to the hostaudio driver.\n"\
 39"    The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
 40
 41#ifndef MODULE
 42static int set_dsp(char *name, int *add)
 43{
 44	dsp = name;
 45	return(0);
 46}
 47
 48__uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
 49
 50static int set_mixer(char *name, int *add)
 51{
 52	mixer = name;
 53	return(0);
 54}
 55
 56__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
 57
 58#else /*MODULE*/
 59
 60MODULE_PARM(dsp, "s");
 61MODULE_PARM_DESC(dsp, DSP_HELP);
 62
 63MODULE_PARM(mixer, "s");
 64MODULE_PARM_DESC(mixer, MIXER_HELP);
 65
 66#endif
 67
 68/* /dev/dsp file operations */
 69
 70static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count, 
 71			      loff_t *ppos)
 72{
 73        struct hostaudio_state *state = file->private_data;
 74	void *kbuf;
 75	int err;
 76
 77#ifdef DEBUG
 78        printk("hostaudio: read called, count = %d\n", count);
 79#endif
 80
 81	kbuf = kmalloc(count, GFP_KERNEL);
 82	if(kbuf == NULL)
 83		return(-ENOMEM);
 84
 85	err = os_read_file(state->fd, kbuf, count);
 86	if(err < 0)
 87		goto out;
 88
 89	if(copy_to_user(buffer, kbuf, err))
 90		err = -EFAULT;
 91
 92 out:
 93	kfree(kbuf);
 94	return(err);
 95}
 96
 97static ssize_t hostaudio_write(struct file *file, const char *buffer, 
 98			       size_t count, loff_t *ppos)
 99{
100        struct hostaudio_state *state = file->private_data;
101	void *kbuf;
102	int err;
103
104#ifdef DEBUG
105        printk("hostaudio: write called, count = %d\n", count);
106#endif
107
108	kbuf = kmalloc(count, GFP_KERNEL);
109	if(kbuf == NULL)
110		return(-ENOMEM);
111
112	err = -EFAULT;
113	if(copy_from_user(kbuf, buffer, count))
114		goto out;
115
116	err = os_write_file(state->fd, kbuf, count);
117	if(err < 0)
118		goto out;
119	*ppos += err;
120
121 out:
122	kfree(kbuf);
123	return(err);
124}
125
126static unsigned int hostaudio_poll(struct file *file, 
127				   struct poll_table_struct *wait)
128{
129        unsigned int mask = 0;
130
131#ifdef DEBUG
132        printk("hostaudio: poll called (unimplemented)\n");
133#endif
134
135        return(mask);
136}
137
138static int hostaudio_ioctl(struct inode *inode, struct file *file, 
139			   unsigned int cmd, unsigned long arg)
140{
141        struct hostaudio_state *state = file->private_data;
142	unsigned long data = 0;
143	int err;
144
145#ifdef DEBUG
146        printk("hostaudio: ioctl called, cmd = %u\n", cmd);
147#endif
148	switch(cmd){
149	case SNDCTL_DSP_SPEED:
150	case SNDCTL_DSP_STEREO:
151	case SNDCTL_DSP_GETBLKSIZE:
152	case SNDCTL_DSP_CHANNELS:
153	case SNDCTL_DSP_SUBDIVIDE:
154	case SNDCTL_DSP_SETFRAGMENT:
155		if(get_user(data, (int *) arg))
156			return(-EFAULT);
157		break;
158	default:
159		break;
160	}
161
162	err = os_ioctl_generic(state->fd, cmd, (unsigned long) &data);
163
164	switch(cmd){
165	case SNDCTL_DSP_SPEED:
166	case SNDCTL_DSP_STEREO:
167	case SNDCTL_DSP_GETBLKSIZE:
168	case SNDCTL_DSP_CHANNELS:
169	case SNDCTL_DSP_SUBDIVIDE:
170	case SNDCTL_DSP_SETFRAGMENT:
171		if(put_user(data, (int *) arg))
172			return(-EFAULT);
173		break;
174	default:
175		break;
176	}
177
178	return(err);
179}
180
181static int hostaudio_open(struct inode *inode, struct file *file)
182{
183        struct hostaudio_state *state;
184        int r = 0, w = 0;
185        int ret;
186
187#ifdef DEBUG
188        printk("hostaudio: open called (host: %s)\n", dsp);
189#endif
190
191        state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
192        if(state == NULL)
193		return(-ENOMEM);
194
195        if(file->f_mode & FMODE_READ) r = 1;
196        if(file->f_mode & FMODE_WRITE) w = 1;
197
198	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
199        if(ret < 0){
200		kfree(state);
201		return(ret);
202        }
203
204	state->fd = ret;
205        file->private_data = state;
206        return(0);
207}
208
209static int hostaudio_release(struct inode *inode, struct file *file)
210{
211        struct hostaudio_state *state = file->private_data;
212
213#ifdef DEBUG
214        printk("hostaudio: release called\n");
215#endif
216
217		os_close_file(state->fd);
218        kfree(state);
219
220	return(0);
221}
222
223/* /dev/mixer file operations */
224
225static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, 
226				  unsigned int cmd, unsigned long arg)
227{
228        struct hostmixer_state *state = file->private_data;
229
230#ifdef DEBUG
231        printk("hostmixer: ioctl called\n");
232#endif
233
234	return(os_ioctl_generic(state->fd, cmd, arg));
235}
236
237static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
238{
239        struct hostmixer_state *state;
240        int r = 0, w = 0;
241        int ret;
242
243#ifdef DEBUG
244        printk("hostmixer: open called (host: %s)\n", mixer);
245#endif
246
247        state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL);
248        if(state == NULL) return(-ENOMEM);
249
250        if(file->f_mode & FMODE_READ) r = 1;
251        if(file->f_mode & FMODE_WRITE) w = 1;
252
253	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
254        
255        if(ret < 0){
256		printk("hostaudio_open_mixdev failed to open '%s', err = %d\n",
257		       dsp, -ret);
258		kfree(state);
259		return(ret);
260        }
261
262        file->private_data = state;
263        return(0);
264}
265
266static int hostmixer_release(struct inode *inode, struct file *file)
267{
268        struct hostmixer_state *state = file->private_data;
269
270#ifdef DEBUG
271        printk("hostmixer: release called\n");
272#endif
273
274		os_close_file(state->fd);
275        kfree(state);
276
277	return(0);
278}
279
280
281/* kernel module operations */
282
283static struct file_operations hostaudio_fops = {
284        .owner          = THIS_MODULE,
285        .llseek         = no_llseek,
286        .read           = hostaudio_read,
287        .write          = hostaudio_write,
288        .poll           = hostaudio_poll,
289        .ioctl          = hostaudio_ioctl,
290        .mmap           = NULL,
291        .open           = hostaudio_open,
292        .release        = hostaudio_release,
293};
294
295static struct file_operations hostmixer_fops = {
296        .owner          = THIS_MODULE,
297        .llseek         = no_llseek,
298        .ioctl          = hostmixer_ioctl_mixdev,
299        .open           = hostmixer_open_mixdev,
300        .release        = hostmixer_release,
301};
302
303struct {
304	int dev_audio;
305	int dev_mixer;
306} module_data;
307
308MODULE_AUTHOR("Steve Schmidtke");
309MODULE_DESCRIPTION("UML Audio Relay");
310MODULE_LICENSE("GPL");
311
312static int __init hostaudio_init_module(void)
313{
314        printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
315	       dsp, mixer);
316
317	module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
318        if(module_data.dev_audio < 0){
319                printk(KERN_ERR "hostaudio: couldn't register DSP device!\n");
320                return -ENODEV;
321        }
322
323	module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1);
324        if(module_data.dev_mixer < 0){
325                printk(KERN_ERR "hostmixer: couldn't register mixer "
326		       "device!\n");
327                unregister_sound_dsp(module_data.dev_audio);
328                return -ENODEV;
329        }
330
331        return 0;
332}
333
334static void __exit hostaudio_cleanup_module (void)
335{
336       unregister_sound_mixer(module_data.dev_mixer);
337       unregister_sound_dsp(module_data.dev_audio);
338}
339
340module_init(hostaudio_init_module);
341module_exit(hostaudio_cleanup_module);
342
343/*
344 * Overrides for Emacs so that we follow Linus's tabbing style.
345 * Emacs will notice this stuff at the end of the file and automatically
346 * adjust the settings for this buffer only.  This must remain at the end
347 * of the file.
348 * ---------------------------------------------------------------------------
349 * Local variables:
350 * c-file-style: "linux"
351 * End:
352 */