netlink实现usb热插拔
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <asm/types.h>
//该头文件需要放在netlink.h前面防止编译出现__kernel_sa_family未定义
#include <sys/socket.h>
#include <sys/epoll.h>
#include <linux/netlink.h>
#include<time.h>
#include "common.h"
#include "list.h"
#include "usb_hotplug.h"
#include "tcp_client.h"
#include "logw.h"
char g_productstr[20] = {0};
int g_iFileReadable = 0;
int g_iUsbhotplugSocket;
EVENTINFO usbev;
struct sockaddr_nl g_stUsbSockAddr;
USB_LIST usblist;
char* usbhotplug_getdevpath(char *str)
{
char *strtmp1 = str;
char *strtmp2;
char *path;
int i,len = 0;
while(*strtmp1++ != '@');
strtmp2 = strtmp1;
while(*strtmp1++ != '\n')
len++;
/*获取devpath路径*/
path = (char*)malloc((len+1) * sizeof(char));
for(i = 0; i <= len; i++)
{
path[i] = strtmp2[i];
}
path[len] = '\0';
return path;
}
int usbhotplug_getparamvalue(char *path, char *val)
{
FILE * fp;
int i;
fp=fopen(path,"r");
if(NULL == fp)
{
LOG(DEBUG, "usb get para err.\n");
return ERROR_FAILED;
}
fgets(val, 100, fp);
for(i=0;i<strlen(val);i++)
if(*(val+i)=='\n')
val[i]='\0';
//printf("%s",val);
fclose(fp);
return ERROR_SUCCESS;
}
void usbhotplug_inmsg_proc(char *path)
{
USB_LIST *pnode;
USBINFO_S *pinfo;
char *parent_path;
int iIndex;
int m=0, n=0;
int ilen = strlen(path);
int parent_len = strlen(path);
char result_str[DATABUFCOMLEN] = "\0";
if(NULL == path)
{
LOG(DEBUG, "path error.\n");
return;
}
pnode = (USB_LIST*)malloc(sizeof(USB_LIST));
pinfo = (USBINFO_S *)malloc (sizeof(USBINFO_S));
while(path[--parent_len] != '/');
parent_path = malloc((parent_len + 1) * sizeof(char));
memset(parent_path, 0, parent_len+1);
for(iIndex = 0; iIndex < parent_len; iIndex++)
{
parent_path[iIndex] = path[iIndex];
}
sprintf(pinfo->path_productname, path);
/*接口协议号路径*/
sprintf(pinfo->path_interfaceprotocol, path);
strcat(pinfo->path_interfaceprotocol, "/bInterfaceProtocol");
usbhotplug_getparamvalue(pinfo->path_interfaceprotocol, pinfo->interfaceprotocol);
/*设备名称*/
sprintf(pinfo->path_productname , parent_path);
strcat(pinfo->path_productname, "/product");
usbhotplug_getparamvalue(pinfo->path_productname, pinfo->productname);
/*厂商名称*/
sprintf(pinfo->path_manufacturername , parent_path);
strcat(pinfo->path_manufacturername, "/manufacturer");
usbhotplug_getparamvalue(pinfo->path_manufacturername, pinfo->manufacturername);
/*设备编号*/
sprintf(pinfo->path_productid , parent_path);
strcat(pinfo->path_productid, "/idProduct");
usbhotplug_getparamvalue(pinfo->path_productid, pinfo->productid);
/*厂商编号*/
sprintf(pinfo->path_vendorid , parent_path);
strcat(pinfo->path_vendorid, "/idVendor");
usbhotplug_getparamvalue(pinfo->path_vendorid, pinfo->vendorid);
/*接口编号*/
for(iIndex = parent_len+1; iIndex < ilen; iIndex++)
{
if(path[iIndex] == ':')
n = m;
pnode->interfacenum[m++] = path[iIndex];
}
pnode->interfacenum[m] = '\0';
//printf("interfacenum %s\n", pnode->interfacenum);
/*USB接口号*/
for(iIndex = 0; iIndex < n; iIndex++)
{
pinfo->usb_interfacenum[iIndex] = pnode->interfacenum[iIndex];
}
pinfo->usb_interfacenum[n] = '\0';
//printf("usb_interfacenum %s\n", pinfo->usb_interfacenum);
snprintf(result_str, DATABUFCOMLEN, "{%s} {%s} {%s} {%s} {%s} {<%s@%s>}",
pinfo->usb_interfacenum, pinfo->productname, pinfo->manufacturername,
pinfo->productid, pinfo->vendorid, pnode->interfacenum, pinfo->interfaceprotocol);
//printf("%s\n", result_str);
tcpclient_eventsend(result_str, EVENT_GENERAL, EVENT_SUBTYPE_USBIN);
/*保存当前usb节点信息到链表*/
pnode->info = pinfo;
list_add_tail(&(pnode->list), &(usblist.list));
}
void usbhotplug_outmsg_proc(char *path)
{
USB_LIST *node;
char szintername[20] = "\0";
int ilen = strlen(path);
int parent_len = strlen(path);
int iIndex;
int m = 0;
char result_str[DATABUFCOMLEN] = "\0";
if(NULL == path)
{
LOG(DEBUG, "path error.\n");
return;
}
while(path[--parent_len] != '/');
for(iIndex = parent_len+1; iIndex < ilen; iIndex++)
{
szintername[m++] = path[iIndex];
}
szintername[m] = '\0';
list_for_each_entry(node, &usblist.list, list)
{
if(strcmp(node->interfacenum, szintername) == 0)
break;
}
if('\0' == node->interfacenum[0] )
{
sprintf(result_str, "{%s} {%s} {%s} {%s} {%s} {<%s@%s>}",
"unknown", "unknown", "unknown", "unknown", "unknown", szintername, "unknown");
LOG(INFO, "%s\n", result_str);
return;
}
snprintf(result_str, DATABUFCOMLEN, "usb remove : {%s} {%s} {%s} {%s} {%s} {<%s@%s>}",
node->info->usb_interfacenum, node->info->productname, node->info->manufacturername,
node->info->productid, node->info->vendorid, node->interfacenum, node->info->interfaceprotocol);
//printf("%s\n", result_str);
tcpclient_eventsend(result_str, EVENT_INFORM, EVENT_SUBTYPE_USBOUT);
list_del(&node->list);
free(node->info);
free(node);
}
void usbhotplug_recv_proc()
{
int iLength = 0;
int iIndex;
char *product_str;
char *pcaction_str;
char *pcsubsystem_str;
char *pcdevpath;
char szsysdevpath[100] = "\0";
struct iovec iov;
struct msghdr stmsg;
char szbuf[4096];
memset(&stmsg,0,sizeof(stmsg));
iov.iov_base=(void *)szbuf;
iov.iov_len=sizeof(szbuf);
stmsg.msg_name=(void *)&g_stUsbSockAddr;
stmsg.msg_namelen=sizeof(g_stUsbSockAddr);
stmsg.msg_iov=&iov;
stmsg.msg_iovlen=1;
iLength=recvmsg(g_iUsbhotplugSocket,&stmsg,0);
if(0 >= iLength)
{
LOG(DEBUG, "receive error\n");
}
if(iLength < 32 || iLength > sizeof(szbuf))
{
LOG(DEBUG, "invalid message");
}
usleep(500);
for(iIndex = 0; iIndex < iLength; iIndex++ )
if(*(szbuf + iIndex) == '\0')
szbuf[iIndex] = '\n';
if((pcaction_str = strstr(szbuf,"add@")) && (product_str=strstr(szbuf,"PRODUCT"))
&& (pcsubsystem_str = strstr(szbuf,"usb_interface")))
{
pcdevpath = usbhotplug_getdevpath(pcaction_str);
sprintf(szsysdevpath, "/sys");
strncat(szsysdevpath, pcdevpath, sizeof(szsysdevpath) - 5);
LOG(INFO, "sysdevpath %s\n", szsysdevpath);
usbhotplug_inmsg_proc(szsysdevpath);
}
if((pcaction_str = strstr(szbuf,"remove@")) && (product_str=strstr(szbuf,"PRODUCT"))
&& (pcsubsystem_str = strstr(szbuf,"usb_interface")))
{
pcdevpath = usbhotplug_getdevpath(pcaction_str);
sprintf(szsysdevpath, "/sys");
strncat(szsysdevpath, pcdevpath, sizeof(szsysdevpath) - 5);
//printf("sysdevpath %s\n", szsysdevpath);
usbhotplug_outmsg_proc(szsysdevpath);
}
}
int init_usbhotplug(int epollfd)
{
struct epoll_event eventItem;
/*初始化usb链表*/
INIT_LIST_HEAD(&usblist.list);
usblist.interfacenum[0] = '\0';
memset(&g_stUsbSockAddr,0,sizeof(g_stUsbSockAddr));
g_stUsbSockAddr.nl_family=AF_NETLINK;
g_stUsbSockAddr.nl_groups=NETLINK_KOBJECT_UEVENT;
g_stUsbSockAddr.nl_pid = 0;/*getpid(); both is ok*/
g_iUsbhotplugSocket=socket(AF_NETLINK,SOCK_RAW,NETLINK_KOBJECT_UEVENT);
if(g_iUsbhotplugSocket==-1)
LOG(ERROR, "socket creating failed:%s\n",strerror(errno));
if(bind(g_iUsbhotplugSocket,(struct sockaddr *)&g_stUsbSockAddr,sizeof(g_stUsbSockAddr))==-1)
LOG(ERROR, "bind error:%s\n",strerror(errno));
eventItem.events = EPOLLIN;
eventItem.data.fd = g_iUsbhotplugSocket;
epoll_ctl(epollfd, EPOLL_CTL_ADD, g_iUsbhotplugSocket, &eventItem);
usbev.fd = g_iUsbhotplugSocket;
usbev.pfcb = usbhotplug_recv_proc;
regeister_callback(USBMODULE, &usbev);
return 0;
}