2023-01-03 05:35:53 +01:00
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include "board/najv4.h"
|
|
|
|
|
|
|
|
#include "jvs/jvs-bus.h"
|
|
|
|
#include "jvs/jvs-cmd.h"
|
|
|
|
#include "jvs/jvs-util.h"
|
|
|
|
|
|
|
|
#include "util/dprintf.h"
|
|
|
|
#include "util/dump.h"
|
|
|
|
|
|
|
|
static void najv4_transact(
|
|
|
|
struct jvs_node *node,
|
|
|
|
const void *bytes,
|
|
|
|
size_t nbytes,
|
|
|
|
struct iobuf *resp);
|
|
|
|
|
|
|
|
static bool najv4_sense(struct jvs_node *node);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd(
|
|
|
|
void *ctx,
|
|
|
|
struct const_iobuf *req,
|
|
|
|
struct iobuf *resp);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_read_id(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_get_cmd_version(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_get_jvs_version(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_get_comm_version(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_get_features(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_write_pcb_info(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_read_switches(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_read_coin(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_read_analogs(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
2023-07-11 05:21:36 +02:00
|
|
|
static HRESULT najv4_cmd_analog_out(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
2023-01-03 05:35:53 +01:00
|
|
|
static HRESULT najv4_cmd_write_gpio(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_reset(struct najv4 *najv4, struct const_iobuf *buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_assign_addr(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_namco_extend_cmd(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_namco_extend_noop_cmd(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf);
|
|
|
|
|
|
|
|
static const uint8_t najv4_ident[] = "namco ltd.;NA-JV;Ver4.00;JPN,Multipurpose";
|
|
|
|
|
|
|
|
static uint8_t najv4_features[] = {
|
|
|
|
/* Feature : 0x01 : Players and switches
|
|
|
|
Param1 : 1 : Number of players
|
|
|
|
Param2 : 18 : Number of switches per player
|
|
|
|
Param3 : 0 : N/A */
|
|
|
|
|
|
|
|
0x01,
|
|
|
|
0x01,
|
|
|
|
0x18,
|
|
|
|
0x00,
|
|
|
|
|
|
|
|
/* Feature : 0x02 : Coin slots
|
|
|
|
Param1 : 2 : Number of coin slots
|
|
|
|
Param2 : 0 : N/A
|
|
|
|
Param3 : 0 : N/A */
|
|
|
|
|
|
|
|
0x02,
|
|
|
|
0x02,
|
|
|
|
0x00,
|
|
|
|
0x00,
|
|
|
|
|
|
|
|
/* Feature : 0x03 : Analog inputs
|
|
|
|
Param1 : 8 : Number of ADC channels
|
|
|
|
Param2 : 10 : Effective bits of resolution per ADC
|
|
|
|
Param3 : 0 : N/A */
|
|
|
|
|
|
|
|
0x03,
|
|
|
|
0x08,
|
|
|
|
0x10,
|
|
|
|
0x00,
|
|
|
|
|
|
|
|
/* Feature : 0x04 : Rotary Input
|
|
|
|
Param1 : 4 : Number of Rotary channels
|
|
|
|
Param2 : 0 : N/A
|
|
|
|
Param3 : 0 : N/A */
|
|
|
|
|
|
|
|
0x04,
|
|
|
|
0x04,
|
|
|
|
0x00,
|
|
|
|
0x00,
|
|
|
|
|
|
|
|
/* Feature : 0x12 : GPIO outputs
|
|
|
|
Param1 : 3 : Number of ports (8 bits per port)
|
|
|
|
Param2 : 0 : N/A
|
|
|
|
Param3 : 0 : N/A
|
|
|
|
*/
|
|
|
|
|
|
|
|
0x12,
|
|
|
|
0x12,
|
|
|
|
0x00,
|
|
|
|
0x00,
|
|
|
|
|
|
|
|
/* Feature : 0x13 : Analog outputs
|
|
|
|
Param1 : 2 : Number of channels
|
|
|
|
Param2 : 0 : N/A
|
|
|
|
Param3 : 0 : N/A
|
|
|
|
*/
|
|
|
|
|
|
|
|
0x13,
|
|
|
|
0x02,
|
|
|
|
0x00,
|
|
|
|
0x00,
|
|
|
|
|
|
|
|
/* Feature : 0x14 : Character Output
|
|
|
|
Param1 : 0x50 : Width
|
|
|
|
Param2 : 0x19 : Height
|
|
|
|
Param3 : 0 : Type
|
|
|
|
*/
|
|
|
|
0x14,
|
|
|
|
0x50,
|
|
|
|
0x19,
|
|
|
|
0x00,
|
|
|
|
|
|
|
|
/* Feature : 0x00 : End of capabilities */
|
|
|
|
|
|
|
|
0x00,
|
|
|
|
};
|
|
|
|
|
|
|
|
void najv4_init(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct jvs_node *next,
|
|
|
|
const struct najv4_ops *ops,
|
|
|
|
void *ops_ctx)
|
|
|
|
{
|
|
|
|
assert(najv4 != NULL);
|
|
|
|
assert(ops != NULL);
|
|
|
|
|
|
|
|
najv4->jvs.next = next;
|
|
|
|
najv4->jvs.transact = najv4_transact;
|
|
|
|
najv4->jvs.sense = najv4_sense;
|
|
|
|
najv4->addr = 0xFF;
|
|
|
|
najv4->ops = ops;
|
|
|
|
najv4->ops_ctx = ops_ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct jvs_node *najv4_to_jvs_node(struct najv4 *najv4)
|
|
|
|
{
|
|
|
|
assert(najv4 != NULL);
|
|
|
|
|
|
|
|
return &najv4->jvs;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void najv4_transact(
|
|
|
|
struct jvs_node *node,
|
|
|
|
const void *bytes,
|
|
|
|
size_t nbytes,
|
|
|
|
struct iobuf *resp)
|
|
|
|
{
|
|
|
|
struct najv4 *najv4;
|
|
|
|
|
|
|
|
assert(node != NULL);
|
|
|
|
assert(bytes != NULL);
|
|
|
|
assert(resp != NULL);
|
|
|
|
|
|
|
|
najv4 = CONTAINING_RECORD(node, struct najv4, jvs);
|
|
|
|
|
|
|
|
jvs_crack_request(bytes, nbytes, resp, najv4->addr, najv4_cmd, najv4);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool najv4_sense(struct jvs_node *node)
|
|
|
|
{
|
|
|
|
struct najv4 *najv4;
|
|
|
|
|
|
|
|
assert(node != NULL);
|
|
|
|
|
|
|
|
najv4 = CONTAINING_RECORD(node, struct najv4, jvs);
|
|
|
|
|
|
|
|
return najv4->addr == 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd(
|
|
|
|
void *ctx,
|
|
|
|
struct const_iobuf *req,
|
|
|
|
struct iobuf *resp)
|
|
|
|
{
|
|
|
|
struct najv4 *najv4;
|
|
|
|
|
|
|
|
najv4 = ctx;
|
|
|
|
|
|
|
|
switch (req->bytes[req->pos]) {
|
|
|
|
case JVS_CMD_READ_ID:
|
|
|
|
return najv4_cmd_read_id(najv4, req, resp);
|
|
|
|
|
|
|
|
case JVS_CMD_GET_CMD_VERSION:
|
|
|
|
return najv4_cmd_get_cmd_version(najv4, req, resp);
|
|
|
|
|
|
|
|
case JVS_CMD_GET_JVS_VERSION:
|
|
|
|
return najv4_cmd_get_jvs_version(najv4, req, resp);
|
|
|
|
|
|
|
|
case JVS_CMD_GET_COMM_VERSION:
|
|
|
|
return najv4_cmd_get_comm_version(najv4, req, resp);
|
|
|
|
|
|
|
|
case JVS_CMD_GET_FEATURES:
|
|
|
|
return najv4_cmd_get_features(najv4, req, resp);
|
|
|
|
|
|
|
|
case JVS_CMD_WRITE_PCB_INFO:
|
|
|
|
return najv4_cmd_write_pcb_info(najv4, req, resp);
|
|
|
|
|
|
|
|
case JVS_CMD_READ_SWITCHES:
|
|
|
|
return najv4_cmd_read_switches(najv4, req, resp);
|
|
|
|
|
|
|
|
case JVS_CMD_READ_COIN:
|
|
|
|
return najv4_cmd_read_coin(najv4, req, resp);
|
|
|
|
|
|
|
|
case JVS_CMD_READ_ANALOGS:
|
|
|
|
return najv4_cmd_read_analogs(najv4, req, resp);
|
|
|
|
|
2023-07-11 05:21:36 +02:00
|
|
|
case JVS_CMD_ANALOG_OUT:
|
|
|
|
return najv4_cmd_analog_out(najv4, req, resp);
|
|
|
|
|
2023-01-03 05:35:53 +01:00
|
|
|
case JVS_CMD_WRITE_GPIO:
|
|
|
|
return najv4_cmd_write_gpio(najv4, req, resp);
|
|
|
|
|
|
|
|
case JVS_CMD_RESET:
|
|
|
|
return najv4_cmd_reset(najv4, req);
|
|
|
|
|
|
|
|
case JVS_CMD_ASSIGN_ADDR:
|
|
|
|
return najv4_cmd_assign_addr(najv4, req, resp);
|
|
|
|
|
|
|
|
case JVS_CMD_NAMCO_EXTEND:
|
|
|
|
return najv4_cmd_namco_extend_cmd(najv4, req, resp);
|
|
|
|
|
|
|
|
default:
|
|
|
|
dprintf("JVS I/O: Node %02x: Unhandled command byte %02x\n",
|
|
|
|
najv4->addr,
|
|
|
|
req->bytes[req->pos]);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_read_id(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
uint8_t req;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
hr = iobuf_read_8(req_buf, &req);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
dprintf("JVS I/O: Read ID\n");
|
|
|
|
|
|
|
|
/* Write report byte */
|
|
|
|
|
|
|
|
hr = iobuf_write_8(resp_buf, 0x01);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write the identification string. The NUL terminator at the end of this C
|
|
|
|
string is also sent, and it naturally terminates the response chunk. */
|
|
|
|
|
|
|
|
return iobuf_write(resp_buf, najv4_ident, sizeof(najv4_ident));
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_get_cmd_version(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
uint8_t req;
|
|
|
|
uint8_t resp[2];
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
hr = iobuf_read_8(req_buf, &req);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
dprintf("JVS I/O: Get command format version\n");
|
|
|
|
resp[0] = 0x01; /* Report byte */
|
|
|
|
resp[1] = 0x13; /* Command format version BCD */
|
|
|
|
|
|
|
|
return iobuf_write(resp_buf, resp, sizeof(resp));
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_get_jvs_version(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
uint8_t req;
|
|
|
|
uint8_t resp[2];
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
hr = iobuf_read_8(req_buf, &req);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
dprintf("JVS I/O: Get JVS version\n");
|
|
|
|
resp[0] = 0x01; /* Report byte */
|
|
|
|
resp[1] = 0x31; /* JVS version BCD */
|
|
|
|
|
|
|
|
return iobuf_write(resp_buf, resp, sizeof(resp));
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_get_comm_version(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
uint8_t req;
|
|
|
|
uint8_t resp[2];
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
hr = iobuf_read_8(req_buf, &req);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
dprintf("JVS I/O: Get communication version\n");
|
|
|
|
resp[0] = 0x01; /* Report byte */
|
|
|
|
resp[1] = 0x10; /* "Communication version" BCD */
|
|
|
|
|
|
|
|
return iobuf_write(resp_buf, resp, sizeof(resp));
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_get_features(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
uint8_t req;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
hr = iobuf_read_8(req_buf, &req);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
dprintf("JVS I/O: Get features\n");
|
|
|
|
|
|
|
|
hr = iobuf_write_8(resp_buf, 0x01); /* Write report byte */
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return iobuf_write(resp_buf, najv4_features, sizeof(najv4_features));
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_write_pcb_info(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
uint8_t strlen = (int)req_buf->nbytes - 4; // subtract 2 bytes at the begining, command byte, and sync byte
|
|
|
|
uint8_t cmd;
|
|
|
|
uint8_t info[100]; // No more then 100 characters
|
|
|
|
|
|
|
|
dprintf("JVS I/O: PCB Info ");
|
|
|
|
|
|
|
|
iobuf_read_8(req_buf, &cmd);
|
|
|
|
|
|
|
|
iobuf_read(req_buf, info, strlen);
|
|
|
|
dprintf("%s\n", info);
|
|
|
|
|
|
|
|
// Just acknowlage we read it
|
|
|
|
return iobuf_write_8(resp_buf, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_read_switches(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
struct jvs_req_read_switches req;
|
|
|
|
struct najv4_switch_state state;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
/* Read req */
|
|
|
|
|
|
|
|
hr = iobuf_read(req_buf, &req, sizeof(req));
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
dprintf("JVS I/O: Read switches, np=%i, bpp=%i\n",
|
|
|
|
req.num_players,
|
|
|
|
req.bytes_per_player);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Build response */
|
|
|
|
|
|
|
|
hr = iobuf_write_8(resp_buf, 0x01); /* Report byte */
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&state, 0, sizeof(state));
|
|
|
|
|
|
|
|
if (najv4->ops != NULL) {
|
|
|
|
najv4->ops->read_switches(najv4->ops_ctx, &state);
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = iobuf_write_8(resp_buf, state.system); /* Test, Tilt lines */
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (req.num_players > 0) {
|
|
|
|
hr = iobuf_write_be16(resp_buf, state.p1);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (req.num_players > 1) {
|
|
|
|
hr = iobuf_write_be16(resp_buf, state.p2);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = iobuf_write_8(resp_buf, 0x00); // Not sure what this byte is but it needs to be here
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_read_coin(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
struct jvs_req_read_coin req;
|
|
|
|
uint16_t ncoins;
|
|
|
|
uint8_t i;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
/* Read req */
|
|
|
|
|
|
|
|
hr = iobuf_read(req_buf, &req, sizeof(req));
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//dprintf("JVS I/O: Read coin, nslots=%i\n", req.nslots);
|
|
|
|
|
|
|
|
/* Write report byte */
|
|
|
|
|
|
|
|
hr = iobuf_write_8(resp_buf, 0x01);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write slot detail */
|
|
|
|
|
|
|
|
for (i = 0 ; i < req.nslots ; i++) {
|
|
|
|
ncoins = 0;
|
|
|
|
if (najv4->ops->read_coin_counter != NULL) {
|
|
|
|
najv4->ops->read_coin_counter(najv4->ops_ctx, i, &ncoins);
|
|
|
|
}
|
|
|
|
hr = iobuf_write_be16(resp_buf, ncoins);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_read_analogs(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
struct jvs_req_read_analogs req;
|
|
|
|
uint16_t analogs[8];
|
|
|
|
uint8_t i;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
/* Read req */
|
|
|
|
|
|
|
|
hr = iobuf_read(req_buf, &req, sizeof(req));
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (req.nanalogs > _countof(analogs)) {
|
|
|
|
dprintf("JVS I/O: Invalid analog count %i\n", req.nanalogs);
|
|
|
|
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//dprintf("JVS I/O: Read analogs, nanalogs=%i\n", req.nanalogs);
|
|
|
|
|
|
|
|
/* Write report byte */
|
|
|
|
|
|
|
|
hr = iobuf_write_8(resp_buf, 0x01);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write analogs */
|
|
|
|
|
|
|
|
memset(analogs, 0, sizeof(analogs));
|
|
|
|
|
|
|
|
if (najv4->ops->read_analogs != NULL) {
|
|
|
|
najv4->ops->read_analogs(najv4->ops_ctx, analogs, req.nanalogs);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0 ; i < req.nanalogs ; i++) {
|
|
|
|
hr = iobuf_write_be16(resp_buf, analogs[i]);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-07-11 05:21:36 +02:00
|
|
|
static HRESULT najv4_cmd_analog_out(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
uint8_t cmd;
|
|
|
|
uint8_t channel_ct;
|
|
|
|
uint16_t bytes[MAX_PATH];
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
hr = iobuf_read_8(req_buf, &cmd);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = iobuf_read_8(req_buf, &channel_ct);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < channel_ct; i++) {
|
|
|
|
iobuf_read_be16(req_buf, &bytes[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//dprintf("JVS I/O: Write Analog Out to %d channels\n", channel_ct);
|
|
|
|
|
|
|
|
return iobuf_write_8(resp_buf, 0x01);
|
|
|
|
}
|
|
|
|
|
2023-01-03 05:35:53 +01:00
|
|
|
static HRESULT najv4_cmd_write_gpio(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
uint8_t cmd;
|
|
|
|
uint8_t nbytes;
|
|
|
|
uint8_t bytes[3];
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
/* Read request header */
|
|
|
|
|
|
|
|
hr = iobuf_read_8(req_buf, &cmd);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = iobuf_read_8(req_buf, &nbytes);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nbytes > 3) {
|
|
|
|
dprintf("JVS I/O: Invalid GPIO write size %i\n", nbytes);
|
|
|
|
hr = iobuf_write_8(resp_buf, 0x02);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read payload */
|
|
|
|
|
|
|
|
memset(bytes, 0, sizeof(bytes));
|
|
|
|
hr = iobuf_read(req_buf, bytes, nbytes);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (najv4->ops->write_gpio != NULL) {
|
|
|
|
najv4->ops->write_gpio(
|
|
|
|
najv4->ops_ctx,
|
|
|
|
bytes[0] | (bytes[1] << 8) | (bytes[2] << 16));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write report byte */
|
|
|
|
|
|
|
|
return iobuf_write_8(resp_buf, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_reset(struct najv4 *najv4, struct const_iobuf *req_buf)
|
|
|
|
{
|
|
|
|
struct jvs_req_reset req;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
hr = iobuf_read(req_buf, &req, sizeof(req));
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
dprintf("JVS I/O: Reset (param %02x)\n", req.unknown);
|
|
|
|
najv4->addr = 0xFF;
|
|
|
|
|
|
|
|
if (najv4->ops->reset != NULL) {
|
|
|
|
najv4->ops->reset(najv4->ops_ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No ack for this since it really is addressed to everybody */
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_assign_addr(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
struct jvs_req_assign_addr req;
|
|
|
|
bool sense;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
hr = iobuf_read(req_buf, &req, sizeof(req));
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
sense = jvs_node_sense(najv4->jvs.next);
|
|
|
|
dprintf("JVS I/O: Assign addr %02x sense %i\n", req.addr, sense);
|
|
|
|
|
|
|
|
if (sense) {
|
|
|
|
/* That address is for somebody else */
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
najv4->addr = req.addr;
|
|
|
|
|
|
|
|
return iobuf_write_8(resp_buf, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_namco_extend_cmd(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
switch(req_buf->bytes[req_buf->pos + 1]) {
|
|
|
|
case JVS_NAMCO_EXTEND_CMD_NOOP_18:
|
|
|
|
return najv4_cmd_namco_extend_noop_cmd(najv4, req_buf, resp_buf);
|
|
|
|
default:
|
|
|
|
dprintf("JVS I/O: Node %X Unknown Namco Extended command %X\n",
|
|
|
|
najv4->addr,
|
|
|
|
req_buf->bytes[req_buf->pos + 1]);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT najv4_cmd_namco_extend_noop_cmd(
|
|
|
|
struct najv4 *najv4,
|
|
|
|
struct const_iobuf *req_buf,
|
|
|
|
struct iobuf *resp_buf)
|
|
|
|
{
|
|
|
|
uint8_t strlen = (int)req_buf->nbytes - 9;
|
|
|
|
uint8_t info[100];
|
|
|
|
uint8_t cmd;
|
|
|
|
uint8_t subcmd;
|
|
|
|
uint16_t hardcode;
|
|
|
|
uint16_t param;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
hr = iobuf_read_8(req_buf, &cmd); // cmd (0x70)
|
|
|
|
hr = iobuf_read_8(req_buf, &subcmd); // subcmd (0x18)
|
|
|
|
hr = iobuf_read_be16(req_buf, &hardcode); // some constant (0x504c)
|
|
|
|
hr = iobuf_read_be16(req_buf, ¶m); // param1
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
dprintf("JVS I/O: Namco Extended Command 0x18 param: %X", param);
|
|
|
|
|
|
|
|
switch (param) {
|
|
|
|
case 0x14d0: // read some string
|
|
|
|
hr = iobuf_read(req_buf, info, strlen);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
dprintf("\t%s\n", info);
|
|
|
|
|
|
|
|
return iobuf_write_8(resp_buf, 1);
|
|
|
|
|
2023-07-11 05:21:36 +02:00
|
|
|
case 0x14B4:
|
2023-01-03 05:35:53 +01:00
|
|
|
case 0x143c: // Run it back??
|
|
|
|
hr = iobuf_read_8(req_buf, &cmd); // cmd (0x70)
|
|
|
|
hr = iobuf_read_8(req_buf, &subcmd); // subcmd (0x18)
|
|
|
|
hr = iobuf_read_be16(req_buf, &hardcode); // some constant (0x504c)
|
|
|
|
hr = iobuf_read_be16(req_buf, ¶m); // param1
|
|
|
|
|
|
|
|
dprintf("\tsecond param: %X\n", param);
|
|
|
|
|
|
|
|
return iobuf_write_8(resp_buf, 1);
|
|
|
|
|
|
|
|
default:
|
2023-07-11 05:21:36 +02:00
|
|
|
dprintf("\nJVS I/O: Namco Extended Command 0x18 param unknown! %04X\n", param);
|
2023-01-03 05:35:53 +01:00
|
|
|
dump_const_iobuf(req_buf);
|
|
|
|
|
|
|
|
return iobuf_write_8(resp_buf, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|