?? the i2c layer.htm
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0061)http://www.geocities.com/marco_corvi/games/lkpe/i2c/index.htm -->
<HTML><HEAD><TITLE>The I2C layer</TITLE>
<META http-equiv=Content-Type content="text/html; charset=windows-1252"><LINK
href="The I2C layer_file/style.css" rel=stylesheet>
<META content="MSHTML 6.00.2800.1170" name=GENERATOR></HEAD>
<BODY>
<H2>The I2C layer</H2>
<DIV>References:<BR><A href="http://secure.netroedge.com/~lm78/"
target=_top>http://secure.netroedge.com/~lm78/</A><BR>Documentation/i2c<BR></DIV><BR
clear=all><BR clear=all><BR clear=all>
<DIV><IMG height=55 src="The I2C layer_file/i2clogo.jpg" width=50 align=left
VALIGN="TOP"> I2C (Inter-Integrated Circuit), pronounced "i square c", is a
simple two wire bus protocol developed by Philips for intercommunication among
integrated circuits. It has become a de-facto standard due to its semplicity and
the possibility to manage flexible addressing. </DIV>
<DIV>The I2C core layer manages bus adapters, device drivers and device clients.
Devices can be on the i2c bus or an attached bus (eg, isa); drivers manages
classes of devices, and clients describe individual devices. The I2C core
provides the communication protocol(s). It uses a callback mechanims the set up
the relations among the components. Callbacks that manage the components
relations cannot be NULL, the other callbacks may be NULL if the object does not
need to do anything. </DIV>
<DIV>Every object (driver, client, adapter, and algorithm) has a name (an
descriptive string up to 32 chars), an id (unique identification number), and
flags (that define how it should be used). clients and adapters have a private
data field which can point to specific structures. </DIV>
<DIV>The <B>driver</B> id's in the range 0xf000 to 0xffff are reserved for local
use. So one can use one of these to test an I2C driver. As for the flags it is
important to define I2C_DF_NOTIFY so that the driver is notified whenever a new
adapter is found. Finally the driver's name should be a descriptive string (up
to 40 chars). </DIV>
<DIV>The driver's inc/dec_use() can just be MOD_INC/DEC_USE_COUNT, so that the
driver's code is not unloaded while an application is using it, if the driver is
compiled as a module. command() is an ioctl-like interface. attach_adapter() is
called by the I2C core when the driver is registered or when a new adapter is
inserted. detach_client() is called when a client is removed. </DIV>
<DIV>The <B>client</B> represents an individual device. It has a pointer to its
driver and to the adapter used for communications. Clients that want to have
usage_count managed by I2C core should set the flags I2C_CLIENT_ALLOW_USE, and
I2C_CLIENT_ALLOW_MULTIPLE_USE for multiple use. These are checked by
i2c_use_client() and i2c_release_client(). </DIV>
<DIV>The <B>algorithm</B> encompasses the data manipulation of a transfer.
functionality() shuold return a flag of supported functionalities (I2C_FUNC_XXX
things). master_xfer() is the core transfer function, on which other i/o
functions rely. </DIV>
<DIV>The <B>adapter</B> describes a bus. It has a pointer to the algorithm used
to transfer data, a list of clients, and two methods to allow client
registration and unregistration. </DIV><BR clear=all><IMG height=480
src="The I2C layer_file/i2c.gif" width=640> <BR clear=all>
<H3>The I2C core functions</H3>
<DIV><B>The object management functions</B>
<UL>
<LI>i2c_adapter_id(adapter) returns the adapter's id;
<LI>i2c_get_functionality(adapter) if the adapter's algorithm has the
functionality() method returns its result, otherwise returns 0xffffffff, which
means "every functionality";
<LI>i2c_check_functionality(adapter, func) checks if func is included in
i2c_get_functionality(adapter) (this is always true if the adapter's algorithm
does not implement functionality();
<LI>i2c_check_addr(adapter, addr) returns -EBUSY if there is already a client
of the adapter that is using the address; <BR>
<LI>i2c_add_adapter(adapter) inserts the adapter in the adapters[] array and
for each driver, that has flags I2C_DF_NOTIFY | I2C_DF_DUMMY, calls the
attach_adapter() callback;
<LI>i2c_del_adapter(adapter) for each client of the adapter calls the driver's
detach_client() callback, and finally it removes the adapter from adapters[];
<BR>
<LI>i2c_add_driver(driver) inserts the driver in the drivers[] array and, if
the driver flags has I2C_DF_NOTIFY | I2C_DF_DUMMY, calls the driver's callback
attach_adapter() on each adapters[];
<LI>i2c_del_driver(driver) scans the adapters[] list and, for each adapter
client that has that driver, calls the driver's detach_client() callback; <BR>
<LI>i2c_attach_client(client): the client must have address (addr) and
adapter. It first checks that the client address is not busy (i2c_check_addr).
Then inserts the client in the adapter's clients[] list, and calls the
adapter's client_register() callback.
<LI>i2c_inc_use_client() and i2c_dec_use_client() are called when an
application opens/closes a client. They forward to the client's driver and
adapter inc/dec_use methods;
<LI>i2c_get_client(dr_id, ad_id, client) ...
<LI>i2c_use_client() and i2c_release_client() change the client's usage_count
and call the i2c/inc/dec_use_client(). </LI></UL></DIV>
<DIV><B>The bus functions</B>
<UL>
<LI>transfer(adapter, msg[], num) calls the adapter's algorithm master_xfer(),
if there is one;
<LI>i2c_master_send(client, buf, cnt) and i2c_master_recv(client, buf, cnt)
prepares a message and calls the adapter's algorithm master_xfer(), if there
is one;
<LI>i2c_probe(adapter, address_data, found_fct) scans the addresses from 0x00
to 0x7f (seven bit address line): skip if the address is in use
(i2c_check_addr), if the adapter id is among the "force" list call the
found_fct(adapter,addr,0,0), otherwise skip if it is among the "ignore", or do
a probe if it is "normal" or "probe": examine if there is a client with
i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) and call the
found_fct(adapter,addr,0,-1). </LI></UL>
<DIV>
<DIV><B>The smbus functions</B> <BR>The I/O functions are defined in terms of
i2c_smbus_xfer():
<UL>
<LI>i2c_smbus_xfer(adapter, addr, flags, rw, cmd, size, data) if the adapter's
algorithm has smbus_xfer() method use it, otherwise use the
i2c_smbus_xfer_emulate() method;
<LI>i2c_smbus_xfer_emulate(...) emulates the SMBus on the I2C bus. It has an
array of two messages (uses 2 for READ, 1 for WRITE). If the size is
I2C_SMBUS_QUICK is a zero-length message. Otherwise sets up the message(s)
data properly and calls i2c_transfer(adapter, msg, num). In case of read,
reads the response back into the data.
<LI>i2c_smbus_write_quick(client, value)
<LI>i2c_smbus_read_byte(client)
<LI>i2c_smbus_write_byte(client, value(;
<LI>i2c_smbus_read_byte_data(client, cmd);
<LI>i2c_smbus_write_byte_data(client, cmd, value);
<LI>i2c_smbus_read_word_data(client, cmd);
<LI>i2c_smbus_write_word_data(client, cmd, value);
<LI>i2c_smbus_process_call(client, cmd, value);
<LI>i2c_smbus_read_block_data(client, cmd, values);
<LI>i2c_smbus_write_block_data(client, cmd, len, values);
<LI>i2c_smbus_write_i2c_block_data(client, cmd, len, values); </LI></UL></DIV>
<H3>The I2C device functions</H3>
<DIV>The module i2c-dev.c provides a /dev interface of i2c adapters to user
applications. Each i2c adapter receives a number from the I2C core. This number
can be seen through the /proc/bus/i2c interface. The I2C adapters are character
devices with major 89 and minor that number assigned by the I2C core. </DIV>
<DIV>The code i2c-dev.c defines a dummy i2c_driver (named i2cdev_driver) with
methods i2cdev_attach_adapter, i2cdev_detach_client, and i2cdev_command, and an
i2c_client template (named i2cdev_client_template) with the i2cdev_driver, no
adapter, and no private data. </DIV>
<DIV>The I2C device operations are (these oerations act on the client which is
stored in the file' private_data filed)
<UL>
<LI>i2cdev_lseek (from version 2.4.10 only): return -ESPIPE.
<LI>i2cdev_read: an i2c_master_recv() on the client.
<LI>i2cdev_write: an i2c_master_send() on the client.
<LI>i2cdev_ioctl.
<LI>i2cdev_open, creates a new client (after the i2cdev_client_template) with
adapter the i2cdev_adaps indexed by the inode minor. Possibly calls the
adapter' inc_use().
<LI>i2cdev_release: free the file' private_data (the client) and possibly
calls the adapter' dec_use(). </LI></UL><BR>The ioctl commands are (arg is the
ioctl argument)
<UL>
<LI>I2C_SLAVE or I2C_SLAVE_FORCE, set the client address to arg;
<LI>I2C_TENBIT: set (arg != 0) or clear the flag I2C_M_TEN (ten-bit
addresses);
<LI>I2C_FUNCS: get the functionality of the client' adapter;
<LI>I2C_RDWR: arg should point to an i2c_rdwr_ioctl_data structure. It copies
the data from user space, calls i2c_transfer(), and eventually copies the data
back to user space.
<LI>I2C_SMBUS: arg should point to an i2c_smbus_ioctl_data structure. It calls
i2c_smbus_xfer(). The i2c_smbus_ioctl_data struct contains a rw flag, a
command, the size of the data and the data pointer (of type i2c_smbus_data).
</LI></UL></DIV>
<DIV>The management functions are
<UL>
<LI>i2cdev_attach_adapter: inserts the adapter in the i2cdev_adaps[] list.
<LI>i2cdev_detach_client: does nothing, returns 0.
<LI>i2cdev_command: always returns -1.
<LI>i2cdev_init: registers a char device ("i2c") with i2cdev_fops, and adds to
it the dummy driver i2cdev_driver.
<LI>i2cdev_cleanup: (possibly) unregister the char dev. </LI></UL></DIV>
<DIV>The SMbus I/O functions are defined in terms of i2c_smbus_access(file, rw,
cmd, size, data), which fills an i2c_smbus_ioctl_data with the arguments and
calls ioctl(file, I2C_SMBUS, args) which in turns calls i2c_smbus_xfer() to do
the actual i/o. </DIV>
<H3>The I2C proc functions</H3>
<DIV>The I2C proc interface is defined in the header file
include/linux/i2c-proc.h. A general callback function type is declared as <PRE> i2c_real_callback( client, op, ctl_name, nrels_mag, results )
</PRE>where "client" is a pointer to a client device we want to interact with,
"op" is an operation flag that can be one of SENSORS_PROC_REAL_INFO/READ/WRITE.
Before using the callback function a ctl_table must be registered; ctl_name -s
the SYSCTL id of the file being accessed. The function reads or writes real
numbers; these are coded as an integer ("results") and a magnitude ("nrels_mag")
which is the power of 10 by which the integer must be divided to get the real
number (the magnitude can also be negative). For READ/WRITE operations
"nrels_mag" contains on return the number of elements read or written. </DIV>
<DIV>The structure ctl_table (include/linux/sysctl.h) contains
<UL>
<LI>ctl_name: a binary id;
<LI>procname: string;
<LI>data: private data pointer, and its "maxlen";
<LI>mode: protection rights;
<LI>two callbacks, proc_handler(), for text formatting, and ctl_handler(), for
all i/o;
<LI>a proc_dir_entry pointer;
<LI>two extra generic (void *) pointers. </LI></UL>Four control tables are
defined in drivers/linux/i2c-proc.c (all terminated by a NULL entry),
<UL>
<LI>sysctl_table, with CTL_DEV, DEV_SENSORS entries, and a zero entry;
<LI>i2c_proc_dev_sensors, with SENSORS_CHIPS entry (callbacks: i2c_proc_chips,
i2c_sysctl_chips);
<LI>i2c_proc_dev, with DEV_SENSORS entry (callback: i2c_proc_dev_sensors);
<LI>i2c_proc, with CTL_DEV entry (callback: i2c_proc_dev). </LI></UL></DIV>
<DIV>i2c_register_entry( client, prefix, ctl_table, module) and
i2c_deregister_entry( id ) are used to add and remove an entry in the
/proc/sys/dev/sensors/chips and a directory in /proc/sys/dev/sensors/.
"ctl_table" should be a template for the newly created directory. A new
ctl_table is allocated and filled. The second extra field is pointed to
"client". The controlling "module" should usually be THIS_MODULE The new table
is registered with sysctl ( register_sysctl_table ) and the etries of the lists
i2c_entries[] (ctl_table_header), i2c_clients[], i2c_inodes[] are updated.
Deregistration is the reversed actions. </DIV>
<DIV>i2c_create_name() returns a nice name for a new proc directory. </DIV>
<DIV>i2c_fill_inode(inode, fill) increases/decreases the MOD_USE_COUNT,
depending on the "fill" parameter. i2c_dir_fill_inode(inode, fill) finds the
i2c_client with the given inode number (inode->i_ino), and calls its driver's
inc/dec_use(). </DIV>
<DIV>i2c_proc_chips( ctl_table, rw, filp, buffer, len ) is the proc interface to
the chips names. For each non-NULL entry in i2c_entries[] writes the
ctl_table->child->child name and procname to the user buffer.
<BR>i2c_sysctl_chips(ctl_table, name, len, oldval, oldlen, newval, newlen,
context) is the sysctl interface. [TO DO] </DIV>
<DIV>i2c_sysctl_real( ctl_table, name, len, oldval, oldlen, newval, newlen,
context) and i2c_proc_real( ctl_table, rw, filp, buffer, len) are the functions
that perform the i/o. i2c_proc_real() firts gets the magnitude, next does the
i/o, which consists of real-long conversion (i2c_parse_reals / i2c_write_reals)
and i/o on the client (using the function callback()). i2c_sysctl_real() ... [TO
DO]. i2c_parse_reals() and i2c_write_reals() are not discussed. </DIV>
<DIV>i2c_detect(adapter, addr_data, found_proc) is an inefficient ISA detect
function, similar to i2c_probe(). [TO DO]. </DIV>
<H3>More reading</H3>
<DIV><A
href="http://www.geocities.com/marco_corvi/games/lkpe/i2c/i2c-proto.htm">I2C
protocol</A><BR></DIV>
<H3>Example</H3>
<DIV>Here are some instructions to write a sample adapter and driver for the I2C
layer: <A
href="http://www.geocities.com/marco_corvi/games/lkpe/i2c/example.htm">example</A>
</DIV><BR clear=all><BR clear=all><FONT size=-1>Marco Corvi - 2003</FONT> <!-- text below generated by server. PLEASE REMOVE --></OBJECT></LAYER></DIV></SPAN></STYLE></NOSCRIPT></TABLE></SCRIPT></APPLET>
<SCRIPT
language=JavaScript>var PUpage="76001084"; var PUprop="geocities"; </SCRIPT>
<SCRIPT language=JavaScript src="The I2C layer_file/pu5geo.js"></SCRIPT>
<SCRIPT language=JavaScript src="The I2C layer_file/ygIELib9.js"></SCRIPT>
<SCRIPT language=JavaScript>var yviContents='http://us.toto.geo.yahoo.com/toto?s=76001084&l=NE&b=1&t=1057746741';yviR='us';yfiEA(0);</SCRIPT>
<SCRIPT language=JavaScript src="The I2C layer_file/mc.js"></SCRIPT>
<SCRIPT language=JavaScript src="The I2C layer_file/geov2.js"></SCRIPT>
<SCRIPT language=javascript>geovisit();</SCRIPT>
<NOSCRIPT><IMG height=1 alt=setstats src="The I2C layer_file/visit.gif" width=1
border=0></NOSCRIPT> <IMG height=1 alt=1 src="The I2C layer_file/serv.gif"
width=1> <!-- w16.geo.scd.yahoo.com compressed/chunked Wed Jul 9 03:32:21 PDT 2003 --></DIV></BODY></HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -