From 10e62c50ad6af74b7460bd2f6eeec0c0babc4811 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Mon, 17 Sep 2018 16:51:14 -0700 Subject: [PATCH] Add hid stub for windows. --- Makefile-mingw | 2 +- hid-macos.c | 26 +++-- hid-windows.c | 268 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 289 insertions(+), 7 deletions(-) create mode 100644 hid-windows.c diff --git a/Makefile-mingw b/Makefile-mingw index 1cd724b..5e1baa3 100644 --- a/Makefile-mingw +++ b/Makefile-mingw @@ -5,7 +5,7 @@ GITCOUNT = $(shell git rev-list HEAD --count) CFLAGS = -g -O -Wall -Werror -DVERSION='"$(VERSION).$(GITCOUNT)"' LDFLAGS = -g -s -OBJS = main.o util.o radio.o dfu-windows.o uv380.o md380.o +OBJS = main.o util.o radio.o dfu-windows.o uv380.o md380.o rd5r.o hid-windows.o LIBS = -lsetupapi # Compiling Windows binary from Linux diff --git a/hid-macos.c b/hid-macos.c index 4cc8af0..30e2e65 100644 --- a/hid-macos.c +++ b/hid-macos.c @@ -87,9 +87,15 @@ void hid_send_recv(const unsigned char *data, unsigned nbytes, unsigned char *rd } // Run main application loop until reply received. - while (nbytes_received == 0) { - //TODO: timeout + for (k=0; ; k++) { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 0); + if (nbytes_received > 0) + break; + if (k >= 5) { + fprintf(stderr, "HID device stopped responding!\n"); + exit(-1); + } + usleep(10000); } if (nbytes_received != sizeof(receive_buf)) { @@ -201,16 +207,24 @@ const char *hid_init(int vid, int pid) IOReturn IOReturn = IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone); if (IOReturn != kIOReturnSuccess) { if (trace_flag) { - fprintf(stderr, "Cannot find USB device %04x:%04x\n", - vid, pid); + fprintf(stderr, "Cannot find USB device %04x:%04x\n", vid, pid); } return 0; } // Run main application loop until device found. - while (!dev) { - //TODO: timeout + int k; + for (k=0; ; k++) { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 0); + if (dev) + break; + if (k >= 3) { + if (trace_flag) { + fprintf(stderr, "Cannot find USB device %04x:%04x\n", vid, pid); + } + return 0; + } + usleep(10000); } static unsigned char reply[38]; diff --git a/hid-windows.c b/hid-windows.c new file mode 100644 index 0000000..d0f0d9c --- /dev/null +++ b/hid-windows.c @@ -0,0 +1,268 @@ +/* + * HID routines for Windows. + * + * Copyright (C) 2018 Serge Vakulenko, KK6ABQ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include "util.h" + +static const unsigned char CMD_PRG[] = "\2PROGRA"; +static const unsigned char CMD_PRG2[] = "M\2"; +static const unsigned char CMD_ACK[] = "A"; +static const unsigned char CMD_READ[] = "Raan"; +static const unsigned char CMD_WRITE[] = "Waan..."; +static const unsigned char CMD_ENDR[] = "ENDR"; +static const unsigned char CMD_ENDW[] = "ENDW"; +static const unsigned char CMD_CWB0[] = "CWB\4\0\0\0\0"; +static const unsigned char CMD_CWB1[] = "CWB\4\0\1\0\0"; + +static unsigned char receive_buf[42]; // receive buffer +static volatile int nbytes_received = 0; // receive result +static unsigned offset = 0; // CWD offset + +// +// Send a request to the device. +// Store the reply into the rdata[] array. +// Terminate in case of errors. +// +void hid_send_recv(const unsigned char *data, unsigned nbytes, unsigned char *rdata, unsigned rlength) +{ + unsigned char buf[42]; + unsigned k; + + memset(buf, 0, sizeof(buf)); + buf[0] = 1; + buf[1] = 0; + buf[2] = nbytes; + buf[3] = nbytes >> 8; + if (nbytes > 0) + memcpy(buf+4, data, nbytes); + nbytes += 4; + + if (trace_flag > 0) { + fprintf(stderr, "---Send"); + for (k=0; k 0) + break; + if (k >= 5) { + fprintf(stderr, "HID device stopped responding!\n"); + exit(-1); + } + usleep(10000); + } +#endif + if (nbytes_received != sizeof(receive_buf)) { + fprintf(stderr, "Short read: %d bytes instead of %d!\n", + nbytes_received, (int)sizeof(receive_buf)); + exit(-1); + } + if (trace_flag > 0) { + fprintf(stderr, "---Recv"); + for (k=0; k= 0x10000 && offset == 0) { + offset = 0x00010000; + hid_send_recv(CMD_CWB1, 8, &ack, 1); + if (ack != CMD_ACK[0]) { + fprintf(stderr, "%s: Wrong acknowledge %#x, expected %#x\n", + __func__, ack, CMD_ACK[0]); + exit(-1); + } + } + + for (n=0; n> 8; + cmd[2] = addr + n; + cmd[3] = 32; + hid_send_recv(cmd, 4, reply, sizeof(reply)); + memcpy(data + n, reply + 4, 32); + } +} + +void hid_write_block(int bno, uint8_t *data, int nbytes) +{ + unsigned addr = bno * nbytes; + unsigned char ack, cmd[4+32]; + int n; + + if (addr < 0x10000 && offset != 0) { + offset = 0; + hid_send_recv(CMD_CWB0, 8, &ack, 1); + if (ack != CMD_ACK[0]) { + fprintf(stderr, "%s: Wrong acknowledge %#x, expected %#x\n", + __func__, ack, CMD_ACK[0]); + exit(-1); + } + } else if (addr >= 0x10000 && offset == 0) { + offset = 0x00010000; + hid_send_recv(CMD_CWB1, 8, &ack, 1); + if (ack != CMD_ACK[0]) { + fprintf(stderr, "%s: Wrong acknowledge %#x, expected %#x\n", + __func__, ack, CMD_ACK[0]); + exit(-1); + } + } + + for (n=0; n> 8; + cmd[2] = addr + n; + cmd[3] = 32; + memcpy(cmd + 4, data + n, 32); + hid_send_recv(cmd, 4+32, &ack, 1); + if (ack != CMD_ACK[0]) { + fprintf(stderr, "%s: Wrong acknowledge %#x, expected %#x\n", + __func__, ack, CMD_ACK[0]); + exit(-1); + } + } +} + +void hid_read_finish() +{ + unsigned char ack; + + hid_send_recv(CMD_ENDR, 4, &ack, 1); + if (ack != CMD_ACK[0]) { + fprintf(stderr, "%s: Wrong acknowledge %#x, expected %#x\n", + __func__, ack, CMD_ACK[0]); + } +} + +void hid_write_finish() +{ + unsigned char ack; + + hid_send_recv(CMD_ENDW, 4, &ack, 1); + if (ack != CMD_ACK[0]) { + fprintf(stderr, "%s: Wrong acknowledge %#x, expected %#x\n", + __func__, ack, CMD_ACK[0]); + } +}