fl2440蜂鸣器测试程序和strcmp()及struct input_event 还有perror()浅析

本文详细介绍了一个用于控制蜂鸣器开关的测试程序,通过分析源代码解释了如何使用struct input_event结构体来模拟按键事件,进而实现蜂鸣器的开启与关闭功能。


前面移植了内核自带的蜂鸣器驱动,现在有时间写一个最简单的测试程序,功能是打开蜂鸣器,或者关闭蜂鸣器。


  1 /*********************************************************************************
  2  *      Copyright:  (C) 2017 fanmaolin<fanmaolinn@gmail.com>
  3  *                  All rights reserved.
  4  *
  5  *       Filename:  test.c
  6  *    Description:  This file 
  7  *                 
  8  *        Version:  1.0.0(04/23/2017)
  9  *         Author:  fanmaolin <fanmaolinn@gmail.com>
 10  *      ChangeLog:  1, Release initial version on "04/23/2017 09:36:39 AM"
 11  *                 
 12  ********************************************************************************/
 13 
 14 #include<stdint.h>
 15 #include<string.h>
 16 #include<fcntl.h>
 17 #include<unistd.h>
 18 #include<stdio.h>
 19 #include<linux/input.h>
 20 #include<unistd.h>
 21 
 22 
 23 int main(int argc, char *argv[])
 24 {
 25     int fd;
 26     
 27     struct input_event event;
 28 
 29 
 30 
 31 if ((fd = open("/dev/event1", O_RDWR)) < 0) {			//打开dev/event1,设置为读写模式
 32 
 33     perror("beep test");						//如果文件打开失败,打印出错信息
 34 
 + testpwm.c                                                                                                                        
 35     return 1;
 36 
 37 }
 38 
 39 
 40 
 41     event.type = EV_SND;			//事件类型设置为支持声音
 42     event.code = SND_TONE;			//设置事件代码为SND_TONE
 43 
 44     if(!strcmp (argv[1],"1"))		//strcmp()函数用来比较两个字符串
 45     {
 46         {
 47             event.value = 2000;   //打开蜂鸣器  
 48             write(fd, &event, sizeof(struct input_event));
 49         }
 50     }
 51 
 52     else if(!strcmp (argv[1],"0"))
 53     {
 54 
 55             event.value = 0;//关闭蜂鸣器
 56             write(fd, &event, sizeof(struct input_event));
 57     }
 58 
 59    close(fd);		//释放占用资源
 60 
 61        return 0;
 62 
 63 }


[fanmaolin@centos6 ~]$ /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc test.c

把生成的a.out文件传到开发板上进行测试




OK


下面展开分析函数和程序

我的蜂鸣器测试程序使用了struct input_even结构体,在写按键驱动时也用到了这个,这里展开仔细讲一下

[fanmaolin@Centeros linux-3.0]$ vim include/linux/input.h    

linux/input.h中有定义,这个文件还定义了标准按键的编码等

struct input_event {

struct timeval time; //按键时间

__u16 type; //类型,在下面有定义

__u16 code; //要模拟成什么按键

__s32 value;//是按下还是释放

};


事件类型中可以看到支持声音

/*

* Event types

*/

#define EV_SYN 0x00

#define EV_KEY 0x01 //按键

#define EV_REL 0x02 //相对坐标(轨迹球)

#define EV_ABS 0x03 //绝对坐标

#define EV_MSC 0x04 //其他

#define EV_SW 0x05

#define EV_LED 0x11 //LED

#define EV_SND 0x12//声音

#define EV_REP 0x14//repeat

#define EV_FF 0x15 

#define EV_PWR 0x16

#define EV_FF_STATUS 0x17

#define EV_MAX 0x1f

#define EV_CNT (EV_MAX+1)



在头文件中追踪SND后发现event.code可以为两种模式

SND_BELL或SND_TONE



