aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/rmi4/rmi_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/rmi4/rmi_dev.c')
-rw-r--r--drivers/input/touchscreen/rmi4/rmi_dev.c428
1 files changed, 428 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/rmi4/rmi_dev.c b/drivers/input/touchscreen/rmi4/rmi_dev.c
new file mode 100644
index 00000000000..fa21ef9b20f
--- /dev/null
+++ b/drivers/input/touchscreen/rmi4/rmi_dev.c
@@ -0,0 +1,428 @@
1/*
2 * Copyright (c) 2011 Synaptics Incorporated
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19#include <linux/fs.h>
20#include <linux/delay.h>
21#include <linux/uaccess.h>
22#include <linux/slab.h>
23#include <linux/input.h>
24#include <linux/interrupt.h>
25#include <linux/syscalls.h>
26
27#include <linux/rmi.h>
28#include "rmi_driver.h"
29
30#define CHAR_DEVICE_NAME "rmi"
31
32#define REG_ADDR_LIMIT 0xFFFF
33
34/*store dynamically allocated major number of char device*/
35static int rmi_char_dev_major_num;
36
37
38/* file operations for RMI char device */
39
40/*
41 * rmi_char_dev_llseek: - use to setup register address
42 *
43 * @filp: file structure for seek
44 * @off: offset
45 * if whence == SEEK_SET,
46 * high 16 bits: page address
47 * low 16 bits: register address
48 *
49 * if whence == SEEK_CUR,
50 * offset from current position
51 *
52 * if whence == SEEK_END,
53 * offset from END(0xFFFF)
54 *
55 * @whence: SEEK_SET , SEEK_CUR or SEEK_END
56 */
57static loff_t rmi_char_dev_llseek(struct file *filp, loff_t off, int whence)
58{
59 loff_t newpos;
60 struct rmi_char_dev *my_char_dev = filp->private_data;
61
62 if (IS_ERR(my_char_dev)) {
63 pr_err("%s: pointer of char device is invalid", __func__);
64 return -EBADF;
65 }
66
67 mutex_lock(&(my_char_dev->mutex_file_op));
68
69 switch (whence) {
70 case SEEK_SET:
71 newpos = off;
72 break;
73
74 case SEEK_CUR:
75 newpos = filp->f_pos + off;
76 break;
77
78 case SEEK_END:
79 newpos = REG_ADDR_LIMIT + off;
80 break;
81
82 default: /* can't happen */
83 newpos = -EINVAL;
84 goto clean_up;
85 }
86
87 if (newpos < 0 || newpos > REG_ADDR_LIMIT) {
88 dev_err(my_char_dev->phys->dev, "newpos 0x%04x is invalid.\n",
89 (unsigned int)newpos);
90 newpos = -EINVAL;
91 goto clean_up;
92 }
93
94 filp->f_pos = newpos;
95
96clean_up:
97 mutex_unlock(&(my_char_dev->mutex_file_op));
98 return newpos;
99}
100
101/*
102 * rmi_char_dev_read: - use to read data from RMI stream
103 *
104 * @filp: file structure for read
105 * @buf: user-level buffer pointer
106 *
107 * @count: number of byte read
108 * @f_pos: offset (starting register address)
109 *
110 * @return number of bytes read into user buffer (buf) if succeeds
111 * negative number if error occurs.
112 */
113static ssize_t rmi_char_dev_read(struct file *filp, char __user *buf,
114 size_t count, loff_t *f_pos)
115{
116 struct rmi_char_dev *my_char_dev = filp->private_data;
117 ssize_t ret_value = 0;
118 unsigned char tmpbuf[count+1];
119 struct rmi_phys_device *phys;
120
121 /* limit offset to REG_ADDR_LIMIT-1 */
122 if (count > (REG_ADDR_LIMIT - *f_pos))
123 count = REG_ADDR_LIMIT - *f_pos;
124
125 if (count == 0)
126 return 0;
127
128 if (IS_ERR(my_char_dev)) {
129 pr_err("%s: pointer of char device is invalid", __func__);
130 ret_value = -EBADF;
131 return ret_value;
132 }
133
134 mutex_lock(&(my_char_dev->mutex_file_op));
135
136 phys = my_char_dev->phys;
137 /*
138 * just let it go through , because we do not know the register is FIFO
139 * register or not
140 */
141
142 ret_value = phys->read_block(phys, *f_pos, tmpbuf, count);
143
144 if (ret_value < 0)
145 goto clean_up;
146 else
147 *f_pos += ret_value;
148
149 if (copy_to_user(buf, tmpbuf, count))
150 ret_value = -EFAULT;
151
152clean_up:
153
154 mutex_unlock(&(my_char_dev->mutex_file_op));
155
156 return ret_value;
157}
158
159/*
160 * rmi_char_dev_write: - use to write data into RMI stream
161 *
162 * @filep : file structure for write
163 * @buf: user-level buffer pointer contains data to be written
164 * @count: number of byte be be written
165 * @f_pos: offset (starting register address)
166 *
167 * @return number of bytes written from user buffer (buf) if succeeds
168 * negative number if error occurs.
169 */
170static ssize_t rmi_char_dev_write(struct file *filp, const char __user *buf,
171 size_t count, loff_t *f_pos)
172{
173 struct rmi_char_dev *my_char_dev = filp->private_data;
174 ssize_t ret_value = 0;
175 unsigned char tmpbuf[count+1];
176 struct rmi_phys_device *phys;
177
178 /* limit offset to REG_ADDR_LIMIT-1 */
179 if (count > (REG_ADDR_LIMIT - *f_pos))
180 count = REG_ADDR_LIMIT - *f_pos;
181
182 if (count == 0)
183 return 0;
184
185 if (IS_ERR(my_char_dev)) {
186 pr_err("%s: pointer of char device is invalid", __func__);
187 ret_value = -EBADF;
188 return ret_value;
189 }
190
191 if (copy_from_user(tmpbuf, buf, count)) {
192 ret_value = -EFAULT;
193 return ret_value;
194 }
195
196 mutex_lock(&(my_char_dev->mutex_file_op));
197
198 phys = my_char_dev->phys;
199 /*
200 * just let it go through , because we do not know the register is FIFO
201 * register or not
202 */
203
204 ret_value = phys->write_block(phys, *f_pos, tmpbuf, count);
205
206 if (ret_value >= 0)
207 *f_pos += count;
208
209 mutex_unlock(&(my_char_dev->mutex_file_op));
210
211 return ret_value;
212}
213
214/*
215 * rmi_char_dev_open: - get a new handle for from RMI stream
216 * @inp : inode struture
217 * @filp: file structure for read/write
218 *
219 * @return 0 if succeeds
220 */
221static int rmi_char_dev_open(struct inode *inp, struct file *filp)
222{
223 /* store the device pointer to file structure */
224 struct rmi_char_dev *my_dev = container_of(inp->i_cdev,
225 struct rmi_char_dev, main_dev);
226 struct rmi_phys_device *phys = my_dev->phys;
227 int ret_value = 0;
228
229 filp->private_data = my_dev;
230
231 if (!phys)
232 return -EACCES;
233
234 mutex_lock(&(my_dev->mutex_file_op));
235 if (my_dev->ref_count < 1)
236 my_dev->ref_count++;
237 else
238 ret_value = -EACCES;
239
240 mutex_unlock(&(my_dev->mutex_file_op));
241
242 return ret_value;
243}
244
245/*
246 * rmi_char_dev_release: - release an existing handle
247 * @inp: inode structure
248 * @filp: file structure for read/write
249 *
250 * @return 0 if succeeds
251 */
252static int rmi_char_dev_release(struct inode *inp, struct file *filp)
253{
254 struct rmi_char_dev *my_dev = container_of(inp->i_cdev,
255 struct rmi_char_dev, main_dev);
256 struct rmi_phys_device *phys = my_dev->phys;
257
258 if (!phys)
259 return -EACCES;
260
261 mutex_lock(&(my_dev->mutex_file_op));
262
263 my_dev->ref_count--;
264 if (my_dev->ref_count < 0)
265 my_dev->ref_count = 0;
266
267 mutex_unlock(&(my_dev->mutex_file_op));
268
269 return 0;
270}
271
272static const struct file_operations rmi_char_dev_fops = {
273 .owner = THIS_MODULE,
274 .llseek = rmi_char_dev_llseek,
275 .read = rmi_char_dev_read,
276 .write = rmi_char_dev_write,
277 .open = rmi_char_dev_open,
278 .release = rmi_char_dev_release,
279};
280
281/*
282 * rmi_char_dev_clean_up - release memory or unregister driver
283 * @rmi_char_dev: rmi_char_dev structure
284 *
285 */
286static void rmi_char_dev_clean_up(struct rmi_char_dev *char_dev,
287 struct class *char_device_class)
288{
289 dev_t devno;
290
291 /* Get rid of our char dev entries */
292 if (char_dev) {
293 devno = char_dev->main_dev.dev;
294
295 cdev_del(&char_dev->main_dev);
296 kfree(char_dev);
297
298 if (char_device_class) {
299 device_destroy(char_device_class, devno);
300 class_unregister(char_device_class);
301 class_destroy(char_device_class);
302 }
303
304 /* cleanup_module is never called if registering failed */
305 unregister_chrdev_region(devno, 1);
306 pr_debug("%s: rmi_char_dev is removed\n", __func__);
307 }
308}
309
310/*
311 * rmi_char_devnode - return device permission
312 *
313 * @dev: char device structure
314 * @mode: file permission
315 *
316 */
317static char *rmi_char_devnode(struct device *dev, mode_t *mode)
318{
319 if (!mode)
320 return NULL;
321 /* rmi** */
322 /**mode = 0666*/
323 *mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
324
325 return kasprintf(GFP_KERNEL, "rmi/%s", dev_name(dev));
326}
327
328/*
329 * rmi_char_dev_register - register char device (called from up-level)
330 *
331 * @phy: a pointer to an rmi_phys_devices structure
332 *
333 * @return: zero if suceeds
334 */
335int rmi_char_dev_register(struct rmi_phys_device *phys)
336{
337 struct rmi_char_dev *char_dev;
338 dev_t dev_no;
339 int err;
340 int result;
341 struct device *device_ptr;
342
343 if (rmi_char_dev_major_num) {
344 dev_no = MKDEV(rmi_char_dev_major_num, 0);
345 result = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME);
346 } else {
347 result = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME);
348 /* let kernel allocate a major for us */
349 rmi_char_dev_major_num = MAJOR(dev_no);
350 dev_info(phys->dev, "Major number of rmi_char_dev: %d\n",
351 rmi_char_dev_major_num);
352 }
353 if (result < 0)
354 return result;
355
356 char_dev = kzalloc(sizeof(struct rmi_char_dev), GFP_KERNEL);
357 if (!char_dev) {
358 dev_err(phys->dev, "Failed to allocate rmi_char_dev.\n");
359 /* unregister the char device region */
360 __unregister_chrdev(rmi_char_dev_major_num, MINOR(dev_no), 1,
361 CHAR_DEVICE_NAME);
362 return -ENOMEM;
363 }
364
365 mutex_init(&char_dev->mutex_file_op);
366
367 phys->char_dev = char_dev;
368 char_dev->phys = phys;
369
370 cdev_init(&char_dev->main_dev, &rmi_char_dev_fops);
371
372 err = cdev_add(&char_dev->main_dev, dev_no, 1);
373 if (err) {
374 dev_err(phys->dev, "Error %d adding rmi_char_dev.\n", err);
375 rmi_char_dev_clean_up(phys->char_dev,
376 phys->rmi_char_device_class);
377 return err;
378 }
379
380 /* create device node */
381 phys->rmi_char_device_class =
382 class_create(THIS_MODULE, CHAR_DEVICE_NAME);
383
384 if (IS_ERR(phys->rmi_char_device_class)) {
385 dev_err(phys->dev, "Failed to create /dev/%s.\n",
386 CHAR_DEVICE_NAME);
387 rmi_char_dev_clean_up(phys->char_dev,
388 phys->rmi_char_device_class);
389 return -ENODEV;
390 }
391 /* setup permission */
392 phys->rmi_char_device_class->devnode = rmi_char_devnode;
393
394 /* class creation */
395 device_ptr = device_create(
396 phys->rmi_char_device_class,
397 NULL, dev_no, NULL,
398 CHAR_DEVICE_NAME"%d",
399 MINOR(dev_no));
400
401 if (IS_ERR(device_ptr)) {
402 dev_err(phys->dev, "Failed to create rmi device.\n");
403 rmi_char_dev_clean_up(phys->char_dev,
404 phys->rmi_char_device_class);
405 return -ENODEV;
406 }
407
408 return 0;
409}
410EXPORT_SYMBOL(rmi_char_dev_register);
411
412/* rmi_char_dev_unregister - unregister char device (called from up-level)
413 *
414 * @phys: pointer to an rmi_phys_device structure
415 */
416
417void rmi_char_dev_unregister(struct rmi_phys_device *phys)
418{
419 /* clean up */
420 if (phys)
421 rmi_char_dev_clean_up(phys->char_dev,
422 phys->rmi_char_device_class);
423}
424EXPORT_SYMBOL(rmi_char_dev_unregister);
425
426MODULE_AUTHOR("Synaptics, Inc.");
427MODULE_DESCRIPTION("RMI4 Char Device");
428MODULE_LICENSE("GPL");