Changeset 9d9ffdd in mainline for uspace/lib/usb/src/debug.c
- Timestamp:
- 2011-03-11T15:42:43Z (14 years ago)
- 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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/debug.c
r60a228f r9d9ffdd 31 31 */ 32 32 /** @file 33 * @brief Debugging support.33 * Debugging and logging support. 34 34 */ 35 35 #include <adt/list.h> … … 40 40 #include <usb/debug.h> 41 41 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 63 42 /** Level of logging messages. */ 64 43 static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING; 44 65 45 /** Prefix for logging messages. */ 66 46 static const char *log_prefix = "usb"; 47 67 48 /** Serialization mutex for logging functions. */ 68 49 static FIBRIL_MUTEX_INITIALIZE(log_serializer); 50 51 /** File where to store the log. */ 69 52 static FILE *log_stream = NULL; 70 53 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 automatically111 * 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 messages145 * 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 }164 54 165 55 /** Enable logging. … … 182 72 } 183 73 184 74 /** Get log level name prefix. 75 * 76 * @param level Log level. 77 * @return String prefix for the message. 78 */ 185 79 static const char *log_level_name(usb_log_level_t level) 186 80 { … … 252 146 } 253 147 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. */ 160 static 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 */ 183 const 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 254 259 /** 255 260 * @}
Note:
See TracChangeset
for help on using the changeset viewer.