// Chinese USB/HID relay command line tool:
//
-// pa01 15-Apr-2014
+// pa02 19-Nov-2014 supports 1,2,4 - relay devices
// Currently finds the 1st matching device by ven,dev, product name string.
-// Two channel devices only!
// TODO:
-// - Enum all matching devices, select one by ID
-// - Determine the relay model (1 or 2 or more) by product string?
+// - Support multiple devices, select one by ID!
// Build for Windows: using VC++ 2008 and WDK7.1
//~~~~~~~~~~~~~~~~~~~~~~~~
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
*/
-#define A_VER_STR "r0.2 (2 ch. only)"
+#define A_VER_STR "r1.1x (1 device only)"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "hidusb-tool.h"
-#define USB_CFG_VENDOR_NAME "www.dcttech.com"
-#define USB_CFG_DEVICE_NAME "USBRelay2" // can be relay1... relay8?
+#define USB_RELAY_VENDOR_NAME "www.dcttech.com"
+#define USB_RELAY1_NAME "USBRelay1" // 1 relay
+#define USB_RELAY2_NAME "USBRelay2" // 2 relays
+#define USB_RELAY4_NAME "USBRelay4" // 4 relays
static int g_max_relay_num = 0;
-static int rel_read_status(USBDEVHANDLE dev, void *raw_data);
+static int rel_read_status_raw(USBDEVHANDLE dev, void *raw_data);
/* ------------------------------------------------------------------------- */
{
static char buffer[80];
- switch(errCode){
+ switch (errCode) {
case USBOPEN_ERR_ACCESS: return "Access to device denied";
case USBOPEN_ERR_NOTFOUND: return "The specified device was not found";
case USBOPEN_ERR_IO: return "Communication error with device";
- default:
- snprintf(buffer, sizeof(buffer), "Unknown USB error %d", errCode);
- return buffer;
}
- return NULL; /* not reached */
+
+ snprintf(buffer, sizeof(buffer), "Unknown USB error %d", errCode);
+ return buffer;
}
static USBDEVHANDLE openDevice(void)
{
USBDEVHANDLE dev = 0;
- char vendorName[] = USB_CFG_VENDOR_NAME,
- productName[] = USB_CFG_DEVICE_NAME;
+ char vendorName[] = USB_RELAY_VENDOR_NAME,
+ productName[] = USB_RELAY1_NAME;
int vid = USB_CFG_VENDOR_ID;
int pid = USB_CFG_DEVICE_ID;
int err;
+ int num = 0;
// TODO: enumerate all instances, then filter by unique ID
- if((err = usbhidOpenDevice(&dev, vid, vendorName, pid, productName, 0)) != 0){
- fprintf(stderr, "error finding %s: %s\n", productName, usbErrorMessage(err));
- return NULL;
+ //$$$ find any one device
+ strcpy(productName, USB_RELAY2_NAME);
+ if((err = usbhidOpenDevice(&dev, vid, vendorName, pid, productName, 0)) == 0) {
+ num = 2;
+ goto check1;
+ }
+
+ strcpy(productName, USB_RELAY1_NAME);
+ if((err = usbhidOpenDevice(&dev, vid, vendorName, pid, productName, 0)) == 0) {
+ num = 1;
+ goto check1;
+ }
+
+ strcpy(productName, USB_RELAY4_NAME);
+ if((err = usbhidOpenDevice(&dev, vid, vendorName, pid, productName, 0)) == 0) {
+ num = 4;
+ goto check1;
}
+ fprintf(stderr, "error finding USB relay: %s\n", usbErrorMessage(err));
+ return NULL;
+
+ check1:
{ /* Check the unique ID: 5 bytes at offs 0 */
char buffer[16];
- err = rel_read_status(dev, buffer);
+ err = rel_read_status_raw(dev, buffer);
if( err < 0 ){
fprintf(stderr, "error reading report 0: %s\n", usbErrorMessage(err));
usbhidCloseDevice(dev);
}
DEBUG_PRINT(("Device %s found: ID=[%5s]\n", USB_CFG_DEVICE_NAME, &buffer[1]));
- g_max_relay_num = 2; /* hardcoded for "USBRelay2" */
+ g_max_relay_num = num;
}
}
{
char *p = strrchr(myName, '\\'); /* windows */
if (p) myName = p + 1;
- p = strrchr(myName, '/'); /* whatever */
+ else p = strrchr(myName, '/'); /* whatever */
if (p) myName = p + 1;
fprintf(stderr, "USBHID relay utility, " A_VER_STR "\n");
// 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(USBDEVHANDLE dev, void *raw_data)
+static int rel_read_status_raw(USBDEVHANDLE dev, void *raw_data)
{
char buffer[10];
int err;
}
if (raw_data) {
- /* REVISE! copy raw report data */
+ /* copy raw report data */
memcpy( raw_data, buffer, sizeof(buffer) );
}
}
// Read back & verify
- err = rel_read_status(dev, NULL);
+ err = rel_read_status_raw(dev, NULL);
if ( err >= 0 ) {
err = (err >> (unsigned)(relaynum -1)) & 1;
err ^= !!is_on;
}
+static int show_status(USBDEVHANDLE dev)
+{
+ int err;
+ char buffer[10];
+ static const char* on_off[] = {"OFF","ON"};
+
+#define onoff(n) on_off[!!(err & (1U << n))]
+
+ err = rel_read_status_raw(dev, buffer);
+ if ( err < 0 ){
+ fprintf(stderr, "error reading data: %s\n", usbErrorMessage(err));
+ err = 1;
+ } else {
+ //hexdump(buffer + 1, len - 1);
+ switch (g_max_relay_num) {
+ case 1:
+ printf("Board ID=[%5.5s] State: R1=%s\n", &buffer[1], onoff(0) );
+ break;
+ case 2:
+ printf("Board ID=[%5.5s] State: R1=%s R2=%s\n",
+ &buffer[1], onoff(0), onoff(1) );
+ break;
+ case 4:
+ printf("Board ID=[%5.5s] State: R1=%s R3=%s R1=%s R4=%s\n",
+ &buffer[1], onoff(0), onoff(1), onoff(2), onoff(3) );
+ break;
+ default:
+ printf("Board ID=[%5.5s] State: %2.2X (hex)\n", &buffer[1], (unsigned char)err );
+ break;
+ }
+ err = 0;
+ }
+ return err;
+#undef onoff
+}
+
int main(int argc, char **argv)
{
- USBDEVHANDLE dev;
+ USBDEVHANDLE dev = 0;
int err;
char const *arg1 = (argc >= 2) ? argv[1] : NULL;
char const *arg2 = (argc >= 3) ? argv[2] : NULL;
if ( !dev )
exit(1);
-// if ( strcasecmp(arg1, "state") == 0 ){
- if ( strncasecmp(arg1, "stat", 4) == 0 ){
- char buffer[10];
- err = rel_read_status(dev, buffer);
- if ( err < 0 ){
- fprintf(stderr, "error reading data: %s\n", usbErrorMessage(err));
- err = 1;
- } else {
- //hexdump(buffer + 1, len - 1);
- printf("State: R1=%d R2=%d Board ID=[%5.5s]\n", !!(err & 0x1), !!(err & 0x2), &buffer[1] );
- }
- }else if( strcasecmp(arg1, "on" ) == 0){
+ if ( strncasecmp(arg1, "stat", 4) == 0 ) { // stat|state|status
+ err = show_status(dev);
+ // TODO enumerate all devices
+ }else if( strcasecmp(arg1, "on" ) == 0) {
err = rel_onoff(dev, 1, arg2);
- }else if( strcasecmp(arg1, "off" ) == 0){
+ }else if( strcasecmp(arg1, "off" ) == 0) {
err = rel_onoff(dev, 0, arg2);
}else {
usage(argv[0]);