/*************************************************************************** mhscanutil.c - description ------------------- begin : 06.02.2022 last modify : 15.08.2022 copyright : (C) 2022 by MHS-Elektronik GmbH & Co. KG, Germany author : Klaus Demlehner, klaus@mhs-elektronik.de ***************************************************************************/ #ifdef __WIN32__ #include #include #include #include #else #include #include #include #include #endif #include "mhscanutil.h" #ifdef __WIN32__ static HINSTANCE CanUtilDllHandle = 0; // Handle to DLL static char *CanUtilDllFileName = NULL; #else static void *CanUtilDllHandle = NULL; #endif #ifdef __WIN32__ // ****** Windows #define mhs_sleep(x) Sleep(x) #define MhsGetProcAddress(h, s) (void *)GetProcAddress((h), (LPCSTR)(s)) #else // ****** Linux #define mhs_sleep(x) usleep((x) * 1000) #define MhsGetProcAddress(h, s) dlsym((h), (s)) #endif #ifdef __WIN32__ #define MhsSafeFree(d) do { \ if ((d)) \ { \ free((d)); \ (d) = NULL; \ } \ } while(0) static char *GetCanUtilDllWithPath(void); #endif typedef int32_t (API_CALL *TCanUtilInit)(void); typedef void (API_CALL *TCanUtilDown)(void); typedef int32_t (API_CALL *TCanUtilRegisterDriver)(void *api_handle, int32_t res); typedef int32_t (API_CALL *TCanUtilCloseWin)(uint32_t win_idx); typedef int32_t (API_CALL *TCanUtilBitrateSelSetHw)(const char *tiny_can, uint32_t revision, const char *snr, struct TCanInfoVar *hw_info, uint32_t hw_info_size, uint32_t index); typedef int32_t (API_CALL *TCanUtilBitrateSelSetDefaults)(uint32_t flags, uint32_t bitrate, double sp, double sp_error, uint32_t fd_bitrate, double fd_sp, double fd_sp_error); typedef int32_t (API_CALL *TCanUtilBitrateSelGetHwResult)(uint32_t *nbtr_value, uint32_t *bitrate, uint32_t *clock_idx, char *bitrate_str, char *description, uint32_t *dbtr_value, uint32_t *fd_bitrate, char *fd_bitrate_str, char *fd_description); typedef int32_t (API_CALL *TCanUtilBitrateSelShowDialog)(const char *title, const char *sub_title, uint32_t flags); typedef int32_t (API_CALL *TCanUtilGetDriverList)(struct TCanUtilDrvInfo **drv_info_list); typedef int32_t (API_CALL *TCanUtilGetDriverListGet)(struct TCanUtilDrvInfo *item); typedef int32_t (API_CALL *TCanUtilGetSelectedDriver)(struct TCanUtilDrvInfo *selected_drv); typedef int32_t (API_CALL *TCanUtilShowDriverList)(const char *title, const char *sub_title, uint32_t flags, char *name); typedef int32_t (API_CALL *TCanUtilGetHwList)(struct TCanDevicesList **list); typedef int32_t (API_CALL *TCanUtilGetHwListGet)(struct TCanDevicesList *item); typedef uint32_t (API_CALL *TCanUtilGetSelectedHw)(struct TCanDevicesList *sel_dev); typedef int32_t (API_CALL *TCanUtilShowHwWin)(const char *title, const char *sub_title, uint32_t flags, char *snr); typedef int32_t (API_CALL *TCanUtilHwInfoWin)(const char *title, const char *sub_title, uint32_t flags, struct TCanInfoVar *hw_info, uint32_t hw_info_size, uint32_t index); static TCanUtilInit PCanUtilInit = NULL; static TCanUtilDown PCanUtilDown = NULL; static TCanUtilRegisterDriver PCanUtilRegisterDriver = NULL; static TCanUtilCloseWin PCanUtilCloseWin = NULL; static TCanUtilBitrateSelSetHw PCanUtilBitrateSelSetHw = NULL; static TCanUtilBitrateSelSetDefaults PCanUtilBitrateSelSetDefaults = NULL; static TCanUtilBitrateSelGetHwResult PCanUtilBitrateSelGetHwResult = NULL; static TCanUtilBitrateSelShowDialog PCanUtilBitrateSelShowDialog = NULL; static TCanUtilGetDriverList PCanUtilGetDriverList = NULL; static TCanUtilGetDriverListGet PCanUtilGetDriverListGet = NULL; static TCanUtilGetSelectedDriver PCanUtilGetSelectedDriver = NULL; static TCanUtilShowDriverList PCanUtilShowDriverList = NULL; static TCanUtilGetHwList PCanUtilGetHwList = NULL; static TCanUtilGetHwListGet PCanUtilGetHwListGet = NULL; static TCanUtilGetSelectedHw PCanUtilGetSelectedHw = NULL; static TCanUtilShowHwWin PCanUtilShowHwWin = NULL; static TCanUtilHwInfoWin PCanUtilHwInfoWin = NULL; /***************************************************************/ /* Treiber DLL laden */ /***************************************************************/ int32_t LoadCanUtil(void) { int32_t error; error = 0; UnloadCanUtil(); #ifdef __WIN32__ if (!(CanUtilDllFileName = GetCanUtilDllWithPath())) return(-100); CanUtilDllHandle = LoadLibraryA(CanUtilDllFileName); #else CanUtilDllHandle = dlopen(file_name, RTLD_LAZY); #endif if (CanUtilDllHandle) { if (!(PCanUtilInit = (TCanUtilInit)MhsGetProcAddress(CanUtilDllHandle, "CanUtilInit"))) error = -1; else if (!(PCanUtilDown = (TCanUtilDown)MhsGetProcAddress(CanUtilDllHandle, "CanUtilDown"))) error = -1; else if (!(PCanUtilRegisterDriver = (TCanUtilRegisterDriver)MhsGetProcAddress(CanUtilDllHandle, "CanUtilRegisterDriver"))) error = -1; else if (!(PCanUtilCloseWin = (TCanUtilCloseWin)MhsGetProcAddress(CanUtilDllHandle, "CanUtilCloseWin"))) error = -1; else if (!(PCanUtilBitrateSelSetHw = (TCanUtilBitrateSelSetHw)MhsGetProcAddress(CanUtilDllHandle, "CanUtilBitrateSelSetHw"))) error = -1; else if (!(PCanUtilBitrateSelSetDefaults = (TCanUtilBitrateSelSetDefaults)MhsGetProcAddress(CanUtilDllHandle, "CanUtilBitrateSelSetDefaults"))) error = -1; else if (!(PCanUtilBitrateSelGetHwResult = (TCanUtilBitrateSelGetHwResult)MhsGetProcAddress(CanUtilDllHandle, "CanUtilBitrateSelGetHwResult"))) error = -1; else if (!(PCanUtilBitrateSelShowDialog = (TCanUtilBitrateSelShowDialog)MhsGetProcAddress(CanUtilDllHandle, "CanUtilBitrateSelShowDialog"))) error = -1; else if (!(PCanUtilGetDriverList = (TCanUtilGetDriverList)MhsGetProcAddress(CanUtilDllHandle, "CanUtilGetDriverList"))) error = -1; else if (!(PCanUtilGetDriverListGet = (TCanUtilGetDriverListGet)MhsGetProcAddress(CanUtilDllHandle, "CanUtilGetDriverListGet"))) error = -1; else if (!(PCanUtilGetSelectedDriver = (TCanUtilGetSelectedDriver)MhsGetProcAddress(CanUtilDllHandle, "CanUtilGetSelectedDriver"))) error = -1; else if (!(PCanUtilShowDriverList = (TCanUtilShowDriverList)MhsGetProcAddress(CanUtilDllHandle, "CanUtilShowDriverList"))) error = -1; else if (!(PCanUtilGetHwList = (TCanUtilGetHwList)MhsGetProcAddress(CanUtilDllHandle, "CanUtilGetHwList"))) error = -1; else if (!(PCanUtilGetHwListGet = (TCanUtilGetHwListGet)MhsGetProcAddress(CanUtilDllHandle, "CanUtilGetHwListGet"))) error = -1; else if (!(PCanUtilGetSelectedHw = (TCanUtilGetSelectedHw)MhsGetProcAddress(CanUtilDllHandle, "CanUtilGetSelectedHw"))) error = -1; else if (!(PCanUtilShowHwWin = (TCanUtilShowHwWin)MhsGetProcAddress(CanUtilDllHandle, "CanUtilShowHwWin"))) error = -1; else if (!(PCanUtilHwInfoWin = (TCanUtilHwInfoWin)MhsGetProcAddress(CanUtilDllHandle, "CanUtilHwInfoWin"))) error = -1; } else error = -1000; if (error) UnloadCanUtil(); return(error); } /***************************************************************/ /* Treiber DLL entladen */ /***************************************************************/ void UnloadCanUtil(void) { #ifdef __WIN32__ HINSTANCE driver_handle; #else void *driver_handle; #endif driver_handle = CanUtilDllHandle; CanUtilDllHandle = NULL; #ifdef __WIN32__ MhsSafeFree(CanUtilDllFileName); #endif PCanUtilInit = NULL; PCanUtilDown = NULL; PCanUtilRegisterDriver = NULL; PCanUtilCloseWin = NULL; PCanUtilBitrateSelSetHw = NULL; PCanUtilBitrateSelSetDefaults = NULL; PCanUtilBitrateSelGetHwResult = NULL; PCanUtilBitrateSelShowDialog = NULL; PCanUtilGetDriverList = NULL; PCanUtilGetDriverListGet = NULL; PCanUtilGetSelectedDriver = NULL; PCanUtilShowDriverList = NULL; PCanUtilGetHwList = NULL; PCanUtilGetHwListGet = NULL; PCanUtilGetSelectedHw = NULL; PCanUtilShowHwWin = NULL; PCanUtilHwInfoWin = NULL; if (driver_handle) { #ifdef __WIN32__ FreeLibrary(driver_handle); #else dlclose(driver_handle); #endif } } int32_t CanUtilInit(void) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilInit)) err = (PCanUtilInit)(); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } void CanUtilDown(void) { if ((CanUtilDllHandle) && (PCanUtilInit)) (PCanUtilDown)(); } int32_t CanUtilRegisterDriver(void *api_handle, int32_t res) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilRegisterDriver)) err = (PCanUtilRegisterDriver)(api_handle, res); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } int32_t CanUtilCloseWin(uint32_t win_idx) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilCloseWin)) err = (PCanUtilCloseWin)(win_idx); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } int32_t CanUtilBitrateSelSetHw(const char *tiny_can, uint32_t revision, const char *snr, struct TCanInfoVar *hw_info, uint32_t hw_info_size, uint32_t index) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilBitrateSelSetHw)) err = (PCanUtilBitrateSelSetHw)(tiny_can, revision, snr, hw_info, hw_info_size, index); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } int32_t CanUtilBitrateSelSetDefaults(uint32_t flags, uint32_t bitrate, double sp, double sp_error, uint32_t fd_bitrate, double fd_sp, double fd_sp_error); { int32_t err; if ((CanUtilDllHandle) && (PCanUtilBitrateSelSetDefaults)) err = (PCanUtilBitrateSelSetDefaults)(flags, bitrate, sp, sp_error, fd_bitrate, fd_sp, fd_sp_error); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } int32_t CanUtilBitrateSelGetHwResult(uint32_t *nbtr_value, uint32_t *bitrate, uint32_t *clock_idx, char *bitrate_str, char *description, uint32_t *dbtr_value, uint32_t *fd_bitrate, char *fd_bitrate_str, char *fd_description) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilBitrateSelGetHwResult)) err = (PCanUtilBitrateSelGetHwResult)(nbtr_value, bitrate, clock_idx, bitrate_str, description, dbtr_value, fd_bitrate, fd_bitrate_str, fd_description); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } int32_t CanUtilBitrateSelShowDialog(const char *title, const char *sub_title, uint32_t flags) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilBitrateSelShowDialog)) err = (PCanUtilBitrateSelShowDialog)(title, sub_title, flags); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } /**************************************************************************************/ /* Driver DLLs Info */ /**************************************************************************************/ int32_t CanUtilGetDriverList(struct TCanUtilDrvInfo **drv_info_list) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilGetDriverList)) err = (PCanUtilGetDriverList)(drv_info_list); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } int32_t CanUtilGetDriverListGet(struct TCanUtilDrvInfo *item) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilGetDriverListGet)) err = (PCanUtilGetDriverListGet)(item); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } int32_t CanUtilGetSelectedDriver(struct TCanUtilDrvInfo *selected_drv) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilGetSelectedDriver)) err = (PCanUtilGetSelectedDriver)(selected_drv); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } int32_t CanUtilShowDriverList(const char *title, const char *sub_title, uint32_t flags, char *name) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilShowDriverList)) err = (PCanUtilShowDriverList)(title, sub_title, flags, name); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } /**************************************************************************************/ /* Connected Hardware */ /**************************************************************************************/ int32_t CanUtilGetHwList(struct TCanDevicesList **list) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilGetHwList)) err = (PCanUtilGetHwList)(list); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } int32_t CanUtilGetHwListGet(struct TCanDevicesList *item) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilGetHwListGet)) err = (PCanUtilGetHwListGet)(item); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } int32_t CanUtilGetSelectedHw(struct TCanDevicesList *sel_dev) { if ((CanUtilDllHandle) && (PCanUtilGetSelectedHw)) return((PCanUtilGetSelectedHw)(sel_dev)); else return(ERR_NO_CAN_UTIL_DLL_LOAD); } int32_t CanUtilShowHwWin(const char *title, const char *sub_title, uint32_t flags, char *snr) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilShowHwWin)) err = (PCanUtilShowHwWin)(title, sub_title, flags, snr); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } /**************************************************************************************/ /* Show Hardware Info */ /**************************************************************************************/ int32_t CanUtilHwInfoWin(const char *title, const char *sub_title, uint32_t flags, struct TCanInfoVar *hw_info, uint32_t *hw_info_size, uint32_t index) { int32_t err; if ((CanUtilDllHandle) && (PCanUtilHwInfoWin)) err = (PCanUtilHwInfoWin)(title, sub_title, flags, hw_info, hw_info_size, index); else err = ERR_NO_CAN_UTIL_DLL_LOAD; return(err); } #ifdef __WIN32__ /***************************************************************/ /* API Treiber Path ermitteln */ /***************************************************************/ #define MAX_PATH_LEN 255 #define DIR_SEPARATOR '\\' #define DIR_SEPARATOR_STR "\\" /**************************************************************************/ /* C O N S T A N T E N */ /**************************************************************************/ #ifdef _WIN64 static const char REG_TINY_CAN_API[] = {"Software\\Wow6432Node\\Tiny-CAN\\API"}; #else static const char REG_TINY_CAN_API[] = {"Software\\Tiny-CAN\\API"}; #endif static const char REG_TINY_CAN_API_PATH_ENTRY[] = {"PATH"}; static const char MHS_CAN_UTIL_DLL[] = {"mhscanutil.dll"}; #ifdef _WIN64 static const char API_DRIVER_X64_DIR[] = {"x64"}; #endif /**************************************************************************/ /* F U N K T I O N E N */ /**************************************************************************/ static char *MhsStpCpy(char *dest, const char *src) { register char *d = dest; register const char *s = src; do *d++ = *s; while (*s++); return(d - 1); } static char *MhsStrDup(const char *str) { size_t len; char *new_str; if (str) { len = strlen(str) + 1; new_str = (char *)malloc(len); if (!new_str) return(NULL); memcpy(new_str, str, len); return(new_str); } else return(NULL); } static char *MhsStrconcat(const char *string1, ...) { size_t l; va_list args; char *s, *concat, *ptr; if (!string1) return(NULL); l = 1 + strlen(string1); va_start(args, string1); s = va_arg(args, char*); while (s) { l += strlen(s); s = va_arg(args, char*); } va_end(args); concat = (char *)malloc(l); if (!concat) return(NULL); ptr = concat; ptr = MhsStpCpy(ptr, string1); va_start (args, string1); s = va_arg (args, char*); while (s) { ptr = MhsStpCpy(ptr, s); s = va_arg(args, char*); } va_end (args); return(concat); } static char *MhsCreateFileName(const char *dir, const char *sub_dir, const char *file_name) { if (!dir) return(MhsStrDup(file_name)); if (!file_name) return(NULL); if (strchr(file_name, DIR_SEPARATOR)) return(MhsStrDup(file_name)); else { if (sub_dir) { if (dir[strlen(dir)-1] == DIR_SEPARATOR) { if (sub_dir[strlen(sub_dir)-1] == DIR_SEPARATOR) return(MhsStrconcat(dir, sub_dir, file_name, NULL)); else return(MhsStrconcat(dir, sub_dir, DIR_SEPARATOR_STR, file_name, NULL)); } else { if (sub_dir[strlen(sub_dir)-1] == DIR_SEPARATOR) return(MhsStrconcat(dir, DIR_SEPARATOR_STR, sub_dir, file_name, NULL)); else return(MhsStrconcat(dir, DIR_SEPARATOR_STR, sub_dir, DIR_SEPARATOR_STR, file_name, NULL)); } } else { if (dir[strlen(dir)-1] == DIR_SEPARATOR) return(MhsStrconcat(dir, file_name, NULL)); else return(MhsStrconcat(dir, DIR_SEPARATOR_STR, file_name, NULL)); } } } static char *MhsRegGetString(HKEY key, const char *value_name) { DWORD type, data_size; char *str; type = 0; data_size = 0; if ((!key) || (!value_name)) return(NULL); // Länge des Strings ermitteln if (RegQueryValueExA(key, value_name, 0, &type, NULL, &data_size) != ERROR_SUCCESS) return(NULL); // Wert ist String ? if (type != REG_SZ) return(NULL); str = malloc(data_size+1); if (!str) return(NULL); // String lesen if (RegQueryValueExA(key, value_name, 0, &type, (LPBYTE)str, &data_size) != ERROR_SUCCESS) { free(str); return(NULL); } str[data_size] = '\0'; return(str); } static char *MhsRegReadStringEntry(const char *path, const char *entry) { HKEY key; char *value; value = NULL; // HKEY_CURRENT_USER ? if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) // KEY_READ { value = MhsRegGetString(key, entry); RegCloseKey(key); } return(value); } static int32_t TestApi(const char *file_name) { HINSTANCE driver_dll; TCanUtilBitrateSelSetup func; func = NULL; driver_dll = LoadLibraryA(file_name); if (driver_dll) { func = (TCanUtilBitrateSelSetup)(void *)GetProcAddress(driver_dll, (LPCSTR)"CanUtilBitrateSelSetup"); FreeLibrary(driver_dll); } if (func) return(0); else return(-1); } static char *GetCanUtilDllWithPath(void) { char *path, *file_name; char app_file[MAX_PATH_LEN]; char app_path[MAX_PATH_LEN]; char *ptr; file_name = NULL; if ((path = MhsRegReadStringEntry(REG_TINY_CAN_API, REG_TINY_CAN_API_PATH_ENTRY))) { #ifdef _WIN64 file_name = MhsCreateFileName(path, API_DRIVER_X64_DIR, MHS_CAN_UTIL_DLL); #else file_name = MhsCreateFileName(path, NULL, MHS_CAN_UTIL_DLL); #endif if (TestApi(file_name)) MhsSafeFree(file_name); free(path); } if (!file_name) { // Programm Path ermitteln GetModuleFileNameA(GetModuleHandle(NULL), app_file, MAX_PATH_LEN); GetFullPathNameA(app_file, sizeof(app_file), app_path, &ptr); app_path[ptr-app_path] = '\0'; file_name = MhsCreateFileName(app_path, NULL, MHS_CAN_UTIL_DLL); if (TestApi(file_name)) MhsSafeFree(file_name); } return(file_name); } #endif