完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一、前言
本文主要分析mtk平台hal层如何获取alps框架下光距感数据和光距感的使能开关对应的hal层接口; hal层涉及文件及目录: vendor/mediatek/proprietary/hardware/sensor/sensors-1.0/sensors.cpp vendor/mediatek/proprietary/hardware/sensor/sensors-1.0/SensorContext.cpp vendor/mediatek/proprietary/hardware/sensor/sensors-1.0/SensorEventReader.cpp vendor/mediatek/proprietary/hardware/sensor/sensors-1.0/AmbienteLight.cpp kernel层涉及文件: kernel-4.4/drivers/misc/mediatek/sensors-1.0/alsps/alsps.c kernel-4.4/drivers/misc/mediatek/sensors-1.0/hwmon/sensor_event/sensor_event.c 二、光距感上报数据的流程 应用层获取光感数据的方式通过open “/dev/m_als_misc”设备节点,调用read函数即可读取到alps架构下的光感数据; 参考第一章所讲的timer_als定时器触发流程,在机器开机的过程中,默认设置下hal层会操控/sys/class/sensor/m_als_misc/alsactive 节点,触发定时器,光感数据通过als_data_report->sensor_input_event函数将获取到的光感值添加到全局的缓存队列buffer中,同时唤醒sensor_event_poll函数中的client->wait等待队列;sensor_event_poll函数就会将对应应用层的休眠进程唤醒,表示这个设备有数据可读,最后调用对应的read函数来读取光感值; //alsps.c //light_fops static int light_open(struct inode *inode, struct file *file) { nonseekable_open(inode, file); //在 open 方法中调用 nonseekable_open() 时,它会通知内核设备不支持 llseek return 0; } static ssize_t light_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { ssize_t read_cnt = 0; read_cnt = sensor_event_read(alsps_context_obj->als_mdev.minor, file, buffer, count, ppos); return read_cnt; } static unsigned int light_poll(struct file *file, poll_table *wait) { return sensor_event_poll(alsps_context_obj->als_mdev.minor, file, wait); } hal层中open ”/dev/m_als_misc“获取fd套接字,根据fd,调用read函数来读取内核中的数据;sensor_event_read函数就是该节点对应的内核读取数据的具体实现; //sensors-1.0hwmonsensor_eventsensor_event.c ssize_t sensor_event_read(unsigned char handle, struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct sensor_event_client *client = &event_obj->client[handle]; struct sensor_event event; size_t read = 0; if (count != 0 && count < sizeof(struct sensor_event)) { SE_PR_ERR("sensor_event_read handle: %d err count(%d)n", handle, (int)count); return -EINVAL; } for (;;) { if (client->head == client->tail) { return 0; } if (count == 0) { SE_LOG("sensor_event_read count: %dn", (int)count); break; } while (read + sizeof(struct sensor_event) <= count && sensor_event_fetch_next(client, &event)) { if (copy_to_user(buffer + read, &event, sizeof(struct sensor_event))) return -EFAULT; read += sizeof(struct sensor_event); } if (read) break; } return read; } unsigned int sensor_event_poll(unsigned char handle, struct file *file, poll_table *wait) { struct sensor_event_client *client = &event_obj->client[handle]; unsigned int mask = 0; poll_wait(file, &client->wait, wait); if (client->head != client->tail) { /* SE_PR_ERR("sensor_event_poll handle:%dn", handle); */ mask |= POLLIN | POLLRDNORM; } return mask; } int sensor_input_event(unsigned char handle, const struct sensor_event *event) { struct sensor_event_client *client = &event_obj->client[handle]; unsigned int dummy = 0; /* spin_lock safe, this function don't support interrupt context */ spin_lock(&client->buffer_lock); if (unlikely(client->buffull == true)) { pr_err_ratelimited("input buffull, handle:%d, head:%d, tail:%dn", handle, client->head, client->tail); spin_unlock(&client->buffer_lock); wake_up_interruptible(&client->wait); return -1; } client->buffer[client->head++] = *event; client->head &= client->bufsize - 1; /* remain 1 count */ dummy = client->head + 1; dummy &= client->bufsize - 1; if (unlikely(dummy == client->tail)) client->buffull = true; spin_unlock(&client->buffer_lock); wake_up_interruptible(&client->wait); return 0; } 1、hal层获取光感驱动层的数据流程 在sensors.cpp文件中init_sensors->dev->device.poll = poll__poll;初始化阶段定义了poll函数; static int poll__poll(struct sensors_poll_device_t * /dev/, sensors_event_t* data, int count) {undefined return mSensorManager->pollEvent(data, count); } 上一章有分析到当驱动层中的光感上报定时器timer_als被触发时,最终会导致驱动的light_poll函数中client->wait等待队列被唤醒,同时给hal层的fd文件描述符fd.revents传入POLLIN | POLLRDNORM; int sensors_poll_context_t::pollEvent(sensors_event_t* data, int count) { int nbEvents = 0; int n = 0; int averageCount = 0, loop = 0, loopcount = 0; int backupcount = count, backuploop = 0; do { loopcount++; computeCountForEachFd(count, &averageCount, &loop); backuploop = loop; for (int i = 0; count && loop && i < numFds; i++) { SensorBase* const sensor(mSensors); //mPollFds.revents值根据内核的poll函数返回值决定的,当光距感light_poll中的队列被唤醒时,mPollFds[3].revents=POLLIN | POLLRDNORM;表示监听光感的文字描述符有相应,调用对应光感的AmbiLightSensor::readEvents方法; if (mPollFds.revents & POLLIN || sensor->pendingEvent()) { int nb = sensor->readEvents(data, averageCount); for (int j = 0; j < nb; j++) { if (data[j].type == SENSOR_TYPE_META_DATA) data[j].meta_data.sensor += ID_OFFSET; else data[j].sensor += ID_OFFSET; } count -= nb; nbEvents += nb; data += nb; loop--; if (count < 0) { } } } n = TEMP_FAILURE_RETRY(poll(mPollFds, numFds, nbEvents ? 0 : -1)); //poll阻塞,当nbEvents返回值为0时唤醒,调用readEvents方法来读取驱动层的光感值; } while (n && count); return nbEvents; } //SensorEventReader.cpp #define DEVICE_PATH "/dev/m_als_misc" AmbiLightSensor::AmbiLightSensor() //将/dev/m_als_misc节点路径传入 if (mSensorReader.selectSensorEventFd(DEVICE_PATH) >= 0) } int SensorEventCircularReader::selectSensorEventFd(const char *path) { mReadFd = TEMP_FAILURE_RETRY(open(path, O_RDONLY));//打开path路径下的节点,成功返回mReadFd文字描述符; } ssize_t SensorEventCircularReader::fill() { size_t numEventsRead = 0; if (mFreeSpace) { //读取mReadFd文字描述符的对应节点值;那么这个mReadFd文字描述符来自哪里呢,在selectSensorEventFd方法中获取的;mReadFd是在SensorEventCircularReader类中定义私有属性;该类中的selectSensorEventFd和fill方法都可以设置和获取该类的属性; //mHead为内核上报数据存放的首地址 const ssize_t nread = TEMP_FAILURE_RETRY(read(mReadFd, mHead, mFreeSpace * sizeof(struct sensor_event))); //mBuffer为上报数据的存放地址; memcpy(mBuffer, mBufferEnd, s * sizeof(struct sensor_event)); return numEventsRead; } //AmbienteLight.cpp int AmbiLightSensor::readEvents(sensors_event_t* data, int count) { if (count < 1) return -EINVAL; ssize_t n = mSensorReader.fill(); //fill方法是根据驱动层的光感设备节点的路径,获取fd; while (count && mSensorReader.readEvent(&event)) {//event指向mCurr; processEvent(event); //根据上报事件的event->handle来设置mPendingEvent,当是光感上报值, if (event->flush_action <= FLUSH_ACTION) { *data++ = mPendingEvent; numEventReceived++; count--; } mSensorReader.next(); //mCurr指向上报数据的地址mBuffer } return numEventReceived; } //SensorEventReader.cpp ssize_t SensorEventCircularReader::fill() { size_t numEventsRead = 0; if (mFreeSpace) { const ssize_t nread = TEMP_FAILURE_RETRY(read(mReadFd, mHead, mFreeSpace * sizeof(struct sensor_event))); if (nread < 0 || nread % sizeof(struct sensor_event)) { return 0; } numEventsRead = nread / sizeof(struct sensor_event); if (numEventsRead) { mHead += numEventsRead; mFreeSpace -= numEventsRead; if (mHead > mBufferEnd) { size_t s = mHead - mBufferEnd; if (s < ULONG_MAX / sizeof(struct sensor_event)) { memcpy(mBuffer, mBufferEnd, s * sizeof(struct sensor_event)); mHead = mBuffer + s; } else ALOGE("SensorEventCircularReader fill data failed"); } } } return numEventsRead; } //SensorEventReader.cpp ssize_t SensorEventCircularReader::readEvent(struct sensor_event const** events) { *events = mCurr; } //SensorEventReader.cpp void SensorEventCircularReader::next() { mCurr = mBuffer; //mCurr指向上报数据的地址; } 2、hal层控制光感驱动,对光感逻辑处理 //AmbienteLight.cpp AmbiLightSensor::AmbiLightSensor() { //当/dev/m_als_misc设备节点不存在时直接返回; if (mSensorReader.selectSensorEventFd(DEVICE_PATH) >= 0) { strlcpy(input_sysfs_path, "/sys/class/sensor/m_als_misc/", sizeof(input_sysfs_path)); input_sysfs_path_len = strlen(input_sysfs_path); } else { ALOGE("couldn't find sensor device "); return; } char datapath[64]={"/sys/class/sensor/m_als_misc/alsactive"}; fd = TEMP_FAILURE_RETRY(open(datapath, O_RDWR)); //打开alsactive节点,获取fd文件描述符 TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf) - 1));//读取该节点值,buf为存放值的地址; } //当调用enable方法时 int AmbiLightSensor::enable(int32_t handle, int en) { int fd = -1; char buf[8] = {0}; ALOGI("enable: handle:%d, en:%d rn", handle, en); strlcpy(&input_sysfs_path[input_sysfs_path_len], "alsactive", sizeof(input_sysfs_path) - input_sysfs_path_len); fd = TEMP_FAILURE_RETRY(open(input_sysfs_path, O_RDWR)); if(fd < 0) { ALOGE("no enable control attrrn" ); return -1; } sprintf(buf, "%d,%d", handle, en); TEMP_FAILURE_RETRY(write(fd, buf, sizeof(buf))); close(fd); return 0; } int AmbiLightSensor::batch(int handle, int flags, int64_t samplingPeriodNs, int64_t maxBatchReportLatencyNs) { int fd = -1; char buf[128] = {0}; ALOGI("batch: handle:%d, flag:%d,samplingPeriodNs:%" PRId64 " maxBatchReportLatencyNs:%" PRId64 "rn", handle, flags,samplingPeriodNs, maxBatchReportLatencyNs); strlcpy(&input_sysfs_path[input_sysfs_path_len], "al***atch", sizeof(input_sysfs_path) - input_sysfs_path_len); fd = TEMP_FAILURE_RETRY(open(input_sysfs_path, O_RDWR)); if(fd < 0) { ALOGD("no batch control attrrn"); return -1; } sprintf(buf, "%d,%d,%" PRId64 ",%" PRId64 "", handle, flags, samplingPeriodNs, maxBatchReportLatencyNs); TEMP_FAILURE_RETRY(write(fd, buf, sizeof(buf))); close(fd); return 0; } |
|
|
|
只有小组成员才能发言,加入小组>>
imx6ull 和 lan8742 工作起来不正常, ping 老是丢包
1149 浏览 0 评论
3338 浏览 9 评论
3016 浏览 16 评论
3508 浏览 1 评论
9103 浏览 16 评论
1220浏览 3评论
631浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
620浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2363浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1928浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-13 03:48 , Processed in 1.145883 second(s), Total 46, Slave 38 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号