驱动模块使用I2C总线范例
来源:互联网 发布:万网解析域名设置 编辑:程序博客网 时间:2024/05/19 16:35
原文http://blog.csdn.net/azloong/article/details/6178657
源码是在linux2.6下写的,为了移值到更高的linux版本,进行了一定的修改。
#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/list.h>#include <linux/i2c.h>#include <linux/hardirq.h>#include <linux/slab.h> #define I2C_API_FAKE_ADDR 0x7f#define I2C_MINORS 256//#define i2c_version_old 1 int i2c_api_attach(struct i2c_adapter *adapter);int i2c_api_detach(struct i2c_adapter *adapter); struct i2c_api { struct list_head list; struct i2c_client *client;}; static LIST_HEAD(i2c_api_list);static DEFINE_SPINLOCK(i2c_api_list_lock); static const unsigned short normal_addr[] = { I2C_API_FAKE_ADDR, I2C_CLIENT_END };static const unsigned short ignore[] = { I2C_CLIENT_END };#ifdef i2c_version_oldstatic struct i2c_client_address_data addr_data = { .normal_i2c = normal_addr, .probe = ignore, .ignore = ignore, .forces = NULL,};#endifstatic const struct i2c_device_id id[] = { {"I2C-API", 0}, {} }; MODULE_DEVICE_TABLE(i2c, id); static struct i2c_driver i2c_api_driver = { .id_table = id, .attach_adapter = i2c_api_attach, //#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) #if 0 .detach_adapter = i2c_api_detach,#endif .command = NULL, .driver = {.name = "I2C-API",.owner = THIS_MODULE, },#ifdef i2c_version_old .address_data = &addr_data,#endif }; static struct i2c_api *get_i2c_api(int bus_id){ struct i2c_api *i2c_api; spin_lock(&i2c_api_list_lock); list_for_each_entry(i2c_api, &i2c_api_list, list) { if (i2c_api->client->adapter->nr == bus_id) goto found; } i2c_api = NULL; found: spin_unlock(&i2c_api_list_lock); return i2c_api;} static struct i2c_api *add_i2c_api(struct i2c_client *client){ struct i2c_api *i2c_api; if (client->adapter->nr >= I2C_MINORS) { printk(KERN_ERR "i2c_api: Out of device minors (%d)/n", client->adapter->nr); return NULL; } i2c_api = kzalloc(sizeof(*i2c_api), GFP_KERNEL); if (!i2c_api) return NULL; i2c_api->client = client; spin_lock(&i2c_api_list_lock); list_add_tail(&i2c_api->list, &i2c_api_list); spin_unlock(&i2c_api_list_lock); return i2c_api;} static void del_i2c_api(struct i2c_api *i2c_api){ spin_lock(&i2c_api_list_lock); list_del(&i2c_api->list); spin_unlock(&i2c_api_list_lock); kfree(i2c_api);} static int i2c_api_do_xfer(int bus_id, char chip_addr, char sub_addr, int mode, char *buf, unsigned int size){/** you could define more transfer mode here, implement it following. */#define I2C_API_XFER_MODE_SEND 0x0 /* standard send */#define I2C_API_XFER_MODE_RECV 0x1 /* standard receive */#define I2C_API_XFER_MODE_SEND_NO_SUBADDR 0x2 /* send without sub-address */#define I2C_API_XFER_MODE_RECV_NO_SUBADDR 0x3 /* receive without sub-address */ int ret = 0; char *tmp; struct i2c_api *i2c_api = get_i2c_api(bus_id); if (!i2c_api) return -ENODEV; i2c_api->client->addr = chip_addr; switch (mode) { case I2C_API_XFER_MODE_SEND: tmp = kmalloc(size + 1,GFP_KERNEL); if (tmp == NULL) return -ENOMEM; tmp[0] = sub_addr; memcpy(&tmp[1], buf, size); ret = i2c_master_send(i2c_api->client, tmp, size + 1); ret = (ret == size + 1) ? size : ret; break; case I2C_API_XFER_MODE_RECV: ret = i2c_master_send(i2c_api->client, &sub_addr, 1); if (ret < 0) return ret; ret = i2c_master_recv(i2c_api->client, buf, size); break; case I2C_API_XFER_MODE_SEND_NO_SUBADDR: ret = i2c_master_send(i2c_api->client, buf, size); break; case I2C_API_XFER_MODE_RECV_NO_SUBADDR: ret = i2c_master_recv(i2c_api->client, buf, size); break; default: return -EINVAL; } return ret;} int i2c_api_do_send(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size){ return i2c_api_do_xfer(bus_id, chip_addr, sub_addr, I2C_API_XFER_MODE_SEND, buf, size);} int i2c_api_do_recv(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size){ return i2c_api_do_xfer(bus_id, chip_addr, sub_addr, I2C_API_XFER_MODE_RECV, buf, size);} int i2c_api_attach(struct i2c_adapter *adap){ struct i2c_board_info info; struct i2c_client *client; memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "i2c_api", I2C_NAME_SIZE); info.addr = I2C_API_FAKE_ADDR; client = i2c_new_device(adap, &info); if (client) add_i2c_api(client); printk(KERN_INFO "i2c_api_attach adap[%d]/n", adap->nr); return 0;} int i2c_api_detach(struct i2c_adapter *adap){ struct i2c_api *i2c_api; i2c_api = get_i2c_api(adap->nr); if (i2c_api) del_i2c_api(i2c_api); return 0;} static int __init i2c_api_init(void){ int ret = i2c_add_driver(&i2c_api_driver); if (ret) { printk(KERN_ERR "[%s] Driver registration failed, module not inserted./n", __func__); return ret; } return 0 ; } static void __exit i2c_api_exit(void){ i2c_del_driver(&i2c_api_driver);} MODULE_AUTHOR("Loon, <sepnic@gmail.com>");MODULE_DESCRIPTION("I2C i2c_api Driver");MODULE_LICENSE("GPL"); module_init(i2c_api_init);module_exit(i2c_api_exit); EXPORT_SYMBOL_GPL(i2c_api_do_send);EXPORT_SYMBOL_GPL(i2c_api_do_recv);
0 0
- 驱动模块使用I2C总线范例
- 驱动模块使用I2C总线范例
- 驱动模块使用SPI总线范例
- 驱动模块使用SPI总线范例
- I2c总线驱动
- I2C总线驱动
- Linux I2C 总线驱动
- linux i2c总线驱动
- I2C总线驱动代码
- I2C总线驱动
- kernel I2C总线驱动
- 浅析I2C总线驱动
- S3C2410 I2C 总线驱动实例
- S3C2410 I2C 总线驱动实例
- Linux驱动之I2C总线
- Linux I2C子系统分析-I2C总线驱动
- Linux I2C子系统分析-I2C总线驱动
- Linux I2C子系统分析-I2C总线驱动
- POJ-2356 Find a multiple(DFS,抽屉原理)
- 每天学习十分钟12之Java学习笔记
- 稀疏矩阵运算器
- 在Activity间使用Intent传递信息
- 二叉树的非递归遍历
- 驱动模块使用I2C总线范例
- 指针与自增运算----(*p)++ 与 *p++ 与 ++*p 拨开一团迷雾
- 浮点数精确到小数点后一位(java)
- 移除Win10资源管理器中OneDrive图标
- 【转】贝叶斯网络+马尔科夫毯 简介
- 什么是窗口句柄
- Win10开发:Flyout的使用及长按弹出菜单的实现
- HTML游戏—爱心鱼
- java入门学习(一)