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