Add support for DDR X

This commit is contained in:
QCDLZCLW3K
2022-05-30 02:00:49 +00:00
parent 537b1fa384
commit 4be866e69e
44 changed files with 1687 additions and 114 deletions
+5
View File
@@ -11,3 +11,8 @@ src_ddrhook-util := \
guid.c \
misc.c \
monitor.c \
extio.c \
_com4.c \
usbmem.c \
spike.c \
p3io.c \
+158
View File
@@ -0,0 +1,158 @@
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <devioctl.h>
#include <ntdef.h>
#include <ntddser.h>
// clang-format on
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "acio/hdxs.h"
#include "acioemu/addr.h"
#include "acioemu/hdxs.h"
#include "acioemu/icca.h"
#include "bemanitools/ddrio.h"
#include "ddrhook-util/_com4.h"
#include "hook/iohook.h"
#include "p3ioemu/uart.h"
#include "util/defs.h"
#include "util/iobuf.h"
#include "util/log.h"
static struct ac_io_emu com4_ac_io_emu;
static struct ac_io_emu_hdxs com4_hdxs;
static struct ac_io_emu_icca com4_icca[2];
static uint32_t check_panel_light(
const struct ac_io_hdxs_output *output,
uint8_t panel_idx,
uint8_t out_idx)
{
if (output->lights[panel_idx].bit) {
return 1 << out_idx;
} else {
return 0;
}
}
static uint8_t upscale_light(uint8_t in_7bit) {
if (in_7bit < 0x10) {
return in_7bit * 2;
} else {
// so we can actually reach 0xFF
return (in_7bit * 2) + 1;
}
}
static void lights_dispatcher(
struct ac_io_emu_hdxs *emu, const struct ac_io_message *req)
{
const struct ac_io_hdxs_output *output = &req->cmd.hdxs_output;
uint32_t lights = 0;
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P1_START, LIGHT_HD_P1_START);
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P1_UP_DOWN, LIGHT_HD_P1_UP_DOWN);
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P1_LEFT_RIGHT, LIGHT_HD_P1_LEFT_RIGHT);
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P2_START, LIGHT_HD_P2_START);
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P2_UP_DOWN, LIGHT_HD_P2_UP_DOWN);
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P2_LEFT_RIGHT, LIGHT_HD_P2_LEFT_RIGHT);
ddr_io_set_lights_hdxs_panel(lights);
for (uint8_t i = 0; i < 4; ++i) {
size_t light_idx = i * 3;
// these are 7 bit, upscale them to 8 bit
uint8_t r = upscale_light(output->lights[light_idx + AC_IO_HDXS_RED].analog);
uint8_t g = upscale_light(output->lights[light_idx + AC_IO_HDXS_GREEN].analog);
uint8_t b = upscale_light(output->lights[light_idx + AC_IO_HDXS_BLUE].analog);
ddr_io_set_lights_hdxs_rgb(i, r, g, b);
}
}
void com4_init(void)
{
uint8_t i;
ac_io_emu_init(&com4_ac_io_emu, L"COM4");
ac_io_emu_hdxs_init(&com4_hdxs, &com4_ac_io_emu, lights_dispatcher);
for (i = 0; i < lengthof(com4_icca); i++) {
ac_io_emu_icca_init(&com4_icca[i], &com4_ac_io_emu, i);
}
}
void com4_fini(void)
{
ac_io_emu_fini(&com4_ac_io_emu);
}
HRESULT
com4_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&com4_ac_io_emu, irp)) {
return iohook_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&com4_ac_io_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&com4_ac_io_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&com4_ac_io_emu, msg, 3);
break;
case 1:
ac_io_emu_icca_dispatch_request(&com4_icca[0], msg);
break;
case 2:
ac_io_emu_icca_dispatch_request(&com4_icca[1], msg);
break;
case 3:
ac_io_emu_hdxs_dispatch_request(&com4_hdxs, msg);
break;
case AC_IO_BROADCAST:
log_warning("Broadcast(?) message on p3io ACIO bus?");
break;
default:
log_warning(
"p3io ACIO message on unhandled bus address: %d",
msg->addr);
break;
}
ac_io_emu_request_pop(&com4_ac_io_emu);
}
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef IIDXHOOK_COM4_H
#define IIDXHOOK_COM4_H
#include "hook/iohook.h"
void com4_init(void);
void com4_fini(void);
HRESULT com4_dispatch_irp(struct irp *irp);
#endif
+171
View File
@@ -0,0 +1,171 @@
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <devioctl.h>
#include <ntdef.h>
#include <ntddser.h>
// clang-format on
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "bemanitools/ddrio.h"
#include "hook/iohook.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/str.h"
static HRESULT extio_open(struct irp *irp);
static HRESULT extio_close(struct irp *irp);
static HRESULT extio_write(struct irp *irp);
static HRESULT extio_read(struct irp *irp);
static HRESULT extio_ioctl(struct irp *irp);
static HANDLE extio_fd;
static bool extio_pending;
void extio_init(void)
{
log_assert(extio_fd == NULL);
HRESULT hr;
hr = iohook_open_nul_fd(&extio_fd);
if (hr != S_OK) {
log_fatal("Opening nul fd failed: %08lx", hr);
}
}
void extio_fini(void)
{
if (extio_fd != NULL) {
CloseHandle(extio_fd);
}
extio_fd = NULL;
}
HRESULT
extio_dispatch_irp(struct irp *irp)
{
log_assert(irp != NULL);
if (irp->op != IRP_OP_OPEN && irp->fd != extio_fd) {
return iohook_invoke_next(irp);
}
switch (irp->op) {
case IRP_OP_OPEN:
return extio_open(irp);
case IRP_OP_CLOSE:
return extio_close(irp);
case IRP_OP_READ:
return extio_read(irp);
case IRP_OP_WRITE:
return extio_write(irp);
case IRP_OP_IOCTL:
return extio_ioctl(irp);
default:
return E_NOTIMPL;
}
}
static HRESULT extio_open(struct irp *irp)
{
log_assert(irp != NULL);
if (!wstr_eq(irp->open_filename, L"COM1")) {
return iohook_invoke_next(irp);
}
log_info("EXTIO RS232 port opened");
irp->fd = extio_fd;
return S_OK;
}
static HRESULT extio_close(struct irp *irp)
{
log_info("EXTIO RS232 port closed");
return S_OK;
}
static HRESULT extio_write(struct irp *irp)
{
const uint32_t *lights_be;
uint32_t lights;
log_assert(irp != NULL);
log_assert(irp->write.bytes != NULL);
if (irp->write.nbytes >= sizeof(lights)) {
lights_be = (const uint32_t *) irp->write.bytes;
lights = _byteswap_ulong(*lights_be);
ddr_io_set_lights_extio(lights);
extio_pending = true;
} else {
log_warning("Short EXTIO write");
}
irp->write.pos = irp->write.nbytes;
return S_OK;
}
static HRESULT extio_read(struct irp *irp)
{
log_assert(irp != NULL);
log_assert(irp->read.bytes != NULL);
if (extio_pending && irp->read.nbytes > 0) {
irp->read.bytes[0] = 0x11;
irp->read.pos = 1;
extio_pending = false;
}
return S_OK;
}
static HRESULT extio_ioctl(struct irp *irp)
{
SERIAL_STATUS *status;
log_assert(irp != NULL);
switch (irp->ioctl) {
case IOCTL_SERIAL_GET_COMMSTATUS:
if (irp->read.bytes == NULL) {
log_warning(
"IOCTL_SERIAL_GET_COMMSTATUS: Output buffer is NULL");
return E_INVALIDARG;
}
if (irp->read.nbytes < sizeof(*status)) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Buffer is too small");
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
status = (SERIAL_STATUS *) irp->read.bytes;
status->Errors = 0;
status->AmountInInQueue = extio_pending ? 1 : 0;
irp->read.pos = sizeof(*status);
break;
default:
break;
}
return S_OK;
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef DDRHOOK_EXTIO_H
#define DDRHOOK_EXTIO_H
#include <windows.h>
#include "hook/iohook.h"
void extio_init(void);
void extio_fini(void);
HRESULT extio_dispatch_irp(struct irp *irp);
#endif
+152
View File
@@ -0,0 +1,152 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "bemanitools/ddrio.h"
#include "ddrhook-util/p3io.h"
#include "p3ioemu/emu.h"
#include "p3ioemu/uart.h"
#include "util/log.h"
extern bool _15khz;
extern bool standard_def;
static HRESULT p3io_ddr_read_jamma(void *ctx, uint32_t *state);
static HRESULT p3io_ddr_set_outputs(void *ctx, uint32_t outputs);
static HRESULT p3io_ddr_get_cab_type(void *ctx, enum p3io_cab_type *type);
static HRESULT p3io_ddr_get_video_freq(void *ctx, enum p3io_video_freq *freq);
static HRESULT p3io_ddr_get_roundplug(
void *ctx, uint8_t plug_id, uint8_t *rom, uint8_t *eeprom);
static const struct p3io_ops p3io_ddr_ops = {
.read_jamma = p3io_ddr_read_jamma,
.set_outputs = p3io_ddr_set_outputs,
.get_cab_type = p3io_ddr_get_cab_type,
.get_video_freq = p3io_ddr_get_video_freq,
};
static const struct p3io_ops p3io_ddr_ops_with_plugs = {
.read_jamma = p3io_ddr_read_jamma,
.set_outputs = p3io_ddr_set_outputs,
.get_cab_type = p3io_ddr_get_cab_type,
.get_video_freq = p3io_ddr_get_video_freq,
.get_roundplug = p3io_ddr_get_roundplug,
};
static struct security_mcode p3io_ddr_mcode;
static struct security_id p3io_ddr_pcbid;
static struct security_id p3io_ddr_eamid;
static struct security_rp_sign_key p3io_black_sign_key;
static struct security_rp_sign_key p3io_white_sign_key;
void p3io_ddr_init(void)
{
/* COM4 isn't a real COM port, we configure the core P3IO emulator code to
generate IRPs addressed to COM4 and then we possibly intercept them in
_com4.c (or possibly don't, in which case the communications will be
sent to the real COM4 on your system) */
p3io_uart_set_path(0, L"COM4");
p3io_emu_init(&p3io_ddr_ops, NULL);
}
void p3io_ddr_init_with_plugs(
const struct security_mcode *mcode,
const struct security_id *pcbid,
const struct security_id *eamid,
const struct security_rp_sign_key *black_sign_key,
const struct security_rp_sign_key *white_sign_key)
{
memcpy(&p3io_ddr_mcode, mcode, sizeof(struct security_mcode));
memcpy(&p3io_ddr_pcbid, pcbid, sizeof(struct security_id));
memcpy(&p3io_ddr_eamid, eamid, sizeof(struct security_id));
memcpy(&p3io_black_sign_key, black_sign_key, sizeof(struct security_rp_sign_key));
memcpy(&p3io_white_sign_key, white_sign_key, sizeof(struct security_rp_sign_key));
/* COM4 isn't a real COM port, we configure the core P3IO emulator code to
generate IRPs addressed to COM4 and then we possibly intercept them in
_com4.c (or possibly don't, in which case the communications will be
sent to the real COM4 on your system) */
p3io_uart_set_path(0, L"COM4");
p3io_emu_init(&p3io_ddr_ops_with_plugs, NULL);
}
void p3io_ddr_fini(void)
{
p3io_emu_fini();
}
static HRESULT p3io_ddr_read_jamma(void *ctx, uint32_t *state)
{
log_assert(state != NULL);
*state = ddr_io_read_pad();
return S_OK;
}
static HRESULT p3io_ddr_set_outputs(void *ctx, uint32_t outputs)
{
ddr_io_set_lights_p3io(outputs);
return S_OK;
}
static HRESULT p3io_ddr_get_cab_type(void *ctx, enum p3io_cab_type *type)
{
if (standard_def) {
*type = P3IO_CAB_TYPE_SD;
} else {
*type = P3IO_CAB_TYPE_HD;
}
return S_OK;
}
static HRESULT p3io_ddr_get_video_freq(void *ctx, enum p3io_video_freq *freq)
{
if (_15khz) {
*freq = P3IO_VIDEO_FREQ_15KHZ;
} else {
*freq = P3IO_VIDEO_FREQ_31KHZ;
}
return S_OK;
}
static HRESULT p3io_ddr_get_roundplug(
void *ctx, uint8_t plug_id, uint8_t *rom, uint8_t *eeprom)
{
struct security_rp3_eeprom eeprom_out;
if (plug_id == 0) {
/* black */
memcpy(rom, p3io_ddr_pcbid.id, sizeof(p3io_ddr_pcbid.id));
security_rp3_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_BLACK,
&p3io_black_sign_key,
&p3io_ddr_mcode,
&p3io_ddr_pcbid,
&eeprom_out);
} else {
/* white */
memcpy(rom, p3io_ddr_eamid.id, sizeof(p3io_ddr_eamid.id));
security_rp3_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_WHITE,
&p3io_white_sign_key,
&security_mcode_eamuse,
&p3io_ddr_eamid,
&eeprom_out);
}
memcpy(eeprom, &eeprom_out, sizeof(struct security_rp3_eeprom));
return S_OK;
}
// TODO coinstock
+23
View File
@@ -0,0 +1,23 @@
#ifndef DDRHOOK_P3IO_H
#define DDRHOOK_P3IO_H
#include <windows.h>
#include "hook/iohook.h"
#include "security/rp-sign-key.h"
#include "security/rp3.h"
extern const wchar_t p3io_dev_node_prefix[];
extern const wchar_t p3io_dev_node[];
void p3io_ddr_init(void);
void p3io_ddr_init_with_plugs(
const struct security_mcode *mcode,
const struct security_id *pcbid,
const struct security_id *eamid,
const struct security_rp_sign_key *black_sign_key,
const struct security_rp_sign_key *white_sign_key);
void p3io_ddr_fini(void);
#endif
+178
View File
@@ -0,0 +1,178 @@
#define LOG_MODULE "spike"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <devioctl.h>
#include <ntdef.h>
#include <ntddser.h>
// clang-format on
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "acioemu/addr.h"
#include "acioemu/emu.h"
#include "hook/iohook.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
static struct ac_io_emu spike_ac_io_emu;
static void spike_handle_broadcast(const struct ac_io_message *bcast);
static void spike_handle_get_version(const struct ac_io_message *req);
static void spike_handle_status(const struct ac_io_message *req);
static void spike_send_empty(const struct ac_io_message *req);
void spike_init(void)
{
ac_io_emu_init(&spike_ac_io_emu, L"COM2");
}
void spike_fini(void)
{
ac_io_emu_fini(&spike_ac_io_emu);
}
HRESULT
spike_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&spike_ac_io_emu, irp)) {
return iohook_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&spike_ac_io_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&spike_ac_io_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&spike_ac_io_emu, msg, 7);
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
switch (ac_io_u16(msg->cmd.code)) {
case AC_IO_CMD_GET_VERSION:
spike_handle_get_version(msg);
break;
case AC_IO_CMD_START_UP:
spike_handle_status(msg);
break;
case AC_IO_CMD_KEEPALIVE:
spike_send_empty(msg);
break;
case 0x100:
case 0x110:
case 0x112:
case 0x128:
spike_handle_status(msg);
break;
default:
log_warning(
"Spike ACIO unhandled cmd: %04X",
ac_io_u16(msg->cmd.code));
}
break;
case AC_IO_BROADCAST:
spike_handle_broadcast(msg);
break;
default:
log_warning(
"Spike ACIO message on unhandled bus address: %d",
msg->addr);
break;
}
ac_io_emu_request_pop(&spike_ac_io_emu);
}
}
static void spike_handle_broadcast(const struct ac_io_message *bcast)
{
/* The payload consists of 7x10 byte chunks. Chunk 0 seems to correspond
to the front LED strip, and chunks 1-6 are the 2x3 spike bundles on the
side of a dedicab. No idea about the format of this data other than
that, try figuring it out if you're bored. */
}
static void spike_handle_get_version(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.version);
resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_LED_SPIKE);
resp.cmd.version.flag = 0x00;
resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x01;
resp.cmd.version.revision = 0x00;
memcpy(
resp.cmd.version.product_code,
"DDRS",
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
ac_io_emu_response_push(&spike_ac_io_emu, &resp, 0);
}
static void spike_handle_status(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.status);
resp.cmd.status = 0x00;
ac_io_emu_response_push(&spike_ac_io_emu, &resp, 0);
}
static void spike_send_empty(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = 0;
ac_io_emu_response_push(&spike_ac_io_emu, &resp, 0);
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef DDRHOOK_SPIKE_H
#define DDRHOOK_SPIKE_H
#include <windows.h>
#include "hook/iohook.h"
void spike_init(void);
void spike_fini(void);
HRESULT spike_dispatch_irp(struct irp *irp);
#endif
+204
View File
@@ -0,0 +1,204 @@
#define LOG_MODULE "usbmem"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <devioctl.h>
#include <ntdef.h>
#include <ntddser.h>
// clang-format on
#include <stdbool.h>
#include <string.h>
#include <wchar.h>
#include "hook/iohook.h"
#include "util/iobuf.h"
#include "util/log.h"
#include "util/str.h"
#define USBMEM_BUF_SIZE 128
static HANDLE usbmem_fd;
static char usbmem_response[USBMEM_BUF_SIZE];
static bool usbmem_pending;
static HRESULT usbmem_open(struct irp *irp);
static HRESULT usbmem_close(struct irp *irp);
static HRESULT usbmem_write(struct irp *irp);
static HRESULT usbmem_read(struct irp *irp);
static HRESULT usbmem_ioctl(struct irp *irp);
void usbmem_init(void)
{
log_assert(usbmem_fd == NULL);
HRESULT hr;
hr = iohook_open_nul_fd(&usbmem_fd);
if (hr != S_OK) {
log_fatal("Opening nul fd failed: %08lx", hr);
}
}
void usbmem_fini(void)
{
if (usbmem_fd != NULL) {
CloseHandle(usbmem_fd);
}
usbmem_fd = NULL;
}
HRESULT
usbmem_dispatch_irp(struct irp *irp)
{
log_assert(irp != NULL);
if (irp->op != IRP_OP_OPEN && irp->fd != usbmem_fd) {
return iohook_invoke_next(irp);
}
switch (irp->op) {
case IRP_OP_OPEN:
return usbmem_open(irp);
case IRP_OP_CLOSE:
return usbmem_close(irp);
case IRP_OP_READ:
return usbmem_read(irp);
case IRP_OP_WRITE:
return usbmem_write(irp);
case IRP_OP_IOCTL:
return usbmem_ioctl(irp);
default:
return E_NOTIMPL;
}
}
static HRESULT usbmem_open(struct irp *irp)
{
log_assert(irp != NULL);
if (!wstr_eq(irp->open_filename, L"COM3")) {
return iohook_invoke_next(irp);
}
irp->fd = usbmem_fd;
log_info("USB edit data PCB opened");
return S_OK;
}
static HRESULT usbmem_close(struct irp *irp)
{
log_info("USB edit data PCB closed");
return S_OK;
}
static HRESULT usbmem_write(struct irp *irp)
{
struct const_iobuf *src;
char request[USBMEM_BUF_SIZE];
uint32_t nbytes;
log_assert(irp != NULL);
log_assert(irp->write.bytes != NULL);
src = &irp->write;
nbytes = src->nbytes > USBMEM_BUF_SIZE ? USBMEM_BUF_SIZE : src->nbytes;
memcpy(request, src->bytes, nbytes);
request[nbytes - 1] = '\0'; /* This is always a CR. */
log_misc(">%s", request);
if (strlen(request) > 0) {
if (str_eq(request, "sver")) {
str_cpy(
usbmem_response,
sizeof(usbmem_response),
"done GQHDXJAA DJHACKRS");
} else if (
str_eq(request, "on_a") || str_eq(request, "on_b") ||
str_eq(request, "offa") || str_eq(request, "offb")) {
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
} else if (
strncmp(request, "lma ", 4) == 0 ||
strncmp(request, "lmb ", 4) == 0) {
str_cpy(usbmem_response, sizeof(usbmem_response), "done");
} else {
str_cpy(usbmem_response, sizeof(usbmem_response), "not connected");
}
}
usbmem_pending = true;
src->pos = nbytes;
return S_OK;
}
static HRESULT usbmem_read(struct irp *irp)
{
struct iobuf *dest;
uint32_t rlength;
log_assert(irp != NULL);
log_assert(irp->read.bytes != NULL);
dest = &irp->read;
if (usbmem_pending) {
if (strlen(usbmem_response) > 0) {
log_misc("%s", usbmem_response);
}
str_cat(usbmem_response, sizeof(usbmem_response), "\r>");
usbmem_pending = false;
}
rlength = strlen(usbmem_response);
memcpy(dest->bytes, usbmem_response, rlength);
memset(usbmem_response, 0, USBMEM_BUF_SIZE);
dest->pos = rlength;
return S_OK;
}
static HRESULT usbmem_ioctl(struct irp *irp)
{
SERIAL_STATUS *status;
log_assert(irp != NULL);
switch (irp->ioctl) {
case IOCTL_SERIAL_GET_COMMSTATUS:
if (irp->read.bytes == NULL) {
log_warning(
"IOCTL_SERIAL_GET_COMMSTATUS: Output buffer is NULL");
return E_INVALIDARG;
}
if (irp->read.nbytes < sizeof(*status)) {
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Buffer is too small");
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
status = (SERIAL_STATUS *) irp->read.bytes;
status->Errors = 0;
status->AmountInInQueue = usbmem_pending ? 1 : 0;
irp->read.pos = sizeof(*status);
break;
default:
break;
}
return S_OK;
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef HOOK_USBMEM_H
#define HOOK_USBMEM_H
void usbmem_init(void);
void usbmem_fini(void);
HRESULT usbmem_dispatch_irp(struct irp *irp);
#endif