diff --git a/Makefile-mingw b/Makefile-mingw index 23b6e69..4fc387a 100644 --- a/Makefile-mingw +++ b/Makefile-mingw @@ -6,7 +6,7 @@ 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 -LIBS = -lsetupapi +LIBS = -lhid -lsetupapi # Compiling Windows binary from Linux ifeq (/usr/bin/i586-mingw32msvc-gcc,$(wildcard /usr/bin/i586-mingw32msvc-gcc)) diff --git a/dfu-windows.c b/dfu-windows.c index c737f90..413ab6c 100644 --- a/dfu-windows.c +++ b/dfu-windows.c @@ -399,8 +399,10 @@ const char *dfu_init(unsigned vid, unsigned pid) } if (!path) { - fprintf(stderr, "Cannot find USB device %04x:%04x\n", vid, pid); - exit(-1); + if (trace_flag) { + fprintf(stderr, "Cannot find DFU device %04x:%04x\n", vid, pid); + } + return 0; } // Open the device. diff --git a/hid-libusb.c b/hid-libusb.c index b61d17f..eb1d52d 100644 --- a/hid-libusb.c +++ b/hid-libusb.c @@ -98,10 +98,10 @@ static int write_read(const unsigned char *data, unsigned length, unsigned char if (! transfer) { // Allocate transfer descriptor on first invocation. transfer = libusb_alloc_transfer(0); - libusb_fill_interrupt_transfer(transfer, dev, - LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN, - reply, rlength, read_callback, 0, TIMEOUT_MSEC); } + libusb_fill_interrupt_transfer(transfer, dev, + LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN, + reply, rlength, read_callback, 0, TIMEOUT_MSEC); again: nbytes_received = 0; libusb_submit_transfer(transfer); diff --git a/hid-windows.c b/hid-windows.c index d0f0d9c..6d0b42c 100644 --- a/hid-windows.c +++ b/hid-windows.c @@ -25,6 +25,9 @@ * 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 @@ -42,8 +45,8 @@ 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 volatile int nbytes_received = 0; // receive result static unsigned offset = 0; // CWD offset // @@ -55,6 +58,7 @@ void hid_send_recv(const unsigned char *data, unsigned nbytes, unsigned char *rd { unsigned char buf[42]; unsigned k; + DWORD nbytes_received; memset(buf, 0, sizeof(buf)); buf[0] = 1; @@ -76,30 +80,22 @@ void hid_send_recv(const unsigned char *data, unsigned nbytes, unsigned char *rd } nbytes_received = 0; memset(receive_buf, 0, sizeof(receive_buf)); -#if 0 - //TODO + // Write to HID device. - IOReturn result = IOHIDDeviceSetReport(dev, kIOHIDReportTypeOutput, 0, buf, sizeof(buf)); - if (result != kIOReturnSuccess) { - fprintf(stderr, "HID output error: %d!\n", result); + if (!WriteFile(dev, buf, sizeof(buf), NULL, NULL)) { + fprintf(stderr, "Error %#lx sending to HID device!\n", GetLastError()); exit(-1); } - // Run main application loop until reply received. - 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); + // Receive reply. + if (!ReadFile(dev, receive_buf, sizeof(receive_buf), &nbytes_received, NULL)) { + fprintf(stderr, "Error %#lx receiving from HID device!\n", GetLastError()); + exit(-1); } -#endif + if (nbytes_received != sizeof(receive_buf)) { - fprintf(stderr, "Short read: %d bytes instead of %d!\n", - nbytes_received, (int)sizeof(receive_buf)); + fprintf(stderr, "Short read: %u bytes instead of %u!\n", + (unsigned)nbytes_received, (unsigned)sizeof(receive_buf)); exit(-1); } if (trace_flag > 0) { @@ -124,15 +120,81 @@ void hid_send_recv(const unsigned char *data, unsigned nbytes, unsigned char *rd } // -// Launch the IOHIDManager. +// Find a HID device with given GUID, vendor ID and product ID. +// Return an opened file descriptor. +// +HANDLE find_hid_device(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; + } + + // Loop through available devices with a given GUID. + int index; + SP_INTERFACE_DEVICE_DATA iface; + iface.cbSize = sizeof(iface); + for (index=0; SetupDiEnumDeviceInterfaces(devinfo, NULL, &guid, index, &iface); ++index) { + + // Obtain a required size of device detail structure. + DWORD needed; + SetupDiGetDeviceInterfaceDetail(devinfo, &iface, NULL, 0, &needed, NULL); + + // Allocate the device detail structure. + PSP_INTERFACE_DEVICE_DETAIL_DATA detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)alloca(needed); + detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); + SP_DEVINFO_DATA did = { sizeof(SP_DEVINFO_DATA) }; + + // Get device information. + if (!SetupDiGetDeviceInterfaceDetail(devinfo, &iface, detail, needed, NULL, &did)) { + printf("Device %d: cannot get path!\n", index); + continue; + } + printf("Device %d: path %s\n", index, detail->DevicePath); + + h = CreateFile(detail->DevicePath, GENERIC_WRITE | GENERIC_READ, + 0, NULL, OPEN_EXISTING, 0, NULL); + if (h == 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); + printf("Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); + + // Check the VID/PID. + if (attrib.VendorID != vid || attrib.ProductID != pid) { + CloseHandle(h); + h = INVALID_HANDLE_VALUE; + continue; + } + + // Required device found. + break; + } + SetupDiDestroyDeviceInfoList(devinfo); + return h; +} + +// +// Open the radio in programming mode. // const char *hid_init(int vid, int pid) { - //TODO - if (trace_flag) { - fprintf(stderr, "Cannot find USB device %04x:%04x\n", vid, 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 0; static unsigned char reply[38]; unsigned char ack; @@ -169,7 +231,10 @@ const char *hid_init(int vid, int pid) // void hid_close() { - //TODO + if (dev != INVALID_HANDLE_VALUE) { + CloseHandle(dev); + dev = INVALID_HANDLE_VALUE; + } } void hid_read_block(int bno, uint8_t *data, int nbytes)