f90b9c065e0361b522f7897b1a30db6195d5d7a8
1 // Chinese USB/HID relay command line tool:
4 // Currently finds the 1st matching device by ven,dev, product name string.
5 // Two channel devices only!
7 // - Enum all matching devices, select one by ID
8 // - Determine the relay model (1 or 2 or more) by product string?
9 // Build for Windows: using VC++ 2008 and WDK7.1
10 //~~~~~~~~~~~~~~~~~~~~~~~~
12 /* Prototype: V-USB example: vusb-20121206/examples/hid-data/commandline/hidtool.c
13 * Author: Christian Starkjohann
14 * Creation Date: 2008-04-11
15 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
18 #define A_VER_STR "r0.2 (2 ch. only)"
23 #include "hidusb-tool.h"
25 #define USB_CFG_VENDOR_NAME "www.dcttech.com"
26 #define USB_CFG_DEVICE_NAME "USBRelay2" // can be relay1... relay8?
29 static int g_max_relay_num
= 0;
31 static int rel_read_status(USBDEVHANDLE dev
, void *raw_data
);
33 /* ------------------------------------------------------------------------- */
35 static const char *usbErrorMessage(int errCode
)
37 static char buffer
[80];
40 case USBOPEN_ERR_ACCESS
: return "Access to device denied";
41 case USBOPEN_ERR_NOTFOUND
: return "The specified device was not found";
42 case USBOPEN_ERR_IO
: return "Communication error with device";
44 snprintf(buffer
, sizeof(buffer
), "Unknown USB error %d", errCode
);
47 return NULL
; /* not reached */
50 static USBDEVHANDLE
openDevice(void)
53 char vendorName
[] = USB_CFG_VENDOR_NAME
,
54 productName
[] = USB_CFG_DEVICE_NAME
;
55 int vid
= USB_CFG_VENDOR_ID
;
56 int pid
= USB_CFG_DEVICE_ID
;
59 // TODO: enumerate all instances, then filter by unique ID
60 if((err
= usbhidOpenDevice(&dev
, vid
, vendorName
, pid
, productName
, 0)) != 0){
61 fprintf(stderr
, "error finding %s: %s\n", productName
, usbErrorMessage(err
));
65 { /* Check the unique ID: 5 bytes at offs 0 */
67 err
= rel_read_status(dev
, buffer
);
69 fprintf(stderr
, "error reading report 0: %s\n", usbErrorMessage(err
));
70 usbhidCloseDevice(dev
);
74 //hexdump(buffer + 1, sizeof(buffer) - 1);
75 for (i
=1; i
<=5; i
++) {
76 unsigned char x
= (unsigned char)buffer
[i
];
77 if (x
<= 0x20 || x
>= 0x7F) {
78 fprintf(stderr
, "Bad device ID!\n");
79 usbhidCloseDevice(dev
);
83 if( buffer
[6] != 0 ) {
84 fprintf(stderr
, "Bad device ID!\n");
85 usbhidCloseDevice(dev
);
89 DEBUG_PRINT(("Device %s found: ID=[%5s]\n", USB_CFG_DEVICE_NAME
, &buffer
[1]));
90 g_max_relay_num
= 2; /* hardcoded for "USBRelay2" */
97 /* ------------------------------------------------------------------------- */
99 static void hexdump(char *buffer
, int len
)
104 for(i
= 0; i
< len
; i
++){
112 fprintf(fp
, "0x%02x", buffer
[i
] & 0xff);
119 /* ------------------------------------------------------------------------- */
121 static void usage(char *myName
)
123 char *p
= strrchr(myName
, '\\'); /* windows */
124 if (p
) myName
= p
+ 1;
125 p
= strrchr(myName
, '/'); /* whatever */
126 if (p
) myName
= p
+ 1;
128 fprintf(stderr
, "USBHID relay utility, " A_VER_STR
"\n");
129 fprintf(stderr
, "Usage:\n");
130 fprintf(stderr
, " %s on <num> - turn relay <num> ON\n", myName
);
131 fprintf(stderr
, " %s off <num> - turn relay <num> OFF\n", myName
);
132 fprintf(stderr
, " %s state - print state of the relays\n", myName
);
136 // Read state of all relays
137 // @return bit mask of all relays (R1->bit 0, R2->bit 1 ...) or -1 on error
138 static int rel_read_status(USBDEVHANDLE dev
, void *raw_data
)
143 int len
= 8 + 1; /* report id 1 byte + 8 bytes data */
144 memset(buffer
, 0, sizeof(buffer
));
146 err
= usbhidGetReport(dev
, reportnum
, buffer
, &len
);
148 fprintf(stderr
, "error reading status: %s\n", usbErrorMessage(err
));
152 if ( len
!= 9 || buffer
[0] != reportnum
) {
153 fprintf(stderr
, "ERROR: wrong HID report returned!\n", len
);
158 /* REVISE! copy raw report data */
159 memcpy( raw_data
, buffer
, sizeof(buffer
) );
162 return (int)(unsigned char)buffer
[8]; /* byte of relay states */
166 static int rel_onoff( USBDEVHANDLE dev
, int is_on
, char const *numstr
)
168 unsigned char buffer
[10];
170 int relaynum
= numstr
? atoi(numstr
) : 0;
172 if ( numstr
&& (0 == strcmp(numstr
,"*")) ) {
173 char x
[2] = {'1', 0};
175 for (i
= 1; i
<= g_max_relay_num
; i
++) {
176 x
[0] = (char)('0' + i
);
177 err
= rel_onoff(dev
, is_on
, x
);
183 if ( relaynum
<= 0 || relaynum
> g_max_relay_num
) {
184 fprintf(stderr
, "Invalid relay number. Must be 1-%d or * (all)\n", g_max_relay_num
);
188 memset(buffer
, 0, sizeof(buffer
));
189 buffer
[0] = 0; /* report # */
190 buffer
[1] = is_on
? 0xFF : 0xFD;
191 buffer
[2] = (unsigned char)relaynum
;
192 if((err
= usbhidSetReport(dev
, buffer
, 9)) != 0) {
193 fprintf(stderr
, "Error writing data: %s\n", usbErrorMessage(err
));
197 // Read back & verify
198 err
= rel_read_status(dev
, NULL
);
200 err
= (err
>> (unsigned)(relaynum
-1)) & 1;
205 fprintf(stderr
, "Error: failed set %s relay %u\n", is_on
? "ON":"OFF", relaynum
);
213 int main(int argc
, char **argv
)
217 char const *arg1
= (argc
>= 2) ? argv
[1] : NULL
;
218 char const *arg2
= (argc
>= 3) ? argv
[2] : NULL
;
229 // if ( strcasecmp(arg1, "state") == 0 ){
230 if ( strncasecmp(arg1
, "stat", 4) == 0 ){
232 err
= rel_read_status(dev
, buffer
);
234 fprintf(stderr
, "error reading data: %s\n", usbErrorMessage(err
));
237 //hexdump(buffer + 1, len - 1);
238 printf("State: R1=%d R2=%d Board ID=[%5.5s]\n", !!(err
& 0x1), !!(err
& 0x2), &buffer
[1] );
240 }else if( strcasecmp(arg1
, "on" ) == 0){
241 err
= rel_onoff(dev
, 1, arg2
);
242 }else if( strcasecmp(arg1
, "off" ) == 0){
243 err
= rel_onoff(dev
, 0, arg2
);
250 usbhidCloseDevice(dev
);
256 /* ------------------------------------------------------------------------- */