1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * Bernard the first version 9 * 2013-06-26 Grissiom refactor 10 */ 11 #include <rtthread.h> 12 #include <log_trace.h> 13 14 #ifdef RT_USING_DFS 15 16 #include <dfs_posix.h> 17 18 struct file_device 19 { 20 struct rt_device parent; 21 22 int fd; 23 char *filename; 24 }; 25 26 /* file device for log trace */ 27 static struct file_device _file_device; 28 29 /* common device interface */ 30 static rt_err_t fdevice_open(rt_device_t dev, rt_uint16_t oflag) 31 { 32 int fd; 33 struct file_device *fdev = (struct file_device *)dev; 34 35 if (fdev->fd >= 0) 36 return -RT_EBUSY; 37 38 /* test and open */ 39 fd = open(fdev->filename, O_RDONLY, 0); 40 if (fd >= 0) 41 { 42 close(fd); 43 fd = open(fdev->filename, O_WRONLY | O_APPEND, 0); 44 } 45 else 46 { 47 /* file not exists */ 48 fd = open(fdev->filename, O_WRONLY | O_CREAT, 0); 49 } 50 fdev->fd = fd; 51 52 return RT_EOK; 53 } 54 55 static rt_err_t fdevice_close(rt_device_t dev) 56 { 57 rt_err_t result; 58 struct file_device *fdev = (struct file_device *)dev; 59 60 if (fdev->fd < 0) 61 return -RT_EBUSY; 62 63 result = close(fdev->fd); 64 if (result == 0) 65 { 66 fdev->fd = -1; 67 } 68 69 return result; 70 } 71 72 static rt_size_t fdevice_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) 73 { 74 struct file_device *fdev = (struct file_device *)dev; 75 76 if (fdev->fd < 0) 77 return 0; 78 79 return write(fdev->fd, buffer, size); 80 } 81 82 static rt_err_t fdevice_control(rt_device_t dev, int cmd, void *arg) 83 { 84 struct file_device *fdev = (struct file_device *)dev; 85 86 if (fdev->fd < 0) 87 return 0; 88 89 switch (cmd) 90 { 91 case LOG_TRACE_CTRL_FLUSH: 92 if (fsync(fdev->fd) != 0) 93 return RT_ERROR; 94 break; 95 default: 96 break; 97 } 98 return RT_EOK; 99 } 100 101 #ifdef RT_USING_DEVICE_OPS 102 const static struct rt_device_ops log_trace_ops = 103 { 104 RT_NULL, 105 fdevice_open, 106 fdevice_close, 107 RT_NULL, 108 fdevice_write, 109 fdevice_control 110 }; 111 #endif 112 113 void log_trace_file_init(const char *filename) 114 { 115 rt_device_t device; 116 117 device = rt_device_find("logfile"); 118 if (device == RT_NULL) 119 { 120 rt_memset(&_file_device, 0x00, sizeof(_file_device)); 121 122 _file_device.parent.type = RT_Device_Class_Char; 123 124 #ifdef RT_USING_DEVICE_OPS 125 _file_device.parent.ops = &log_trace_ops; 126 #else 127 _file_device.parent.init = RT_NULL; 128 _file_device.parent.open = fdevice_open; 129 _file_device.parent.close = fdevice_close; 130 _file_device.parent.write = fdevice_write; 131 _file_device.parent.control = fdevice_control; 132 #endif 133 134 rt_device_register(&_file_device.parent, "logfile", O_RDWR); 135 } 136 137 _file_device.filename = rt_strdup(filename); 138 _file_device.fd = -1; 139 } 140 141 void log_trace_set_file(const char *filename) 142 { 143 log_trace_file_init(filename); 144 log_trace_set_device("logfile"); 145 } 146 #ifdef RT_USING_FINSH 147 #include <finsh.h> 148 FINSH_FUNCTION_EXPORT_ALIAS(log_trace_set_file, log_file, set output filename of log trace); 149 #endif 150 151 #endif /* RT_USING_DFS */ 152