Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
i2c
i2c-stub.c
Go to the documentation of this file.
1
/*
2
i2c-stub.c - I2C/SMBus chip emulator
3
4
Copyright (c) 2004 Mark M. Hoffman <
[email protected]
>
5
Copyright (C) 2007, 2012 Jean Delvare <
[email protected]
>
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
#define DEBUG 1
23
24
#include <
linux/init.h
>
25
#include <linux/module.h>
26
#include <linux/kernel.h>
27
#include <linux/slab.h>
28
#include <linux/errno.h>
29
#include <linux/i2c.h>
30
31
#define MAX_CHIPS 10
32
#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
33
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
34
I2C_FUNC_SMBUS_I2C_BLOCK)
35
36
static
unsigned
short
chip_addr[
MAX_CHIPS
];
37
module_param_array
(chip_addr,
ushort
,
NULL
,
S_IRUGO
);
38
MODULE_PARM_DESC
(chip_addr,
39
"Chip addresses (up to 10, between 0x03 and 0x77)"
);
40
41
static
unsigned
long
functionality =
STUB_FUNC
;
42
module_param
(functionality,
ulong
,
S_IRUGO
|
S_IWUSR
);
43
MODULE_PARM_DESC
(functionality,
"Override functionality bitfield"
);
44
45
struct
stub_chip
{
46
u8
pointer
;
47
u16
words
[256];
/* Byte operations use the LSB as per SMBus
48
specification */
49
};
50
51
static
struct
stub_chip
*stub_chips;
52
53
/* Return negative errno on error. */
54
static
s32
stub_xfer(
struct
i2c_adapter
*adap,
u16
addr
,
unsigned
short
flags
,
55
char
read_write,
u8
command
,
int
size
,
union
i2c_smbus_data
*
data
)
56
{
57
s32
ret
;
58
int
i
,
len
;
59
struct
stub_chip
*
chip
=
NULL
;
60
61
/* Search for the right chip */
62
for
(i = 0; i <
MAX_CHIPS
&& chip_addr[
i
]; i++) {
63
if
(addr == chip_addr[i]) {
64
chip = stub_chips +
i
;
65
break
;
66
}
67
}
68
if
(!chip)
69
return
-
ENODEV
;
70
71
switch
(size) {
72
73
case
I2C_SMBUS_QUICK
:
74
dev_dbg
(&adap->
dev
,
"smbus quick - addr 0x%02x\n"
, addr);
75
ret = 0;
76
break
;
77
78
case
I2C_SMBUS_BYTE
:
79
if
(read_write ==
I2C_SMBUS_WRITE
) {
80
chip->
pointer
=
command
;
81
dev_dbg
(&adap->
dev
,
82
"smbus byte - addr 0x%02x, wrote 0x%02x.\n"
,
83
addr, command);
84
}
else
{
85
data->
byte
= chip->
words
[chip->
pointer
++] & 0xff;
86
dev_dbg
(&adap->
dev
,
87
"smbus byte - addr 0x%02x, read 0x%02x.\n"
,
88
addr, data->
byte
);
89
}
90
91
ret = 0;
92
break
;
93
94
case
I2C_SMBUS_BYTE_DATA
:
95
if
(read_write ==
I2C_SMBUS_WRITE
) {
96
chip->
words
[
command
] &= 0xff00;
97
chip->
words
[
command
] |= data->
byte
;
98
dev_dbg
(&adap->
dev
,
99
"smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n"
,
100
addr, data->
byte
, command);
101
}
else
{
102
data->
byte
= chip->
words
[
command
] & 0xff;
103
dev_dbg
(&adap->
dev
,
104
"smbus byte data - addr 0x%02x, read 0x%02x at 0x%02x.\n"
,
105
addr, data->
byte
, command);
106
}
107
chip->
pointer
= command + 1;
108
109
ret = 0;
110
break
;
111
112
case
I2C_SMBUS_WORD_DATA
:
113
if
(read_write ==
I2C_SMBUS_WRITE
) {
114
chip->
words
[
command
] = data->
word
;
115
dev_dbg
(&adap->
dev
,
116
"smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n"
,
117
addr, data->
word
, command);
118
}
else
{
119
data->
word
= chip->
words
[
command
];
120
dev_dbg
(&adap->
dev
,
121
"smbus word data - addr 0x%02x, read 0x%04x at 0x%02x.\n"
,
122
addr, data->
word
, command);
123
}
124
125
ret = 0;
126
break
;
127
128
case
I2C_SMBUS_I2C_BLOCK_DATA
:
129
len = data->
block
[0];
130
if
(read_write ==
I2C_SMBUS_WRITE
) {
131
for
(i = 0; i < len; i++) {
132
chip->
words
[command +
i
] &= 0xff00;
133
chip->
words
[command +
i
] |= data->
block
[1 +
i
];
134
}
135
dev_dbg
(&adap->
dev
,
136
"i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n"
,
137
addr, len, command);
138
}
else
{
139
for
(i = 0; i < len; i++) {
140
data->
block
[1 +
i
] =
141
chip->
words
[command +
i
] & 0xff;
142
}
143
dev_dbg
(&adap->
dev
,
144
"i2c block data - addr 0x%02x, read %d bytes at 0x%02x.\n"
,
145
addr, len, command);
146
}
147
148
ret = 0;
149
break
;
150
151
default
:
152
dev_dbg
(&adap->
dev
,
"Unsupported I2C/SMBus command\n"
);
153
ret = -
EOPNOTSUPP
;
154
break
;
155
}
/* switch (size) */
156
157
return
ret
;
158
}
159
160
static
u32
stub_func(
struct
i2c_adapter
*
adapter
)
161
{
162
return
STUB_FUNC
& functionality;
163
}
164
165
static
const
struct
i2c_algorithm
smbus_algorithm = {
166
.functionality = stub_func,
167
.smbus_xfer = stub_xfer,
168
};
169
170
static
struct
i2c_adapter
stub_adapter = {
171
.owner =
THIS_MODULE
,
172
.class =
I2C_CLASS_HWMON
|
I2C_CLASS_SPD
,
173
.algo = &smbus_algorithm,
174
.name =
"SMBus stub driver"
,
175
};
176
177
static
int
__init
i2c_stub_init(
void
)
178
{
179
int
i
,
ret
;
180
181
if
(!chip_addr[0]) {
182
pr_err
(
"i2c-stub: Please specify a chip address\n"
);
183
return
-
ENODEV
;
184
}
185
186
for
(i = 0; i <
MAX_CHIPS
&& chip_addr[
i
]; i++) {
187
if
(chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
188
pr_err
(
"i2c-stub: Invalid chip address 0x%02x\n"
,
189
chip_addr[i]);
190
return
-
EINVAL
;
191
}
192
193
pr_info
(
"i2c-stub: Virtual chip at 0x%02x\n"
, chip_addr[i]);
194
}
195
196
/* Allocate memory for all chips at once */
197
stub_chips = kzalloc(i *
sizeof
(
struct
stub_chip
),
GFP_KERNEL
);
198
if
(!stub_chips) {
199
pr_err
(
"i2c-stub: Out of memory\n"
);
200
return
-
ENOMEM
;
201
}
202
203
ret =
i2c_add_adapter
(&stub_adapter);
204
if
(ret)
205
kfree
(stub_chips);
206
return
ret
;
207
}
208
209
static
void
__exit
i2c_stub_exit(
void
)
210
{
211
i2c_del_adapter
(&stub_adapter);
212
kfree
(stub_chips);
213
}
214
215
MODULE_AUTHOR
(
"Mark M. Hoffman <
[email protected]
>"
);
216
MODULE_DESCRIPTION
(
"I2C stub driver"
);
217
MODULE_LICENSE
(
"GPL"
);
218
219
module_init
(i2c_stub_init);
220
module_exit
(i2c_stub_exit);
Generated on Thu Jan 10 2013 13:35:58 for Linux Kernel by
1.8.2