1.应用程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char**argv)
{
int fd;
char buf[6];
int len;
fd = open("/dev/Ap3216c", O_RDWR);
if (fd == -1)
{
printf("can not open /dev/Ap3216c");
return -1;
}
while(1)
{
len = read(fd,buf,6);
printf("App read: ");
for (len = 0; len < 6; len++)
{
printf("%02x ",buf[len]);
}
printf("\n");
sleep(2);
}
close(fd);
return 0;
}
2.i2c-driver程序
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/mod_devicetable.h>
#include <linux/bitops.h>
#include <linux/jiffies.h>
#include <linux/property.h>
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/nvmem-provider.h>
#include <linux/regmap.h>
#include <linux/pm_runtime.h>
#include <linux/gpio/consumer.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
static int major = 0;
static struct i2c_client *Ap3216c_client;
static struct class *Ap3216c_class;
static int Ap3216c_open(struct inode *node, struct file *file)
{
//printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
i2c_smbus_write_byte_data(Ap3216c_client, 0, 0x4);
mdelay(250);
i2c_smbus_write_byte_data(Ap3216c_client, 0, 0x3);
mdelay(250);
return 0;
}
static ssize_t Ap3216c_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
int err;
char kernel_buf[6];
int val;
//printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
if (size != 6)
{
return -EINVAL;
}
val = i2c_smbus_read_word_data(Ap3216c_client, 0xA); /* read IR */
kernel_buf[0] = val & 0xff;
kernel_buf[1] = (val >> 8) & 0xff;
val = i2c_smbus_read_word_data(Ap3216c_client, 0xC); /* read 光强 */
kernel_buf[2] = val & 0xff;
kernel_buf[3] = (val >> 8) & 0xff;
val = i2c_smbus_read_word_data(Ap3216c_client, 0xE); /* read 距离 */
kernel_buf[4] = val & 0xff;
kernel_buf[5] = (val >> 8) & 0xff;
err = copy_to_user(buf, kernel_buf, size);
if (err < 0)
{
printk("copy_to_user err\n");
return -1;
}
return size;
}
static const struct of_device_id of_match_ids_Ap3216c[] ={
{.compatible = "lite-on,Ap3216c", .data = NULL },
{/* END OF LIST */}
};
static const struct file_operations Ap3216c_ops = {
.owner = THIS_MODULE,
.open = Ap3216c_open,
.read = Ap3216c_read,
};
static int Ap3216c_probe(struct i2c_client * client, const struct i2c_device_id * id)
{
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
Ap3216c_client = client;
/* 注册字符设备 */
major = register_chrdev(major, "Ap3216c", &Ap3216c_ops);
if (major < 0)
{
printk("register_chrdev err\n");
return -1;
}
/* 注册类 */
Ap3216c_class = class_create(THIS_MODULE, "Ap3216c_class");
/* 注册设备 */
device_create(Ap3216c_class, NULL, MKDEV(major,0), NULL, "Ap3216c");
return 0;
}
static int Ap3216c_remove(struct i2c_client * client)
{
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
device_destroy(Ap3216c_class, MKDEV(major,0));
class_destroy(Ap3216c_class);
unregister_chrdev(major, "Ap3216c");
return 0;
}
static const struct i2c_device_id Ap3216c_ids[] = {
{"Ap3216c", (kernel_ulong_t)NULL },
{/* END OF LIST */}
};
static struct i2c_driver i2c_Ap3216c_driver = {
.driver = {
.name = "Ap3216c",
.of_match_table = of_match_ids_Ap3216c,
},
.probe = Ap3216c_probe,
.remove = Ap3216c_remove,
.id_table = Ap3216c_ids,
};
static int __init i2c_driver_Ap3216c_init(void)
{
printk("%s %s line: %d\n", __FILE__, __FUNCTION__, __LINE__);
return i2c_add_driver(&i2c_Ap3216c_driver);
}
static void __exit i2c_driver_Ap3216c_exit(void)
{
i2c_del_driver(&i2c_Ap3216c_driver);
}
module_init(i2c_driver_Ap3216c_init);
module_exit(i2c_driver_Ap3216c_exit);
MODULE_LICENSE("GPL");
3.i2c-client程序
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/mod_devicetable.h>
#include <linux/bitops.h>
#include <linux/jiffies.h>
#include <linux/property.h>
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/nvmem-provider.h>
#include <linux/regmap.h>
#include <linux/pm_runtime.h>
#include <linux/gpio/consumer.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#if 1
static struct i2c_client *Ap3216c_client;
static int __init i2c_client_Ap3216c_init(void)
{
struct i2c_adapter* adapter;
struct i2c_board_info board_info = {
I2C_BOARD_INFO("Ap3216c", 0x1e),
};
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
/* register I2C device */
adapter = i2c_get_adapter(0);
Ap3216c_client = i2c_new_device(adapter, &board_info);
i2c_put_adapter(adapter);
return 0;
}
#else
static i2c_client *Ap3216c_client;
/* Addresses to scan */
static const unsigned short normal_i2c[] = {
0x1e, I2C_CLIENT_END
};
static int __init i2c_client_ap3216c_init(void)
{
struct i2c_adapter *adapter;
struct i2c_board_info board_info;
memset(&board_info, 0, sizeof(struct i2c_board_info));
strscpy(board_info.type, "Ap3216c", sizeof(board_info.type));
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
/* register I2C device */
adapter = i2c_get_adapter(0);
Ap3216c_client = i2c_new_probed_device(adapter, &board_info,
normal_i2c, NULL);
i2c_put_adapter(adapter);
return 0;
}
#endif
static void __init i2c_client_Ap3216c_exit(void)
{
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
i2c_unregister_device(Ap3216c_client);
}
module_init(i2c_client_Ap3216c_init);
module_exit(i2c_client_Ap3216c_exit);
MODULE_LICENSE("GPL");
4.Makefile
KERN_DIR = /home/book/100ask_imx6ull-sdk/Linux-4.9.88
all:
make -C $(KERN_DIR) M=`pwd` modules
$(CROSS_COMPILE)gcc -o ap3216c_drv_test ap3216c_drv_test.c
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
rm -rf ap3216c_drv_test
obj-m += ap3216c_drv.o
obj-m += ap3216c_client.o
5.测试结果
6.文件路径
/home/book/nfs_rootfs/优快云/02_I2C/ap3216c