Bemanitools v5.26 release

This commit is contained in:
icex2
2019-09-27 22:36:50 +02:00
commit cbd7720349
718 changed files with 62731 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
libs += ezusb2
libs_ezusb := \
ezusb \
ldflags_ezusb2 := \
src_ezusb2 := \
ezusb2.c \

206
src/main/ezusb2/cyioctl.h Normal file
View File

@@ -0,0 +1,206 @@
/*
Copyright (c) 2011 Cypress Semiconductor Corporation
Module Name:
CyIoclt.h
Additional Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
*/
#ifndef __IOCTL_H__
#define __IOCTL_H__
#ifndef DRIVER
#ifndef CTL_CODE
#include <devioctl.h>
#endif
#ifndef BM_REQUEST_TYPE
#include "usb200.h"
#endif
#define DIR_HOST_TO_DEVICE 0
#define DIR_DEVICE_TO_HOST 1
#define DEVICE_SPEED_UNKNOWN 0x00000000
#define DEVICE_SPEED_LOW_FULL 0x00000001
#define DEVICE_SPEED_HIGH 0x00000002
typedef struct _WORD_SPLIT {
UCHAR lowByte;
UCHAR hiByte;
} WORD_SPLIT, *PWORD_SPLIT;
typedef struct _BM_REQ_TYPE {
UCHAR Recipient:2;
UCHAR Reserved:3;
UCHAR Type:2;
UCHAR Direction:1;
} BM_REQ_TYPE, *PBM_REQ_TYPE;
typedef struct _SETUP_PACKET {
union {
BM_REQ_TYPE bmReqType;
UCHAR bmRequest;
};
UCHAR bRequest;
union {
WORD_SPLIT wVal;
USHORT wValue;
};
union {
WORD_SPLIT wIndx;
USHORT wIndex;
};
union {
WORD_SPLIT wLen;
USHORT wLength;
};
ULONG ulTimeOut;
} SETUP_PACKET, *PSETUP_PACKET;
#define USB_ISO_ID 0x4945
#define USB_ISO_CMD_ASAP 0x8000
#define USB_ISO_CMD_CURRENT_FRAME 0x8001
#define USB_ISO_CMD_SET_FRAME 0x8002
typedef struct _ISO_ADV_PARAMS {
USHORT isoId;
USHORT isoCmd;
ULONG ulParam1;
ULONG ulParam2;
} ISO_ADV_PARAMS, *PISO_ADV_PARAMS;
typedef struct _ISO_PACKET_INFO {
ULONG Status;
ULONG Length;
} ISO_PACKET_INFO, *PISO_PACKET_INFO;
/* icex2 changes: force packed struct */
#pragma pack(push, packing)
#pragma pack(1)
typedef struct _SINGLE_TRANSFER {
union {
SETUP_PACKET SetupPacket;
ISO_ADV_PARAMS IsoParams;
};
UCHAR reserved;
UCHAR ucEndpointAddress;
ULONG NtStatus;
ULONG UsbdStatus;
ULONG IsoPacketOffset;
ULONG IsoPacketLength;
ULONG BufferOffset;
ULONG BufferLength;
} SINGLE_TRANSFER, *PSINGLE_TRANSFER;
#pragma pack(pop, packing)
#endif // #ifndef DRIVER
typedef struct _SET_TRANSFER_SIZE_INFO {
UCHAR EndpointAddress;
ULONG TransferSize;
} SET_TRANSFER_SIZE_INFO, *PSET_TRANSFER_SIZE_INFO;
//
// Macro to extract function out of the device io control code
//
#ifdef WIN_98_DDK
#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0xffff0000)) >> 16)
#endif
#define FUNCTION_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0x00003FFC)) >> 2)
#define ACCESS_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0x000C0000)) >> 14)
//#define METHOD_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0x00000003)))
#define IOCTL_ADAPT_INDEX 0x0000
// Get the driver version
#define IOCTL_ADAPT_GET_DRIVER_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Get the current USBDI version
#define IOCTL_ADAPT_GET_USBDI_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+1, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Get the current device alt interface settings from driver
#define IOCTL_ADAPT_GET_ALT_INTERFACE_SETTING CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+2, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Set the device interface and alt interface setting
#define IOCTL_ADAPT_SELECT_INTERFACE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+3, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Get device address from driver
#define IOCTL_ADAPT_GET_ADDRESS CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+4, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Get number of endpoints for current interface and alt interface setting from driver
#define IOCTL_ADAPT_GET_NUMBER_ENDPOINTS CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+5, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Get the current device power state
#define IOCTL_ADAPT_GET_DEVICE_POWER_STATE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+6, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Set the device power state
#define IOCTL_ADAPT_SET_DEVICE_POWER_STATE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+7, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Send a raw packet to endpoint 0
#define IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+8, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Send/receive data to/from nonep0
#define IOCTL_ADAPT_SEND_NON_EP0_TRANSFER CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+9, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Simulate a disconnect/reconnect
#define IOCTL_ADAPT_CYCLE_PORT CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+10, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Reset the pipe
#define IOCTL_ADAPT_RESET_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+11, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Reset the device
#define IOCTL_ADAPT_RESET_PARENT_PORT CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+12, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Get the current transfer size of an endpoint (in number of bytes)
#define IOCTL_ADAPT_GET_TRANSFER_SIZE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+13, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Set the transfer size of an endpoint (in number of bytes)
#define IOCTL_ADAPT_SET_TRANSFER_SIZE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+14, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Return the name of the device
#define IOCTL_ADAPT_GET_DEVICE_NAME CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+15, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Return the "Friendly Name" of the device
#define IOCTL_ADAPT_GET_FRIENDLY_NAME CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+16, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Abort all outstanding transfers on the pipe
#define IOCTL_ADAPT_ABORT_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+17, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Send/receive data to/from nonep0 w/ direct buffer acccess (no buffering)
#define IOCTL_ADAPT_SEND_NON_EP0_DIRECT CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+18, METHOD_NEITHER, FILE_ANY_ACCESS)
// Return device speed
#define IOCTL_ADAPT_GET_DEVICE_SPEED CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+19, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Get the current USB frame number
#define IOCTL_ADAPT_GET_CURRENT_FRAME CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+20, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define NUMBER_OF_ADAPT_IOCTLS 21 // Last IOCTL_ADAPT_INDEX + 1
#endif // __IOCTL_H__

