#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <stdio.h>
#include <linux/input.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct uevent {
const char *action;
const char *path;
const char *subsystem;
const char *firmware;
int major;
int minor;
};
#define DEVNAME "/sys/kernel/config/usb_gadget/rockchip/UDC"
static int read_udc(void){
char dcin_det_val[32];
int fd;
int ret = 0;
//printf("%s \n",__func__);
if((fd = open(DEVNAME, O_RDWR | O_NONBLOCK))!= -1){
memset(dcin_det_val, 0, sizeof(dcin_det_val));
read(fd, dcin_det_val, sizeof(dcin_det_val));
//printf("dcin_det_val value[char]: %s\n", dcin_det_val);
close(fd);
} else {
printf("open dev fail: fd[%d]\n", fd);
}
//if(dcin_det_val != NULL){
if(strstr(dcin_det_val,"fe800000.dwc3")){
ret = 1 ;
}
//}
return ret;
}
static int open_uevent_socket(void)
{
struct sockaddr_nl addr;
int sz = 64*1024; // XXX larger? udev uses
int on = 1;
int s;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid();
//可以接收所有的family消息 , 单播设置0
addr.nl_groups = 0xffffffff;
//地址族(Address Family) PF_NETLINK
//协议号NETLINK_KOBJECT_UEVENT
//数据传输方式/socket类型 SOCK_DGRAM | SOCK_CLOEXEC
s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if(s < 0)
return -1;
setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
//SO_PEERCRED 远端的资格
setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(s);
return -1;
}
return s;
}
static void parse_event(const char *msg, struct uevent *uevent)
{
#if 1
uevent->action = "";
uevent->path = "";
uevent->subsystem = "";
uevent->firmware = "";
uevent->major = -1;
uevent->minor = -1;
//printf("%s msg:%s\n",__func__, msg);
/* currently ignoring SEQNUM */
while(*msg) {
//printf("%s\n", msg);
if(strstr(msg,"STATE=USB=1")){
if(read_udc() == 0){
printf("/etc/init.d/adbd.sh start\n");
system("/etc/init.d/adbd.sh start");
}
}else{
//printf("CONNECTED STATE=USB=0 YES\n\n");
}
if(!strncmp(msg, "ACTION=", 7)) {
msg += 7;
uevent->action = msg;
} else if(!strncmp(msg, "DEVPATH=", 8)) {
msg += 8;
uevent->path = msg;
} else if(!strncmp(msg, "SUBSYSTEM=", 10)) {
msg += 10;
uevent->subsystem = msg;
} else if(!strncmp(msg, "FIRMWARE=", 9)) {
msg += 9;
uevent->firmware = msg;
} else if(!strncmp(msg, "MAJOR=", 6)) {
msg += 6;
uevent->major = atoi(msg);
} else if(!strncmp(msg, "MINOR=", 6)) {
msg += 6;
uevent->minor = atoi(msg);
}
/* advance to after the next \0 */
while(*msg++)
;
}
/* printf("event { '%s', '%s', '%s', '%s', %d, %d } \n",
uevent->action, uevent->path, uevent->subsystem,
uevent->firmware, uevent->major, uevent->minor);*/
#endif
}
#define UEVENT_MSG_LEN 1024
void handle_device_fd(int fd)
{
for(;;) {
char msg[UEVENT_MSG_LEN+2];
int ucredsize = sizeof(struct ucred);
char cred_msg[CMSG_SPACE(ucredsize)];
struct iovec iov = {msg, sizeof(msg)};
struct sockaddr_nl snl;
struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0};
//printf("enter %s\n", __func__);
ssize_t n = recvmsg(fd, &hdr, 0);
if (n <= 0) {
break;
}
if ((snl.nl_groups != 1) || (snl.nl_pid != 0)) {
/* ignoring non-kernel netlink multicast message */
continue;
}
struct cmsghdr * cmsg = CMSG_FIRSTHDR(&hdr);
if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
/* no sender credentials received, ignore message */
continue;
}
struct ucred * cred = (struct ucred *)CMSG_DATA(cmsg);
if (cred->uid != 0) {
/* message from non-root user, ignore */
continue;
}
if(n >= UEVENT_MSG_LEN) /* overflow -- discard */
continue;
msg[n] = '\0';
msg[n+1] = '\0';
struct uevent uevent;
parse_event(msg, &uevent);
}
}
int main(void)
{
int fd = 0;
fd = open_uevent_socket();
if (fd < 0) {
printf("error!\n");
return -1;
}
handle_device_fd(fd);
}
利用USB kevent之重启adb
最新推荐文章于 2024-09-27 18:01:25 发布