root/i2c/trunk/kernel/i2c-dev.c @ 3986

Revision 3986, 13.6 KB (checked in by khali, 8 years ago)

Spelling fix. Original patch from Tobias Klauser.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    i2c-dev.c - i2c-bus driver, char device interface 
3
4    Copyright (C) 1995-97 Simon G. Vogl
5    Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22/* Note that this is a complete rewrite of Simon Vogl's i2c-dev module.
23   But I have used so much of his original code and ideas that it seems
24   only fair to recognize him as co-author -- Frodo */
25
26/* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
27
28/* The devfs code is contributed by Philipp Matthias Hahn
29   <pmhahn@titan.lahn.de> */
30
31/* $Id$ */
32
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/fs.h>
36#include <linux/slab.h>
37#include <linux/smp_lock.h>
38#ifdef CONFIG_DEVFS_FS
39#include <linux/devfs_fs_kernel.h>
40#endif
41#include <linux/init.h>
42#include "i2c.h"
43#include "i2c-dev.h"
44#include <asm/uaccess.h>
45
46/* If you want debugging uncomment: */
47/* #define DEBUG */
48
49
50/* struct file_operations changed too often in the 2.1 series for nice code */
51
52static ssize_t i2cdev_read (struct file *file, char *buf, size_t count, 
53                            loff_t *offset);
54static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count, 
55                             loff_t *offset);
56
57static int i2cdev_ioctl (struct inode *inode, struct file *file, 
58                         unsigned int cmd, unsigned long arg);
59static int i2cdev_open (struct inode *inode, struct file *file);
60
61static int i2cdev_release (struct inode *inode, struct file *file);
62
63static int i2cdev_attach_adapter(struct i2c_adapter *adap);
64static int i2cdev_detach_client(struct i2c_client *client);
65static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
66                           void *arg);
67
68static struct file_operations i2cdev_fops = {
69        .owner          = THIS_MODULE,
70        .llseek         = no_llseek,
71        .read           = i2cdev_read,
72        .write          = i2cdev_write,
73        .ioctl          = i2cdev_ioctl,
74        .open           = i2cdev_open,
75        .release        = i2cdev_release,
76};
77
78#define I2CDEV_ADAPS_MAX I2C_ADAP_MAX
79static struct i2c_adapter *i2cdev_adaps[I2CDEV_ADAPS_MAX];
80#ifdef CONFIG_DEVFS_FS
81static devfs_handle_t devfs_i2c[I2CDEV_ADAPS_MAX];
82static devfs_handle_t devfs_handle = NULL;
83#endif
84
85static struct i2c_driver i2cdev_driver = {
86        .name           = "i2c-dev dummy driver",
87        .id             = I2C_DRIVERID_I2CDEV,
88        .flags          = I2C_DF_DUMMY,
89        .attach_adapter = i2cdev_attach_adapter,
90        .detach_client  = i2cdev_detach_client,
91        .command        = i2cdev_command,
92};
93
94static struct i2c_client i2cdev_client_template = {
95        .name           = "I2C /dev entry",
96        .addr           = -1,
97        .driver         = &i2cdev_driver,
98};
99
100static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
101                            loff_t *offset)
102{
103        char *tmp;
104        int ret;
105
106#ifdef DEBUG
107        struct inode *inode = file->f_dentry->d_inode;
108#endif /* DEBUG */
109
110        struct i2c_client *client = (struct i2c_client *)file->private_data;
111
112        if (count > 8192)
113                count = 8192;
114
115        /* copy user space data to kernel space. */
116        tmp = kmalloc(count,GFP_KERNEL);
117        if (tmp==NULL)
118                return -ENOMEM;
119
120#ifdef DEBUG
121        printk(KERN_DEBUG "i2c-dev.o: i2c-%d reading %d bytes.\n",minor(inode->i_rdev),
122               count);
123#endif
124
125        ret = i2c_master_recv(client,tmp,count);
126        if (ret >= 0)
127                ret = copy_to_user(buf,tmp,count)?-EFAULT:ret;
128        kfree(tmp);
129        return ret;
130}
131
132static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
133                             loff_t *offset)
134{
135        int ret;
136        char *tmp;
137        struct i2c_client *client = (struct i2c_client *)file->private_data;
138
139#ifdef DEBUG
140        struct inode *inode = file->f_dentry->d_inode;
141#endif /* DEBUG */
142
143        if (count > 8192)
144                count = 8192;
145
146        /* copy user space data to kernel space. */
147        tmp = kmalloc(count,GFP_KERNEL);
148        if (tmp==NULL)
149                return -ENOMEM;
150        if (copy_from_user(tmp,buf,count)) {
151                kfree(tmp);
152                return -EFAULT;
153        }
154
155#ifdef DEBUG
156        printk(KERN_DEBUG "i2c-dev.o: i2c-%d writing %d bytes.\n",minor(inode->i_rdev),
157               count);
158#endif
159        ret = i2c_master_send(client,tmp,count);
160        kfree(tmp);
161        return ret;
162}
163
164int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, 
165                  unsigned long arg)
166{
167        struct i2c_client *client = (struct i2c_client *)file->private_data;
168        struct i2c_rdwr_ioctl_data rdwr_arg;
169        struct i2c_smbus_ioctl_data data_arg;
170        union i2c_smbus_data temp;
171        struct i2c_msg *rdwr_pa;
172        u8 **data_ptrs;
173        int i,datasize,res;
174        unsigned long funcs;
175
176#ifdef DEBUG
177        printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n", 
178               minor(inode->i_rdev),cmd, arg);
179#endif /* DEBUG */
180
181        switch ( cmd ) {
182        case I2C_SLAVE:
183        case I2C_SLAVE_FORCE:
184                if ((arg > 0x3ff) || 
185                    (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
186                        return -EINVAL;
187                if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
188                        return -EBUSY;
189                client->addr = arg;
190                return 0;
191        case I2C_TENBIT:
192                if (arg)
193                        client->flags |= I2C_M_TEN;
194                else
195                        client->flags &= ~I2C_M_TEN;
196                return 0;
197        case I2C_PEC:
198                if (arg)
199                        client->flags |= I2C_CLIENT_PEC;
200                else
201                        client->flags &= ~I2C_CLIENT_PEC;
202                return 0;
203        case I2C_FUNCS:
204                funcs = i2c_get_functionality(client->adapter);
205                return (copy_to_user((unsigned long *)arg,&funcs,
206                                     sizeof(unsigned long)))?-EFAULT:0;
207
208        case I2C_RDWR:
209                if (copy_from_user(&rdwr_arg, 
210                                   (struct i2c_rdwr_ioctl_data *)arg, 
211                                   sizeof(rdwr_arg)))
212                        return -EFAULT;
213
214                /* Put an arbitrary limit on the number of messages that can
215                 * be sent at once */
216                if (rdwr_arg.nmsgs > 42)
217                        return -EINVAL;
218               
219                rdwr_pa = (struct i2c_msg *)
220                        kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), 
221                        GFP_KERNEL);
222
223                if (rdwr_pa == NULL) return -ENOMEM;
224
225                if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
226                                   rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
227                        kfree(rdwr_pa);
228                        return -EFAULT;
229                }
230
231                data_ptrs = (u8 **) kmalloc(rdwr_arg.nmsgs * sizeof(u8 *),
232                                            GFP_KERNEL);
233                if (data_ptrs == NULL) {
234                        kfree(rdwr_pa);
235                        return -ENOMEM;
236                }
237
238                res = 0;
239                for( i=0; i<rdwr_arg.nmsgs; i++ )
240                {
241                        /* Limit the size of the message to a sane amount */
242                        if (rdwr_pa[i].len > 8192) {
243                                res = -EINVAL;
244                                break;
245                        }
246                        data_ptrs[i] = rdwr_pa[i].buf;
247                        rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
248                        if(rdwr_pa[i].buf == NULL)
249                        {
250                                res = -ENOMEM;
251                                break;
252                        }
253                        if(copy_from_user(rdwr_pa[i].buf,
254                                data_ptrs[i],
255                                rdwr_pa[i].len))
256                        {
257                                ++i; /* Needs to be kfreed too */
258                                res = -EFAULT;
259                                break;
260                        }
261                }
262                if (res < 0) {
263                        int j;
264                        for (j = 0; j < i; ++j)
265                                kfree(rdwr_pa[j].buf);
266                        kfree(data_ptrs);
267                        kfree(rdwr_pa);
268                        return res;
269                }
270
271                res = i2c_transfer(client->adapter,
272                        rdwr_pa,
273                        rdwr_arg.nmsgs);
274                while(i-- > 0)
275                {
276                        if( res>=0 && (rdwr_pa[i].flags & I2C_M_RD))
277                        {
278                                if(copy_to_user(
279                                        data_ptrs[i],
280                                        rdwr_pa[i].buf,
281                                        rdwr_pa[i].len))
282                                {
283                                        res = -EFAULT;
284                                }
285                        }
286                        kfree(rdwr_pa[i].buf);
287                }
288                kfree(data_ptrs);
289                kfree(rdwr_pa);
290                return res;
291
292        case I2C_SMBUS:
293                if (copy_from_user(&data_arg,
294                                   (struct i2c_smbus_ioctl_data *) arg,
295                                   sizeof(struct i2c_smbus_ioctl_data)))
296                        return -EFAULT;
297                if ((data_arg.size != I2C_SMBUS_BYTE) && 
298                    (data_arg.size != I2C_SMBUS_QUICK) &&
299                    (data_arg.size != I2C_SMBUS_BYTE_DATA) && 
300                    (data_arg.size != I2C_SMBUS_WORD_DATA) &&
301                    (data_arg.size != I2C_SMBUS_PROC_CALL) &&
302                    (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
303                    (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
304                    (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
305#ifdef DEBUG
306                        printk(KERN_DEBUG "i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n",
307                               data_arg.size);
308#endif
309                        return -EINVAL;
310                }
311                /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
312                   so the check is valid if size==I2C_SMBUS_QUICK too. */
313                if ((data_arg.read_write != I2C_SMBUS_READ) && 
314                    (data_arg.read_write != I2C_SMBUS_WRITE)) {
315#ifdef DEBUG
316                        printk(KERN_DEBUG "i2c-dev.o: read_write out of range (%x) in ioctl I2C_SMBUS.\n",
317                               data_arg.read_write);
318#endif
319                        return -EINVAL;
320                }
321
322                /* Note that command values are always valid! */
323
324                if ((data_arg.size == I2C_SMBUS_QUICK) ||
325                    ((data_arg.size == I2C_SMBUS_BYTE) && 
326                    (data_arg.read_write == I2C_SMBUS_WRITE)))
327                        /* These are special: we do not use data */
328                        return i2c_smbus_xfer(client->adapter, client->addr,
329                                              client->flags,
330                                              data_arg.read_write,
331                                              data_arg.command,
332                                              data_arg.size, NULL);
333
334                if (data_arg.data == NULL) {
335#ifdef DEBUG
336                        printk(KERN_DEBUG "i2c-dev.o: data is NULL pointer in ioctl I2C_SMBUS.\n");
337#endif
338                        return -EINVAL;
339                }
340
341                if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
342                    (data_arg.size == I2C_SMBUS_BYTE))
343                        datasize = sizeof(data_arg.data->byte);
344                else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || 
345                         (data_arg.size == I2C_SMBUS_PROC_CALL))
346                        datasize = sizeof(data_arg.data->word);
347                else /* size == smbus block, i2c block, or block proc. call */
348                        datasize = sizeof(data_arg.data->block);
349
350                if ((data_arg.size == I2C_SMBUS_PROC_CALL) || 
351                    (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || 
352                    (data_arg.read_write == I2C_SMBUS_WRITE)) {
353                        if (copy_from_user(&temp, data_arg.data, datasize))
354                                return -EFAULT;
355                }
356                res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
357                      data_arg.read_write,
358                      data_arg.command,data_arg.size,&temp);
359                if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || 
360                              (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || 
361                              (data_arg.read_write == I2C_SMBUS_READ))) {
362                        if (copy_to_user(data_arg.data, &temp, datasize))
363                                return -EFAULT;
364                }
365                return res;
366
367        default:
368                return i2c_control(client,cmd,arg);
369        }
370        return 0;
371}
372
373int i2cdev_open (struct inode *inode, struct file *file)
374{
375        unsigned int minor = minor(inode->i_rdev);
376        struct i2c_client *client;
377
378        if ((minor >= I2CDEV_ADAPS_MAX) || ! (i2cdev_adaps[minor])) {
379#ifdef DEBUG
380                printk(KERN_DEBUG "i2c-dev.o: Trying to open unattached adapter i2c-%d\n",
381                       minor);
382#endif
383                return -ENODEV;
384        }
385
386        /* Note that we here allocate a client for later use, but we will *not*
387           register this client! Yes, this is safe. No, it is not very clean. */
388        if(! (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)))
389                return -ENOMEM;
390        memcpy(client,&i2cdev_client_template,sizeof(struct i2c_client));
391
392        /* registered with adapter, passed as client to user */
393        client->adapter = i2cdev_adaps[minor];
394        file->private_data = client;
395
396        if (client->adapter->inc_use)
397                client->adapter->inc_use(client->adapter);
398
399#ifdef DEBUG
400        printk(KERN_DEBUG "i2c-dev.o: opened i2c-%d\n",minor);
401#endif
402        return 0;
403}
404
405static int i2cdev_release (struct inode *inode, struct file *file)
406{
407        struct i2c_client *client;
408#ifdef DEBUG
409        unsigned int minor = minor(inode->i_rdev);
410#endif
411
412        client = file->private_data;
413        file->private_data = NULL;
414        if (client->adapter->dec_use)
415                client->adapter->dec_use(client->adapter);
416        kfree(client);
417#ifdef DEBUG
418        printk(KERN_DEBUG "i2c-dev.o: Closed: i2c-%d\n", minor);
419#endif
420        return 0;
421}
422
423int i2cdev_attach_adapter(struct i2c_adapter *adap)
424{
425        int i;
426        char name[8];
427
428        if ((i = i2c_adapter_id(adap)) < 0) {
429                printk(KERN_DEBUG "i2c-dev.o: Unknown adapter ?!?\n");
430                return -ENODEV;
431        }
432        if (i >= I2CDEV_ADAPS_MAX) {
433                printk(KERN_DEBUG "i2c-dev.o: Adapter number too large?!? (%d)\n",i);
434                return -ENODEV;
435        }
436
437        sprintf (name, "%d", i);
438        if (! i2cdev_adaps[i]) {
439                i2cdev_adaps[i] = adap;
440#ifdef CONFIG_DEVFS_FS
441                devfs_i2c[i] = devfs_register (devfs_handle, name,
442                        DEVFS_FL_DEFAULT, I2C_MAJOR, i,
443                        S_IFCHR | S_IRUSR | S_IWUSR,
444                        &i2cdev_fops, adap);
445#endif
446                printk(KERN_DEBUG "i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i);
447        } else {
448                /* This is actually a detach_adapter call! */
449#ifdef CONFIG_DEVFS_FS
450                devfs_unregister(devfs_i2c[i]);
451#endif
452                i2cdev_adaps[i] = NULL;
453#ifdef DEBUG
454                printk(KERN_DEBUG "i2c-dev.o: Adapter unregistered: %s\n",adap->name);
455#endif
456        }
457
458        return 0;
459}
460
461int i2cdev_detach_client(struct i2c_client *client)
462{
463        return 0;
464}
465
466static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
467                           void *arg)
468{
469        return -1;
470}
471
472static int __init i2c_dev_init(void)
473{
474        int res;
475
476        printk(KERN_INFO "i2c-dev.o: i2c /dev entries driver module version %s (%s)\n", I2C_VERSION, I2C_DATE);
477
478#ifdef CONFIG_DEVFS_FS
479        if (devfs_register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops)) {
480#else
481        if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) {
482#endif
483                printk(KERN_ERR "i2c-dev.o: unable to get major %d for i2c bus\n",
484                       I2C_MAJOR);
485                return -EIO;
486        }
487#ifdef CONFIG_DEVFS_FS
488        devfs_handle = devfs_mk_dir(NULL, "i2c", NULL);
489#endif
490        if ((res = i2c_add_driver(&i2cdev_driver))) {
491                printk(KERN_ERR "i2c-dev.o: Driver registration failed, module not inserted.\n");
492#ifdef CONFIG_DEVFS_FS
493                devfs_unregister(devfs_handle);
494#endif
495                unregister_chrdev(I2C_MAJOR,"i2c");
496                return res;
497        }
498        return 0;
499}
500
501static void __exit i2c_dev_exit(void)
502{
503        i2c_del_driver(&i2cdev_driver);
504#ifdef CONFIG_DEVFS_FS
505        devfs_unregister(devfs_handle);
506#endif
507        unregister_chrdev(I2C_MAJOR,"i2c");
508}
509
510EXPORT_NO_SYMBOLS;
511
512MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>");
513MODULE_DESCRIPTION("I2C /dev entries driver");
514MODULE_LICENSE("GPL");
515
516module_init(i2c_dev_init);
517module_exit(i2c_dev_exit);
Note: See TracBrowser for help on using the browser.