blob: 8c1893b155d737178d7bcfe248268a06f6372236 [file] [log] [blame]
#include "hotplug.h"
static hotplug_parse_func hotplug_parse_ptr[DEVICE_TYPE_MAX] = {NULL};
static hotplug_proc_func hotplug_proc_ptr[DEVICE_TYPE_MAX] = {NULL};
#define RTC_ALARM_TIMEOUT_MSG "PMIC RTC ALARM IRQ COME"
#define RTC_TIMER_TIMEOUT_MSG "PMIC RTC TIMER IRQ COME"
static const char *hotplug_action_str[] = {
[KOBJ_ADD] = "add",
[KOBJ_REMOVE] = "remove",
[KOBJ_CHANGE] = "change",
[KOBJ_MOVE] = "move",
[KOBJ_ONLINE] = "online",
[KOBJ_OFFLINE] = "offline",
};
static int get_action_type(const char *buf, int count)
{
int action;
if (count && (buf[count - 1] == '\n' || buf[count - 1] == '\0'))
count--;
if (!count)
goto err_out;
for (action = 0; action < KOBJ_MAX; action++) {
if (0 == strncmp(hotplug_action_str[action], buf, count)) {
return action;
}
}
err_out:
return -1;
}
/*½«UEVENTÖеÄ'\0' Ìæ»»³É'\n'£¬·ÀÖ¹»ñÈ¡²»µ½'\0'ºóÃæµÄÄÚÈÝ*/
void char_replace(char*buf, int count, char orig_char, char replace_char)
{
int index = 0;
if (!buf || count <= 0) {
slog(NET_PRINT, SLOG_ERR,"[%s][%d]\n", __func__, __LINE__);
return;
}
for (index = 0; index < count; ++index) {
if (buf[index] == orig_char) {
buf[index] = replace_char;
}
}
}
/*×¢²ádeviceµÄueventÏûÏ¢½âÎöº¯Êý*/
int hotplug_parse_register(int device_type, hotplug_parse_func func)
{
if (device_type < DEVICE_TYPE_MAX && device_type >= 0) {
hotplug_parse_ptr[device_type] = func;
}
return 0;
}
/*×¢²ádeviceµÄueventÏûÏ¢½âÎöº¯Êý*/
int hotplug_proc_register(int device_type, hotplug_proc_func func)
{
if (device_type < DEVICE_TYPE_MAX && device_type >= 0) {
hotplug_proc_ptr[device_type] = func;
}
return 0;
}
/*ÈȰβåÏûÏ¢½âÎö*/
static int hotplug_msg_parse(const char *msg, int msglen, struct hotplug_event *event)
{
int i = 0;
int ret = 0;
int act_type = 0;
char *act_ptr = NULL;
char *p = NULL;
if (NULL == msg || NULL == event) {
slog(NET_PRINT, SLOG_ERR,"[%s][%d]\n", __func__, __LINE__);
return -1;
}
memset(event, 0, sizeof(struct hotplug_event));
slog(NET_PRINT, SLOG_ERR, "[%s][%d]uevent message = %s, %d, %d\n", __func__, __LINE__, msg, msglen, strlen(msg));
//´¦ÀíÇý¶¯ÈȲå°ÎÉϱ¨ÏûÏ¢
act_ptr = strchr(msg, '@');
if (NULL == act_ptr) {
slog(NET_PRINT, SLOG_ERR, "hotplug msg parse failed!\n");
return -1;
}
act_type = get_action_type(msg, act_ptr - msg);
if (act_type < 0) {
slog(NET_PRINT, SLOG_ERR, "hotplug get action type failed!\n");
return -1;
}
event->action = act_type;
slog(NET_PRINT, SLOG_NORMAL, "[%s][%d]action = %s\n", __func__, __LINE__, hotplug_action_str[act_type]);
for (i = 0; i < DEVICE_TYPE_MAX; i++) {
if (hotplug_parse_ptr[i]) {
ret = hotplug_parse_ptr[i](msg, msglen, event);
if (0 == ret){
if (hotplug_proc_ptr[event->type])
hotplug_proc_ptr[event->type](event);
}
}
}
return -1;
}
/*ÈȰβåÌ×½Ó×Ö³õʼ»¯*/
int hotplug_sock_init()
{
int sockfd = 0;
int ret;
struct sockaddr_nl snl;
bzero(&snl, sizeof(struct sockaddr_nl));
snl.nl_family = AF_NETLINK;
snl.nl_pid = getpid();
snl.nl_groups = 1;
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
perror("signal");
sockfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if (sockfd < 0) {
slog(NET_PRINT, SLOG_ERR, "create hotplug socket failed!\n");
return -1;
}
// setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
ret = bind(sockfd, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl));
if (ret < 0) {
slog(NET_PRINT, SLOG_ERR, "hotplug socket bind fail!\n");
close(sockfd);
return -1;
}
return sockfd;
}
void hotplug_init()
{
/*ÍøÂçÉ豸³õʼ»¯*/
netdev_hotplug_init();
/*Çý¶¯É豸³õʼ»¯*/
drv_hotplug_init();
}
int zte_hotplug_main(int argc, char * argv[])
{
int hotplug_fd = 0;
fd_set readfds;
int maxfd = 0;
char buf[UEVENT_BUFFER_SIZE] = {0};
int len = 0;
int ret = 0;
struct hotplug_event hot_event;
prctl(PR_SET_NAME, "hotplug", 0, 0, 0);
//¸ù¾ÝNV³õʼ»¯´òÓ¡¼¶±ð£¬²¢×¢²á¶¯Ì¬µ÷Õû´òÓ¡¼¶±ðÐźÅÁ¿
loglevel_init();
hotplug_fd = hotplug_sock_init();
if (hotplug_fd < 0) {
slog(NET_PRINT, SLOG_ERR, "hotplug socket init fail!\n");
return -1;
}
/*ÈȰβåÉ豸µÄ³õʼ»¯*/
hotplug_init();
maxfd = hotplug_fd;
while (1) {
FD_ZERO(&readfds);
FD_SET(hotplug_fd, &readfds);
ret = select(maxfd + 1, &readfds, NULL, NULL, NULL);
if (ret == -1 && errno == EINTR)
continue;
if (FD_ISSET(hotplug_fd, &readfds)) {
memset(buf, 0, sizeof(buf));
len = recv(hotplug_fd, &buf, sizeof(buf), 0);
if (len <= 0) {
slog(NET_PRINT, SLOG_ERR, "hotplug recv msg fail!\n");
continue;
}
/*½øÐÐueventÏûÏ¢½âÎö£¬·µ»Ø½âÎö½á¹û*/
ret = hotplug_msg_parse(buf, len, &hot_event);
#if 0 //klocwork
if (ret < 0)
continue;
if (hot_event.type >= DEVICE_TYPE_MAX || hot_event.type < 0)
continue;
#endif
/*É豸ueventʼþ´¦Àí
if (hotplug_proc_ptr[hot_event.type])
hotplug_proc_ptr[hot_event.type](&hot_event);*/
}
}
return 0;
}