drm/rockchip: Don't change hdmi reference clock rate
[drm/drm-misc.git] / drivers / accessibility / speakup / devsynth.c
blobe3d909bd048048a05e1d84d140c3e8f128bad9a9
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/errno.h>
3 #include <linux/miscdevice.h> /* for misc_register, and MISC_DYNAMIC_MINOR */
4 #include <linux/types.h>
5 #include <linux/uaccess.h>
7 #include "speakup.h"
8 #include "spk_priv.h"
10 static int synth_registered, synthu_registered;
11 static int dev_opened;
13 /* Latin1 version */
14 static ssize_t speakup_file_write(struct file *fp, const char __user *buffer,
15 size_t nbytes, loff_t *ppos)
17 size_t count = nbytes;
18 const char __user *ptr = buffer;
19 size_t bytes;
20 unsigned long flags;
21 u_char buf[256];
23 if (!synth)
24 return -ENODEV;
25 while (count > 0) {
26 bytes = min(count, sizeof(buf));
27 if (copy_from_user(buf, ptr, bytes))
28 return -EFAULT;
29 count -= bytes;
30 ptr += bytes;
31 spin_lock_irqsave(&speakup_info.spinlock, flags);
32 synth_write(buf, bytes);
33 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
35 return (ssize_t)nbytes;
38 /* UTF-8 version */
39 static ssize_t speakup_file_writeu(struct file *fp, const char __user *buffer,
40 size_t nbytes, loff_t *ppos)
42 size_t count = nbytes, consumed, want;
43 const char __user *ptr = buffer;
44 size_t bytes;
45 unsigned long flags;
46 unsigned char buf[256];
47 u16 ubuf[256];
48 size_t in, out;
50 if (!synth)
51 return -ENODEV;
53 want = 1;
54 while (count >= want) {
55 /* Copy some UTF-8 piece from userland */
56 bytes = min(count, sizeof(buf));
57 if (copy_from_user(buf, ptr, bytes))
58 return -EFAULT;
60 /* Convert to u16 */
61 for (in = 0, out = 0; in < bytes; in += consumed) {
62 s32 value;
64 value = synth_utf8_get(buf + in, bytes - in, &consumed, &want);
65 if (value == -1) {
66 /* Invalid or incomplete */
68 if (want > bytes - in)
69 /* We don't have it all yet, stop here
70 * and wait for the rest
72 bytes = in;
74 continue;
77 if (value < 0x10000)
78 ubuf[out++] = value;
81 count -= bytes;
82 ptr += bytes;
84 /* And speak this up */
85 if (out) {
86 spin_lock_irqsave(&speakup_info.spinlock, flags);
87 for (in = 0; in < out; in++)
88 synth_buffer_add(ubuf[in]);
89 synth_start();
90 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
94 return (ssize_t)(nbytes - count);
97 static ssize_t speakup_file_read(struct file *fp, char __user *buf,
98 size_t nbytes, loff_t *ppos)
100 return 0;
103 static int speakup_file_open(struct inode *ip, struct file *fp)
105 if (!synth)
106 return -ENODEV;
107 if (xchg(&dev_opened, 1))
108 return -EBUSY;
109 return 0;
112 static int speakup_file_release(struct inode *ip, struct file *fp)
114 dev_opened = 0;
115 return 0;
118 static const struct file_operations synth_fops = {
119 .read = speakup_file_read,
120 .write = speakup_file_write,
121 .open = speakup_file_open,
122 .release = speakup_file_release,
125 static const struct file_operations synthu_fops = {
126 .read = speakup_file_read,
127 .write = speakup_file_writeu,
128 .open = speakup_file_open,
129 .release = speakup_file_release,
132 static struct miscdevice synth_device = {
133 .minor = MISC_DYNAMIC_MINOR,
134 .name = "synth",
135 .fops = &synth_fops,
138 static struct miscdevice synthu_device = {
139 .minor = MISC_DYNAMIC_MINOR,
140 .name = "synthu",
141 .fops = &synthu_fops,
144 void speakup_register_devsynth(void)
146 if (!synth_registered) {
147 if (misc_register(&synth_device)) {
148 pr_warn("Couldn't initialize miscdevice /dev/synth.\n");
149 } else {
150 pr_info("initialized device: /dev/synth, node (MAJOR %d, MINOR %d)\n",
151 MISC_MAJOR, synth_device.minor);
152 synth_registered = 1;
155 if (!synthu_registered) {
156 if (misc_register(&synthu_device)) {
157 pr_warn("Couldn't initialize miscdevice /dev/synthu.\n");
158 } else {
159 pr_info("initialized device: /dev/synthu, node (MAJOR %d, MINOR %d)\n",
160 MISC_MAJOR, synthu_device.minor);
161 synthu_registered = 1;
166 void speakup_unregister_devsynth(void)
168 if (synth_registered) {
169 pr_info("speakup: unregistering synth device /dev/synth\n");
170 misc_deregister(&synth_device);
171 synth_registered = 0;
173 if (synthu_registered) {
174 pr_info("speakup: unregistering synth device /dev/synthu\n");
175 misc_deregister(&synthu_device);
176 synthu_registered = 0;