如果为SND_BELL,不管input_event.value为多少,最终的value只能为1000或0,即不能改变蜂鸣器的频率。1000表示蜂鸣器打开,0表示蜂鸣器关闭。
如果为SND_TONE,则可以通过改变input_event.value的值来调整蜂鸣器的频率,从而发出各种不同的音调。

至于为什么要使用struct input_even结构体有些时候我们要模拟按键来达到控制设备的目的,具体 方法就是操作/dev/input/eventx文件,向它写入个input_event结构体就可以模拟按键的输入了,查看/dev/input/eventX是什么类型的事件, cat /proc/bus/input/devices,比如我的测试程序中event.value=2000时蜂鸣器响,等于0时蜂鸣器关闭,就是相当于按键的event.value=1时按键按下,等于0时按键抬起,这就是一个模拟按键的典型例子,不同的是type,code,value不同。

http://blog.youkuaiyun.com/bingqingsuimeng/article/details/8178122(struct input_even结构体参考


strcmp()函数

int strcmp(const char *s1, const char *s2);

比较两个字符串

设这两个字符串为str1,str2,
若str1==str2,则返回零;
若str1<str2,则返回负数;
若str1>str2,则返回正数。
44     if(!strcmp (argv[1],"1"))	
 52     else if(!strcmp (argv[1],"0"))
我们在这里,利用int main(int argc, char *argv[])

argc是命令行总的参数个数 , argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数命令行后面跟的用户输入的参数,char   *argv[]是一个字符数组,其大小是int   argc,主要用于命令行参数   argv[]   参数,数组里每个元素代表一个参数;   

 比如我们在执行这个程序时输入./a.out会导致段错误,因为没有给argv数组赋值,正确的是./a.out x ,这里的"x"会和“1”、“0”做比较,从而判断是否打开蜂鸣器。



perror()函数

  perror("beep test");	

#include <stdio.h>
void perror(const char *s);
perror ( )用 来 将 上 一 个 函 数 发 生 错 误 的 原 因 输 出 到 标 准 设备 (stderr) 。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。


问题总结:

一、

./a.out: line 1: syntax error: unexpected "("

要交叉编译 /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc test1.c
生成的a.out才能在开发板上执行,这也是交叉编译器的作用。

二、
>: ./a.out
Segmentation fault

段错误,我没有给arg[]赋值,使他变成了野指针。在执行时应该./a.out 1 打开  或者 ./a.out 0 关闭,给它赋值“1”或“0”。上面也有分析。
详细解释:http://blog.chinaunix.net/uid-23069658-id-3959636.html

三、
我执行了./a.out 1 但是蜂鸣器并没有响,加了printf后,发现文件已经打开,但为什么蜂鸣器不能正常工作。

我们在启动开发板进入内核时,会有哔的一声,说明蜂鸣器驱动没有问题,后来发现是我们的测试程序打开错误的文件,之前看是event0但是后来移植了按键驱动后按键驱动变成了event0,蜂鸣器变为event1,所以应该open(event1...),用cat proc/bus/input/devices查看
这是之前的:

移植按键驱动后:


蜂鸣器的测试程序是模拟按键的,所以这里有kbd event1,但是我们要知道蜂鸣器是event1就可以了,所以应该是open("/dev/event1",O_RDWR),以后要特别注意这个问题。

参考:

strcmp():http://baike.baidu.com/link?url=1PJKyqgobTbIYt8fbVku1Loxdz4GEyqYjGAyAMpzNTJ61xT6Rvi_6DvGRVlD53tjnMfyZjvKFN-a9t3uHBT61_

perror():http://blog.youkuaiyun.com/ypist/article/details/7886209

struct input event :http://blog.sina.com.cn/s/blog_602f87700101dno6.html

     http://blog.youkuaiyun.com/bingqingsuimeng/article/details/8178122

