blob: 2427d40b3f9fbc9083ec650123e0142d04246c7d [file] [log] [blame]
David Ngcac0b622012-10-18 19:13:49 -07001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdint.h>
30#include <stdarg.h>
31#include <stdio.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <fcntl.h>
35#include <linux/coresight-stm.h>
36#include <stm-log.h>
37#include <string.h>
38
39#ifdef DEBUG
40#define LOG_TAG "STM-LOG"
41#include <cutils/log.h>
42#endif
43
44#define STM_LOG_DEV "/dev/coresight-stm"
45#define STM_LOG_MAGIC_0 0xf0
46#define STM_LOG_MAGIC_1 0xf1
47
David Ng7ad27f22012-10-26 12:34:24 -070048#define STM_LOG_STR_MAX 1024
49#define STM_LOG_BIN_MAX 2048
50
David Ngcac0b622012-10-18 19:13:49 -070051static uint8_t dflt_stm_entity_id = OST_ENTITY_NONE;
52static uint8_t dflt_stm_proto_id = 0;
53static uint32_t dflt_stm_options = STM_OPTION_TIMESTAMPED;
54
55typedef struct
56{
57 uint8_t magic[2];
58 uint8_t entity;
59 uint8_t proto;
60 uint32_t options;
61} stmlog_t;
62
63void stm_log_initdefaults(uint32_t init_mask,
64 uint8_t entity_id,
65 uint8_t proto_id,
66 uint32_t options)
67{
68 if ((init_mask & STM_DFLT_ENTITY) != 0) {
69 dflt_stm_entity_id = entity_id;
70 }
71 if ((init_mask & STM_DFLT_PROTOCOL) != 0) {
72 dflt_stm_proto_id = proto_id;
73 }
74 if ((init_mask & STM_DFLT_OPTIONS) != 0) {
75 dflt_stm_options = options;
76 }
77#ifdef DEBUG
78 if ((init_mask & ~(STM_DFLT_ENTITY
79 | STM_DFLT_PROTOCOL
80 | STM_DFLT_OPTIONS)) != 0) {
81 ALOGE("Invalid init mask 0x%08x", init_mask);
82 }
83#endif
84}
85
David Ng7ad27f22012-10-26 12:34:24 -070086static int STMLOG_WRITE(int len, void *data, int *pfd) {
David Ngcac0b622012-10-18 19:13:49 -070087 int fd;
88 int rc = -1;
David Ng7ad27f22012-10-26 12:34:24 -070089
90 if (!pfd || (pfd && *pfd == -1))
91 fd = open(STM_LOG_DEV, O_WRONLY);
92 else
93 fd = *pfd;
94
95 if (fd != -1) {
David Ngcac0b622012-10-18 19:13:49 -070096 do {
97 rc = write(fd, data, len);
98 if (rc == -1)
99 break;
100 len -= rc;
101 } while (len > 0);
David Ng7ad27f22012-10-26 12:34:24 -0700102
103 if (pfd)
104 *pfd = fd;
105 else
106 close(fd);
David Ngcac0b622012-10-18 19:13:49 -0700107 }
David Ngcac0b622012-10-18 19:13:49 -0700108 return rc;
109}
110
111void stm_log(const char *format, ...)
112{
113 va_list ap;
David Ng7ad27f22012-10-26 12:34:24 -0700114
David Ngcac0b622012-10-18 19:13:49 -0700115 va_start(ap, format);
116 stm_log_ex(dflt_stm_entity_id,
117 dflt_stm_proto_id,
118 dflt_stm_options,
119 format,
120 ap);
121 va_end(ap);
122}
123
124void stm_logbin(int length, void *data)
125{
126 stm_logbin_ex(dflt_stm_entity_id,
127 dflt_stm_proto_id,
128 dflt_stm_options,
129 length,
130 data);
131}
132
133void stm_log_ex(uint8_t entity_id,
134 uint8_t proto_id,
135 uint32_t options,
136 const char *format, ...)
137{
David Ng7ad27f22012-10-26 12:34:24 -0700138 int length;
139 char *buf;
David Ngcac0b622012-10-18 19:13:49 -0700140 stmlog_t *log;
David Ng7ad27f22012-10-26 12:34:24 -0700141 va_list ap;
David Ngcac0b622012-10-18 19:13:49 -0700142
143 va_start(ap, format);
144 length = vsnprintf(NULL, 0, format, ap);
145 if (length >= 0) {
146 length++;
David Ng7ad27f22012-10-26 12:34:24 -0700147 if (length > STM_LOG_STR_MAX)
148 length = STM_LOG_STR_MAX;
149
David Ngcac0b622012-10-18 19:13:49 -0700150 buf = (char *)malloc(sizeof(stmlog_t) + length);
151 if (buf) {
152 log = (stmlog_t *)buf;
153 log->magic[0] = STM_LOG_MAGIC_0;
154 log->magic[1] = STM_LOG_MAGIC_1;
155 log->entity = entity_id;
156 log->proto = proto_id;
157 log->options = options;
158 vsnprintf(buf + sizeof(stmlog_t), length, format, ap);
David Ng7ad27f22012-10-26 12:34:24 -0700159 STMLOG_WRITE(sizeof(stmlog_t) + length, buf, NULL);
David Ngcac0b622012-10-18 19:13:49 -0700160 free(buf);
161 }
162#ifdef DEBUG
163 else {
164 ALOGE("Out of memory allocating temp buffer");
165 }
166#endif
167 }
168 va_end(ap);
169}
170
171void stm_logbin_ex(uint8_t entity_id,
172 uint8_t proto_id,
173 uint32_t options,
174 int length,
175 void *data)
176{
David Ng7ad27f22012-10-26 12:34:24 -0700177 uint8_t *usrdata = (uint8_t *)data;
David Ngcac0b622012-10-18 19:13:49 -0700178 uint8_t *buf;
179 stmlog_t *stm;
David Ng7ad27f22012-10-26 12:34:24 -0700180 int pktlen;
181 int fd = -1;
182
183 if (length < 0)
184 return;
185 else if (length > STM_LOG_BIN_MAX)
186 pktlen = STM_LOG_BIN_MAX;
187 else
188 pktlen = length;
189
190 buf = (uint8_t *)malloc(sizeof(stmlog_t) + pktlen);
David Ngcac0b622012-10-18 19:13:49 -0700191 if (buf) {
192 stm = (stmlog_t *)buf;
193 stm->magic[0] = STM_LOG_MAGIC_0;
194 stm->magic[1] = STM_LOG_MAGIC_1;
195 stm->entity = entity_id;
196 stm->proto = proto_id;
197 stm->options = options;
David Ng7ad27f22012-10-26 12:34:24 -0700198
199 do {
200 memcpy(buf + sizeof(stmlog_t), usrdata, pktlen);
201 STMLOG_WRITE(sizeof(stmlog_t) + pktlen, buf, &fd);
202 usrdata += pktlen;
203 length -= pktlen;
204 if (length < pktlen)
205 pktlen = length;
206 } while (length > 0);
207
David Ngcac0b622012-10-18 19:13:49 -0700208 free(buf);
David Ng7ad27f22012-10-26 12:34:24 -0700209 if (fd != -1)
210 close(fd);
David Ngcac0b622012-10-18 19:13:49 -0700211 }
212#ifdef DEBUG
213 else {
214 ALOGE("Out of memory allocating temp buffer");
215 }
216#endif
217}