File: /usr/src/linux/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     
546