/* Copyright(c) 2009-2018 TP-Link Systems Inc. * * file tplogd_input.c * brief functions about how message input. * details * * author Kuang MinLong * version 1.0.0 * date 2Jul18 * * history \arg 1.0.0, 2Jul18, Kuang Minlong, Create the file. */ #include <syslog.h> #include <libubox/blobmsg.h> #include <libtpsocket/libtpsocket.h> #include "tplogd.h" /**************************************************************************************************/ /* LOCAL_FUNCTIONS */ /**************************************************************************************************/ int dbg_client_dbg_log(struct tplogd_input_tpdbg_client *client, int log_level, const char *format, ...) { va_list args; int ret; va_start(args, format); ret = tplogd_core_add_entry_internal(client->server->core, TPLOG_ENTRY_TYPE_DBG, log_level, client->module_name, "tpdbg", format, args); va_end(args); return ret; } static void dbg_client_close_output(struct tplogd_input_tpdbg_client_output *output, int poll) { if (output->ufd.fd != -1) { if (poll) { output->poll_all = 1; output->ufd.cb(&output->ufd, ULOOP_READ); output->poll_all = 0; } uloop_fd_delete(&output->ufd); close(output->ufd.fd); output->ufd.fd = -1; } output->log_level = -1; } static void dbg_client_output_entry_strip(char *msg, int *plen) { int i, j; int len = *plen; /* strip console color control */ for (i = 0; i+1 < len; ) { if (msg[i] == '\033' && msg[i+1] == '[') { j = i + 2; while (j < len && (isdigit(msg[j]) || msg[j] == ';')) { ++j; } if (msg[j] == 'm') { ++j; memmove(msg+i, msg+j, len+1 - j); len -= j - i; } else { ++i; } } else { ++i; } } /* strip tail space */ while (len && isspace(msg[len-1])) { msg[--len] = '\0'; } *plen = len; } static void dbg_client_add_output_entry(struct tplogd_input_tpdbg_client_output *output, struct timespec *ts, char *msg, int len) { struct tplogd_input_tpdbg_client *client = output->client; struct tplog_entry_hdr hdr; const char *submod = (output == &client->output[0]) ? "out" : "err"; const char *msgv[3] = {client->module_name, submod, msg}; int lenv[3] = {client->module_name_len, 3, -1}; dbg_client_output_entry_strip(msg, &len); if (len <= 0) { return; } lenv[2] = len; hdr.type = TPLOG_ENTRY_TYPE_DBG; hdr.source = TPLOG_ENTRY_SOURCE_TPDBG; hdr.log_level = output->log_level; hdr.time_format = TPLOG_TIME_REALTIME; hdr.t_sec = ts->tv_sec; hdr.t_nsec = ts->tv_nsec; ++output->counter; tplogd_core_add_entry(client->server->core, &hdr, msgv, lenv); } static void dbg_client_output_handler(struct uloop_fd *u, unsigned int events) { struct tplogd_input_tpdbg_client_output *output = container_of(u, struct tplogd_input_tpdbg_client_output, ufd); struct timespec ts; static char static_buff[BUFSIZ + 1]; char *const buf = static_buff; char *const tail = static_buff + sizeof(static_buff) - 1; char *head, *end; ssize_t len; char *tmp; struct timespec ts0, ts1; unsigned int ms; int read_more = 1; if (events & ULOOP_READ) { clock_gettime(CLOCK_REALTIME, &ts); memcpy(&ts0, &ts, sizeof(ts)); head = buf; for (; read_more; clock_gettime(CLOCK_REALTIME, &ts)) { len = read(u->fd, head, tail - head); if (len <= 0) { len = 0; } if (len == 0 || (len < tail - head && head[len-1] == '\n')) { read_more = 0; } else { read_more = 1; } end = head + len; head = buf; *end = '\0'; while ((tmp = strchr(head, '\n')) != NULL) { *tmp = '\0'; dbg_client_add_output_entry(output, &ts, head, tmp - head); head = tmp + 1; } /* move the rest to buf, reset head */ if (head != buf) { memmove(buf, head, end + 1 - head); } head = buf + (end - head); /* break if we use too much time */ /* TBD: do not truncate line */ if (read_more && !u->error && !output->poll_all) { clock_gettime(CLOCK_REALTIME, &ts1); ms = (ts1.tv_sec - ts0.tv_sec) * 1000 + ts1.tv_nsec/1000000 - ts0.tv_nsec/1000000; if (ms > 1500) { read_more = 0; } } /* truncate for buff full or cann't read a line */ if (head != buf && (!read_more || head == tail)) { dbg_client_add_output_entry(output, &ts, buf, head - buf); head = buf; *head = '\0'; } } } if (u->error) { dbg_client_close_output(output, 0); dbg_client_dbg_log(output->client, TPLOG_LEVEL_DEBUG, "Read error. Disable log of std%s.", (output == &output->client->output[0]) ? "out" : "err"); } } static struct tplogd_input_tpdbg_client *dbg_client_new(struct tplogd_input_tpdbg *dbg) { struct tplogd_input_tpdbg_client *client; int i; client = malloc(sizeof(*client)); if (client) { memset(client, 0, sizeof(*client)); client->server = dbg; client->log_level = -1; for (i = 0; i < 2; ++i) { client->output[i].ufd.fd = -1; client->output[i].ufd.cb = dbg_client_output_handler; client->output[i].log_level = -1; client->output[i].poll_all = 0; client->output[i].client = client; } list_add_tail(&client->list, &dbg->clients); } return client; } static void dbg_client_del(struct tplogd_input_tpdbg_client *client, int poll) { dbg_client_close_output(&client->output[0], poll); dbg_client_close_output(&client->output[1], poll); dbg_client_dbg_log(client, TPLOG_LEVEL_DEBUG, poll ? "Terminate." : "Force terminate."); free(client->module_name); list_del(&client->list); free(client); } static void tplogd_input_tpdbg_client_process_msg(struct tplogd_input_tpdbg_client *client, void *buf, int len, int fd) { struct tplog_msg_log *log = buf; struct tplog_msg_header *cfg = buf; struct tplog_entry_hdr hdr; struct tplogd_input_tpdbg_client_output *o; const char *msgv[3]; int lenv[3]; if (len > (int)sizeof(*log) && (log->type == TPLOG_MSG_TYPE_LOG || log->type == TPLOG_MSG_TYPE_DBG)) { if (log->msg_failed | log->msg_discarded) { dbg_client_dbg_log(client, TPLOG_LEVEL_WARNING, "%u dbg message failed, %u dbg message droped.", log->msg_failed, log->msg_discarded); } hdr.type = (log->type == TPLOG_MSG_TYPE_LOG) ? TPLOG_ENTRY_TYPE_LOG : TPLOG_ENTRY_TYPE_DBG; hdr.source = TPLOG_ENTRY_SOURCE_TPDBG; hdr.log_level = log->log_level <= TPLOG_LEVEL_DEBUG ? log->log_level : TPLOG_LEVEL_DEBUG; hdr.time_format = log->time_format; hdr.t_sec = log->t_sec; hdr.t_nsec = log->t_nsec; if (!tplog_entry_parse_data(log->module_len, log->submod_len, log->data, len - sizeof(*log), msgv, lenv)) { ++client->counter[hdr.log_level]; tplogd_core_add_entry(client->server->core, &hdr, msgv, lenv); } else { tplogd_core_add_entry_self_dbg(client->server->core, TPLOG_LEVEL_INFO, "invalid tpdbg message from %s", client->module_name ? client->module_name : ""); } } else if (len > (int)sizeof(*cfg) && cfg->type == TPLOG_MSG_TYPE_CONFIG && client) { struct blobmsg ( blobmsg_string module_name, blobmsg_int32 log_level, blobmsg_int32 blocking, blobmsg_int32 time_format, blobmsg_int32 output_log_level, blobmsg_int32 output_idx, ) (req, ((struct blob_attr *)cfg->data), false); if (req.module_name) { if (req.module_name) { free(client->module_name); if (blobmsg_get_string(req.module_name)[0] != '\0') { client->module_name = strdup(blobmsg_get_string(req.module_name)); } else { client->module_name = NULL; } client->module_name_len = client->module_name ? strlen(client->module_name) : 0; } if (req.log_level) { client->log_level = blobmsg_get_u32(req.log_level); } if (req.blocking) { client->blocking = blobmsg_get_u32(req.blocking); } if (req.time_format) { client->time_format = blobmsg_get_u32(req.time_format); } dbg_client_dbg_log(client, TPLOG_LEVEL_DEBUG, "Config. log_level:%d blocking:%d time_format:%s", client->log_level, client->blocking, client->time_format == TPLOG_TIME_MONOTONIC ? "monotonic" : "realtime"); } if (req.output_log_level && req.output_idx) { int level, idx; int close_old = 0; level = blobmsg_get_u32(req.output_log_level); idx = blobmsg_get_u32(req.output_idx); if (level >= -1 && level <= TPLOG_LEVEL_DEBUG && idx >= 0 && idx <= 1) { o = &client->output[idx]; if (o->ufd.fd != -1) { dbg_client_close_output(o, 1); close_old = 1; } if (fd != -1 && level != -1) { o->ufd.fd = fd; fd = -1; uloop_fd_add(&o->ufd, ULOOP_READ | ULOOP_ERROR_CB); o->log_level = level; dbg_client_dbg_log(client, TPLOG_LEVEL_DEBUG, "Config. Set std%s output to log_level:%d.%s", idx == 0 ? "out" : "err", level, close_old ? " Disable preview log config." : ""); } else { if (close_old) { dbg_client_dbg_log(client, TPLOG_LEVEL_DEBUG, "Config. Disable log of std%s.", idx == 0 ? "out" : "err"); } } } } } if (fd != -1) { close(fd); } } static void tplogd_input_tplog_client_process_msg(struct tplogd_input_tplog *tplog, void *buf, int len, int fd) { struct tplog_msg_log *log = buf; struct tplog_msg_header *cfg = buf; struct tplog_entry_hdr hdr; const char *msgv[3]; int lenv[3]; if (len > (int)sizeof(*log) && (log->type == TPLOG_MSG_TYPE_LOG || log->type == TPLOG_MSG_TYPE_DBG)) { hdr.type = (log->type == TPLOG_MSG_TYPE_LOG) ? TPLOG_ENTRY_TYPE_LOG : TPLOG_ENTRY_TYPE_DBG; hdr.source = TPLOG_ENTRY_SOURCE_TPLOG; hdr.log_level = log->log_level <= TPLOG_LEVEL_DEBUG ? log->log_level : TPLOG_LEVEL_DEBUG; hdr.time_format = log->time_format; hdr.t_sec = log->t_sec; hdr.t_nsec = log->t_nsec; if (!tplog_entry_parse_data(log->module_len, log->submod_len, log->data, len - sizeof(*log), msgv, lenv)) { ++tplog->counter[hdr.log_level]; tplogd_core_add_entry(tplog->core, &hdr, msgv, lenv); } else { tplogd_core_add_entry_self_dbg(tplog->core, TPLOG_LEVEL_INFO, "Invalid tplog message"); } } else if (len > (int)sizeof(*cfg) && cfg->type == TPLOG_MSG_TYPE_CONFIG) { int highlight = -1, verbose = 0; struct blobmsg ( blobmsg_int32 config_output, blobmsg_int32 highlight, blobmsg_int32 verbose, ) (req, ((struct blob_attr *)cfg->data), false); if (req.config_output) { if (req.highlight) { highlight = blobmsg_get_u32(req.highlight); } if (req.verbose) { verbose = blobmsg_get_u32(req.verbose); } tplogd_output_console_config(tplog->core, fd, &highlight, &verbose, NULL); if (fd != -1) { fd = -1; } } } if (fd != -1) { close(fd); } } static bool tplogd_input_tpdbg_server_handler(struct tpsocket_handler *handler, struct list_head *buf, int event) { struct tpsocket_fd *sock = container_of(handler, struct tpsocket_fd, handler); struct tpsocket_buf *pbuf; int fd; struct tplogd_input_tpdbg_client *client; switch(event) { case TPSOCKET_EVENT_LISTEN: break; case TPSOCKET_EVENT_ACCEPT: handler->priv = client = dbg_client_new(handler->priv); if (client) { client->tpsock = sock; } break; case TPSOCKET_EVENT_CONNECTED: break; case TPSOCKET_EVENT_MESSAGE: pbuf = list_first_entry(buf, struct tpsocket_buf, list); if (pbuf) { if (!tpsocket_recv_fd(sock, &fd)) { fd = -1; } tplogd_input_tpdbg_client_process_msg(handler->priv, tpbuf_data(pbuf), tpbuf_data_len(pbuf), fd); } break; case TPSOCKET_EVENT_RESET: break; case TPSOCKET_EVENT_CLOSED: if (handler->priv) { dbg_client_del(handler->priv, 1); } break; case TPSOCKET_EVENT_ERROR: default: break; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); return true; } static bool tplogd_input_tplog_server_handler(struct tpsocket_handler *handler, struct list_head *buf, int event) { struct tpsocket_fd *sock = container_of(handler, struct tpsocket_fd, handler); struct tpsocket_buf *pbuf; int fd; switch(event) { case TPSOCKET_EVENT_LISTEN: break; case TPSOCKET_EVENT_ACCEPT: break; case TPSOCKET_EVENT_CONNECTED: break; case TPSOCKET_EVENT_MESSAGE: pbuf = list_first_entry(buf, struct tpsocket_buf, list); if (pbuf) { if (!tpsocket_recv_fd(sock, &fd)) { fd = -1; } tplogd_input_tplog_client_process_msg(handler->priv, tpbuf_data(pbuf), tpbuf_data_len(pbuf), fd); } break; case TPSOCKET_EVENT_RESET: break; case TPSOCKET_EVENT_CLOSED: break; case TPSOCKET_EVENT_ERROR: default: break; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); return true; } static struct tpsocket_fd *tplogd_input_tpdbg_server_new(struct tplogd_input_tpdbg *dbg) { struct tpsocket_handler handler = { .cb = tplogd_input_tpdbg_server_handler, .priv = dbg, }; return tpsocket_from_url("unixspd:/" TPLOG_MSG_DBG_SOCKET_PATH, &handler); } static struct tpsocket_fd *tplogd_input_tplog_server_new(struct tplogd_input_tplog *log) { struct tpsocket_handler handler = { .cb = tplogd_input_tplog_server_handler, .priv = log, }; return tpsocket_from_url("unixdgramd:/" TPLOG_MSG_LOG_SOCKET_PATH, &handler); } static int tplogd_input_tpdbg_set_enable(struct tplogd_input_class *ci, int enable) { struct tplogd_input_tpdbg *dbg; struct tplogd_input_tpdbg_client *client, *tmp; if (!ci->enabled && enable) { dbg = malloc(sizeof(*dbg)); if (!dbg) { return -1; } dbg->core = ci->core; dbg->tpsock = tplogd_input_tpdbg_server_new(dbg); INIT_LIST_HEAD(&dbg->clients); ci->enabled = 1; ci->priv = dbg; ci->core->tpdbg = dbg; } else if (ci->enabled && !enable) { dbg = ci->priv; list_for_each_entry_safe(client, tmp, &dbg->clients, list) { client->tpsock->handler.priv = NULL; dbg_client_del(client, 0); } tpsocket_free(dbg->tpsock); free(dbg); unlink(TPLOG_MSG_DBG_SOCKET_PATH); ci->enabled = 0; ci->priv = NULL; ci->core->tpdbg = NULL; } return 0; } static int tplogd_input_tplog_set_enable(struct tplogd_input_class *ci, int enable) { struct tplogd_input_tplog *log; if (!ci->enabled && enable) { log = malloc(sizeof(*log)); if (!log) { return -1; } memset(log, 0, sizeof(*log)); log->core = ci->core; log->tpsock = tplogd_input_tplog_server_new(log); ci->enabled = 1; ci->priv = log; ci->core->tplog = log; } else if (ci->enabled && !enable) { log = ci->priv; tpsocket_free(log->tpsock); free(log); unlink(TPLOG_MSG_LOG_SOCKET_PATH); ci->enabled = 0; ci->priv = NULL; ci->core->tplog = NULL; } return 0; } static int tplogd_input_ubus_set_enable(struct tplogd_input_class *ci, int enable) { ci->enabled = enable; ci->core->ubus_input_enabled = enable; return 0; } static int tplogd_input_ubusevent_set_enable(struct tplogd_input_class *ci, int enable) { ci->enabled = enable; ci->core->ubusevent_input_enabled = enable; if (enable) { memset(&ci->core->ubus_dbg_event_counter, 0, sizeof(ci->core->ubus_dbg_event_counter)); } return 0; } static void tplogd_input_syslog_client_process_msg(struct tplogd_input_syslog *syslog, char *buf, int len) { static const char *const fac_str[13] = { "kern", "user", "mail", "daemon", "auth", "syslog", "lpr", "news", "uucp", "cron", "authpriv", "ftp", "local", }; const char *msgv[3] = {"syslog", NULL, NULL}; int lenv[3] = {6, -1, -1}; struct tplog_entry_hdr hdr; char *p; int pri = (LOG_USER | LOG_NOTICE); struct timespec ts; while (len && (buf[len-1] == '\n' || buf[len-1] == '\0')) { --len; } buf[len] = '\0'; /* parse priority */ p = buf; if (*p == '<') { pri = strtoul(p + 1, &p, 10); if (*p == '>') { p++; } if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) { pri = (LOG_USER | LOG_NOTICE); } } /* parse time */ if (len - (p - buf) >= 16 && p[3] == ' ' && p[6] == ' ' && p[9] == ':' && p[12] == ':' && p[15] == ' ') { p += 16; } // TBD: parse time & escape msg ++syslog->counter[LOG_PRI(pri)]; hdr.type = TPLOG_ENTRY_TYPE_DBG; hdr.source = TPLOG_ENTRY_SOURCE_SYSLOG; hdr.log_level = LOG_PRI(pri); hdr.time_format = TPLOG_TIME_REALTIME; clock_gettime(CLOCK_REALTIME, &ts); hdr.t_sec = ts.tv_sec; hdr.t_nsec = ts.tv_nsec; if (LOG_FAC(pri) > 12) { msgv[1] = fac_str[12]; } else { msgv[1] = fac_str[LOG_FAC(pri)]; } msgv[2] = p; lenv[2] = len - (p - buf); tplogd_core_add_entry(syslog->core, &hdr, msgv, lenv); } static bool tplogd_input_syslog_server_handler(struct tpsocket_handler *handler, struct list_head *buf, int event) { struct tpsocket_buf *pbuf; switch(event) { case TPSOCKET_EVENT_LISTEN: break; case TPSOCKET_EVENT_ACCEPT: break; case TPSOCKET_EVENT_CONNECTED: break; case TPSOCKET_EVENT_MESSAGE: pbuf = list_first_entry(buf, struct tpsocket_buf, list); if (pbuf) { if (tpbuf_tailroom(pbuf) >= 1) { tplogd_input_syslog_client_process_msg(handler->priv, tpbuf_data(pbuf), tpbuf_data_len(pbuf)); } else { /* drop */ } } break; case TPSOCKET_EVENT_RESET: break; case TPSOCKET_EVENT_CLOSED: break; case TPSOCKET_EVENT_ERROR: default: break; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); return true; } static struct tpsocket_fd *tplogd_input_syslog_server_new(struct tplogd_input_syslog *syslog) { struct tpsocket_handler handler = { .cb = tplogd_input_syslog_server_handler, .priv = syslog, }; return tpsocket_from_url("unixdgramd:/" TPLOGD_SYSLOG_SOCKET_PATH, &handler); } static int tplogd_input_syslog_set_enable(struct tplogd_input_class *ci, int enable) { struct tplogd_input_syslog *syslog; if (!ci->enabled && enable) { syslog = malloc(sizeof(*syslog)); if (!syslog) { return -1; } memset(syslog, 0, sizeof(*syslog)); syslog->core = ci->core; syslog->tpsock = tplogd_input_syslog_server_new(syslog); ci->enabled = 1; ci->priv = syslog; ci->core->syslog = syslog; } else if (ci->enabled && !enable) { syslog = ci->priv; tpsocket_free(syslog->tpsock); free(syslog); unlink(TPLOGD_SYSLOG_SOCKET_PATH); ci->enabled = 0; ci->priv = NULL; ci->core->syslog = NULL; } return 0; } static struct tplogd_input_class *tplogd_input_class_find(struct tplogd_core *core, const char *name) { struct tplogd_input_class *ci; list_for_each_entry(ci, &core->inputs, list) { if (!strcmp(ci->name, name)) { return ci; } } return NULL; } static struct tplogd_input_class *tplogd_input_class_create(struct tplogd_core *core, const char *name) { struct tplogd_input_class *ci; ci = malloc(sizeof(*ci)); if (ci) { memset(ci, 0, sizeof(*ci)); INIT_LIST_HEAD(&ci->list); ci->name = strdup(name); if (!ci->name) { free(ci); return NULL; } ci->core = core; list_add_tail(&ci->list, &core->inputs); } return ci; } /**************************************************************************************************/ /* PUBLIC_FUNCTIONS */ /**************************************************************************************************/ int tplogd_input_init(struct tplogd_core *core) { struct tplogd_input_class *ci; ci = tplogd_input_class_create(core, "tplog"); if (ci) { ci->set_enable = tplogd_input_tplog_set_enable; } ci = tplogd_input_class_create(core, "tpdbg"); if (ci) { ci->set_enable = tplogd_input_tpdbg_set_enable; } ci = tplogd_input_class_create(core, "ubus"); if (ci) { ci->set_enable = tplogd_input_ubus_set_enable; } ci = tplogd_input_class_create(core, "ubusevent"); if (ci) { ci->set_enable = tplogd_input_ubusevent_set_enable; } ci = tplogd_input_class_create(core, "syslog"); if (ci) { ci->set_enable = tplogd_input_syslog_set_enable; } // TBD : kmsg /* ci = tplogd_input_class_create(core, "kmsg"); */ return 0; } void tplogd_input_exit(struct tplogd_core *core) { struct tplogd_input_class *ci, *ci_tmp; list_for_each_entry_safe(ci, ci_tmp, &core->inputs, list) { if (ci->enabled) { ci->set_enable(ci, 0); } if (ci->name) { free(ci->name); } free(ci); } } int tplogd_input_set_enable(struct tplogd_core *core, const char *name, int enable) { struct tplogd_input_class *ci = tplogd_input_class_find(core, name); int succ = 0; if (ci && ci->set_enable) { if (ci->enabled != enable) { succ = !ci->set_enable(ci, enable); tplogd_core_add_entry_self_dbg(core, TPLOG_LEVEL_DEBUG, "%s input \"%s\" %s.", enable ? "Enable" : "Disable", ci->name, succ ? "done" : "failed"); } else { succ = 1; } } return succ ? 0 : -1; }
最新发布
12-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值