OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [i2c/] [i2c-dev.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.