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