Added format protection block to avoid re-ordering of header files according to formatting rules.
150 lines
3.0 KiB
C
150 lines
3.0 KiB
C
// clang-format off
|
|
// Don't format because the order is important here
|
|
#include <windows.h>
|
|
#include <setupapi.h>
|
|
// clang-format on
|
|
|
|
#include "ezusb/ezusb.h"
|
|
#include "ezusb/ezusbsys2.h"
|
|
|
|
#include "util/log.h"
|
|
#include "util/str.h"
|
|
|
|
static bool ezusb_reset(HANDLE handle, bool hold)
|
|
{
|
|
VENDOR_OR_CLASS_REQUEST_CONTROL req;
|
|
DWORD outpkt;
|
|
|
|
/* fml...I can't believe these values are correct. according to
|
|
the documentation they are wrong D: */
|
|
|
|
req.direction = 0xA0;
|
|
|
|
if (hold) {
|
|
req.requestType = 0x00;
|
|
} else {
|
|
req.requestType = 0x84;
|
|
}
|
|
|
|
req.recepient = 0x92;
|
|
|
|
req.requestTypeReservedBits = 0x7F;
|
|
req.request = 0x00;
|
|
req.value = 0x0001;
|
|
|
|
if (hold) {
|
|
req.index = 0x0100;
|
|
} else {
|
|
/* release */
|
|
req.index = 0x0000;
|
|
}
|
|
|
|
if (!DeviceIoControl(
|
|
handle,
|
|
IOCTL_Ezusb_VENDOR_REQUEST,
|
|
&req,
|
|
sizeof(req),
|
|
&req,
|
|
sizeof(req),
|
|
&outpkt,
|
|
NULL)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool ezusb_write_firmware(
|
|
HANDLE handle, const void *buffer, uint16_t ram_offset, uint32_t size)
|
|
{
|
|
ANCHOR_DOWNLOAD_CONTROL req;
|
|
DWORD outpkt;
|
|
|
|
req.Offset = ram_offset;
|
|
|
|
if (!DeviceIoControl(
|
|
handle,
|
|
IOCTL_EZUSB_ANCHOR_DOWNLOAD,
|
|
&req,
|
|
sizeof(req),
|
|
(void *) buffer,
|
|
size,
|
|
&outpkt,
|
|
NULL)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
HANDLE
|
|
ezusb_open(const char *path)
|
|
{
|
|
log_assert(path);
|
|
|
|
return CreateFileA(
|
|
path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
|
}
|
|
|
|
bool ezusb_get_ident(HANDLE handle, struct ezusb_ident *ident)
|
|
{
|
|
USB_DEVICE_DESCRIPTOR desc;
|
|
DWORD outpkt;
|
|
|
|
log_assert(handle);
|
|
log_assert(handle != INVALID_HANDLE_VALUE);
|
|
log_assert(ident);
|
|
|
|
if (!DeviceIoControl(
|
|
handle,
|
|
IOCTL_Ezusb_GET_DEVICE_DESCRIPTOR,
|
|
&desc,
|
|
sizeof(desc),
|
|
&desc,
|
|
sizeof(desc),
|
|
&outpkt,
|
|
NULL)) {
|
|
return false;
|
|
}
|
|
|
|
memset(ident->name, 0, sizeof(ident->name));
|
|
ident->vid = desc.idVendor;
|
|
ident->pid = desc.idProduct;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ezusb_download_firmware(HANDLE handle, struct ezusb_firmware *fw)
|
|
{
|
|
log_assert(handle);
|
|
log_assert(handle != INVALID_HANDLE_VALUE);
|
|
log_assert(fw);
|
|
|
|
if (!ezusb_reset(handle, true)) {
|
|
return false;
|
|
}
|
|
|
|
for (uint16_t i = 0; i < fw->segment_count; i++) {
|
|
if (!ezusb_write_firmware(
|
|
handle,
|
|
fw->segments[i]->data,
|
|
fw->segments[i]->offset,
|
|
fw->segments[i]->size)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!ezusb_reset(handle, false)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void ezusb_close(HANDLE handle)
|
|
{
|
|
log_assert(handle);
|
|
log_assert(handle != INVALID_HANDLE_VALUE);
|
|
|
|
CloseHandle(handle);
|
|
} |