Chinaunix首页 | 论坛 | 博客
  • 博客访问: 175783
  • 博文数量: 27
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 618
  • 用 户 组: 普通用户
  • 注册时间: 2013-11-15 09:12
文章分类
文章存档

2014年(17)

2013年(10)

我的朋友

分类: Android平台

2013-11-29 09:19:50

APDS990X 是AVAGO的L和P集成的传感器芯片

设备挂在I2C设备上所以开始使用 I2C_add_driver函数注册一个I2C设备

static struct apds990x_chip *apds990x_alloc_dev(void) 初始化一个mutex锁,初始化L&P的一个工作队列的头(其实就是一个节点)
mutex_init(&chip->mutex);
init_waitqueue_head(&chip->ps_workq_head);                                                                                        
init_waitqueue_head(&chip->als_wordq_head);
INIT_LIST_HEAD(&chip->als_list);
INIT_LIST_HEAD(&chip->ps_list);

取得平台初始化数据连接I2C 适配器
chip->client = client;
chip->pdata = client->dev.platform_data;
i2c_set_clientdata(client, chip);

读取chip的型号
static int apds990x_detect(struct apds990x_chip *chip)

根据chip的型号初始化数据,配置寄存器,设置chip状态
apds990x_init_params(chip);
apds990x_configure(chip);                                                                                                         
apds990x_set_arate(chip, APDS_LUX_DEFAULT_RATE);
apds990x_switch(chip, APDS_POWER_DOWN);

创建文件节点
sysfs_create_group(&chip->client->dev.kobj, apds990x_attribute_group);

定义P/L 的设备号 名称 给上层的接口函数
chip->ps_dev.minor = MISC_DYNAMIC_MINOR;
chip->ps_dev.name = "apds990x_psensor";
chip->ps_dev.fops = &ps_fops;                                                                                                     

chip->als_dev.minor = MISC_DYNAMIC_MINOR;
chip->als_dev.name = "apds990x_lsensor";
chip->als_dev.fops = &als_fops;

注册成misc设备
misc_register(&chip->ps_dev);                                                                                                         
misc_register(&chip->als_dev);

注册中断线程处理函数
static int apds990x_setup_irq(struct apds990x_chip *chip)
request_threaded_irq(client->irq, NULL,apds990x_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "apds990x", chip);

打开中断
enable_irq_wake(client->irq);

这两行是要取得下次中断上报饿数据(算是初始化下吧,可能会丢弃第一次报的值)
apds990x_force_a_refresh(chip);                                                                                                   
apds990x_force_p_refresh(chip);

工作流程如下:

当硬件检测到有L/P有变化后,出发中断,执行中断函数,apds990x_irq,中断函数中判断是L的中断还是P的中断,然后执行
if (status & APDS990X_ST_AINT)
        als_handle_irq(chip);                                                                                           
if (status & APDS990X_ST_PINT)
         ps_handle_irq(chip);

读出来值,设置状态,唤醒队列头(其实就是一个结构体)
set_bit(ALS_DATA_READY, &client->status);
wake_up(&chip->als_wordq_head);

在poll函数中,将实现
poll_wait(filep, &chip->ps_workq_head, wait);             -------------------->当上层poll这个文件节点时候,程序会等待到这里读(是否阻塞需要看mask值),知道工作队列头被wake_up了
if (test_bit(PS_DATA_READY, &client->status))
        mask |= (POLLIN | POLLRDNORM);

上层会open文件节点,然后poll这个fd,如果发现有改变,返回了,就要执行read函数了,
read把数据拷贝到user区域,然后清除一些状态
if (chip->alsps_switch & APDS_ALS_ENABLE) {
        lux = min(chip->lux, APDS_ALS_MAX_LUX);
        clear_bit(ALS_DATA_READY, &client->status);
        if (copy_to_user(buffer, &lux, sizeof(lux)))
                ret = -EFAULT;
        ret = sizeof(lux);
}

这样就完成了一次完整的数据发送。

上层的sensor的代码存放在
hardware/intel/sensors



阅读(3013) | 评论(1) | 转发(1) |
给主人留下些什么吧!~~

歹戈木木夕2013-11-29 09:30:31

啊啊啊啊啊啊 我已经尽力了!!!!!汪汪汪