source: mainline/uspace/lib/usb/src/debug.c@ 621afdb

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 621afdb was 6028ec8, checked in by Vojtech Horky <vojtechhorky@…>, 14 years ago

Add generic logging functions

See ticket #52.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 * Copyright (c) 2010-2011 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libusb
30 * @{
31 */
32/** @file
33 * @brief Debugging support.
34 */
35#include <adt/list.h>
36#include <fibril_synch.h>
37#include <errno.h>
38#include <stdlib.h>
39#include <stdio.h>
40#include <usb/debug.h>
41
42/** Debugging tag. */
43typedef struct {
44 /** Linked list member. */
45 link_t link;
46 /** Tag name.
47 * We always have a private copy of the name.
48 */
49 char *tag;
50 /** Enabled level of debugging. */
51 int level;
52} usb_debug_tag_t;
53
54/** Get instance of usb_debug_tag_t from link_t. */
55#define USB_DEBUG_TAG_INSTANCE(iterator) \
56 list_get_instance(iterator, usb_debug_tag_t, link)
57
58/** List of all known tags. */
59static LIST_INITIALIZE(tag_list);
60/** Mutex guard for the list of all tags. */
61static FIBRIL_MUTEX_INITIALIZE(tag_list_guard);
62
63/** Level of logging messages. */
64static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
65/** Prefix for logging messages. */
66static const char *log_prefix = "usb";
67/** Serialization mutex for logging functions. */
68static FIBRIL_MUTEX_INITIALIZE(log_serializer);
69
70/** Find or create new tag with given name.
71 *
72 * @param tagname Tag name.
73 * @return Debug tag structure.
74 * @retval NULL Out of memory.
75 */
76static usb_debug_tag_t *get_tag(const char *tagname)
77{
78 link_t *link;
79 for (link = tag_list.next; \
80 link != &tag_list; \
81 link = link->next) {
82 usb_debug_tag_t *tag = USB_DEBUG_TAG_INSTANCE(link);
83 if (str_cmp(tag->tag, tagname) == 0) {
84 return tag;
85 }
86 }
87
88 /*
89 * Tag not found, we will create a new one.
90 */
91 usb_debug_tag_t *new_tag = malloc(sizeof(usb_debug_tag_t));
92 int rc = asprintf(&new_tag->tag, "%s", tagname);
93 if (rc < 0) {
94 free(new_tag);
95 return NULL;
96 }
97 list_initialize(&new_tag->link);
98 new_tag->level = 1;
99
100 /*
101 * Append it to the end of known tags.
102 */
103 list_append(&new_tag->link, &tag_list);
104
105 return new_tag;
106}
107
108/** Print debugging information.
109 * If the tag is used for the first time, its structures are automatically
110 * created and initial verbosity level is set to 1.
111 *
112 * @param tagname Tag name.
113 * @param level Level (verbosity) of the message.
114 * @param format Formatting string for printf().
115 */
116void usb_dprintf(const char *tagname, int level, const char *format, ...)
117{
118 fibril_mutex_lock(&tag_list_guard);
119 usb_debug_tag_t *tag = get_tag(tagname);
120 if (tag == NULL) {
121 printf("USB debug: FATAL ERROR - failed to create tag.\n");
122 goto leave;
123 }
124
125 if (tag->level < level) {
126 goto leave;
127 }
128
129 va_list args;
130 va_start(args, format);
131
132 printf("[%s:%d]: ", tagname, level);
133 vprintf(format, args);
134
135 va_end(args);
136
137leave:
138 fibril_mutex_unlock(&tag_list_guard);
139}
140
141/** Enable debugging prints for given tag.
142 *
143 * Setting level to <i>n</i> will cause that only printing messages
144 * with level lower or equal to <i>n</i> will be printed.
145 *
146 * @param tagname Tag name.
147 * @param level Enabled level.
148 */
149void usb_dprintf_enable(const char *tagname, int level)
150{
151 fibril_mutex_lock(&tag_list_guard);
152 usb_debug_tag_t *tag = get_tag(tagname);
153 if (tag == NULL) {
154 printf("USB debug: FATAL ERROR - failed to create tag.\n");
155 goto leave;
156 }
157
158 tag->level = level;
159
160leave:
161 fibril_mutex_unlock(&tag_list_guard);
162}
163
164/** Enable logging.
165 *
166 * @param level Maximal enabled level (including this one).
167 * @param message_prefix Prefix for each printed message.
168 */
169void usb_log_enable(usb_log_level_t level, const char *message_prefix)
170{
171 log_prefix = message_prefix;
172 log_level = level;
173}
174
175
176static const char *log_level_name(usb_log_level_t level)
177{
178 switch (level) {
179 case USB_LOG_LEVEL_FATAL:
180 return " FATAL";
181 case USB_LOG_LEVEL_ERROR:
182 return " ERROR";
183 case USB_LOG_LEVEL_WARNING:
184 return " WARN";
185 case USB_LOG_LEVEL_INFO:
186 return " info";
187 default:
188 return "";
189 }
190}
191
192/** Print logging message.
193 *
194 * @param level Verbosity level of the message.
195 * @param format Formatting directive.
196 */
197void usb_log_printf(usb_log_level_t level, const char *format, ...)
198{
199 if (level > log_level) {
200 return;
201 }
202
203 FILE *stream = NULL;
204 switch (level) {
205 case USB_LOG_LEVEL_FATAL:
206 case USB_LOG_LEVEL_ERROR:
207 stream = stderr;
208 break;
209 default:
210 stream = stdout;
211 break;
212 }
213 assert(stream != NULL);
214
215 va_list args;
216 va_start(args, format);
217
218 fibril_mutex_lock(&log_serializer);
219 fprintf(stream, "[%s]%s: ", log_prefix, log_level_name(level));
220 vfprintf(stream, format, args);
221 fibril_mutex_unlock(&log_serializer);
222
223 va_end(args);
224}
225
226/**
227 * @}
228 */
Note: See TracBrowser for help on using the repository browser.