📄 usbd-debug.c
字号:
/* * linux/drivers/usbd/usbd-debug.c * * Copyright (c) 2000, 2001, 2002 Lineo * Copyright (c) 2001 Hewlett Packard * * By: * Stuart Lynne <sl@lineo.com>, * Tom Rushworth <tbr@lineo.com>, * Bruce Balden <balden@lineo.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <linux/types.h>#include <linux/kernel.h>#include "usbd-debug.h"static int gn(char *cp){ /* Dumb little number scanner to avoid stdlib (atoi). */ int val = 0; char d; while ('0' <= (d = *cp++) && d <= '9') { val = val * 10 + (d - '0'); } return(val);}static char *ss(char *str, char c){ /* Dumb little string scanner to avoid stdlib (strchr). */ char d; do { if (c == (d = *str)) { return(str); } str += 1; } while (0 != d); return(NULL);}static char *sc(char *dst, char *src){ /* Dumb little string copier to avoid stdlib (~strcpy). */ char c; while (0 != (c = *src++)) { *dst++ = c; } *dst = c; // Terminate destination str, but don't point past 0 return(dst);}static int se(char *s1, char *s2){ /* Dumb little string comparer to avoid stdlib (strcmp). */ char c1,c2; do { if ((c1 = *s1++) != (c2 = *s2++)) { return(c1-c2); } } while (0 != c1); return(0);}debug_option *find_debug_option( debug_option *options, char *opt2find){ debug_option *op; char *sl; int r; for (op = options; NULL != op && NULL != op->name; op++) { if (NULL != op->sub_table) { /* This option is the name of a sub-table, check the prefix of opt2find (using ss, to avoid stdlib) */ if (NULL != (sl = ss(opt2find,'/'))) { *sl = 0; } r = se(opt2find,op->name); if (NULL != sl) { *sl = '/'; } if (0 == r) { /* Got a match. */ if (NULL == sl) { /* Match was to name of entire table. */ return(op); } return(find_debug_option(op->sub_table,sl+1)); } } else if (0 == se(opt2find,op->name)) { return(op); } } return(NULL);}static void print_options( debug_option *options, char *ps, char *pe){ debug_option *op; char *npe; for (op = options; NULL != op && NULL != op->name; op++) { if (NULL == op->sub_table) { printk(KERN_ERR "%s%s - %s\n", ps,op->name,op->description); } else { npe = sc(pe,op->name); npe = sc(npe,"/"); print_options(op->sub_table,ps,npe); *pe = 0; } }}static void print_all_options( char *caller_name, debug_option *options){ char opt_prefix[100], *prefix_end; prefix_end = sc(opt_prefix,caller_name); prefix_end = sc(prefix_end,": "); print_options(options,opt_prefix,prefix_end);}static void set_all_options( debug_option *options, int level){ debug_option *op; for (op = options; NULL != op && NULL != op->name; op++) { if (NULL == op->sub_table) { *(op->level) = level; } else { set_all_options(op->sub_table,level); } }}static int set_debug_option( char *caller_name, debug_option *options, char *value){ debug_option *op; int level; char *eq; if (NULL != (eq = ss(value,'='))) { /* There is an '='. */ *eq = 0; level = gn(eq+1); } else if (!('0' <= *value && *value <= '9')) { /* name with no '=', default to level 1. */ level = 1; } else { /* level with no name, set all options to level. */ level = gn(value); set_all_options(options,level); return(0); } op = find_debug_option(options,value); if (NULL != eq) { *eq = '='; } if (NULL != op) { /* Got a match. */ if (NULL != op->level) { *(op->level) = level; } else { /* Value matched an entire sub_table */ set_all_options(op,level); } return(0); } /* Unknown debug option. */ if (NULL == caller_name) { /* Silently ignore it. */ return(0); } printk(KERN_ERR "%s: unknown dbg option `%s', valid options are:\n", caller_name,value); print_all_options(caller_name,options); return(1);}int scan_debug_options(char *caller_name, debug_option *options, char *values){ char *cp; int rc = 0; if (NULL == values || NULL == options || NULL == caller_name) { return(0); } if ('~' == *values) { /* Ignore unknown options. */ values += 1; caller_name = NULL; } /* Pick apart a colon separated list of option=value. */ while (NULL != values && 0 != *values) { if (NULL != (cp = ss(values,':'))) { *cp = 0; } rc += set_debug_option(caller_name,options,values); if (NULL != cp) { *cp++ = ':'; } values = cp; } return(rc);}static char to_hex[] = {"0123456789ABCDEF"};void dbgPRINT_mem(u8 *mem, u32 len){ /* Display a portion of memory. */ u8 dbg_xbuff[52]; u8 dbg_sbuff[52]; u8 dbg_cbuff[20]; u8 b,*end,*mark; u8 *dp,*cp; int byte_count; end = (mark = mem) + len; dp = dbg_xbuff; cp = dbg_cbuff; byte_count = 0; while (mem < end) { if (byte_count > 0) { /* Space between bytes. */ *dp++ = ' '; if (!(0x3 & (unsigned)(void*)mem)) { /* Add an extra space on 4-byte boundary. */ *dp++ = ' '; } } b = *mem++; *dp++ = to_hex[b>>4]; *dp++ = to_hex[b&15]; *cp++ = (b < ' ' || '~' < b) ? '.' : b; byte_count += 1; if (byte_count >= 16) { /* Dump this line. */ *cp = *dp = 0; PRINTK(" #%08x |%s| |%s|\n", (unsigned)(void*)mark,dbg_xbuff,dbg_cbuff); byte_count = 0; dp = dbg_xbuff; cp = dbg_cbuff; mark = mem; } } if (byte_count > 0) { /* Dump last line. */ *cp = *dp = 0; // Find number of spaces needed for vertical alignment // Why am I wasting time on this? :) memset(dbg_sbuff,' ',sizeof(dbg_sbuff)); dbg_sbuff[50 - (byte_count*3 - 1 + ((byte_count-1)/4))] = 0; PRINTK(" #%08x |%s|%s |%s|\n", (unsigned)(void*)mark,dbg_xbuff,dbg_sbuff,dbg_cbuff); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -