IO device shows as connected, no auto read tho

This commit is contained in:
Hay1tsme 2022-01-07 21:16:33 -05:00
parent 5bfd5ae850
commit 0d3e93ce82
2 changed files with 259 additions and 21 deletions

View File

@ -28,9 +28,17 @@ static HRESULT touch1_handle_irp_locked(struct irp *irp);
static HRESULT touch_req_dispatch(const struct touch_req *req); static HRESULT touch_req_dispatch(const struct touch_req *req);
static HRESULT touch_frame_decode(struct touch_req *dest, struct iobuf *iobuf, int side); static HRESULT touch_frame_decode(struct touch_req *dest, struct iobuf *iobuf, int side);
static HRESULT touch_frame_encode(struct iobuf *dest, const void *ptr, size_t nbytes);
static uint8_t calc_checksum(const void *ptr, size_t nbytes);
static HRESULT touch_handle_get_rev_date(const struct touch_req *req); static HRESULT touch_handle_get_rev_date(const struct touch_req *req);
static HRESULT touch_handle_startup(const struct touch_req *req); static HRESULT touch_handle_startup(const struct touch_req *req);
static HRESULT touch_handle_get_rev_date_detail(const struct touch_req *req);
static HRESULT touch_handle_mystery1(const struct touch_req *req);
static HRESULT touch_handle_mystery2(const struct touch_req *req);
static HRESULT touch_handle_start_auto_scan(const struct touch_req *req);
uint8_t input_frame_count = 0x7b;
static CRITICAL_SECTION touch0_lock; static CRITICAL_SECTION touch0_lock;
static struct uart touch0_uart; static struct uart touch0_uart;
@ -43,9 +51,9 @@ static uint8_t touch1_written_bytes[520];
static uint8_t touch1_readable_bytes[520]; static uint8_t touch1_readable_bytes[520];
HRESULT touch_hook_init(const struct touch_config *cfg) HRESULT touch_hook_init(const struct touch_config *cfg)
{ {
assert(cfg != NULL); assert(cfg != NULL);
assert(mercury_dll.touch_init != NULL); assert(mercury_dll.touch_init != NULL);
// not sure why this always returns false... // not sure why this always returns false...
/*if (!cfg->enable) { /*if (!cfg->enable) {
@ -82,7 +90,7 @@ static HRESULT touch_handle_irp(struct irp *irp)
hr = touch0_handle_irp_locked(irp); hr = touch0_handle_irp_locked(irp);
LeaveCriticalSection(&touch0_lock); LeaveCriticalSection(&touch0_lock);
} }
else if (uart_match_irp(&touch1_uart, irp)) { else if (uart_match_irp(&touch1_uart, irp)) {
EnterCriticalSection(&touch1_lock); EnterCriticalSection(&touch1_lock);
hr = touch1_handle_irp_locked(irp); hr = touch1_handle_irp_locked(irp);
LeaveCriticalSection(&touch1_lock); LeaveCriticalSection(&touch1_lock);
@ -117,7 +125,7 @@ static HRESULT touch0_handle_irp_locked(struct irp *irp)
} }
for (;;) { for (;;) {
#if 1 #if 0
dprintf("TX0 Buffer:\n"); dprintf("TX0 Buffer:\n");
dump_iobuf(&touch0_uart.written); dump_iobuf(&touch0_uart.written);
#endif #endif
@ -164,7 +172,7 @@ static HRESULT touch1_handle_irp_locked(struct irp *irp)
} }
for (;;) { for (;;) {
#if 1 #if 0
dprintf("TX1 Buffer:\n"); dprintf("TX1 Buffer:\n");
dump_iobuf(&touch1_uart.written); dump_iobuf(&touch1_uart.written);
#endif #endif
@ -196,37 +204,191 @@ static HRESULT touch_req_dispatch(const struct touch_req *req)
return touch_handle_get_rev_date(req); return touch_handle_get_rev_date(req);
case CMD_STARTUP: case CMD_STARTUP:
return touch_handle_startup(req); return touch_handle_startup(req);
case CMD_GET_REV_DATE_DETAIL:
return touch_handle_get_rev_date_detail(req);
case CMD_MYSTERY1:
return touch_handle_mystery1(req);
case CMD_MYSTERY2:
return touch_handle_mystery2(req);
case CMD_START_AUTO_SCAN:
return touch_handle_start_auto_scan(req);
case CMD_BEGIN_WRITE:
dprintf("Wacca touch: Begin write for side %d\n", req->side);
return S_OK;
case CMD_NEXT_WRITE:
dprintf("Wacca touch: continue write for side %d\n", req->side);
return S_OK;
default: default:
dprintf("Wacca touch: Unhandled command %02x\n", req->cmd); dprintf("Wacca touch: Unhandled command %02x\n", req->cmd);
return S_OK; return S_OK;
} }
} }
static HRESULT touch_handle_get_rev_date(const struct touch_req *req) static HRESULT touch_handle_get_rev_date(const struct touch_req *req)
{ {
struct touch_resp_get_rev_date resp;
HRESULT hr;
uint8_t rev[6] = { 0x31, 0x39, 0x30, 0x35, 0x32, 0x33 };
dprintf("Wacca Touch%d: Get board rev date\n", req->side); dprintf("Wacca Touch%d: Get board rev date\n", req->side);
resp.cmd = 0xa0;
memcpy(resp.data, rev, sizeof(rev));
//resp.data = rev;
if (req->side == 0) { if (req->side == 0) {
// TODO: a0 31 39 30 35 32 33 2c hr = touch_frame_encode(&touch0_uart.readable, &resp, sizeof(resp));
} }
else { else {
// TODO: see above hr = touch_frame_encode(&touch1_uart.readable, &resp, sizeof(resp));
} }
return S_OK; return hr;
} }
/* TODO: Very ugly please make better before upstreaming */
static HRESULT touch_handle_startup(const struct touch_req *req) static HRESULT touch_handle_startup(const struct touch_req *req)
{ {
struct touch_resp_startup resp;
HRESULT hr;
uint8_t *rev;
dprintf("Wacca Touch%d: Startup\n", req->side); dprintf("Wacca Touch%d: Startup\n", req->side);
if (req->side == 0) {
// TODO: 20 20 20 20 30 20 20 20 20 30 20 20 20 20 31 20 20 20 20 32 20 20 20 20 33 20 20 20 20 34 20 20 20 20 35 20 20 20 31 35 20 20 20 31 35 20 20 20 31 35 20 20 20 31 35 20 20 20 31 35 20 20 20 31 35 20 20 20 31 31 20 20 20 31 31 20 20 20 31 31 0d switch (req->data[2]) {
case 0x30:
rev = (uint8_t[80]) { 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20,
0x20, 0x20, 0x20, 0x31, 0x20, 0x20, 0x20, 0x20, 0x32, 0x20, 0x20, 0x20, 0x20,
0x33, 0x20, 0x20, 0x20, 0x20, 0x34, 0x20, 0x20, 0x20, 0x20, 0x35, 0x20, 0x20,
0x20, 0x31, 0x35, 0x20, 0x20, 0x20, 0x31, 0x35, 0x20, 0x20, 0x20, 0x31, 0x35,
0x20, 0x20, 0x20, 0x31, 0x35, 0x20, 0x20, 0x20, 0x31, 0x35, 0x20, 0x20, 0x20,
0x31, 0x35, 0x20, 0x20, 0x20, 0x31, 0x31, 0x20, 0x20, 0x20, 0x31, 0x31, 0x20,
0x20, 0x20, 0x31, 0x31 };
break;
case 0x31:
rev = (uint8_t[80]) { 0x20, 0x20, 0x20, 0x31, 0x31, 0x20, 0x20, 0x20, 0x31, 0x31, 0x20,
0x20, 0x20, 0x31, 0x31, 0x20, 0x20, 0x31, 0x32, 0x38, 0x20, 0x20, 0x31, 0x30,
0x33, 0x20, 0x20, 0x31, 0x30, 0x33, 0x20, 0x20, 0x31, 0x31, 0x35, 0x20, 0x20,
0x31, 0x33, 0x38, 0x20, 0x20, 0x31, 0x32, 0x37, 0x20, 0x20, 0x31, 0x30, 0x33,
0x20, 0x20, 0x31, 0x30, 0x35, 0x20, 0x20, 0x31, 0x31, 0x31, 0x20, 0x20, 0x31,
0x32, 0x36, 0x20, 0x20, 0x31, 0x31, 0x33, 0x20, 0x20, 0x20, 0x39, 0x35, 0x20,
0x20, 0x31, 0x30, 0x30 };
break;
case 0x33:
rev = (uint8_t[80]) { 0x20, 0x20, 0x31, 0x30, 0x31, 0x20, 0x20, 0x31, 0x31, 0x35, 0x20,
0x20, 0x20, 0x39, 0x38, 0x20, 0x20, 0x20, 0x38, 0x36, 0x20, 0x20, 0x20, 0x37,
0x36, 0x20, 0x20, 0x20, 0x36, 0x37, 0x20, 0x20, 0x20, 0x36, 0x38, 0x20, 0x20,
0x20, 0x34, 0x38, 0x20, 0x20, 0x31, 0x31, 0x37, 0x20, 0x20, 0x20, 0x20, 0x30,
0x20, 0x20, 0x20, 0x38, 0x32, 0x20, 0x20, 0x31, 0x35, 0x34, 0x20, 0x20, 0x20,
0x20, 0x30, 0x20, 0x20, 0x20, 0x20, 0x36, 0x20, 0x20, 0x20, 0x33, 0x35, 0x20,
0x20, 0x20, 0x20, 0x34 };
break;
default:
dprintf("Wacca touch: BAD STARTUP REQUEST %2hx\n", req->data[2]);
return 1;
}
memcpy(resp.data, rev, 80 * sizeof(uint8_t));
if (req->side == 0) {
hr = touch_frame_encode(&touch0_uart.readable, &resp, sizeof(resp));
} }
else { else {
// TODO: see above hr = touch_frame_encode(&touch1_uart.readable, &resp, sizeof(resp));
} }
return S_OK; return hr;
} }
static HRESULT touch_handle_get_rev_date_detail(const struct touch_req *req)
{
struct touch_resp_get_rev_date_detail resp;
HRESULT hr;
uint8_t rev[43] = { 0x31, 0x39, 0x30, 0x35, 0x32, 0x33, 0x52, 0x31,
0x39, 0x30, 0x35, 0x31, 0x34, 0x31, 0x39, 0x30, 0x35, 0x31, 0x34, 0x31,
0x39, 0x30, 0x35, 0x31, 0x34, 0x31, 0x39, 0x30, 0x35, 0x31, 0x34, 0x31,
0x39, 0x30, 0x35, 0x31, 0x34, 0x31, 0x39, 0x30, 0x35, 0x31, 0x34 };
dprintf("Wacca Touch%d: get rev date detail\n", req->side);
resp.cmd = 0xa8;
memcpy(resp.data, rev, sizeof(rev));
if (req->side == 0) {
hr = touch_frame_encode(&touch0_uart.readable, &resp, sizeof(resp));
}
else {
hr = touch_frame_encode(&touch1_uart.readable, &resp, sizeof(resp));
}
return hr;
}
static HRESULT touch_handle_mystery1(const struct touch_req *req)
{
struct touch_resp_mystery1 resp;
HRESULT hr;
dprintf("Wacca Touch%d: mystery command 1\n", req->side);
resp.cmd = 0xa2;
resp.data = 0x3f;
if (req->side == 0) {
hr = touch_frame_encode(&touch0_uart.readable, &resp, sizeof(resp));
}
else {
hr = touch_frame_encode(&touch1_uart.readable, &resp, sizeof(resp));
}
return hr;
}
static HRESULT touch_handle_mystery2(const struct touch_req *req)
{
struct touch_resp_mystery2 resp;
HRESULT hr;
dprintf("Wacca Touch%d: mystery command 2\n", req->side);
resp.cmd = 0x94;
resp.data = 0;
if (req->side == 0) {
hr = touch_frame_encode(&touch0_uart.readable, &resp, sizeof(resp));
}
else {
hr = touch_frame_encode(&touch1_uart.readable, &resp, sizeof(resp));
}
return hr;
}
static HRESULT touch_handle_start_auto_scan(const struct touch_req *req)
{
struct touch_resp_start_auto resp;
HRESULT hr;
uint8_t data1[24] = { 0 };
uint8_t data2[9] = { 0x0d, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00 };
dprintf("Wacca Touch%d: Start Auto\n", req->side);
resp.cmd = 0x9c;
resp.data = 0;
resp.checksum = 0x49;
resp.frame.cmd= 0x81;
resp.frame.count = input_frame_count++;
memcpy(resp.frame.data1, data1, sizeof(data1));
memcpy(resp.frame.data2, data2, sizeof(data2));
resp.frame.checksum = calc_checksum(&resp.frame, sizeof(resp.frame));
if (req->side == 0) {
hr = touch_frame_encode(&touch0_uart.readable, &resp, sizeof(resp));
}
else {
hr = touch_frame_encode(&touch1_uart.readable, &resp, sizeof(resp));
}
return hr;
}
/* Decodes the response into a struct that's easier to work with. */
static HRESULT touch_frame_decode(struct touch_req *dest, struct iobuf *iobuf, int side) static HRESULT touch_frame_decode(struct touch_req *dest, struct iobuf *iobuf, int side)
{ {
dest->side = side; dest->side = side;
@ -243,3 +405,39 @@ static HRESULT touch_frame_decode(struct touch_req *dest, struct iobuf *iobuf, i
return S_OK; return S_OK;
} }
/* Encode and send the response.
* The last byte of every response is a checksum.
* This checksum is calculated by bitwise XORing
* every byte in the response, then dropping the MSB.
* Thanks the CrazyRedMachine for figuring that out!!
*/
static HRESULT touch_frame_encode(struct iobuf *dest, const void *ptr, size_t nbytes)
{
const uint8_t *src;
uint8_t checksum = 0;
src = ptr;
for (size_t i = 0; i < nbytes; i++) {
dest->bytes[dest->pos++] = src[i];
checksum = checksum^(src[i]);
}
dest->bytes[dest->pos++] = checksum&0x7f;
return S_OK;
}
static uint8_t calc_checksum(const void *ptr, size_t nbytes)
{
const uint8_t *src;
uint8_t checksum = 0;
src = ptr;
for (size_t i = 0; i < nbytes; i++) {
checksum = checksum^(src[i]);
}
return checksum&0x7f;
}

View File

@ -12,20 +12,60 @@ enum touch_cmd {
CMD_GET_REV_DATE = 0xa0, CMD_GET_REV_DATE = 0xa0,
CMD_STARTUP = 0x72, CMD_STARTUP = 0x72,
CMD_GET_REV_DATE_DETAIL = 0xa8, CMD_GET_REV_DATE_DETAIL = 0xa8,
CMD_UNKNOWN1 = 0xa2, CMD_MYSTERY1 = 0xa2,
CMD_UNKNOWN2 = 0x94, CMD_MYSTERY2 = 0x94,
CMD_START_AUTO = 0xc9 CMD_START_AUTO_SCAN = 0xc9,
CMD_BEGIN_WRITE = 0x77,
CMD_NEXT_WRITE = 0x20
}; };
struct touch_req { struct touch_req {
int side; uint8_t side; // COM3 or COM4
int cmd; // First byte is the command byte uint8_t cmd; // First byte is the command byte
int data[256]; // rest of the data goes here uint8_t data[256]; // rest of the data goes here
int data_length; // Size of the data including command byte uint8_t data_length; // Size of the data including command byte
}; };
// The checksum is only calculated when we're about to send it so
// it's not part of any of these structs. Just note that the last
// byte of every response is a checksum
struct touch_input_frame { struct touch_input_frame {
int data[36]; uint8_t cmd;
uint8_t data1[24];
uint8_t data2[9];
uint8_t count;
uint8_t checksum;
};
struct touch_resp_get_rev_date {
uint8_t cmd;
uint8_t data[6];
};
struct touch_resp_startup {
uint8_t data[80];
};
struct touch_resp_get_rev_date_detail {
uint8_t cmd;
uint8_t data[43];
};
struct touch_resp_mystery1 {
uint8_t cmd;
uint8_t data;
};
struct touch_resp_mystery2 {
uint8_t cmd;
uint8_t data;
};
struct touch_resp_start_auto {
uint8_t cmd;
uint8_t data;
uint8_t checksum;
struct touch_input_frame frame;
}; };
HRESULT touch_hook_init(const struct touch_config *cfg); HRESULT touch_hook_init(const struct touch_config *cfg);