diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-28 09:44:56 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-28 09:44:56 -0700 |
commit | e4c5bf8e3dca827a1b3a6fac494eae8c74b7e1e7 (patch) | |
tree | ea51b391f7d74ca695dcb9f5e46eb02688a92ed9 /drivers/staging/speakup/devsynth.c | |
parent | 81280572ca6f54009edfa4deee563e8678784218 (diff) | |
parent | a4ac0d847af9dd34d5953a5e264400326144b6b2 (diff) | |
download | op-kernel-dev-e4c5bf8e3dca827a1b3a6fac494eae8c74b7e1e7.zip op-kernel-dev-e4c5bf8e3dca827a1b3a6fac494eae8c74b7e1e7.tar.gz |
Merge 'staging-next' to Linus's tree
This merges the staging-next tree to Linus's tree and resolves
some conflicts that were present due to changes in other trees that were
affected by files here.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/speakup/devsynth.c')
-rw-r--r-- | drivers/staging/speakup/devsynth.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/drivers/staging/speakup/devsynth.c b/drivers/staging/speakup/devsynth.c new file mode 100644 index 0000000..39dc586 --- /dev/null +++ b/drivers/staging/speakup/devsynth.c @@ -0,0 +1,94 @@ +#include <linux/errno.h> +#include <linux/miscdevice.h> /* for misc_register, and SYNTH_MINOR */ +#include <linux/types.h> +#include <linux/uaccess.h> + +#include "speakup.h" +#include "spk_priv.h" + +#ifndef SYNTH_MINOR +#define SYNTH_MINOR 25 +#endif + +static int misc_registered; +static int dev_opened; + +static ssize_t speakup_file_write(struct file *fp, const char *buffer, + size_t nbytes, loff_t *ppos) +{ + size_t count = nbytes; + const char *ptr = buffer; + int bytes; + unsigned long flags; + u_char buf[256]; + if (synth == NULL) + return -ENODEV; + while (count > 0) { + bytes = min_t(size_t, count, sizeof(buf)); + if (copy_from_user(buf, ptr, bytes)) + return -EFAULT; + count -= bytes; + ptr += bytes; + spk_lock(flags); + synth_write(buf, bytes); + spk_unlock(flags); + } + return (ssize_t) nbytes; +} + +static ssize_t speakup_file_read(struct file *fp, char *buf, size_t nbytes, + loff_t *ppos) +{ + return 0; +} + +static int speakup_file_open(struct inode *ip, struct file *fp) +{ + if (synth == NULL) + return -ENODEV; + if (xchg(&dev_opened, 1)) + return -EBUSY; + return 0; +} + +static int speakup_file_release(struct inode *ip, struct file *fp) +{ + dev_opened = 0; + return 0; +} + +static const struct file_operations synth_fops = { + .read = speakup_file_read, + .write = speakup_file_write, + .open = speakup_file_open, + .release = speakup_file_release, +}; + +static struct miscdevice synth_device = { + .minor = SYNTH_MINOR, + .name = "synth", + .fops = &synth_fops, +}; + +void speakup_register_devsynth(void) +{ + if (misc_registered != 0) + return; +/* zero it so if register fails, deregister will not ref invalid ptrs */ + if (misc_register(&synth_device)) + pr_warn("Couldn't initialize miscdevice /dev/synth.\n"); + else { + pr_info("initialized device: /dev/synth, node (MAJOR %d, MINOR %d)\n", + MISC_MAJOR, SYNTH_MINOR); + misc_registered = 1; + } +} + +void speakup_unregister_devsynth(void) +{ + if (!misc_registered) + return; + pr_info("speakup: unregistering synth device /dev/synth\n"); + misc_deregister(&synth_device); + misc_registered = 0; +} |