Changeset 9d9ffdd in mainline for uspace/lib/usb/src/debug.c


Ignore:
Timestamp:
2011-03-11T15:42:43Z (14 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0bd4810c
Parents:
60a228f (diff), a8def7d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge with hidd

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/debug.c

    r60a228f r9d9ffdd  
    3131 */
    3232/** @file
    33  * @brief Debugging support.
     33 * Debugging and logging support.
    3434 */
    3535#include <adt/list.h>
     
    4040#include <usb/debug.h>
    4141
    42 /** Debugging tag. */
    43 typedef 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. */
    59 static LIST_INITIALIZE(tag_list);
    60 /** Mutex guard for the list of all tags. */
    61 static FIBRIL_MUTEX_INITIALIZE(tag_list_guard);
    62 
    6342/** Level of logging messages. */
    6443static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
     44
    6545/** Prefix for logging messages. */
    6646static const char *log_prefix = "usb";
     47
    6748/** Serialization mutex for logging functions. */
    6849static FIBRIL_MUTEX_INITIALIZE(log_serializer);
     50
     51/** File where to store the log. */
    6952static FILE *log_stream = NULL;
    7053
    71 /** Find or create new tag with given name.
    72  *
    73  * @param tagname Tag name.
    74  * @return Debug tag structure.
    75  * @retval NULL Out of memory.
    76  */
    77 static usb_debug_tag_t *get_tag(const char *tagname)
    78 {
    79         link_t *link;
    80         for (link = tag_list.next; \
    81             link != &tag_list; \
    82             link = link->next) {
    83                 usb_debug_tag_t *tag = USB_DEBUG_TAG_INSTANCE(link);
    84                 if (str_cmp(tag->tag, tagname) == 0) {
    85                         return tag;
    86                 }
    87         }
    88 
    89         /*
    90          * Tag not found, we will create a new one.
    91          */
    92         usb_debug_tag_t *new_tag = malloc(sizeof(usb_debug_tag_t));
    93         int rc = asprintf(&new_tag->tag, "%s", tagname);
    94         if (rc < 0) {
    95                 free(new_tag);
    96                 return NULL;
    97         }
    98         list_initialize(&new_tag->link);
    99         new_tag->level = 1;
    100 
    101         /*
    102          * Append it to the end of known tags.
    103          */
    104         list_append(&new_tag->link, &tag_list);
    105 
    106         return new_tag;
    107 }
    108 
    109 /** Print debugging information.
    110  * If the tag is used for the first time, its structures are automatically
    111  * created and initial verbosity level is set to 1.
    112  *
    113  * @param tagname Tag name.
    114  * @param level Level (verbosity) of the message.
    115  * @param format Formatting string for printf().
    116  */
    117 void usb_dprintf(const char *tagname, int level, const char *format, ...)
    118 {
    119         fibril_mutex_lock(&tag_list_guard);
    120         usb_debug_tag_t *tag = get_tag(tagname);
    121         if (tag == NULL) {
    122                 printf("USB debug: FATAL ERROR - failed to create tag.\n");
    123                 goto leave;
    124         }
    125 
    126         if (tag->level < level) {
    127                 goto leave;
    128         }
    129 
    130         va_list args;
    131         va_start(args, format);
    132 
    133         printf("[%s:%d]: ", tagname, level);
    134         vprintf(format, args);
    135 
    136         va_end(args);
    137 
    138 leave:
    139         fibril_mutex_unlock(&tag_list_guard);
    140 }
    141 
    142 /** Enable debugging prints for given tag.
    143  *
    144  * Setting level to <i>n</i> will cause that only printing messages
    145  * with level lower or equal to <i>n</i> will be printed.
    146  *
    147  * @param tagname Tag name.
    148  * @param level Enabled level.
    149  */
    150 void usb_dprintf_enable(const char *tagname, int level)
    151 {
    152         fibril_mutex_lock(&tag_list_guard);
    153         usb_debug_tag_t *tag = get_tag(tagname);
    154         if (tag == NULL) {
    155                 printf("USB debug: FATAL ERROR - failed to create tag.\n");
    156                 goto leave;
    157         }
    158 
    159         tag->level = level;
    160 
    161 leave:
    162         fibril_mutex_unlock(&tag_list_guard);
    163 }
    16454
    16555/** Enable logging.
     
    18272}
    18373
    184 
     74/** Get log level name prefix.
     75 *
     76 * @param level Log level.
     77 * @return String prefix for the message.
     78 */
    18579static const char *log_level_name(usb_log_level_t level)
    18680{
     
    252146}
    253147
     148
     149#define REMAINDER_STR_FMT " (%zu)..."
     150/* string + terminator + number width (enough for 4GB)*/
     151#define REMAINDER_STR_LEN (5 + 1 + 10)
     152
     153/** How many bytes to group together. */
     154#define BUFFER_DUMP_GROUP_SIZE 4
     155
     156/** Size of the string for buffer dumps. */
     157#define BUFFER_DUMP_LEN 240 /* Ought to be enough for everybody ;-). */
     158
     159/** Fibril local storage for the dumped buffer. */
     160static fibril_local char buffer_dump[BUFFER_DUMP_LEN];
     161
     162/** Dump buffer into string.
     163 *
     164 * The function dumps given buffer into hexadecimal format and stores it
     165 * in a static fibril local string.
     166 * That means that you do not have to deallocate the string (actually, you
     167 * can not do that) and you do not have to guard it against concurrent
     168 * calls to it.
     169 * The only limitation is that each call rewrites the buffer again.
     170 * Thus, it is necessary to copy the buffer elsewhere (that includes printing
     171 * to screen or writing to file).
     172 * Since this function is expected to be used for debugging prints only,
     173 * that is not a big limitation.
     174 *
     175 * @warning You cannot use this function twice in the same printf
     176 * (see detailed explanation).
     177 *
     178 * @param buffer Buffer to be printed (can be NULL).
     179 * @param size Size of the buffer in bytes (can be zero).
     180 * @param dumped_size How many bytes to actually dump (zero means all).
     181 * @return Dumped buffer as a static (but fibril local) string.
     182 */
     183const char *usb_debug_str_buffer(const uint8_t *buffer, size_t size,
     184    size_t dumped_size)
     185{
     186        /*
     187         * Remove previous string (that might also reveal double usage of
     188         * this function).
     189         */
     190        bzero(buffer_dump, BUFFER_DUMP_LEN);
     191
     192        if (buffer == NULL) {
     193                return "(null)";
     194        }
     195        if (size == 0) {
     196                return "(empty)";
     197        }
     198        if ((dumped_size == 0) || (dumped_size > size)) {
     199                dumped_size = size;
     200        }
     201
     202        /* How many bytes are available in the output buffer. */
     203        size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;
     204        char *it = buffer_dump;
     205
     206        size_t index = 0;
     207
     208        while (index < size) {
     209                /* Determine space before the number. */
     210                const char *space_before;
     211                if (index == 0) {
     212                        space_before = "";
     213                } else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
     214                        space_before = "  ";
     215                } else {
     216                        space_before = " ";
     217                }
     218
     219                /*
     220                 * Add the byte as a hexadecimal number plus the space.
     221                 * We do it into temporary buffer to ensure that always
     222                 * the whole byte is printed.
     223                 */
     224                int val = buffer[index];
     225                char current_byte[16];
     226                int printed = snprintf(current_byte, 16,
     227                    "%s%02x", space_before, val);
     228                if (printed < 0) {
     229                        break;
     230                }
     231
     232                if ((size_t) printed > buffer_remaining_size) {
     233                        break;
     234                }
     235
     236                /* We can safely add 1, because space for end 0 is reserved. */
     237                str_append(it, buffer_remaining_size + 1, current_byte);
     238
     239                buffer_remaining_size -= printed;
     240                /* Point at the terminator 0. */
     241                it += printed;
     242                index++;
     243
     244                if (index >= dumped_size) {
     245                        break;
     246                }
     247        }
     248
     249        /* Add how many bytes were not printed. */
     250        if (index < size) {
     251                snprintf(it, REMAINDER_STR_LEN,
     252                    REMAINDER_STR_FMT, size - index);
     253        }
     254
     255        return buffer_dump;
     256}
     257
     258
    254259/**
    255260 * @}
Note: See TracChangeset for help on using the changeset viewer.