⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 the i2c layer.htm

📁 LINUX内核编程的一些程序例子
💻 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-&gt;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-&gt;child-&gt;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 + -