295
src/main/ezusb2/ezusb2.c Normal file
View File

@@ -0,0 +1,295 @@
#include <windows.h>
#include <setupapi.h>
#include "ezusb/ezusb.h"
#include "ezusb2/cyioctl.h"
#include "ezusb2/ezusb2.h"
#include "util/crc.h"
#include "util/fs.h"
#include "util/log.h"
#include "util/str.h"
#define REQ_TYPE_HOST_TO_DEV 0x40
#define REQ_TYPE_DEV_TO_HOST 0x80
#define REQ_TIMEOUT_SEC 5
#define REQ_CODE_EP0 0x00
#define EP0_GET_DESCRIPTOR 0x06
#define EP0_EZUSB_WRITE_RAM 0xA0
/* nope, it's not 0x01, probably an endianess mistake (?) */
#define EP0_DESCRIPTOR_TYPE_DEVICE 0x0100
/* Also not 0x03, 0x0301 from DeviceIoCtl dump */
#define EP0_DESCRIPTOR_TYPE_STRING 0x0301
#define EP0_EZUSB_RAM_CPU_RESET_ADDR 0xE600
static int ezusb2_ctrl_transfer(HANDLE handle, uint32_t ioctl_code,
uint8_t endpoint, uint8_t req_type, uint8_t req, uint16_t value,
uint16_t index, void* buf, uint32_t buf_len)
{
int xmit_buf_size = sizeof(SINGLE_TRANSFER) + buf_len;
char xmit_buf[xmit_buf_size];
DWORD ret_len;
memset(xmit_buf, 0, xmit_buf_size);
PSINGLE_TRANSFER transfer = (PSINGLE_TRANSFER) xmit_buf;
memset(transfer, 0, sizeof(SINGLE_TRANSFER));
transfer->SetupPacket.bmRequest = req_type;
transfer->SetupPacket.bRequest = req;
transfer->SetupPacket.wValue = value;
transfer->SetupPacket.wIndex = index;
transfer->SetupPacket.wLength = buf_len;
/* Timeout is in seconds, wtf ?! */
transfer->SetupPacket.ulTimeOut = REQ_TIMEOUT_SEC;
transfer->ucEndpointAddress = endpoint;
transfer->BufferOffset = sizeof(SINGLE_TRANSFER);
transfer->BufferLength = buf_len;
/* All other attributes 0 */
if (buf) {
memcpy(xmit_buf + sizeof(SINGLE_TRANSFER), buf, buf_len);
}
if (!DeviceIoControl(handle, ioctl_code, xmit_buf, xmit_buf_size, xmit_buf,
xmit_buf_size, &ret_len, NULL)) {
return -1;
}
if (buf) {
memcpy(buf, xmit_buf + sizeof(SINGLE_TRANSFER), buf_len);
}
return ret_len - sizeof(SINGLE_TRANSFER);
}
static int ezusb2_ep0_transfer(HANDLE handle, uint8_t req_type, uint8_t req,
uint16_t value, uint16_t index, void* buf, uint32_t buf_len)
{
return ezusb2_ctrl_transfer(handle, IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER,
REQ_CODE_EP0, req_type, req, value, index, buf, buf_len);
}
/* Any other endpoint than 0 */
static int ezusb2_epx_transfer(HANDLE handle, uint8_t endpoint,
uint8_t req_type, uint8_t req, uint16_t value, uint16_t index,
void* buf, uint32_t buf_len)
{
return ezusb2_ctrl_transfer(handle, IOCTL_ADAPT_SEND_NON_EP0_TRANSFER,
endpoint, req_type, req, value, index, buf, buf_len);
}
static char* ezusb2_get_device_name(HANDLE handle)
{
const int len = 256;
char buf[len];
DWORD received;
memset(&buf, 0, len);
if (!DeviceIoControl(handle, IOCTL_ADAPT_GET_FRIENDLY_NAME, &buf, len, &buf,
len, &received, NULL)) {
return NULL;
}
return str_dup((const char*) &buf);
}
static bool ezusb2_get_device_descriptor(HANDLE handle,
USB_DEVICE_DESCRIPTOR* desc)
{
int res;
memset(desc, 0, sizeof(USB_DEVICE_DESCRIPTOR));
/* 0: not used */
res = ezusb2_ep0_transfer(handle, REQ_TYPE_DEV_TO_HOST, EP0_GET_DESCRIPTOR,
EP0_DESCRIPTOR_TYPE_DEVICE, 0, desc, sizeof(USB_DEVICE_DESCRIPTOR));
if (res != sizeof(USB_DEVICE_DESCRIPTOR)) {
return false;
}
return true;
}
static bool ezusb2_write_ram(HANDLE handle, const void* buffer,
uint16_t ram_offset, uint32_t size)
{
return ezusb2_ep0_transfer(handle, REQ_TYPE_HOST_TO_DEV, EP0_EZUSB_WRITE_RAM,
ram_offset, 0, (void*) buffer, size) == size;
}
static bool ezusb2_reset(HANDLE handle, bool hold)
{
uint8_t flag;
/* Write CPU state */
flag = hold ? 1 : 0;
return ezusb2_write_ram(handle, &flag, EP0_EZUSB_RAM_CPU_RESET_ADDR,
sizeof(uint8_t));
}
char* ezusb2_find(const GUID* guid)
{
HDEVINFO info;
SP_DEVICE_INTERFACE_DATA iface;
BOOL result;
ULONG required_len;
PSP_DEVICE_INTERFACE_DETAIL_DATA detail;
ULONG length;
char* res;
log_assert(guid);
result = FALSE;
required_len = 0;
detail = NULL;
info = SetupDiGetClassDevs(guid, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (info == INVALID_HANDLE_VALUE) {
return NULL;
}
/* Enum devices that support the GUID, get first only */
memset(&iface, 0, sizeof(iface));
iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
result = SetupDiEnumDeviceInterfaces(info, NULL, guid, 0, &iface);
if (!result) {
SetupDiDestroyDeviceInfoList(info);
return NULL;
}
/* Get information about the found device interface. We don't
know how much memory to allocate to get this information, so
we will ask by passing in a null buffer and location to
receive the size of the buffer needed. */
result = SetupDiGetDeviceInterfaceDetail(info, &iface, NULL, 0,
&required_len, NULL);
if (!required_len) {
return NULL;
}
/* Okay, we got a size back, so let's allocate memory
for the interface detail information we want. */
detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalAlloc(LMEM_FIXED,
required_len);
if (detail == NULL) {
SetupDiDestroyDeviceInfoList(info);
return NULL;
}
detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
length = required_len;
result = SetupDiGetDeviceInterfaceDetail(info, &iface, detail,
length, &required_len, NULL);
if (!result) {
SetupDiDestroyDeviceInfoList(info);
LocalFree(detail);
return NULL;
}
res = str_dup((const char*) &detail->DevicePath);
LocalFree(detail);
SetupDiDestroyDeviceInfoList(info);
return res;
}
HANDLE ezusb2_open(const char* device_path)
{
log_assert(device_path);
return CreateFileA(device_path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
}
bool ezusb2_get_ident(HANDLE handle, struct ezusb_ident* ident)
{
char* name;
USB_DEVICE_DESCRIPTOR desc;
log_assert(handle != INVALID_HANDLE_VALUE);
log_assert(handle);
log_assert(ident);
memset(ident, 0, sizeof(struct ezusb_ident));
name = ezusb2_get_device_name(handle);
if (!name) {
return false;
}
memcpy(ident->name, name, strlen(name));
free(name);
if (!ezusb2_get_device_descriptor(handle, &desc)) {
return false;
}
ident->vid = desc.idVendor;
ident->pid = desc.idProduct;
return true;
}
bool ezusb2_download_firmware(HANDLE handle, struct ezusb_firmware* fw)
{
log_assert(handle != INVALID_HANDLE_VALUE);
log_assert(handle);
log_assert(fw);
if (!ezusb2_reset(handle, true)) {
return false;
}
for (uint16_t i = 0; i < fw->segment_count; i++) {
/* Important: Writing the full binary does NOT work on the FX2 device
compared to the legacy ezusb device */
if (!ezusb2_write_ram(handle, fw->segments[i]->data,
fw->segments[i]->offset, fw->segments[i]->size)) {
return false;
}
}
if (!ezusb2_reset(handle, false)) {
return false;
}
return true;
}
bool ezusb2_endpoint_transfer(HANDLE handle, uint8_t endpoint, void* data,
uint32_t size)
{
if (endpoint == 0) {
return false;
}
return ezusb2_epx_transfer(handle, endpoint, 0, 0, 0, 0, data, size);
}
void ezusb2_close(HANDLE handle)
{
log_assert(handle != INVALID_HANDLE_VALUE);
log_assert(handle);
CloseHandle(handle);
}

90
src/main/ezusb2/ezusb2.h Normal file
View File

@@ -0,0 +1,90 @@
/**
* Module for fundamental communication with an Ezusb FX2 board, e.g.
* IIDX/Pop'n IO2. Credit also goes to willxinc for his initial implemention
* which, for some unknown reason, did not work on my machines.
*
* This module does not implement any sort of higher level protocol which is
* required by the games to exchange data with the device, e.g. getting input
* states of keys and setting light outputs. Further modules are utilizing this
* base layer to implement higher level communication.
*
* Note: This module requires the newer "cyusb3" driver which is compatible
* with WinXP, Win7, Win8 and Win10 (both 32 and 64-bit). The old "cyusb" driver
* does NOT work with this.
*
* @author icex2, willxinc
*/
#ifndef EZUSB2_H
#define EZUSB2_H
#include <stdbool.h>
#include <stdint.h>
#include <windows.h>
#include "ezusb/util.h"
/**
* GUID of Ezusb FX2 board
*/
static const GUID EZUSB2_GUID = {0xAE18AA60L, 0x7F6A, 0x11D4,
{0x97, 0xDD, 0x00, 0x01, 0x02, 0x29, 0xB9, 0x59}};
/**
* Scan for connected devices which match the provided GUID.
*
* @param guid GUID of device to find.
* @return Allocated device path string of first device found matching the GUID
* provided. Caller has to free buffer.
*/
char* ezusb2_find(const GUID* guid);
/**
* Open a connected Ezusb FX2 device.
*
* @param device_path Path to the Ezusb FX2 device obtained by using
* the ezusb2_find function.
* @return A valid handle to the device on success, INVALID_HANDLE_VALUE on
* error.
*/
HANDLE ezusb2_open(const char* device_path);
/**
* Get identifier information of the device.
*
* @param handle Valid device handle.
* @param ident Pointer to memory to write the identifier information to.
* @return True if successful and identifier information was written to the
* the struct, false on error.
*/
bool ezusb2_get_ident(HANDLE handle, struct ezusb_ident* ident);
/**
* Download a firmware to the ezusb device.
*
* @param handle Valid device handle.
* @param fw Firmware to write to the target ezusb device.
* @return True on success, false on failure.
*/
bool ezusb2_download_firmware(HANDLE handle, struct ezusb_firmware* fw);
/**
* Execute a data transfer to a specific endpoint other than endpoint 0.
*
* @param handle Valid device handle.
* @param endpoint Target endpoint, in and out valid but not 0.
* @param data Buffer with data to transfer or for data to receive.
* @param size Size of buffer.
* @return True on success, false on failure.
*/
bool ezusb2_endpoint_transfer(HANDLE handle, uint8_t endpoint, void* data,
uint32_t size);
/**
* Close an opened ezusb device handle.
*
* @param handle Valid handle to close.
*/
void ezusb2_close(HANDLE handle);
#endif