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