diff --git a/Makefile b/Makefile index 8042199..cf57e28 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ UNAME = $(shell uname) CFLAGS = -g -O -Wall -Werror -DVERSION='"$(VERSION).$(GITCOUNT)"' LDFLAGS = -g -OBJS = main.o util.o radio.o dfu-libusb.o uv380.o md380.o rd5r.o +OBJS = main.o util.o radio.o dfu-libusb.o uv380.o md380.o rd5r.o hid.o LIBS = -lusb-1.0 # Linux diff --git a/Makefile-mingw b/Makefile-mingw index 4fc387a..6397465 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 rd5r.o hid-windows.o +OBJS = main.o util.o radio.o dfu-windows.o uv380.o md380.o rd5r.o hid.o hid-windows.o LIBS = -lhid -lsetupapi # Compiling Windows binary from Linux diff --git a/hid-libusb.c b/hid-libusb.c index eb1d52d..3f95335 100644 --- a/hid-libusb.c +++ b/hid-libusb.c @@ -32,25 +32,11 @@ #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 libusb_context *ctx = NULL; // libusb context static libusb_device_handle *dev; // libusb device static struct libusb_transfer *transfer; // async transfer descriptor static unsigned char receive_buf[42]; // receive buffer static volatile int nbytes_received = 0; // receive result -static unsigned offset = 0; // CWD offset - -#define HID_INTERFACE 0 // interface index -#define TIMEOUT_MSEC 500 // receive timeout // // Callback function for asynchronous receive. @@ -205,9 +191,8 @@ void hid_send_recv(const unsigned char *data, unsigned nbytes, unsigned char *rd // // Connect to the specified device. // Initiate the programming session. -// Query and return the device identification string. // -const char *hid_init(int vid, int pid) +int hid_init(int vid, int pid) { int error = libusb_init(&ctx); if (error < 0) { @@ -224,7 +209,7 @@ const char *hid_init(int vid, int pid) } libusb_exit(ctx); ctx = 0; - return 0; + return -1; } if (libusb_kernel_driver_active(dev, 0)) { libusb_detach_kernel_driver(dev, 0); @@ -239,35 +224,7 @@ const char *hid_init(int vid, int pid) ctx = 0; exit(-1); } - - static unsigned char reply[38]; - unsigned char ack; - - hid_send_recv(CMD_PRG, 7, &ack, 1); - if (ack != CMD_ACK[0]) { - fprintf(stderr, "%s: Wrong PRD acknowledge %#x, expected %#x\n", - __func__, ack, CMD_ACK[0]); - return 0; - } - - hid_send_recv(CMD_PRG2, 2, reply, 16); - - hid_send_recv(CMD_ACK, 1, &ack, 1); - if (ack != CMD_ACK[0]) { - fprintf(stderr, "%s: Wrong PRG2 acknowledge %#x, expected %#x\n", - __func__, ack, CMD_ACK[0]); - return 0; - } - - // Reply: - // 42 46 2d 35 52 ff ff ff 56 32 31 30 00 04 80 04 - // B F - 5 R V 2 1 0 - - // Terminate the string. - char *p = memchr(reply, 0xff, sizeof(reply)); - if (p) - *p = 0; - return (char*)reply; + return 0; } void hid_close() @@ -284,98 +241,3 @@ void hid_close() libusb_exit(ctx); ctx = 0; } - -void hid_read_block(int bno, uint8_t *data, int nbytes) -{ - unsigned addr = bno * nbytes; - unsigned char ack, cmd[4], reply[32+4]; - 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; - 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]); - } -} diff --git a/hid-macos.c b/hid-macos.c index 8d84cea..823a7a6 100644 --- a/hid-macos.c +++ b/hid-macos.c @@ -32,21 +32,10 @@ #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 volatile IOHIDDeviceRef dev; // device handle static unsigned char transfer_buf[42]; // device buffer 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. @@ -57,6 +46,7 @@ void hid_send_recv(const unsigned char *data, unsigned nbytes, unsigned char *rd { unsigned char buf[42]; unsigned k; + IOReturn result; memset(buf, 0, sizeof(buf)); buf[0] = 1; @@ -80,7 +70,7 @@ void hid_send_recv(const unsigned char *data, unsigned nbytes, unsigned char *rd memset(receive_buf, 0, sizeof(receive_buf)); again: // Write to HID device. - IOReturn result = IOHIDDeviceSetReport(dev, kIOHIDReportTypeOutput, 0, buf, sizeof(buf)); + result = IOHIDDeviceSetReport(dev, kIOHIDReportTypeOutput, 0, buf, sizeof(buf)); if (result != kIOReturnSuccess) { fprintf(stderr, "HID output error: %d!\n", result); exit(-1); @@ -89,9 +79,9 @@ again: // Run main application loop until reply received. CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 0); for (k = 0; nbytes_received <= 0; k++) { - usleep(10000); + usleep(100); CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 0); - if (k >= 10) { + if (k >= 1000) { if (trace_flag > 0) { fprintf(stderr, "No response from HID device!\n"); } @@ -179,7 +169,7 @@ static void callback_close(void *ontext, // // Launch the IOHIDManager. // -const char *hid_init(int vid, int pid) +int hid_init(int vid, int pid) { // Create the USB HID Manager. IOHIDManagerRef HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, @@ -210,7 +200,7 @@ const char *hid_init(int vid, int pid) if (trace_flag) { fprintf(stderr, "Cannot find USB device %04x:%04x\n", vid, pid); } - return 0; + return -1; } // Run main application loop until device found. @@ -218,44 +208,16 @@ const char *hid_init(int vid, int pid) for (k=0; ; k++) { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 0); if (dev) - break; + return 0; + if (k >= 3) { if (trace_flag) { fprintf(stderr, "Cannot find USB device %04x:%04x\n", vid, pid); } - return 0; + return -1; } usleep(10000); } - - static unsigned char reply[38]; - unsigned char ack; - - hid_send_recv(CMD_PRG, 7, &ack, 1); - if (ack != CMD_ACK[0]) { - fprintf(stderr, "%s: Wrong PRD acknowledge %#x, expected %#x\n", - __func__, ack, CMD_ACK[0]); - return 0; - } - - hid_send_recv(CMD_PRG2, 2, reply, 16); - - hid_send_recv(CMD_ACK, 1, &ack, 1); - if (ack != CMD_ACK[0]) { - fprintf(stderr, "%s: Wrong PRG2 acknowledge %#x, expected %#x\n", - __func__, ack, CMD_ACK[0]); - return 0; - } - - // Reply: - // 42 46 2d 35 52 ff ff ff 56 32 31 30 00 04 80 04 - // B F - 5 R V 2 1 0 - - // Terminate the string. - char *p = memchr(reply, 0xff, sizeof(reply)); - if (p) - *p = 0; - return (char*)reply; } // @@ -269,98 +231,3 @@ void hid_close() IOHIDDeviceClose(dev, kIOHIDOptionsTypeNone); dev = 0; } - -void hid_read_block(int bno, uint8_t *data, int nbytes) -{ - unsigned addr = bno * nbytes; - unsigned char ack, cmd[4], reply[32+4]; - 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; - 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]); - } -} diff --git a/hid-windows.c b/hid-windows.c index 17b719a..88c4ea2 100644 --- a/hid-windows.c +++ b/hid-windows.c @@ -35,19 +35,8 @@ #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"; - HANDLE dev = INVALID_HANDLE_VALUE;; // HID device static unsigned char receive_buf[42]; // receive buffer -static unsigned offset = 0; // CWD offset // // Send a request to the device. @@ -120,24 +109,25 @@ void hid_send_recv(const unsigned char *data, unsigned nbytes, unsigned char *rd } // +// Open the radio in programming mode. // Find a HID device with given GUID, vendor ID and product ID. -// Return an opened file descriptor. +// Setup `dev' file descriptor. // -HANDLE find_hid_device(int vid, int pid) +int hid_init(int vid, int pid) { static GUID guid = { 0x4d1e55b2, 0xf16f, 0x11cf, { 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } }; - HANDLE h = INVALID_HANDLE_VALUE; HDEVINFO devinfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); if (devinfo == INVALID_HANDLE_VALUE) { printf("Cannot get devinfo!\n"); - return 0; + return -1; } // Loop through available devices with a given GUID. int index; SP_INTERFACE_DEVICE_DATA iface; iface.cbSize = sizeof(iface); + dev = INVALID_HANDLE_VALUE; for (index=0; SetupDiEnumDeviceInterfaces(devinfo, NULL, &guid, index, &iface); ++index) { // Obtain a required size of device detail structure. @@ -156,22 +146,22 @@ HANDLE find_hid_device(int vid, int pid) } //printf("Device %d: path %s\n", index, detail->DevicePath); - h = CreateFile(detail->DevicePath, GENERIC_WRITE | GENERIC_READ, + dev = CreateFile(detail->DevicePath, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); - if (h == INVALID_HANDLE_VALUE) { + if (dev == INVALID_HANDLE_VALUE) { continue; } // Get the Vendor ID and Product ID for this device. HIDD_ATTRIBUTES attrib; attrib.Size = sizeof(HIDD_ATTRIBUTES); - HidD_GetAttributes(h, &attrib); + HidD_GetAttributes(dev, &attrib); //printf("Vendor/Product: %04x %04x\n", attrib.VendorID, attrib.ProductID); // Check the VID/PID. if (attrib.VendorID != vid || attrib.ProductID != pid) { - CloseHandle(h); - h = INVALID_HANDLE_VALUE; + CloseHandle(dev); + dev = INVALID_HANDLE_VALUE; continue; } @@ -179,51 +169,14 @@ HANDLE find_hid_device(int vid, int pid) break; } SetupDiDestroyDeviceInfoList(devinfo); - return h; -} -// -// Open the radio in programming mode. -// -const char *hid_init(int vid, int pid) -{ - // Find HID device. - dev = find_hid_device(vid, pid); if (dev == INVALID_HANDLE_VALUE) { if (trace_flag) { fprintf(stderr, "Cannot find HID device %04x:%04x\n", vid, pid); } - return 0; + return -1; } - - static unsigned char reply[38]; - unsigned char ack; - - hid_send_recv(CMD_PRG, 7, &ack, 1); - if (ack != CMD_ACK[0]) { - fprintf(stderr, "%s: Wrong PRD acknowledge %#x, expected %#x\n", - __func__, ack, CMD_ACK[0]); - return 0; - } - - hid_send_recv(CMD_PRG2, 2, reply, 16); - - hid_send_recv(CMD_ACK, 1, &ack, 1); - if (ack != CMD_ACK[0]) { - fprintf(stderr, "%s: Wrong PRG2 acknowledge %#x, expected %#x\n", - __func__, ack, CMD_ACK[0]); - return 0; - } - - // Reply: - // 42 46 2d 35 52 ff ff ff 56 32 31 30 00 04 80 04 - // B F - 5 R V 2 1 0 - - // Terminate the string. - char *p = memchr(reply, 0xff, sizeof(reply)); - if (p) - *p = 0; - return (char*)reply; + return 0; } // @@ -236,98 +189,3 @@ void hid_close() dev = INVALID_HANDLE_VALUE; } } - -void hid_read_block(int bno, uint8_t *data, int nbytes) -{ - unsigned addr = bno * nbytes; - unsigned char ack, cmd[4], reply[32+4]; - 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; - 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]); - } -} diff --git a/hid.c b/hid.c new file mode 100644 index 0000000..26e6f07 --- /dev/null +++ b/hid.c @@ -0,0 +1,174 @@ +/* + * HID routines, OS independent. + * + * 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 "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 offset = 0; // CWD offset + +// +// Query and return the device identification string. +// +const char *hid_identify() +{ + static unsigned char reply[38]; + unsigned char ack; + + hid_send_recv(CMD_PRG, 7, &ack, 1); + if (ack != CMD_ACK[0]) { + fprintf(stderr, "%s: Wrong PRD acknowledge %#x, expected %#x\n", + __func__, ack, CMD_ACK[0]); + return 0; + } + + hid_send_recv(CMD_PRG2, 2, reply, 16); + + hid_send_recv(CMD_ACK, 1, &ack, 1); + if (ack != CMD_ACK[0]) { + fprintf(stderr, "%s: Wrong PRG2 acknowledge %#x, expected %#x\n", + __func__, ack, CMD_ACK[0]); + return 0; + } + + // Reply: + // 42 46 2d 35 52 ff ff ff 56 32 31 30 00 04 80 04 + // B F - 5 R V 2 1 0 + + // Terminate the string. + char *p = memchr(reply, 0xff, sizeof(reply)); + if (p) + *p = 0; + return (char*)reply; +} + +void hid_read_block(int bno, unsigned char *data, int nbytes) +{ + unsigned addr = bno * nbytes; + unsigned char ack, cmd[4], reply[32+4]; + 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; + hid_send_recv(cmd, 4, reply, sizeof(reply)); + memcpy(data + n, reply + 4, 32); + } +} + +void hid_write_block(int bno, unsigned char *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]); + } +} diff --git a/radio.c b/radio.c index d613c90..c204503 100644 --- a/radio.c +++ b/radio.c @@ -91,7 +91,8 @@ void radio_connect() ident = dfu_init(0x0483, 0xdf11); if (! ident) { // Try RD-5R. - ident = hid_init(0x15a2, 0x0073); + if (hid_init(0x15a2, 0x0073) >= 0) + ident = hid_identify(); } if (! ident) { fprintf(stderr, "No radio detected.\n"); diff --git a/util.h b/util.h index c4bf349..99ce826 100644 --- a/util.h +++ b/util.h @@ -68,9 +68,10 @@ void dfu_reboot(void); // // HID functions. // -const char *hid_init(int vid, int pid); +int hid_init(int vid, int pid); +const char *hid_identify(void); void hid_close(void); -int hid_write_read(const unsigned char *data, unsigned length, unsigned char *reply, unsigned rlength); +void hid_send_recv(const unsigned char *data, unsigned nbytes, unsigned char *rdata, unsigned rlength); void hid_read_block(int bno, unsigned char *data, int nbytes); void hid_read_finish(void); void hid_write_block(int bno, unsigned char *data, int nbytes);