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

Revision 4022, 13.5 KB (checked in by khali, 7 years ago)

Drop i2c-dev's empty command implementation. This is a backport
from Linux 2.6, original patch from Laurent Riffard. Also update the
documentation not to suggest an empty implementation of command.

  • 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};
92
93static struct i2c_client i2cdev_client_template = {
94        .name           = "I2C /dev entry",
95        .addr           = -1,
96        .driver         = &i2cdev_driver,
97};
98
99static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
100                            loff_t *offset)
101{
102        char *tmp;
103        int ret;
104
105#ifdef DEBUG
106        struct inode *inode = file->f_dentry->d_inode;
107#endif /* DEBUG */
108
109        struct i2c_client *client = (struct i2c_client *)file->private_data;
110
111        if (count > 8192)
112                count = 8192;
113
114        /* copy user space data to kernel space. */
115        tmp = kmalloc(count,GFP_KERNEL);
116        if (tmp==NULL)
117                return -ENOMEM;
118
119#ifdef DEBUG
120        printk(KERN_DEBUG "i2c-dev.o: i2c-%d reading %d bytes.\n",minor(inode->i_rdev),
121               count);
122#endif
123
124        ret = i2c_master_recv(client,tmp,count);
125        if (ret >= 0)
126                ret = copy_to_user(buf,tmp,count)?-EFAULT:ret;
127        kfree(tmp);
128        return ret;
129}
130
131static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
132                             loff_t *offset)
133{
134        int ret;
135        char *tmp;
136        struct i2c_client *client = (struct i2c_client *)file->private_data;
137
138#ifdef DEBUG
139        struct inode *inode = file->f_dentry->d_inode;
140#endif /* DEBUG */
141
142        if (count > 8192)
143                count = 8192;
144
145        /* copy user space data to kernel space. */
146        tmp = kmalloc(count,GFP_KERNEL);
147        if (tmp==NULL)
148                return -ENOMEM;
149        if (copy_from_user(tmp,buf,count)) {
150                kfree(tmp);
151                return -EFAULT;
152        }
153
154#ifdef DEBUG
155        printk(KERN_DEBUG "i2c-dev.o: i2c-%d writing %d bytes.\n",minor(inode->i_rdev),
156               count);
157#endif
158        ret = i2c_master_send(client,tmp,count);
159        kfree(tmp);
160        return ret;
161}
162
163int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, 
164                  unsigned long arg)
165{
166        struct i2c_client *client = (struct i2c_client *)file->private_data;
167        struct i2c_rdwr_ioctl_data rdwr_arg;
168        struct i2c_smbus_ioctl_data data_arg;
169        union i2c_smbus_data temp;
170        struct i2c_msg *rdwr_pa;
171        u8 **data_ptrs;
172        int i,datasize,res;
173        unsigned long funcs;
174
175#ifdef DEBUG
176        printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n", 
177               minor(inode->i_rdev),cmd, arg);
178#endif /* DEBUG */
179
180        switch ( cmd ) {
181        case I2C_SLAVE:
182        case I2C_SLAVE_FORCE:
183                if ((arg > 0x3ff) || 
184                    (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
185                        return -EINVAL;
186                if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
187                        return -EBUSY;
188                client->addr = arg;
189                return 0;
190        case I2C_TENBIT:
191                if (arg)
192                        client->flags |= I2C_M_TEN;
193                else
194                        client->flags &= ~I2C_M_TEN;
195                return 0;
196        case I2C_PEC:
197                if (arg)
198                        client->flags |= I2C_CLIENT_PEC;
199                else
200                        client->flags &= ~I2C_CLIENT_PEC;
201                return 0;
202        case I2C_FUNCS:
203                funcs = i2c_get_functionality(client->adapter);
204                return (copy_to_user((unsigned long *)arg,&funcs,
205                                     sizeof(unsigned long)))?-EFAULT:0;
206
207        case I2C_RDWR:
208                if (copy_from_user(&rdwr_arg, 
209                                   (struct i2c_rdwr_ioctl_data *)arg, 
210                                   sizeof(rdwr_arg)))
211                        return -EFAULT;
212
213                /* Put an arbitrary limit on the number of messages that can
214                 * be sent at once */
215                if (rdwr_arg.nmsgs > 42)
216                        return -EINVAL;
217               
218                rdwr_pa = (struct i2c_msg *)
219                        kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), 
220                        GFP_KERNEL);
221
222                if (rdwr_pa == NULL) return -ENOMEM;
223
224                if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
225                                   rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
226                        kfree(rdwr_pa);
227                        return -EFAULT;
228                }
229
230                data_ptrs = (u8 **) kmalloc(rdwr_arg.nmsgs * sizeof(u8 *),
231                                            GFP_KERNEL);
232                if (data_ptrs == NULL) {
233                        kfree(rdwr_pa);
234                        return -ENOMEM;
235                }
236
237                res = 0;
238                for( i=0; i<rdwr_arg.nmsgs; i++ )
239                {
240                        /* Limit the size of the message to a sane amount */
241                        if (rdwr_pa[i].len > 8192) {
242                                res = -EINVAL;
243                                break;
244                        }
245                        data_ptrs[i] = rdwr_pa[i].buf;
246                        rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
247                        if(rdwr_pa[i].buf == NULL)
248                        {
249                                res = -ENOMEM;
250                                break;
251                        }
252                        if(copy_from_user(rdwr_pa[i].buf,
253                                data_ptrs[i],
254                                rdwr_pa[i].len))
255                        {
256                                ++i; /* Needs to be kfreed too */
257                                res = -EFAULT;
258                                break;
259                        }
260                }
261                if (res < 0) {
262                        int j;
263                        for (j = 0; j < i; ++j)
264                                kfree(rdwr_pa[j].buf);
265                        kfree(data_ptrs);
266                        kfree(rdwr_pa);
267                        return res;
268                }
269
270                res = i2c_transfer(client->adapter,
271                        rdwr_pa,
272                        rdwr_arg.nmsgs);
273                while(i-- > 0)
274                {
275                        if( res>=0 && (rdwr_pa[i].flags & I2C_M_RD))
276                        {
277                                if(copy_to_user(
278                                        data_ptrs[i],
279                                        rdwr_pa[i].buf,
280                                        rdwr_pa[i].len))
281                                {
282                                        res = -EFAULT;
283                                }
284                        }
285                        kfree(rdwr_pa[i].buf);
286                }
287                kfree(data_ptrs);
288                kfree(rdwr_pa);
289                return res;
290
291        case I2C_SMBUS:
292                if (copy_from_user(&data_arg,
293                                   (struct i2c_smbus_ioctl_data *) arg,
294                                   sizeof(struct i2c_smbus_ioctl_data)))
295                        return -EFAULT;
296                if ((data_arg.size != I2C_SMBUS_BYTE) && 
297                    (data_arg.size != I2C_SMBUS_QUICK) &&
298                    (data_arg.size != I2C_SMBUS_BYTE_DATA) && 
299                    (data_arg.size != I2C_SMBUS_WORD_DATA) &&
300                    (data_arg.size != I2C_SMBUS_PROC_CALL) &&
301                    (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
302                    (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
303                    (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
304#ifdef DEBUG
305                        printk(KERN_DEBUG "i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n",
306                               data_arg.size);
307#endif
308                        return -EINVAL;
309                }
310                /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
311                   so the check is valid if size==I2C_SMBUS_QUICK too. */
312                if ((data_arg.read_write != I2C_SMBUS_READ) && 
313                    (data_arg.read_write != I2C_SMBUS_WRITE)) {
314#ifdef DEBUG
315                        printk(KERN_DEBUG "i2c-dev.o: read_write out of range (%x) in ioctl I2C_SMBUS.\n",
316                               data_arg.read_write);
317#endif
318                        return -EINVAL;
319                }
320
321                /* Note that command values are always valid! */
322
323                if ((data_arg.size == I2C_SMBUS_QUICK) ||
324                    ((data_arg.size == I2C_SMBUS_BYTE) && 
325                    (data_arg.read_write == I2C_SMBUS_WRITE)))
326                        /* These are special: we do not use data */
327                        return i2c_smbus_xfer(client->adapter, client->addr,
328                                              client->flags,
329                                              data_arg.read_write,
330                                              data_arg.command,
331                                              data_arg.size, NULL);
332
333                if (data_arg.data == NULL) {
334#ifdef DEBUG
335                        printk(KERN_DEBUG "i2c-dev.o: data is NULL pointer in ioctl I2C_SMBUS.\n");
336#endif
337                        return -EINVAL;
338                }
339
340                if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
341                    (data_arg.size == I2C_SMBUS_BYTE))
342                        datasize = sizeof(data_arg.data->byte);
343                else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || 
344                         (data_arg.size == I2C_SMBUS_PROC_CALL))
345                        datasize = sizeof(data_arg.data->word);
346                else /* size == smbus block, i2c block, or block proc. call */
347                        datasize = sizeof(data_arg.data->block);
348
349                if ((data_arg.size == I2C_SMBUS_PROC_CALL) || 
350                    (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || 
351                    (data_arg.read_write == I2C_SMBUS_WRITE)) {
352                        if (copy_from_user(&temp, data_arg.data, datasize))
353                                return -EFAULT;
354                }
355                res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
356                      data_arg.read_write,
357                      data_arg.command,data_arg.size,&temp);
358                if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || 
359                              (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || 
360                              (data_arg.read_write == I2C_SMBUS_READ))) {
361                        if (copy_to_user(data_arg.data, &temp, datasize))
362                                return -EFAULT;
363                }
364                return res;
365
366        default:
367                return i2c_control(client,cmd,arg);
368        }
369        return 0;
370}
371
372int i2cdev_open (struct inode *inode, struct file *file)
373{
374        unsigned int minor = minor(inode->i_rdev);
375        struct i2c_client *client;
376
377        if ((minor >= I2CDEV_ADAPS_MAX) || ! (i2cdev_adaps[minor])) {
378#ifdef DEBUG
379                printk(KERN_DEBUG "i2c-dev.o: Trying to open unattached adapter i2c-%d\n",
380                       minor);
381#endif
382                return -ENODEV;
383        }
384
385        /* Note that we here allocate a client for later use, but we will *not*
386           register this client! Yes, this is safe. No, it is not very clean. */
387        if(! (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)))
388                return -ENOMEM;
389        memcpy(client,&i2cdev_client_template,sizeof(struct i2c_client));
390
391        /* registered with adapter, passed as client to user */
392        client->adapter = i2cdev_adaps[minor];
393        file->private_data = client;
394
395        if (client->adapter->inc_use)
396                client->adapter->inc_use(client->adapter);
397
398#ifdef DEBUG
399        printk(KERN_DEBUG "i2c-dev.o: opened i2c-%d\n",minor);
400#endif
401        return 0;
402}
403
404static int i2cdev_release (struct inode *inode, struct file *file)
405{
406        struct i2c_client *client;
407#ifdef DEBUG
408        unsigned int minor = minor(inode->i_rdev);
409#endif
410
411        client = file->private_data;
412        file->private_data = NULL;
413        if (client->adapter->dec_use)
414                client->adapter->dec_use(client->adapter);
415        kfree(client);
416#ifdef DEBUG
417        printk(KERN_DEBUG "i2c-dev.o: Closed: i2c-%d\n", minor);
418#endif
419        return 0;
420}
421
422int i2cdev_attach_adapter(struct i2c_adapter *adap)
423{
424        int i;
425        char name[8];
426
427        if ((i = i2c_adapter_id(adap)) < 0) {
428                printk(KERN_DEBUG "i2c-dev.o: Unknown adapter ?!?\n");
429                return -ENODEV;
430        }
431        if (i >= I2CDEV_ADAPS_MAX) {
432                printk(KERN_DEBUG "i2c-dev.o: Adapter number too large?!? (%d)\n",i);
433                return -ENODEV;
434        }
435
436        sprintf (name, "%d", i);
437        if (! i2cdev_adaps[i]) {
438                i2cdev_adaps[i] = adap;
439#ifdef CONFIG_DEVFS_FS
440                devfs_i2c[i] = devfs_register (devfs_handle, name,
441                        DEVFS_FL_DEFAULT, I2C_MAJOR, i,
442                        S_IFCHR | S_IRUSR | S_IWUSR,
443                        &i2cdev_fops, adap);
444#endif
445                printk(KERN_DEBUG "i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i);
446        } else {
447                /* This is actually a detach_adapter call! */
448#ifdef CONFIG_DEVFS_FS
449                devfs_unregister(devfs_i2c[i]);
450#endif
451                i2cdev_adaps[i] = NULL;
452#ifdef DEBUG
453                printk(KERN_DEBUG "i2c-dev.o: Adapter unregistered: %s\n",adap->name);
454#endif
455        }
456
457        return 0;
458}
459
460int i2cdev_detach_client(struct i2c_client *client)
461{
462        return 0;
463}
464
465static int __init i2c_dev_init(void)
466{
467        int res;
468
469        printk(KERN_INFO "i2c-dev.o: i2c /dev entries driver module version %s (%s)\n", I2C_VERSION, I2C_DATE);
470
471#ifdef CONFIG_DEVFS_FS
472        if (devfs_register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops)) {
473#else
474        if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) {
475#endif
476                printk(KERN_ERR "i2c-dev.o: unable to get major %d for i2c bus\n",
477                       I2C_MAJOR);
478                return -EIO;
479        }
480#ifdef CONFIG_DEVFS_FS
481        devfs_handle = devfs_mk_dir(NULL, "i2c", NULL);
482#endif
483        if ((res = i2c_add_driver(&i2cdev_driver))) {
484                printk(KERN_ERR "i2c-dev.o: Driver registration failed, module not inserted.\n");
485#ifdef CONFIG_DEVFS_FS
486                devfs_unregister(devfs_handle);
487#endif
488                unregister_chrdev(I2C_MAJOR,"i2c");
489                return res;
490        }
491        return 0;
492}
493
494static void __exit i2c_dev_exit(void)
495{
496        i2c_del_driver(&i2cdev_driver);
497#ifdef CONFIG_DEVFS_FS
498        devfs_unregister(devfs_handle);
499#endif
500        unregister_chrdev(I2C_MAJOR,"i2c");
501}
502
503EXPORT_NO_SYMBOLS;
504
505MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>");
506MODULE_DESCRIPTION("I2C /dev entries driver");
507MODULE_LICENSE("GPL");
508
509module_init(i2c_dev_init);
510module_exit(i2c_dev_exit);
Note: See TracBrowser for help on using the browser.