Ignore:
File:
1 edited

Legend:

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

    r6fd7062 r1efe89b  
    3131 */
    3232/** @file
    33  * Debugging and logging support.
     33 * @brief Debugging support.
    3434 */
    3535#include <adt/list.h>
     
    4040#include <usb/debug.h>
    4141
     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
    4263/** Level of logging messages. */
    4364static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
    44 
    4565/** Prefix for logging messages. */
    4666static const char *log_prefix = "usb";
    47 
    4867/** Serialization mutex for logging functions. */
    4968static FIBRIL_MUTEX_INITIALIZE(log_serializer);
    50 
    51 /** File where to store the log. */
    5269static FILE *log_stream = NULL;
    5370
     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 */
     77static 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 */
     117void 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
     138leave:
     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 */
     150void 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
     161leave:
     162        fibril_mutex_unlock(&tag_list_guard);
     163}
    54164
    55165/** Enable logging.
     
    72182}
    73183
    74 /** Get log level name prefix.
    75  *
    76  * @param level Log level.
    77  * @return String prefix for the message.
    78  */
     184
    79185static const char *log_level_name(usb_log_level_t level)
    80186{
     
    150256/* string + terminator + number width (enough for 4GB)*/
    151257#define REMAINDER_STR_LEN (5 + 1 + 10)
    152 
    153 /** How many bytes to group together. */
    154258#define BUFFER_DUMP_GROUP_SIZE 4
    155 
    156 /** Size of the string for buffer dumps. */
    157259#define BUFFER_DUMP_LEN 240 /* Ought to be enough for everybody ;-). */
    158 
    159 /** Fibril local storage for the dumped buffer. */
    160 static fibril_local char buffer_dump[2][BUFFER_DUMP_LEN];
    161 /** Fibril local storage for buffer switching. */
    162 static fibril_local int buffer_dump_index = 0;
     260static fibril_local char buffer_dump[BUFFER_DUMP_LEN];
    163261
    164262/** Dump buffer into string.
     
    167265 * in a static fibril local string.
    168266 * That means that you do not have to deallocate the string (actually, you
    169  * can not do that) and you do not have to guard it against concurrent
     267 * can not do that) and you do not have to save it agains concurrent
    170268 * calls to it.
    171  * The only limitation is that each second call rewrites the buffer again
    172  * (internally, two buffer are used in cyclic manner).
     269 * The only limitation is that each call rewrites the buffer again.
    173270 * Thus, it is necessary to copy the buffer elsewhere (that includes printing
    174271 * to screen or writing to file).
     
    176273 * that is not a big limitation.
    177274 *
    178  * @warning You cannot use this function more than twice in the same printf
     275 * @warning You cannot use this function twice in the same printf
    179276 * (see detailed explanation).
    180277 *
     
    188285{
    189286        /*
    190          * Remove previous string.
    191          */
    192         bzero(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN);
     287         * Remove previous string (that might also reveal double usage of
     288         * this function).
     289         */
     290        bzero(buffer_dump, BUFFER_DUMP_LEN);
    193291
    194292        if (buffer == NULL) {
     
    204302        /* How many bytes are available in the output buffer. */
    205303        size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;
    206         char *it = buffer_dump[buffer_dump_index];
     304        char *it = buffer_dump;
    207305
    208306        size_t index = 0;
     
    255353        }
    256354
    257         /* Next time, use the other buffer. */
    258         buffer_dump_index = 1 - buffer_dump_index;
    259 
    260         /* Need to take the old one due to previous line. */
    261         return buffer_dump[1 - buffer_dump_index];
     355        return buffer_dump;
    262356}
    263357
Note: See TracChangeset for help on using the changeset viewer.