本篇文章的内容与LCD/HDMI OUT的内容关系不大,事件上报是内核与上层通信的一种方式,在有些时候需要上报一些插拔事件或者上报分辨率等信息时会接触到。还是和之前的文章一样,本篇文章将介绍三种事件上报的方式但是只是介绍具体操作步骤,而理论知识以及上报过程需要自己找资料理解。
kobject是高通自带的上报接口之一,调用kobject_uevent函数即可上报,以下为为电源插拔做的事件上报,并建立进程接受到上报事件后重置USB的示例。
首先找到电源驱动并找到电源插拔函数,添加事件上报的函数:
intval表示是否插入电源,当其为1使表示插入,为0时表示拔出,因为插入与拔出会有物理抖动,所以在这里加入了一个dcflag消抖。在插入的判断中加入kobject事件上报,需要注意的是这里的第一个参数为设备结构体中的kobj,如果没有设备结构体则需要自己添加。第二个参数表示事件上报类型,一般为ADD类型。
到这里内核的事件上报已经结束,但是我们无法得知上报是否有效,所以可以自己建立一个进程来接受上报的事件。在这不细讲进程的几种状态了,可以自己去了解,大致是事件上报打破了进程的阻塞态使其运行需要执行的功能。
接下来是建立进程的步骤,不具体介绍为什么加在某个文件,按照流程这样做成功后可以自己去学习一下。
首先是自己写一个功能函数,这里的文件和大学写的demo是一样的,只不过需要调用一些自己不熟悉的接口来实现想要的功能,比如我是需要接收到事件上报的消息进行USB重置:
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <utils/Log.h>
#include <string.h>
#include <stdio.h>
#include <linux/usbdevice_fs.h>
#include <cutils/uevent.h>#define UEVENT_MSG_LEN 1024
#define TF09_PATH_MAX 128struct usb_device_descriptor {unsigned char bLength;unsigned char bDescriptorType;unsigned short int bcdUSB;unsigned char bDeviceClass;unsigned char bDeviceSubClass;unsigned char bDeviceProtocol;unsigned char bMaxPacketSize0;unsigned short int idVendor;unsigned short int idProduct;unsigned short int bcdDevice;unsigned char iManufacturer;unsigned char iProduct;unsigned char iSerialNumber;unsigned char bNumConfigurations;
} __attribute__ ((packed));const static char * usbpath[] = {"/dev/bus/usb/001", "/dev/bus/usb/002"}; //usb devfs可能存在的位置int find_device()
{DIR * usb_dir;struct dirent *bus;char devpath[TF09_PATH_MAX];struct usb_device_descriptor dev_des;int fd, usb_index = 0 ; //查找usb设备的总线位置cfor(usb_index=0;usb_index<(sizeof(usbpath)/sizeof(char*));usb_index++) //搜索并打开总线所在目录{usb_dir = opendir(usbpath[usb_index]);if (NULL != usb_dir){while(NULL != (bus=readdir(usb_dir))) //读取usb devfs下的每一项,即bus{if(!strchr("1234567890", bus->d_name[0]))continue;snprintf(devpath, TF09_PATH_MAX, "%s/%s", usbpath[usb_index], bus->d_name);
// ALOGE("linjiahui devpath =%sn",devpath);if(strstr(devpath,"/dev/bus/usb/001/001") != NULL || strstr(devpath,"/dev/bus/usb/002/001") != NULL){ALOGE("linjiahui 001001");}else{if((fd = open(devpath, O_RDWR))<0)continue;if(read(fd, (void *)(&dev_des), sizeof(dev_des)) > 0) //客户需要的设备{ALOGE("dev_des.idVendor==%x ,dev_des.idProduct==%xn",dev_des.idVendor ,dev_des.idProduct);}else{close(fd);}} }}}return 0;
}int reset_sdr()
{int fd, usb_index = 0;int ret = 0;DIR * usb_dir;struct dirent *bus;struct usb_device_descriptor dev_des;char devpath[TF09_PATH_MAX];for(usb_index=0;usb_index<(sizeof(usbpath)/sizeof(char*));usb_index++){usb_dir = opendir(usbpath[usb_index]);if (NULL != usb_dir){while(NULL != (bus=readdir(usb_dir))){if(!strchr("1234567890", bus->d_name[0]))continue;snprintf(devpath, TF09_PATH_MAX, "%s/%s", usbpath[usb_index], bus->d_name);fd = open(devpath, O_WRONLY);ALOGE("linjiahui 001001:%s", devpath);if (fd < 0) {ALOGE("linjiahui Failed to open file");}ALOGE("linjiahui ioctl Resetting USB device %sn", devpath);if(read(fd, (void *)(&dev_des), sizeof(dev_des)) > 0)ret = ioctl(fd, USBDEVFS_RESET, 0);if (ret < 0){ALOGE("linjiahui The ioctl operation failed %sn",devpath);}}}} close(fd);return 0;
}int main()
{int device_fd;char msg[UEVENT_MSG_LEN+2];int n;int i;char str[] = "c200000.dwc3";ALOGE("linjiahui FAIOT unplug service start!n");device_fd = uevent_open_socket(64*1024, true);if(device_fd < 0){ALOGE("linjiahui FAIOT uevent_open_socket fail!n");return -1;}while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {msg[n] = '