From c099d658d0d02871e1387172c8509fe2b57d2beb Mon Sep 17 00:00:00 2001 From: pavel Date: Wed, 14 Jan 2015 00:29:01 +0200 Subject: [PATCH] Windows DLL src added, vc2008 --- lib/usb-relay-dll/.gitignore | 1 + lib/usb-relay-dll/dllmain.c | 8 +- lib/usb-relay-dll/stdafx.h | 16 - lib/usb-relay-dll/targetver.h | 4 + ...ll.vcproj => usb-relay-dll(vc2008).vcproj} | 16 +- lib/usb-relay-dll/usb_relay_lib_win32.c | 139 ----- lib/usb_relay_device.h | 61 +- lib/usb_relay_hw.h | 6 +- lib/usb_relay_lib.c | 558 ++++++++++++++++++ 9 files changed, 608 insertions(+), 201 deletions(-) delete mode 100644 lib/usb-relay-dll/stdafx.h rename lib/usb-relay-dll/{usb-relay-dll.vcproj => usb-relay-dll(vc2008).vcproj} (92%) delete mode 100644 lib/usb-relay-dll/usb_relay_lib_win32.c create mode 100644 lib/usb_relay_lib.c diff --git a/lib/usb-relay-dll/.gitignore b/lib/usb-relay-dll/.gitignore index ac01e66..9789aa7 100644 --- a/lib/usb-relay-dll/.gitignore +++ b/lib/usb-relay-dll/.gitignore @@ -1,2 +1,3 @@ /Debug/ /Release/ +/x64/ diff --git a/lib/usb-relay-dll/dllmain.c b/lib/usb-relay-dll/dllmain.c index 6403fcc..4f49b7d 100644 --- a/lib/usb-relay-dll/dllmain.c +++ b/lib/usb-relay-dll/dllmain.c @@ -1,6 +1,8 @@ -// dllmain.cpp : Defines the entry point for the DLL +// dllmain.c : Defines the entry point for the DLL -#include "stdafx.h" +#include "targetver.h" +#define WIN32_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#include BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, @@ -10,6 +12,8 @@ BOOL APIENTRY DllMain( HMODULE hModule, switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hModule); + break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: diff --git a/lib/usb-relay-dll/stdafx.h b/lib/usb-relay-dll/stdafx.h deleted file mode 100644 index 96a9747..0000000 --- a/lib/usb-relay-dll/stdafx.h +++ /dev/null @@ -1,16 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -#include "targetver.h" - -#define WIN32_EXTRALEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files: -#include - - - -// TODO: reference additional headers your program requires here diff --git a/lib/usb-relay-dll/targetver.h b/lib/usb-relay-dll/targetver.h index c117daf..542d538 100644 --- a/lib/usb-relay-dll/targetver.h +++ b/lib/usb-relay-dll/targetver.h @@ -1,3 +1,5 @@ +#if defined (WIN32) || defined (_WIN32) + #pragma once // The following macros define the minimum required platform. The minimum required platform @@ -22,3 +24,5 @@ #ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. #define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. #endif + +#endif // WIN32 diff --git a/lib/usb-relay-dll/usb-relay-dll.vcproj b/lib/usb-relay-dll/usb-relay-dll(vc2008).vcproj similarity index 92% rename from lib/usb-relay-dll/usb-relay-dll.vcproj rename to lib/usb-relay-dll/usb-relay-dll(vc2008).vcproj index d08981d..6dc7e0e 100644 --- a/lib/usb-relay-dll/usb-relay-dll.vcproj +++ b/lib/usb-relay-dll/usb-relay-dll(vc2008).vcproj @@ -41,6 +41,7 @@ + + @@ -196,10 +202,6 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > - - diff --git a/lib/usb-relay-dll/usb_relay_lib_win32.c b/lib/usb-relay-dll/usb_relay_lib_win32.c deleted file mode 100644 index b1b74b7..0000000 --- a/lib/usb-relay-dll/usb_relay_lib_win32.c +++ /dev/null @@ -1,139 +0,0 @@ -// Windows version - -#include "stdafx.h" - -#define USBRL_API __declspec(dllexport) -#include "../usb_relay_device.h" -#include "../usb_relay_hw.h" - -#include - -#ifdef _MSC_VER -#pragma comment(lib, "setupapi") -#pragma comment(lib, "hid") -#endif /*_MSC_VER*/ - -#undef ERROR -#define ERROR (-1) -#define OK (0) - -#define dbgprintf(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) -//#define dbgprintf(fmt, ...) printf(fmt, __VA_ARGS__) -//#define dbgprintf(fmt, ...) __noop(fmt, __VA_ARGS__) - -#ifdef __cplusplus -extern "C" { -#endif - -// Globals - - -// Public functions: - -/** Initialize the USB Relay Library -@returns: This function returns 0 on success and -1 on error. -*/ -int USBRL_API usb_relay_init(void) -{ - dbgprintf("Init lib\n"); - return ERROR; -} - -/** Finalize the USB Relay Library. -This function frees all of the static data associated with USB Relay Library. -It should be called at the end of execution to avoid memory leaks. -@returns: This function returns 0 on success and -1 on error. -*/ -int USBRL_API usb_relay_exit(void) -{ - return OK; -} - -/** Enumerate the USB Relay Devices.*/ -struct usb_relay_device_info USBRL_API * usb_relay_device_enumerate(void) -{ - return NULL; -} - - -/** Free an enumeration Linked List*/ -void USBRL_API usb_relay_device_free_enumerate(struct usb_relay_device_info *di) -{ - return; -} - -/** Open device by serial number -@return: This function returns a valid handle to the device on success or NULL on failure. -Example: usb_relay_device_open_with_serial_number("abcde", 5) */ -intptr_t USBRL_API usb_relay_device_open_with_serial_number(const char *serial_number, unsigned len) -{ - return ERROR; -} - -/* Open a USB relay device -@return: This function returns a valid handle to the device on success or NULL on failure. -*/ -intptr_t USBRL_API usb_relay_device_open(struct usb_relay_device_info *device_info) -{ - return ERROR; -} - -/* Close a USB relay device*/ -void USBRL_API usb_relay_device_close(intptr_t hHandle) -{ - return; -} - -/** Turn ON a relay channel on the USB-Relay-Device -@param index -- which channel your want to open -@param hHandle -- which usb relay device your want to operate -@returns: 0 -- success; 1 -- error; 2 -- index is outnumber the number of the usb relay device -*/ -int USBRL_API usb_relay_device_open_one_relay_channel(intptr_t hHandle, int index) -{ - return ERROR; -} - -/** Turn ON all relay channels on the USB-Relay-Device -@param hHandle -- which usb relay device your want to operate -@returns: 0 -- success; 1 -- error -*/ -int USBRL_API usb_relay_device_open_all_relay_channel(intptr_t hHandle) -{ - return ERROR; -} - -/** Turn OFF a relay channel on the USB-Relay-Device -@param index -- which channel your want to close -@paramhHandle -- which usb relay device your want to operate -@returns: 0 -- success; 1 -- error; 2 -- index is outnumber the number of the usb relay device -*/ -int USBRL_API usb_relay_device_close_one_relay_channel(intptr_t hHandle, int index) -{ - return ERROR; -} - -/** Turn OFF all relay channels on the USB-Relay-Device -@paramter: hHandle -- which usb relay device your want to operate -@returns: 0 -- success; 1 -- error -*/ -int USBRL_API usb_relay_device_close_all_relay_channel(intptr_t hHandle) -{ - return ERROR; -} - -/* -Status bits: one bit indicate a relay status. -bit 0/1/2/3/4/5/6/7/8 indicate channel 1/2/3/4/5/6/7/8 status - 1 -- means ON, 0 -- means OFF. -@returns: 0 -- success; 1 -- error -*/ -int USBRL_API usb_relay_device_get_status(intptr_t hHandle, unsigned int *status) -{ - return ERROR; -} - -#ifdef __cplusplus -} -#endif - diff --git a/lib/usb_relay_device.h b/lib/usb_relay_device.h index ab6d398..7250fcc 100644 --- a/lib/usb_relay_device.h +++ b/lib/usb_relay_device.h @@ -1,21 +1,23 @@ #ifndef USB_RELAY_DEVICE_H__ #define USB_RELAY_DEVICE_H__ +#define USBRELAY_LIB_VER 0x02 + #ifdef WIN32 -#ifndef USBRL_API -# define USBRL_API __declspec(dllimport) +#ifndef USBRL_CALL +# define USBRL_CALL _cdecl #endif -#ifndef CDECL -# define CDECL _cdecl +#ifndef USBRL_API +# define USBRL_API __declspec(dllimport) USBRL_CALL #endif # #else /* !WIN32 */ # -#ifndef USBRL_API -# define USBRL_API +#ifndef USBRL_CALL +# define USBRL_CALL #endif -#ifndef CDECL -# define CDECL +#ifndef USBRL_API +# define USBRL_API USBRL_CALL #endif # #endif /* WIN32 */ @@ -34,12 +36,14 @@ enum usb_relay_device_type /** USB relay board info structure*/ struct usb_relay_device_info { - unsigned char *serial_number; + char *serial_number; char *device_path; - enum usb_relay_device_type type; + intptr_t /*enum usb_relay_device_type*/ type; struct usb_relay_device_info* next; }; +typedef struct usb_relay_device_info *pusb_relay_device_info_t; + #ifdef __cplusplus extern "C" { #endif @@ -47,72 +51,60 @@ extern "C" { /** Initialize the USB Relay Library @returns: This function returns 0 on success and -1 on error. */ -USBRL_API -int CDECL usb_relay_init(void); +int USBRL_API usb_relay_init(void); /** Finalize the USB Relay Library. This function frees all of the static data associated with USB Relay Library. It should be called at the end of execution to avoid memory leaks. @returns:This function returns 0 on success and -1 on error. */ -USBRL_API -int CDECL usb_relay_exit(void); - +int USBRL_API usb_relay_exit(void); /** Enumerate the USB Relay Devices.*/ -USBRL_API -struct usb_relay_device_info * CDECL usb_relay_device_enumerate(void); +pusb_relay_device_info_t USBRL_API usb_relay_device_enumerate(void); /** Free an enumeration Linked List*/ -USBRL_API -void CDECL usb_relay_device_free_enumerate(struct usb_relay_device_info*); +void USBRL_API usb_relay_device_free_enumerate(struct usb_relay_device_info*); /** Open device that serial number is serial_number @return: This function returns a valid handle to the device on success or NULL on failure. e.g: usb_relay_device_open_with_serial_number("abcde", 5") */ -USBRL_API -intptr_t CDECL usb_relay_device_open_with_serial_number(const char *serial_number, unsigned len); +intptr_t USBRL_API usb_relay_device_open_with_serial_number(const char *serial_number, unsigned len); /* Open a USB relay device @return: This function returns a valid handle to the device on success or NULL on failure. */ -USBRL_API -intptr_t CDECL usb_relay_device_open(struct usb_relay_device_info *device_info); +intptr_t USBRL_API usb_relay_device_open(struct usb_relay_device_info *device_info); /* Close a USB relay device*/ -USBRL_API -void CDECL usb_relay_device_close(intptr_t hHandle); +void USBRL_API usb_relay_device_close(intptr_t hHandle); /** Turn ON a relay channel on the USB-Relay-Device @param hHandle -- which usb relay device your want to operate @param index -- the channel number: 1...max @returns: 0 -- success; 1 -- error; 2 -- index is invalid */ -USBRL_API -int CDECL usb_relay_device_open_one_relay_channel(intptr_t hHandle, int index); +int USBRL_API usb_relay_device_open_one_relay_channel(intptr_t hHandle, int index); /** Turn ON all relay channels on the USB-Relay-Device @param hHandle -- which usb relay device your want to operate @returns: 0 -- success; 1 -- error */ -USBRL_API -int CDECL usb_relay_device_open_all_relay_channel(intptr_t hHandle); +int USBRL_API usb_relay_device_open_all_relay_channel(intptr_t hHandle); /** Turn OFF a relay channel on the USB-Relay-Device @param index -- which channel your want to close @param hHandle -- which usb relay device your want to operate @returns: 0 -- success; 1 -- error */ -USBRL_API -int CDECL usb_relay_device_close_one_relay_channel(intptr_t hHandle, int index); +int USBRL_API usb_relay_device_close_one_relay_channel(intptr_t hHandle, int index); /** Turn OFF all relay channels on the USB-Relay-Device @param hHandle -- which usb relay device your want to operate @returns: 0 -- success; 1 -- error; 2 -- index is invalid */ -USBRL_API -int CDECL usb_relay_device_close_all_relay_channel(intptr_t hHandle); +int USBRL_API usb_relay_device_close_all_relay_channel(intptr_t hHandle); /* Status bits: one bit indicate a relay status. @@ -120,8 +112,7 @@ bit 0/1/2/3/4/5/6/7/8 indicate channel 1/2/3/4/5/6/7/8 status Bit value 1 means ON, 0 means OFF. @returns: 0 -- success; 1 -- error */ -USBRL_API -int CDECL usb_relay_device_get_status(intptr_t hHandle, unsigned int *status); +int USBRL_API usb_relay_device_get_status(intptr_t hHandle, unsigned int *status); #ifdef __cplusplus diff --git a/lib/usb_relay_hw.h b/lib/usb_relay_hw.h index 56adf17..4e3b845 100644 --- a/lib/usb_relay_hw.h +++ b/lib/usb_relay_hw.h @@ -3,7 +3,9 @@ #define USB_CFG_VENDOR_ID 0x16c0 /* 5824 = voti.nl */ #define USB_CFG_DEVICE_ID 0x05DF /* obdev's shared PID for HIDs */ -#define USB_CFG_VENDOR_NAME "www.dcttech.com" -#define USB_CFG_DEVICE_NAME2 "USBRelay2" /* can be relay1... relay8?*/ +#define USB_RELAY_VENDOR_NAME "www.dcttech.com" +#define USB_RELAY_NAME_PREF "USBRelay" /* can be relay1... relay8 */ + +#define USB_RELAY_ID_STR_LEN 5 /* length of "unique serial number" in the devices */ #endif /*USB_RELAY_DEVICE_HW__*/ diff --git a/lib/usb_relay_lib.c b/lib/usb_relay_lib.c new file mode 100644 index 0000000..abfd9f3 --- /dev/null +++ b/lib/usb_relay_lib.c @@ -0,0 +1,558 @@ +/** +* USB HID relays API library +* http://git.io/bGcxrQ +* +* 12-jan-2015 pa01 Win32 version +*/ + +#define MY_VERSION 0x02 + +#if defined (WIN32) || defined (_WIN32) + +// Windows 32 or 64 bit +#include "targetver.h" +#define WIN32_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#include + +#define USBRL_API __declspec(dllexport) +#define USBRL_CALL _cdecl +#define snprintf _snprintf + +#endif //WIN32 + +#include "usb_relay_device.h" + +#if USBRELAY_LIB_VER != MY_VERSION +#error "Oops. Wrong version of usb_relay_device.h" +#endif + +#include "usb_relay_hw.h" +#include "hiddata.h" +#include +#include +#include + +//#define dbgprintf(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) +//#define dbgprintf(fmt, ...) printf(fmt, __VA_ARGS__) +#define dbgprintf(fmt, ...) __noop(fmt, __VA_ARGS__) +//#define printerr(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) +//#define printerr(fmt, ...) printf(fmt, __VA_ARGS__) +#define printerr(fmt, ...) __noop(fmt, __VA_ARGS__) + +#ifdef __cplusplus +extern "C" { +#endif + +struct usbrelay_internal_s { + struct usb_relay_device_info urdi; //public part + // Private part: + USBDEVHANDLE usbh; // handle + char idstr[8]; +}; + +// struct for enum context +struct enumctx_s { + struct usbrelay_internal_s *head, *tail; + int numdevs; + int status; +}; + +// Globals + +const char *g_dummyPath = "NOTHING"; // passing dev.path to client not implemented, I return this as path. + +static const char *usbErrorMessage(int errCode) +{ + static char buffer[80]; + buffer[0] = 0; + if ( errCode != USBHID_ERR_UNKNOWN ) { + usbhidStrerror_r(errCode, buffer, sizeof(buffer)); + } + if ( 0 == buffer[0] ) { + snprintf(buffer, sizeof(buffer), "Unknown error (%d)", errCode); + } + return buffer; +} + +// Read state of all relays +// @return bit mask of all relays (R1->bit 0, R2->bit 1 ...) or -1 on error +static int rel_read_status_raw(USBDEVHANDLE dev, void *raw_data) +{ + char buffer[10]; + int err; + int reportnum = 0; + int len = 8 + 1; /* report id 1 byte + 8 bytes data */ + memset(buffer, 0, sizeof(buffer)); + + err = usbhidGetReport(dev, reportnum, buffer, &len); + if ( err ) { + printerr("error reading status: %s\n", usbErrorMessage(err)); + return -1; + } + + if ( len != 9 || buffer[0] != reportnum ) { + printerr("ERROR: wrong HID report returned! %d\n", len); + return -2; + } + + if (raw_data) { + /* copy raw report data */ + memcpy( raw_data, buffer, len ); + } + + return (unsigned char)buffer[8]; /* byte of relay states */ +} + +// Turn relay on/off. +// @param relaynum: positive (1-N): one relay index, negative: all, -num = number of relays +// @returns 0 ok, else error +static int rel_onoff( USBDEVHANDLE dev, int is_on, int relaynum ) +{ + unsigned char buffer[10]; + int err = -1; + unsigned char cmd1, cmd2, mask, maskval; + + if ( relaynum < 0 && (-relaynum) <= 8 ) { + mask = 0xFF; + cmd2 = 0; + if (is_on) { + cmd1 = 0xFE; + maskval = (unsigned char)( (1U << (-relaynum)) - 1 ); + } else { + cmd1 = 0xFC; + maskval = 0; + } + } else { + if ( relaynum <= 0 || relaynum > 8 ) { + printerr("Relay number must be 1-8\n"); + return 1; + } + mask = (unsigned char)(1U << relaynum); + cmd2 = (unsigned char)relaynum; + if (is_on) { + cmd1 = 0xFF; + maskval = mask; + } else { + cmd1 = 0xFD; + maskval = 0; + } + } + + memset(buffer, 0, sizeof(buffer)); + buffer[0] = 0; /* report # */ + buffer[1] = cmd1; + buffer[2] = cmd2; + if((err = usbhidSetReport(dev, (void*)buffer, 9)) != 0) { + printerr("Error writing data: %s\n", usbErrorMessage(err)); + return 1; + } + + // Read back & verify + err = rel_read_status_raw(dev, NULL); + if ( err < 0 ) { + printerr("Error read back: %s\n", usbErrorMessage(err)); + return 1; + } + + err = err & mask; + if (err != maskval) { + printerr("Error: failed to set relay %u %s\n", relaynum, is_on ? "ON":"OFF"); + return 1; + } + + return 0; +} + + +// Public functions: + +/** Initialize the USB Relay Library +@returns: This function returns 0 on success and -1 on error. +*/ +int USBRL_API usb_relay_init(void) +{ + return 0; +} + +/** Finalize the USB Relay Library. +This function frees all of the static data associated with USB Relay Library. +It should be called at the end of execution to avoid memory leaks. +@returns: This function returns 0 on success and -1 on error. +*/ +int USBRL_API usb_relay_exit(void) +{ + return 0; +} + +// Enum function for building list of devices +static +int enumfunc(USBDEVHANDLE usbh, void *context) +{ +// static const char vendorName[] = USB_RELAY_VENDOR_NAME; + static const char productName[] = USB_RELAY_NAME_PREF; + int err; + char buffer[128*sizeof(short)]; // max USB string is 128 UTF-16 chars + int num = 0; + int i; + struct usbrelay_internal_s *q; + struct enumctx_s *ectx = (struct enumctx_s *)context; + + //NOTE: Ignore vendor string. This is against ObjDev rules, restore the check if needed! + + err = usbhidGetProductString(usbh, buffer, sizeof(buffer)); + if (err) + { + goto next; + } + + i = (int)strlen(buffer); + if ( i != strlen(productName) + 1 ) + { + goto next; + } + + /* the last char of ProductString is number of relays */ + num = (int)(buffer[i - 1]) - (int)'0'; + buffer[i - 1] = 0; + + if ( 0 != strcmp( buffer, productName) ) + { + goto next; + } + + if ( num <= 0 || num > 8 ) + { + dbgprintf("Unknown relay device? num relays=%d\n", num); + goto next; + } + + /* Check the unique ID: USB_RELAY_ID_STR_LEN bytes at offset 1 (just after the report id) */ + err = rel_read_status_raw(usbh, buffer); + if( err < 0 ) + { + dbgprintf("Error reading report 0: %s\n", usbErrorMessage(err)); + goto next; + } + + for (i = 1; i <= USB_RELAY_ID_STR_LEN; i++) + { + unsigned char x = (unsigned char)buffer[i]; + if (x <= 0x20 || x >= 0x7F) + { + dbgprintf("Bad usbrelay ID string!\n"); + goto next; + } + } + + if( buffer[USB_RELAY_ID_STR_LEN + 1] != 0 ) + { + dbgprintf("Bad usbrelay ID string!\n"); + goto next; + } + + dbgprintf("Device %s%d found: ID=[%5s]\n", productName, num, &buffer[1]); + + // allocate & save info + q = (struct usbrelay_internal_s *)calloc(1, sizeof(struct usbrelay_internal_s)); + if (!q) { + dbgprintf("Malloc err\n"); + goto next; //$$$ revise + } + /* keep this device, continue */ + q->usbh = usbh; + memcpy(q->idstr, &buffer[1], USB_RELAY_ID_STR_LEN); + q->urdi.type = num; // enum = number of relays + q->urdi.serial_number = &q->idstr[0]; + q->urdi.device_path = (char*)g_dummyPath; + + if (!ectx->head) { + ectx->head = q; + ectx->tail =q; + } else { + ectx->tail->urdi.next = (pusb_relay_device_info_t)q; + } + + ++ectx->numdevs; + return 1; + + next: + /* Continue search */ + usbhidCloseDevice(usbh); + return 1; +} + +// Enum function for open one device by ID +static +int enumOpenfunc(USBDEVHANDLE usbh, void *context) +{ +// static const char vendorName[] = USB_RELAY_VENDOR_NAME; + static const char productName[] = USB_RELAY_NAME_PREF; + int err; + char buffer[128*sizeof(short)]; // max USB string is 128 UTF-16 chars + int num = 0; + int i; + struct enumctx_s *ectx = (struct enumctx_s *)context; + struct usbrelay_internal_s *q = ectx->head; + + //NOTE: Ignore vendor string. This is against ObjDev rules, restore the check if needed! + + err = usbhidGetProductString(usbh, buffer, sizeof(buffer)); + if (err) + { + goto next; + } + + i = (int)strlen(buffer); + if ( i != strlen(productName) + 1 ) + { + goto next; + } + + /* the last char of ProductString is number of relays */ + num = (int)(buffer[i - 1]) - (int)'0'; + buffer[i - 1] = 0; + + if ( 0 != strcmp( buffer, productName) ) + { + goto next; + } + + if ( num <= 0 || num > 8 ) + { + dbgprintf("Unknown relay device? num relays=%d\n", num); + goto next; + } + + /* Check the unique ID: USB_RELAY_ID_STR_LEN bytes at offset 1 (just after the report id) */ + err = rel_read_status_raw(usbh, buffer); + if( err < 0 ) + { + dbgprintf("Error reading report 0: %s\n", usbErrorMessage(err)); + goto next; + } + + for (i = 1; i <= USB_RELAY_ID_STR_LEN; i++) + { + unsigned char x = (unsigned char)buffer[i]; + if (x <= 0x20 || x >= 0x7F) + { + dbgprintf("Bad usbrelay ID string!\n"); + goto next; + } + } + + if( buffer[USB_RELAY_ID_STR_LEN + 1] != 0 ) + { + dbgprintf("Bad usbrelay ID string!\n"); + goto next; + } + + dbgprintf("Device %s%d found: ID=[%5s]\n", productName, num, &buffer[1]); + + if ( 0 == memcmp( q->idstr, &buffer[1], USB_RELAY_ID_STR_LEN) ) { + q->usbh = usbh; + q->urdi.type = num; // enum = number of relays + q->urdi.serial_number = &q->idstr[0]; + q->urdi.device_path = (char*)g_dummyPath; + ++ectx->numdevs; + return 0; + } + + next: + /* Continue search */ + usbhidCloseDevice(usbh); + return 1; +} + +/** Enumerate the USB Relay Devices.*/ +pusb_relay_device_info_t USBRL_API usb_relay_device_enumerate(void) +{ + struct enumctx_s ectx; + int ret; + memset(&ectx, 0, sizeof(ectx)); + ret = usbhidEnumDevices(USB_CFG_VENDOR_ID, USB_CFG_DEVICE_ID, + (void*)&ectx, + enumfunc); + + return (pusb_relay_device_info_t)ectx.head; +} + + +/** Free an enumeration Linked List*/ +void USBRL_API usb_relay_device_free_enumerate(struct usb_relay_device_info *dilist) +{ + struct usbrelay_internal_s *p = (struct usbrelay_internal_s *)dilist; + + while (p) { + struct usbrelay_internal_s *q = (struct usbrelay_internal_s *)((pusb_relay_device_info_t)p)->next; + if (p->usbh && ((USBDEVHANDLE)(-1)) != p->usbh) { + usbhidCloseDevice(p->usbh); + p->usbh = 0; + } + free(p); + p = q; + } + + return; +} + +/** Open device by serial number +serial_number == NULL is valid and means any one device. +@return: This function returns a valid handle to the device on success or NULL on failure. +Example: usb_relay_device_open_with_serial_number("abcde", 5) */ +intptr_t USBRL_API usb_relay_device_open_with_serial_number(const char *serial_number, unsigned len) +{ + struct enumctx_s ectx; + int ret; + struct usbrelay_internal_s *q; + memset(&ectx, 0, sizeof(ectx)); + + if (serial_number && len != USB_RELAY_ID_STR_LEN) { + printerr("Specified invalid str id length: %u", len); + return (intptr_t)0; + } + + q = ectx.head = calloc(1, sizeof(*ectx.head)); + if (!q) + return (intptr_t)0; + + memcpy(q->idstr, serial_number, len); + + ret = usbhidEnumDevices(USB_CFG_VENDOR_ID, USB_CFG_DEVICE_ID, + (void*)&ectx, + enumfunc); + if (ret != 0) + goto ret_err; // error during enum + + if (ectx.numdevs == 0 || q->usbh == 0) { + goto ret_err; // not found + } + + q->urdi.next = (void*)q; // mark this element as standalone + return (intptr_t)q; + + ret_err: + free(q); + return (intptr_t)0; +} + +/** Open a USB relay device +@return: This function returns a valid handle to the device on success or NULL on failure. +*/ +intptr_t USBRL_API usb_relay_device_open(struct usb_relay_device_info *device_info) +{ + struct usbrelay_internal_s *p = (struct usbrelay_internal_s *)device_info; + if (!device_info) + return 0; + if ( (uintptr_t)p->usbh == 0 || (uintptr_t)p->usbh == (uintptr_t)-1 ) + return 0; + //$$$ validate more + return (uintptr_t)device_info; +} + +/** Close a USB relay device*/ +void USBRL_API usb_relay_device_close(intptr_t hHandle) +{ + struct usbrelay_internal_s *p = (struct usbrelay_internal_s *)hHandle; + if ( 0 == hHandle || ((intptr_t)-1) == hHandle ) + return; + + if ( (void*)(p->urdi.next) == (void*)p ) { + // This was made by usb_relay_device_open_with_serial_number() so free it now: + if ( p->usbh && ((intptr_t)-1) != (intptr_t)(p->usbh)) { + usbhidCloseDevice(p->usbh); + p->usbh = 0; + } + p->urdi.next = NULL; + free( (void*)p ); + } + // Else this can be in the list, don't do anything. +} + +/** Turn ON a relay channel on the USB-Relay-Device +@param index -- which channel your want to open +@param hHandle -- which usb relay device your want to operate +@returns: 0 -- success; 1 -- error; 2 -- index is outnumber the number of the usb relay device +*/ +int USBRL_API usb_relay_device_open_one_relay_channel(intptr_t hHandle, int index) +{ + struct usbrelay_internal_s *p = (struct usbrelay_internal_s *)hHandle; + if (!p) + return 1; + if ( index <= 0 || index > (int)p->urdi.type ) + return 2; + return rel_onoff( p->usbh, 1, index); +} + +/** Turn ON all relay channels on the USB-Relay-Device +@param hHandle -- which usb relay device your want to operate +@returns: 0 -- success; 1 -- error +*/ +int USBRL_API usb_relay_device_open_all_relay_channel(intptr_t hHandle) +{ + struct usbrelay_internal_s *p = (struct usbrelay_internal_s *)hHandle; + if (!p) + return 1; + return rel_onoff( p->usbh, 1, -(int)p->urdi.type ); +} + +/** Turn OFF a relay channel on the USB-Relay-Device +@param index -- which channel your want to close +@param hHandle -- which usb relay device your want to operate +@returns: 0 -- success; 1 -- error; 2 -- index is outnumber the number of the usb relay device +*/ +int USBRL_API usb_relay_device_close_one_relay_channel(intptr_t hHandle, int index) +{ + struct usbrelay_internal_s *p = (struct usbrelay_internal_s *)hHandle; + if (!p) + return 1; + if ( index <= 0 || index > (int)p->urdi.type ) + return 2; + return rel_onoff( p->usbh, 0, index); +} + +/** Turn OFF all relay channels on the USB-Relay-Device +@param hHandle -- which usb relay device your want to operate +@returns 0 -- success; 1 -- error +*/ +int USBRL_API usb_relay_device_close_all_relay_channel(intptr_t hHandle) +{ + struct usbrelay_internal_s *p = (struct usbrelay_internal_s *)hHandle; + if (!p) + return 1; + return rel_onoff( p->usbh, 0, -(int)p->urdi.type ); +} + +/** Get status of all relays on the device +Status bits: one bit indicate a relay status. +bit 0/1/2/3/4/5/6/7/8 indicate channel 1/2/3/4/5/6/7/8 status + 1 -- means ON, 0 -- means OFF. +@returns: 0 -- success; 1 -- error +*/ +int USBRL_API usb_relay_device_get_status(intptr_t hHandle, unsigned int *status) +{ + struct usbrelay_internal_s *p = (struct usbrelay_internal_s *)hHandle; + int err; + if (!p) + return 1; + err = rel_read_status_raw(p->usbh, NULL); + if ( err < 0 ) { + printerr("Error reading data: %s\n", usbErrorMessage(err)); + return 1; + } + + *status = (unsigned char)err; + return 0; +} + +/** Return lib version +*/ +int USBRL_API usb_relay_device_lib_version(void) +{ + return (int)(MY_VERSION); +} + +#ifdef __cplusplus +} +#endif + -- 2.25.1