v2.4.8 -> v2.4.8.1
[opensuse:kernel.git] / drivers / i2c / i2c-dev.c
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: i2c-dev.c,v 1.36 2000/09/22 02:19:35 mds Exp $ */
32
33 #include <linux/config.h>
34 #include <linux/kernel.h>
35 #include <linux/module.h>
36 #include <linux/fs.h>
37 #include <linux/slab.h>
38 #include <linux/version.h>
39 #if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
40 #include <linux/smp_lock.h>
41 #endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
42 #ifdef CONFIG_DEVFS_FS
43 #include <linux/devfs_fs_kernel.h>
44 #endif
45
46
47 /* If you want debugging uncomment: */
48 /* #define DEBUG */
49
50 #include <linux/init.h>
51 #include <asm/uaccess.h>
52
53 #include <linux/i2c.h>
54 #include <linux/i2c-dev.h>
55
56 #ifdef MODULE
57 extern int init_module(void);
58 extern int cleanup_module(void);
59 #endif /* def MODULE */
60
61 /* struct file_operations changed too often in the 2.1 series for nice code */
62
63 static ssize_t i2cdev_read (struct file *file, char *buf, size_t count, 
64                             loff_t *offset);
65 static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count, 
66                              loff_t *offset);
67
68 static int i2cdev_ioctl (struct inode *inode, struct file *file, 
69                          unsigned int cmd, unsigned long arg);
70 static int i2cdev_open (struct inode *inode, struct file *file);
71
72 static int i2cdev_release (struct inode *inode, struct file *file);
73
74 static int i2cdev_attach_adapter(struct i2c_adapter *adap);
75 static int i2cdev_detach_client(struct i2c_client *client);
76 static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
77                            void *arg);
78
79 #ifdef MODULE
80 static
81 #else
82 extern
83 #endif
84        int __init i2c_dev_init(void);
85 static int i2cdev_cleanup(void);
86
87 static struct file_operations i2cdev_fops = {
88 #if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
89         owner:          THIS_MODULE,
90 #endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
91         llseek:         no_llseek,
92         read:           i2cdev_read,
93         write:          i2cdev_write,
94         ioctl:          i2cdev_ioctl,
95         open:           i2cdev_open,
96         release:        i2cdev_release,
97 };
98
99 #define I2CDEV_ADAPS_MAX I2C_ADAP_MAX
100 static struct i2c_adapter *i2cdev_adaps[I2CDEV_ADAPS_MAX];
101 #ifdef CONFIG_DEVFS_FS
102 static devfs_handle_t devfs_i2c[I2CDEV_ADAPS_MAX];
103 static devfs_handle_t devfs_handle = NULL;
104 #endif
105
106 static struct i2c_driver i2cdev_driver = {
107         name:           "i2c-dev dummy driver",
108         id:             I2C_DRIVERID_I2CDEV,
109         flags:          I2C_DF_DUMMY,
110         attach_adapter: i2cdev_attach_adapter,
111         detach_client:  i2cdev_detach_client,
112         command:        i2cdev_command,
113 /*      inc_use:        NULL,
114         dec_use:        NULL, */
115 };
116
117 static struct i2c_client i2cdev_client_template = {
118         name:           "I2C /dev entry",
119         id:             1,
120         flags:          0,
121         addr:           -1,
122 /*      adapter:        NULL, */
123         driver:         &i2cdev_driver,
124 /*      data:           NULL */
125 };
126
127 static int i2cdev_initialized;
128
129 static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
130                             loff_t *offset)
131 {
132         char *tmp;
133         int ret;
134
135 #ifdef DEBUG
136         struct inode *inode = file->f_dentry->d_inode;
137 #endif /* DEBUG */
138
139         struct i2c_client *client = (struct i2c_client *)file->private_data;
140
141         /* copy user space data to kernel space. */
142         tmp = kmalloc(count,GFP_KERNEL);
143         if (tmp==NULL)
144                 return -ENOMEM;
145
146 #ifdef DEBUG
147         printk("i2c-dev.o: i2c-%d reading %d bytes.\n",MINOR(inode->i_rdev),
148                count);
149 #endif
150
151         ret = i2c_master_recv(client,tmp,count);
152         if (ret >= 0)
153                 ret = copy_to_user(buf,tmp,count)?-EFAULT:ret;
154         kfree(tmp);
155         return ret;
156 }
157
158 static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
159                              loff_t *offset)
160 {
161         int ret;
162         char *tmp;
163         struct i2c_client *client = (struct i2c_client *)file->private_data;
164
165 #ifdef DEBUG
166         struct inode *inode = file->f_dentry->d_inode;
167 #endif /* DEBUG */
168
169         /* copy user space data to kernel space. */
170         tmp = kmalloc(count,GFP_KERNEL);
171         if (tmp==NULL)
172                 return -ENOMEM;
173         if (copy_from_user(tmp,buf,count)) {
174                 kfree(tmp);
175                 return -EFAULT;
176         }
177
178 #ifdef DEBUG
179         printk("i2c-dev.o: i2c-%d writing %d bytes.\n",MINOR(inode->i_rdev),
180                count);
181 #endif
182         ret = i2c_master_send(client,tmp,count);
183         kfree(tmp);
184         return ret;
185 }
186
187 int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, 
188                   unsigned long arg)
189 {
190         struct i2c_client *client = (struct i2c_client *)file->private_data;
191         struct i2c_rdwr_ioctl_data rdwr_arg;
192         struct i2c_smbus_ioctl_data data_arg;
193         union i2c_smbus_data temp;
194         struct i2c_msg *rdwr_pa;
195         int i,datasize,res;
196         unsigned long funcs;
197
198 #ifdef DEBUG
199         printk("i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n", 
200                MINOR(inode->i_rdev),cmd, arg);
201 #endif /* DEBUG */
202
203         switch ( cmd ) {
204         case I2C_SLAVE:
205         case I2C_SLAVE_FORCE:
206                 if ((arg > 0x3ff) || 
207                     (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
208                         return -EINVAL;
209                 if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
210                         return -EBUSY;
211                 client->addr = arg;
212                 return 0;
213         case I2C_TENBIT:
214                 if (arg)
215                         client->flags |= I2C_M_TEN;
216                 else
217                         client->flags &= ~I2C_M_TEN;
218                 return 0;
219         case I2C_FUNCS:
220                 funcs = i2c_get_functionality(client->adapter);
221                 return (copy_to_user((unsigned long *)arg,&funcs,
222                                      sizeof(unsigned long)))?-EFAULT:0;
223
224         case I2C_RDWR:
225                 if (copy_from_user(&rdwr_arg, 
226                                    (struct i2c_rdwr_ioctl_data *)arg, 
227                                    sizeof(rdwr_arg)))
228                         return -EFAULT;
229
230                 if(rdwr_arg.nmsgs > 2048)
231                         return -EINVAL;
232                         
233                 rdwr_pa = (struct i2c_msg *)
234                         kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), 
235                         GFP_KERNEL);
236
237                 if (rdwr_pa == NULL) return -ENOMEM;
238
239                 res = 0;
240                 for( i=0; i<rdwr_arg.nmsgs; i++ )
241                 {
242                         if(copy_from_user(&(rdwr_pa[i]),
243                                         &(rdwr_arg.msgs[i]),
244                                         sizeof(rdwr_pa[i])))
245                         {
246                                 res = -EFAULT;
247                                 break;
248                         }
249                         rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
250                         if(rdwr_pa[i].buf == NULL)
251                         {
252                                 res = -ENOMEM;
253                                 break;
254                         }
255                         if(copy_from_user(rdwr_pa[i].buf,
256                                 rdwr_arg.msgs[i].buf,
257                                 rdwr_pa[i].len))
258                         {
259                                 kfree(rdwr_pa[i].buf);
260                                 res = -EFAULT;
261                                 break;
262                         }
263                 }
264                 if (!res) 
265                 {
266                         res = i2c_transfer(client->adapter,
267                                 rdwr_pa,
268                                 rdwr_arg.nmsgs);
269                 }
270                 while(i-- > 0)
271                 {
272                         if( res>=0 && (rdwr_pa[i].flags & I2C_M_RD))
273                         {
274                                 if(copy_to_user(
275                                         rdwr_arg.msgs[i].buf,
276                                         rdwr_pa[i].buf,
277                                         rdwr_pa[i].len))
278                                 {
279                                         res = -EFAULT;
280                                 }
281                         }
282                         kfree(rdwr_pa[i].buf);
283                 }
284                 kfree(rdwr_pa);
285                 return res;
286
287         case I2C_SMBUS:
288                 if (copy_from_user(&data_arg,
289                                    (struct i2c_smbus_ioctl_data *) arg,
290                                    sizeof(struct i2c_smbus_ioctl_data)))
291                         return -EFAULT;
292                 if ((data_arg.size != I2C_SMBUS_BYTE) && 
293                     (data_arg.size != I2C_SMBUS_QUICK) &&
294                     (data_arg.size != I2C_SMBUS_BYTE_DATA) && 
295                     (data_arg.size != I2C_SMBUS_WORD_DATA) &&
296                     (data_arg.size != I2C_SMBUS_PROC_CALL) &&
297                     (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
298                     (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA)) {
299 #ifdef DEBUG
300                         printk("i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n",
301                                data_arg.size);
302 #endif
303                         return -EINVAL;
304                 }
305                 /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, 
306                    so the check is valid if size==I2C_SMBUS_QUICK too. */
307                 if ((data_arg.read_write != I2C_SMBUS_READ) && 
308                     (data_arg.read_write != I2C_SMBUS_WRITE)) {
309 #ifdef DEBUG
310                         printk("i2c-dev.o: read_write out of range (%x) in ioctl I2C_SMBUS.\n",
311                                data_arg.read_write);
312 #endif
313                         return -EINVAL;
314                 }
315
316                 /* Note that command values are always valid! */
317
318                 if ((data_arg.size == I2C_SMBUS_QUICK) ||
319                     ((data_arg.size == I2C_SMBUS_BYTE) && 
320                     (data_arg.read_write == I2C_SMBUS_WRITE)))
321                         /* These are special: we do not use data */
322                         return i2c_smbus_xfer(client->adapter, client->addr,
323                                               client->flags,
324                                               data_arg.read_write,
325                                               data_arg.command,
326                                               data_arg.size, NULL);
327
328                 if (data_arg.data == NULL) {
329 #ifdef DEBUG
330                         printk("i2c-dev.o: data is NULL pointer in ioctl I2C_SMBUS.\n");
331 #endif
332                         return -EINVAL;
333                 }
334
335                 if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
336                     (data_arg.size == I2C_SMBUS_BYTE))
337                         datasize = sizeof(data_arg.data->byte);
338                 else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || 
339                          (data_arg.size == I2C_SMBUS_PROC_CALL))
340                         datasize = sizeof(data_arg.data->word);
341                 else /* size == I2C_SMBUS_BLOCK_DATA */
342                         datasize = sizeof(data_arg.data->block);
343
344                 if ((data_arg.size == I2C_SMBUS_PROC_CALL) || 
345                     (data_arg.read_write == I2C_SMBUS_WRITE)) {
346                         if (copy_from_user(&temp, data_arg.data, datasize))
347                                 return -EFAULT;
348                 }
349                 res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
350                       data_arg.read_write,
351                       data_arg.command,data_arg.size,&temp);
352                 if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || 
353                               (data_arg.read_write == I2C_SMBUS_READ))) {
354                         if (copy_to_user(data_arg.data, &temp, datasize))
355                                 return -EFAULT;
356                 }
357                 return res;
358
359         default:
360                 return i2c_control(client,cmd,arg);
361         }
362         return 0;
363 }
364
365 int i2cdev_open (struct inode *inode, struct file *file)
366 {
367         unsigned int minor = MINOR(inode->i_rdev);
368         struct i2c_client *client;
369
370         if ((minor >= I2CDEV_ADAPS_MAX) || ! (i2cdev_adaps[minor])) {
371 #ifdef DEBUG
372                 printk("i2c-dev.o: Trying to open unattached adapter i2c-%d\n",
373                        minor);
374 #endif
375                 return -ENODEV;
376         }
377
378         /* Note that we here allocate a client for later use, but we will *not*
379            register this client! Yes, this is safe. No, it is not very clean. */
380         if(! (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)))
381                 return -ENOMEM;
382         memcpy(client,&i2cdev_client_template,sizeof(struct i2c_client));
383         client->adapter = i2cdev_adaps[minor];
384         file->private_data = client;
385
386         if (i2cdev_adaps[minor]->inc_use)
387                 i2cdev_adaps[minor]->inc_use(i2cdev_adaps[minor]);
388 #if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0)
389         MOD_INC_USE_COUNT;
390 #endif /* LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0) */
391
392 #ifdef DEBUG
393         printk("i2c-dev.o: opened i2c-%d\n",minor);
394 #endif
395         return 0;
396 }
397
398 static int i2cdev_release (struct inode *inode, struct file *file)
399 {
400         unsigned int minor = MINOR(inode->i_rdev);
401         kfree(file->private_data);
402         file->private_data=NULL;
403 #ifdef DEBUG
404         printk("i2c-dev.o: Closed: i2c-%d\n", minor);
405 #endif
406 #if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0)
407         MOD_DEC_USE_COUNT;
408 #else /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
409         lock_kernel();
410 #endif /* LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0) */
411         if (i2cdev_adaps[minor]->dec_use)
412                 i2cdev_adaps[minor]->dec_use(i2cdev_adaps[minor]);
413 #if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
414         unlock_kernel();
415 #endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
416         return 0;
417 }
418
419 int i2cdev_attach_adapter(struct i2c_adapter *adap)
420 {
421         int i;
422         char name[8];
423
424         if ((i = i2c_adapter_id(adap)) < 0) {
425                 printk("i2c-dev.o: Unknown adapter ?!?\n");
426                 return -ENODEV;
427         }
428         if (i >= I2CDEV_ADAPS_MAX) {
429                 printk("i2c-dev.o: Adapter number too large?!? (%d)\n",i);
430                 return -ENODEV;
431         }
432
433         sprintf (name, "%d", i);
434         if (! i2cdev_adaps[i]) {
435                 i2cdev_adaps[i] = adap;
436 #ifdef CONFIG_DEVFS_FS
437                 devfs_i2c[i] = devfs_register (devfs_handle, name,
438                         DEVFS_FL_DEFAULT, I2C_MAJOR, i,
439                         S_IFCHR | S_IRUSR | S_IWUSR,
440                         &i2cdev_fops, NULL);
441 #endif
442                 printk("i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i);
443         } else {
444                 /* This is actually a detach_adapter call! */
445 #ifdef CONFIG_DEVFS_FS
446                 devfs_unregister(devfs_i2c[i]);
447 #endif
448                 i2cdev_adaps[i] = NULL;
449 #ifdef DEBUG
450                 printk("i2c-dev.o: Adapter unregistered: %s\n",adap->name);
451 #endif
452         }
453
454         return 0;
455 }
456
457 int i2cdev_detach_client(struct i2c_client *client)
458 {
459         return 0;
460 }
461
462 static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
463                            void *arg)
464 {
465         return -1;
466 }
467
468 int __init i2c_dev_init(void)
469 {
470         int res;
471
472         printk("i2c-dev.o: i2c /dev entries driver module\n");
473
474         i2cdev_initialized = 0;
475 #ifdef CONFIG_DEVFS_FS
476         if (devfs_register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops)) {
477 #else
478         if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) {
479 #endif
480                 printk("i2c-dev.o: unable to get major %d for i2c bus\n",
481                        I2C_MAJOR);
482                 return -EIO;
483         }
484 #ifdef CONFIG_DEVFS_FS
485         devfs_handle = devfs_mk_dir(NULL, "i2c", NULL);
486 #endif
487         i2cdev_initialized ++;
488
489         if ((res = i2c_add_driver(&i2cdev_driver))) {
490                 printk("i2c-dev.o: Driver registration failed, module not inserted.\n");
491                 i2cdev_cleanup();
492                 return res;
493         }
494         i2cdev_initialized ++;
495         return 0;
496 }
497
498 int i2cdev_cleanup(void)
499 {
500         int res;
501
502         if (i2cdev_initialized >= 2) {
503                 if ((res = i2c_del_driver(&i2cdev_driver))) {
504                         printk("i2c-dev.o: Driver deregistration failed, "
505                                "module not removed.\n");
506                         return res;
507                 }
508         i2cdev_initialized ++;
509         }
510
511         if (i2cdev_initialized >= 1) {
512 #ifdef CONFIG_DEVFS_FS
513                 devfs_unregister(devfs_handle);
514                 if ((res = devfs_unregister_chrdev(I2C_MAJOR, "i2c"))) {
515 #else
516                 if ((res = unregister_chrdev(I2C_MAJOR,"i2c"))) {
517 #endif
518                         printk("i2c-dev.o: unable to release major %d for i2c bus\n",
519                                I2C_MAJOR);
520                         return res;
521                 }
522                 i2cdev_initialized --;
523         }
524         return 0;
525 }
526
527 EXPORT_NO_SYMBOLS;
528
529 #ifdef MODULE
530
531 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>");
532 MODULE_DESCRIPTION("I2C /dev entries driver");
533
534 int init_module(void)
535 {
536         return i2c_dev_init();
537 }
538
539 int cleanup_module(void)
540 {
541         return i2cdev_cleanup();
542 }
543
544 #endif /* def MODULE */
545