417 lines
10 KiB
C
417 lines
10 KiB
C
/* Error & Logging functions
|
|
|
|
Copyright (C) 2010 Travis Robinson. <libusbdotnet@gmail.com>
|
|
website: http://sourceforge.net/projects/libusb-win32
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU Lesser 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 Lesser General Public
|
|
License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program; if not, please visit www.gnu.org.
|
|
*/
|
|
|
|
#include "error.h"
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#if IS_DRIVER
|
|
#ifdef __GNUC__
|
|
#define OBJ_KERNEL_HANDLE 0x00000200L
|
|
#include <ddk/usb100.h>
|
|
#include <ddk/usbdi.h>
|
|
#include <ddk/winddk.h>
|
|
#include "usbdlib_gcc.h"
|
|
#else
|
|
#include <ntddk.h>
|
|
#endif
|
|
#else
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#define USB_ERROR_BEGIN 500000
|
|
|
|
#ifndef LOG_APPNAME
|
|
#define LOG_APPNAME "LOG_APPNAME define missing"
|
|
#endif
|
|
|
|
#define GetLogLevel(UsbLogLevel) ((UsbLogLevel & LOG_LEVEL_MASK)>LOG_LEVEL_MAX?LOG_LEVEL_MAX:UsbLogLevel & LOG_LEVEL_MASK)
|
|
#define GetLogOuput(LogOutputType) (LogOutputType>0?(_LOG_OUTPUT_TYPE & LogOutputType):1)
|
|
|
|
void usb_err_v (const char* function, const char* format, va_list args);
|
|
void usb_wrn_v (const char* function, const char* format, va_list args);
|
|
void usb_msg_v (const char* function, const char* format, va_list args);
|
|
void usb_dbg_v (const char* function, const char* format, va_list args);
|
|
|
|
void usb_log_v (enum USB_LOG_LEVEL level, const char* function, const char* format, va_list args);
|
|
void _usb_log (enum USB_LOG_LEVEL level, const char* app_name, const char* function, const char* format, ...);
|
|
void _usb_log_v (enum USB_LOG_LEVEL level, const char* app_name, const char* function, const char* format, va_list args);
|
|
|
|
static int usb_log_def_handler(enum USB_LOG_LEVEL level,
|
|
const char* app_name,
|
|
const char* prefix,
|
|
const char* func,
|
|
int app_prefix_func_end,
|
|
char* message,
|
|
int message_length);
|
|
|
|
#define STRIP_PREFIX(stringSrc, stringPrefix) \
|
|
(strstr(stringSrc,stringPrefix)==stringSrc?stringSrc+strlen(stringPrefix):stringSrc)
|
|
|
|
static const char *log_level_string[LOG_LEVEL_MAX+1] =
|
|
{
|
|
"off",
|
|
"err",
|
|
"wrn",
|
|
"",
|
|
"dbg",
|
|
|
|
"unknown",
|
|
};
|
|
|
|
static const char *skipped_function_prefix_list[] =
|
|
{
|
|
"usb_registry_",
|
|
"usb_",
|
|
NULL
|
|
};
|
|
|
|
int usb_error_errno = 0;
|
|
log_hander_t user_log_hander = NULL;
|
|
|
|
#if (defined(_DEBUG) || defined(DEBUG) || defined(DBG))
|
|
int __usb_log_level = LOG_LEVEL_MAX;
|
|
#else
|
|
int __usb_log_level = LOG_OFF;
|
|
#endif
|
|
|
|
usb_error_type_t usb_error_type = USB_ERROR_TYPE_NONE;
|
|
|
|
const char** skipped_function_prefix = skipped_function_prefix_list;
|
|
|
|
#if !IS_DRIVER
|
|
|
|
char usb_error_str[LOGBUF_SIZE] = "";
|
|
|
|
char *usb_strerror(void)
|
|
{
|
|
switch (usb_error_type)
|
|
{
|
|
case USB_ERROR_TYPE_NONE:
|
|
return "No error";
|
|
case USB_ERROR_TYPE_STRING:
|
|
return usb_error_str;
|
|
case USB_ERROR_TYPE_ERRNO:
|
|
if (usb_error_errno > -USB_ERROR_BEGIN)
|
|
return strerror(usb_error_errno);
|
|
else
|
|
/* Any error we don't know falls under here */
|
|
return "Unknown error";
|
|
}
|
|
|
|
return "Unknown error";
|
|
}
|
|
|
|
/* returns Windows' last error in a human readable form */
|
|
const char *usb_win_error_to_string(void)
|
|
{
|
|
static char tmp[LOGBUF_SIZE];
|
|
|
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
|
|
LANG_USER_DEFAULT, tmp, sizeof(tmp) - 1, NULL);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
|
|
int usb_win_error_to_errno(void)
|
|
{
|
|
switch (GetLastError())
|
|
{
|
|
case ERROR_SUCCESS:
|
|
return 0;
|
|
case ERROR_INVALID_PARAMETER:
|
|
return EINVAL;
|
|
case ERROR_SEM_TIMEOUT:
|
|
case ERROR_OPERATION_ABORTED:
|
|
return ETRANSFER_TIMEDOUT;
|
|
case ERROR_NOT_ENOUGH_MEMORY:
|
|
return ENOMEM;
|
|
default:
|
|
return EIO;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
void usb_err(const char* function, const char* format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
usb_err_v(function, format, args);
|
|
va_end(args);
|
|
}
|
|
void usb_wrn(const char* function, const char* format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
usb_wrn_v(function, format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
void usb_msg(const char* function, const char* format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
usb_msg_v(function, format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
void usb_dbg(const char* function, const char* format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
usb_dbg_v(function, format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
void usb_log(enum USB_LOG_LEVEL level, const char* function, const char* format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
usb_log_v(level, function, format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
void usb_err_v(const char* function, const char* format, va_list args)
|
|
{
|
|
usb_log_v(LOG_ERROR, function, format, args);
|
|
}
|
|
|
|
void usb_wrn_v(const char* function, const char* format, va_list args)
|
|
{
|
|
usb_log_v(LOG_WARNING, function, format, args);
|
|
}
|
|
|
|
void usb_msg_v(const char* function, const char* format, va_list args)
|
|
{
|
|
usb_log_v(LOG_INFO, function, format, args);
|
|
}
|
|
|
|
void usb_dbg_v(const char* function, const char* format, va_list args)
|
|
{
|
|
usb_log_v(LOG_DEBUG, function, format, args);
|
|
}
|
|
|
|
void usb_log_v(enum USB_LOG_LEVEL level, const char* function, const char* format, va_list args)
|
|
{
|
|
_usb_log_v(level, LOG_APPNAME, function, format, args);
|
|
}
|
|
|
|
void _usb_log(enum USB_LOG_LEVEL level, const char* app_name, const char* function, const char* format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
_usb_log_v(level, app_name, function, format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
void _usb_log_v(enum USB_LOG_LEVEL level,
|
|
const char* app_name,
|
|
const char* function,
|
|
const char* format,
|
|
va_list args)
|
|
{
|
|
|
|
char local_buffer[LOGBUF_SIZE];
|
|
int totalCount, count;
|
|
const char* prefix;
|
|
const char* func;
|
|
char* buffer;
|
|
int masked_level;
|
|
int app_prefix_func_end;
|
|
#ifndef LOG_STYLE_SHORT
|
|
const char** skip_list = NULL;
|
|
#endif
|
|
|
|
masked_level = GetLogLevel(level);
|
|
|
|
if (__usb_log_level < masked_level && masked_level != LOG_ERROR) return;
|
|
buffer = local_buffer;
|
|
totalCount = 0;
|
|
count = 0;
|
|
prefix = log_level_string[masked_level];
|
|
func = function;
|
|
app_prefix_func_end = 0;
|
|
|
|
if (masked_level > LOG_LEVEL_MAX) masked_level = LOG_LEVEL_MAX;
|
|
|
|
if ((level & LOG_RAW) == LOG_RAW)
|
|
{
|
|
count = _vsnprintf(buffer, LOGBUF_SIZE-1, format, args);
|
|
if (count > 0)
|
|
{
|
|
buffer += count;
|
|
totalCount += count;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef LOG_STYLE_SHORT
|
|
if ((prefix) && strlen(prefix))
|
|
{
|
|
count = _snprintf(buffer, (LOGBUF_SIZE-1), "%s: ", prefix);
|
|
}
|
|
else
|
|
{
|
|
count = 0;
|
|
}
|
|
func = "";
|
|
#else
|
|
func = function;
|
|
|
|
if (func)
|
|
{
|
|
// strip some prefixes to shorten function names
|
|
skip_list=skipped_function_prefix;
|
|
while(*skip_list && ((func)) && func[0])
|
|
{
|
|
func = STRIP_PREFIX(func,skip_list[0]);
|
|
skip_list++;
|
|
}
|
|
}
|
|
|
|
if(!func) func="none";
|
|
|
|
// print app name, level string and short function name
|
|
if ((prefix) && strlen(prefix))
|
|
{
|
|
count = _snprintf(buffer, (LOGBUF_SIZE-1), "%s:%s [%s] ", app_name, prefix, func);
|
|
}
|
|
else
|
|
{
|
|
count = _snprintf(buffer, (LOGBUF_SIZE-1), "%s:[%s] ", app_name, func);
|
|
}
|
|
#endif
|
|
|
|
if (count >= 0)
|
|
{
|
|
app_prefix_func_end = count;
|
|
buffer += count;
|
|
totalCount += count;
|
|
count = _vsnprintf(buffer, (LOGBUF_SIZE-1) - totalCount, format, args);
|
|
if (count > 0)
|
|
{
|
|
buffer += count;
|
|
totalCount += count;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (count < 0)
|
|
totalCount = LOGBUF_SIZE - 1;
|
|
|
|
// make sure its null terminated
|
|
local_buffer[totalCount] = 0;
|
|
|
|
#if (!IS_DRIVER)
|
|
if (masked_level == LOG_ERROR)
|
|
{
|
|
// if this is an error message then store it
|
|
strncpy(usb_error_str, local_buffer, totalCount);
|
|
usb_error_str[totalCount] = '\0';
|
|
usb_error_type = USB_ERROR_TYPE_STRING;
|
|
}
|
|
#endif
|
|
|
|
if (user_log_hander)
|
|
{
|
|
if (user_log_hander(level, app_name, prefix, func, app_prefix_func_end, local_buffer, totalCount))
|
|
return;
|
|
}
|
|
if (__usb_log_level >= masked_level)
|
|
{
|
|
usb_log_def_handler(level, app_name, prefix, func, app_prefix_func_end, local_buffer, totalCount);
|
|
}
|
|
}
|
|
|
|
void usb_log_set_level(enum USB_LOG_LEVEL level)
|
|
{
|
|
// Debug builds of the driver force all messages on; all the time;
|
|
// Application can no longer change this.
|
|
//
|
|
#if (defined(_DEBUG) || defined(DEBUG) || defined(DBG))
|
|
__usb_log_level = LOG_LEVEL_MAX;
|
|
#else
|
|
__usb_log_level = level > LOG_LEVEL_MAX ? LOG_LEVEL_MAX : level;
|
|
#endif
|
|
}
|
|
|
|
int usb_log_get_level()
|
|
{
|
|
return __usb_log_level;
|
|
}
|
|
|
|
/* Default log handler
|
|
*/
|
|
static int usb_log_def_handler(enum USB_LOG_LEVEL level,
|
|
const char* app_name,
|
|
const char* prefix,
|
|
const char* func,
|
|
int app_prefix_func_end,
|
|
char* message,
|
|
int message_length)
|
|
{
|
|
#if IS_DRIVER
|
|
DbgPrint("%s",message);
|
|
#else
|
|
#if GetLogOuput(LOG_OUTPUT_TYPE_FILE)
|
|
FILE* file;
|
|
file = fopen(LOG_FILE_PATH,"a");
|
|
if (file)
|
|
{
|
|
fwrite(message,1,strlen(message),file);
|
|
fflush(file);
|
|
fclose(file);
|
|
}
|
|
#endif
|
|
|
|
#if GetLogOuput(LOG_OUTPUT_TYPE_STDERR)
|
|
fprintf(stderr, "%s", message);
|
|
#endif
|
|
|
|
#if GetLogOuput(LOG_OUTPUT_TYPE_DEBUGWINDOW)
|
|
OutputDebugStringA(message);
|
|
#endif
|
|
|
|
|
|
#if GetLogOuput(LOG_OUTPUT_TYPE_MSGBOX)
|
|
if (GetLogLevel(level)==LOG_ERROR)
|
|
{
|
|
message[app_prefix_func_end-1]='\0';
|
|
MessageBoxA(NULL,message+strlen(message),message,MB_OK|MB_ICONERROR);
|
|
}
|
|
#endif
|
|
|
|
#endif // IS_DRIVER
|
|
|
|
return 1;
|
|
}
|
|
|
|
void usb_log_set_handler(log_hander_t log_hander)
|
|
{
|
|
user_log_hander = log_hander;
|
|
}
|
|
|
|
log_hander_t usb_log_get_handler(void)
|
|
{
|
|
return user_log_hander;
|
|
}
|