debug.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010-2011 Vojtech Horky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <adt/list.h>
00036 #include <fibril_synch.h>
00037 #include <errno.h>
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <usb/debug.h>
00041 
00043 static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
00044 
00046 static const char *log_prefix = "usb";
00047 
00049 static FIBRIL_MUTEX_INITIALIZE(log_serializer);
00050 
00052 static FILE *log_stream = NULL;
00053 
00054 
00060 void usb_log_enable(usb_log_level_t level, const char *message_prefix)
00061 {
00062         log_prefix = message_prefix;
00063         log_level = level;
00064         if (log_stream == NULL) {
00065                 char *fname;
00066                 int rc = asprintf(&fname, "/log/%s", message_prefix);
00067                 if (rc > 0) {
00068                         log_stream = fopen(fname, "w");
00069                         free(fname);
00070                 }
00071         }
00072 }
00073 
00079 static const char *log_level_name(usb_log_level_t level)
00080 {
00081         switch (level) {
00082                 case USB_LOG_LEVEL_FATAL:
00083                         return " FATAL";
00084                 case USB_LOG_LEVEL_ERROR:
00085                         return " ERROR";
00086                 case USB_LOG_LEVEL_WARNING:
00087                         return " WARN";
00088                 case USB_LOG_LEVEL_INFO:
00089                         return " info";
00090                 default:
00091                         return "";
00092         }
00093 }
00094 
00100 void usb_log_printf(usb_log_level_t level, const char *format, ...)
00101 {
00102         FILE *screen_stream = NULL;
00103         switch (level) {
00104                 case USB_LOG_LEVEL_FATAL:
00105                 case USB_LOG_LEVEL_ERROR:
00106                         screen_stream = stderr;
00107                         break;
00108                 default:
00109                         screen_stream = stdout;
00110                         break;
00111         }
00112         assert(screen_stream != NULL);
00113 
00114         va_list args;
00115 
00116         /*
00117          * Serialize access to log files.
00118          * Print to screen only messages with higher level than the one
00119          * specified during logging initialization.
00120          * Print also to file, to it print one more (lower) level as well.
00121          */
00122         fibril_mutex_lock(&log_serializer);
00123 
00124         const char *level_name = log_level_name(level);
00125 
00126         if ((log_stream != NULL) && (level <= log_level + 1)) {
00127                 va_start(args, format);
00128 
00129                 fprintf(log_stream, "[%s]%s: ", log_prefix, level_name);
00130                 vfprintf(log_stream, format, args);
00131                 fflush(log_stream);
00132 
00133                 va_end(args);
00134         }
00135 
00136         if (level <= log_level) {
00137                 va_start(args, format);
00138 
00139                 fprintf(screen_stream, "[%s]%s: ", log_prefix, level_name);
00140                 vfprintf(screen_stream, format, args);
00141                 fflush(screen_stream);
00142 
00143                 va_end(args);
00144         }
00145 
00146         fibril_mutex_unlock(&log_serializer);
00147 }
00148 
00149 
00150 #define REMAINDER_STR_FMT " (%zu)..."
00151 /* string + terminator + number width (enough for 4GB)*/
00152 #define REMAINDER_STR_LEN (5 + 1 + 10)
00153 
00155 #define BUFFER_DUMP_GROUP_SIZE 4
00156 
00158 #define BUFFER_DUMP_LEN 240 /* Ought to be enough for everybody ;-). */
00159 
00161 static fibril_local char buffer_dump[2][BUFFER_DUMP_LEN];
00163 static fibril_local int buffer_dump_index = 0;
00164 
00187 const char *usb_debug_str_buffer(const uint8_t *buffer, size_t size,
00188     size_t dumped_size)
00189 {
00190         /*
00191          * Remove previous string.
00192          */
00193         bzero(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN);
00194 
00195         if (buffer == NULL) {
00196                 return "(null)";
00197         }
00198         if (size == 0) {
00199                 return "(empty)";
00200         }
00201         if ((dumped_size == 0) || (dumped_size > size)) {
00202                 dumped_size = size;
00203         }
00204 
00205         /* How many bytes are available in the output buffer. */
00206         size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;
00207         char *it = buffer_dump[buffer_dump_index];
00208 
00209         size_t index = 0;
00210 
00211         while (index < size) {
00212                 /* Determine space before the number. */
00213                 const char *space_before;
00214                 if (index == 0) {
00215                         space_before = "";
00216                 } else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
00217                         space_before = "  ";
00218                 } else {
00219                         space_before = " ";
00220                 }
00221 
00222                 /*
00223                  * Add the byte as a hexadecimal number plus the space.
00224                  * We do it into temporary buffer to ensure that always
00225                  * the whole byte is printed.
00226                  */
00227                 int val = buffer[index];
00228                 char current_byte[16];
00229                 int printed = snprintf(current_byte, 16,
00230                     "%s%02x", space_before, val);
00231                 if (printed < 0) {
00232                         break;
00233                 }
00234 
00235                 if ((size_t) printed > buffer_remaining_size) {
00236                         break;
00237                 }
00238 
00239                 /* We can safely add 1, because space for end 0 is reserved. */
00240                 str_append(it, buffer_remaining_size + 1, current_byte);
00241 
00242                 buffer_remaining_size -= printed;
00243                 /* Point at the terminator 0. */
00244                 it += printed;
00245                 index++;
00246 
00247                 if (index >= dumped_size) {
00248                         break;
00249                 }
00250         }
00251 
00252         /* Add how many bytes were not printed. */
00253         if (index < size) {
00254                 snprintf(it, REMAINDER_STR_LEN,
00255                     REMAINDER_STR_FMT, size - index);
00256         }
00257 
00258         /* Next time, use the other buffer. */
00259         buffer_dump_index = 1 - buffer_dump_index;
00260 
00261         /* Need to take the old one due to previous line. */
00262         return buffer_dump[1 - buffer_dump_index];
00263 }
00264 
00265 

Generated on Thu Jun 2 07:45:48 2011 for HelenOS/USB by  doxygen 1.4.7