at v3.0 94 lines 2.0 kB view raw
1#include <linux/errno.h> 2#include <linux/miscdevice.h> /* for misc_register, and SYNTH_MINOR */ 3#include <linux/types.h> 4#include <linux/uaccess.h> 5 6#include "speakup.h" 7#include "spk_priv.h" 8 9#ifndef SYNTH_MINOR 10#define SYNTH_MINOR 25 11#endif 12 13static int misc_registered; 14static int dev_opened; 15 16static ssize_t speakup_file_write(struct file *fp, const char *buffer, 17 size_t nbytes, loff_t *ppos) 18{ 19 size_t count = nbytes; 20 const char *ptr = buffer; 21 int bytes; 22 unsigned long flags; 23 u_char buf[256]; 24 if (synth == NULL) 25 return -ENODEV; 26 while (count > 0) { 27 bytes = min_t(size_t, count, sizeof(buf)); 28 if (copy_from_user(buf, ptr, bytes)) 29 return -EFAULT; 30 count -= bytes; 31 ptr += bytes; 32 spk_lock(flags); 33 synth_write(buf, bytes); 34 spk_unlock(flags); 35 } 36 return (ssize_t) nbytes; 37} 38 39static ssize_t speakup_file_read(struct file *fp, char *buf, size_t nbytes, 40 loff_t *ppos) 41{ 42 return 0; 43} 44 45static int speakup_file_open(struct inode *ip, struct file *fp) 46{ 47 if (synth == NULL) 48 return -ENODEV; 49 if (xchg(&dev_opened, 1)) 50 return -EBUSY; 51 return 0; 52} 53 54static int speakup_file_release(struct inode *ip, struct file *fp) 55{ 56 dev_opened = 0; 57 return 0; 58} 59 60static const struct file_operations synth_fops = { 61 .read = speakup_file_read, 62 .write = speakup_file_write, 63 .open = speakup_file_open, 64 .release = speakup_file_release, 65}; 66 67static struct miscdevice synth_device = { 68 .minor = SYNTH_MINOR, 69 .name = "synth", 70 .fops = &synth_fops, 71}; 72 73void speakup_register_devsynth(void) 74{ 75 if (misc_registered != 0) 76 return; 77/* zero it so if register fails, deregister will not ref invalid ptrs */ 78 if (misc_register(&synth_device)) 79 pr_warn("Couldn't initialize miscdevice /dev/synth.\n"); 80 else { 81 pr_info("initialized device: /dev/synth, node (MAJOR %d, MINOR %d)\n", 82 MISC_MAJOR, SYNTH_MINOR); 83 misc_registered = 1; 84 } 85} 86 87void speakup_unregister_devsynth(void) 88{ 89 if (!misc_registered) 90 return; 91 pr_info("speakup: unregistering synth device /dev/synth\n"); 92 misc_deregister(&synth_device); 93 misc_registered = 0; 94}