This repository has been archived on 2022-09-26. You can view files and clone it, but cannot push or open issues or pull requests.
spyderta/win/shim.c

370 lines
7.9 KiB
C

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "sdnet.h"
#define export __declspec(dllexport)
#define ADDR "192.168.1.1"
#define PORT 1394
static FILE *log;
static SOCKET sock = INVALID_SOCKET;
static WSADATA wsd;
static FILE *makelog(void) {
char buf[128];
time_t t = time(NULL);
snprintf(buf, sizeof(buf), "logfile-%lu.txt", (unsigned long) t);
return fopen(buf, "w");
}
static SOCKET makesock(void) {
struct addrinfo hints, *ai, *p;
SOCKET s;
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
fputs(log, "wsa\n");
return INVALID_SOCKET;
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(ADDR, PORT, &hints, &ai) != 0) {
fputs(log, "getaddrinfo\n");
return INVALID_SOCKET;
}
for (p = ai; p; p = p->ai_next) {
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (s == INVALID_SOCKET)
continue;
if (connect(s, p->ai_addr, (int)->ai_addrlen) == SOCKET_ERROR) {
closesocket(s);
continue;
}
break;
}
freeaddrinfo(ai);
if (!p) {
fputs(log, "getaddrinfo socket connect\n");
return INVALID_SOCKET;
}
return s;
}
export LONG sdNET_OpenAdapter(PHANDLE hDevice, ULONG wwuid,
ULONG adpNumber) {
(void)wwuid;
(void)adpNumber;
if (!log)
return sdNET_ERR_ADAPTER_BUSY;
log = makelog();
if (!log)
return sdNET_ERR_ADAPTER_BUSY;
fputs(log, "open log\n");
sock = makesock();
if (!sock)
return sdNET_ERR_ADAPTER_BUSY;
*hDevice = 1394;
return sdNET_ERR_SUCCESS;
}
export LONG sdNET_CloseAdapter(PHANDLE hDevice) {
if (*hDevice != 1394)
return sdNET_ERR_INVALID_HANDLE;
fputs(log, "Closing\n");
fclose(log);
closesocket(sock);
log = NULL;
sock = INVALID_SOCKET;
return sdNET_ERR_INVALID_HANDLE;
}
static int dump_tcode(unsigned long tcode)
{
unsigned long other = tcode & ~IEEE1394_tCODE_MASK;
int is_iso = 0;
fprint(logfile, "Transaction Code: ");
switch (tcode & IEEE1394_tCODE_MASK) {
case IEEE1394_QUAD_WRREQ:
log("Async request subaction, quadlet");
break;
case IEEE1394_BLOCK_WRREQ:
log(Async request subaction, block");
break;
case IEEE1394_WRRESP:
log("Async response subaction for both write request types, no payload");
break;
case IEEE1394_QUAD_RDREQ:
log("Async request subaction, no payload");
break;
case IEEE1394_BLOCK_RDREQ:
log("Async request subaction quadlet payload");
break;
case IEEE1394_QUAD_RDRESP:
log("Async response subaction to request for quadlet, quadlet payload");
break;
case IEEE1394_BLOCK_RDRESP:
log("Async response subaction to request for block, block payload");
break;
case IEEE1394_CYCLE_START_REQ:
log("Async request to start isochronous cycle, quadlet payload");
break;
case IEEE1394_LOCK_REQ:
log("Async request subaction, block payload");
break;
case IEEE1394_ISOBLOCK_REQ:
log("Isochronous subaction, block payload");
is_iso = 1;
break;
case IEEE194_LOCK_RESP:
log("Asynchronous request subaction for lock request, block payload");
break;
default:
log("Unknown code %lu", tcode & IEEE1394_tCODE_MASK);
break;
}
if (other) {
log("Other transaction code: %lu", other);
}
log("\n");
return is_iso;
}
static void dump_data(unsigned long len, unsigned long *data)
{
/* Dump in base52 instead? */
unsigned long i;
log("Data length: %lu\n", len);
log("Data:");
for (i = 0; i < len >> 2; i++) {
fprintf(" %08lX", *data);
data++;
}
log("\n");
}
static void dump_asy(PsdNET_Packet_t p)
{
fprintf(logfile,
"Asynchronous Packet.\n"
"Bus: %lu\n"
"Node: %lu\n"
"Address Offset, High: 0x%08lX\n"
"Address Offset, Low: 0x%08lX\n"
"Transaction Label: %lu\n",
p->type.asy.bus,
p->type.asy.node,
p->type.asy.offsetHigh,
p->type.asy.offsetLow
);
log("Retry code: ");
switch (p->type.asy.retryCode) {
case IEEE1394_Retry_0:
log("Initial subaction.\n");
break;
case IEEE1394_Retry_X:
log("Retry subaction from acknowledge busy, or retry from acknowledge busy A or B.\n");
break;
case IEEE1394_Retry_A:
log("Retry subaction, dual-phase retry node, A.\n");
break;
case IEEE1394_Retry_B:
log("Retry subaction, dual-phase retry node, B.\n");
break;
default:
log("Unknown %lu\n", p->type.asy.retryCode);
break;
}
log("Response code: ");
switch(p->type.asy.rCode) {
case IEEE1394_RESP_COMPLETE:
log("Complete\n");
break;
case IEEE1394_RESP_CONFLICT_ERROR:
log("Resource conflict\n");
break;
case IEEE1394_RESP_DATA_ERROR:
log("Hardware error\n");
break;
case IEEE1394_RESP_TYPE_ERROR:
log("Invalid value or transaction\n");
break;
case IEEE1394_RESP_ADDR_ERROR:
log("Destination not accessable\n");
break;
default:
log("Unknown %lu\n", p->type.asy.rCode);
}
log("Extended response code: ");
switch (p->type.asy.xtCode) {
case IEEE1394_MASK_SWAP:
log("Mask swap\n");
break;
case IEEE1394_COMPARE_SWAP:
log("Compare swap\n");
break;
case IEEE1394_FETCH_ADD:
log("Fetch add\n");
break;
case IEEE1394_BOUNDED_ADD:
log("Bounded add\n");
break;
case IEEE1394_WRAP_ADD:
log("Wrap add\n");
break;
case IEEE1394_VENDER_DEP:
log("Vendor dependent\n");
default:
log("Unknown %lu\n", p->type.asy.xtCode);
}
}
static void dump_iso(PsdNET_Packet_t p)
{
log("Isochronous packet.\n"
"Channel: %lu\n"
"Synchronization code: %lu\n",
p->type.iso.channel,
p->type.iso.synchro);
log("Tag: ");
switch (p->type.iso.tag) {
case IEEE1394_TAG_UNFORMATTED:
log("Unformatted\n");
break;
case IEEE1394_TAG_FORMAT1:
log("1\n");
break;
case IEEE1394_TAG_FORMAT2:
log("2\n");
break;
case IEEE1394_TAG_FORMAT3:
log("3\n");
break;
default:
log("Unknown tag %lu\n", p->type.iso.tag);
break;
}
}
static void dump_packet(PsdNET_Packet_t p)
{
log("Timeout: %lu\n", p->tCode);
log("Flags:");
if (p->flags & SDNET__NOBLOCKINGMODE) {
log(" Nonblocking");
} else if (p->flags & SDNET__BLOCKINGMODE) {
log(" Blocking");
}
log("\n");
if (dump_tcode(p->tCode) == 1)
dump_iso(p);
else
dump_asy(p);
log("Acknowledge code: ");
switch (p->ack) {
case IEEE1394_ACK_COMPLETE:
log("Accepted and completed\n");
break;
case IEEE1394_ACK_PENDING:
log("Accepted and pending\n");
break;
case IEEE1394_ACK_BUSY_X:
log("Rejected, retry\n");
break;
case IEEE1394_ACK_BUSY_A:
log("Rejected, retry at phase A\n");
break;
case IEEE1394_ACK_BUSY_B:
log("Rejected, retry at phase B\n");
break;
case IEEE1394_ACK_DATA_ERROR:
log("CRC/length check fail\n");
break;
case IEEE1394_ACK_TYPE_ERROR:
log("Unsupported or incorrect value, or invalid transaction\n");
default:
log("Unknown %lu\n", p->ack);
}
log("Speed: ");
switch (p->speed) {
case IEEE1394_ASYSPD_100Mbits:
case IEEE1394_ISOSPD_100Mbits:
log("100\n");
break;
case IEEE1394_ASYSPD200Mbits:
case IEEE1394_ISOSPD200Mbits:
log("200\n");
break;
case IEEE1394_ASYSPD400Mbits:
case IEEE1394_ISOSPD400Mbits:
log("400\n");
break;
default:
log("Unknown %lu\n", p->speed);
}
dump_data(p->datalen, p->data);
}
export LONG sdNET_SendAsyncPacket(PHANDLE hDevice, PsdNET_Packet_t pk) {
fputs(log, "Send Async\n");
dump_packet(pk);
/* TODO: convert pk->asy.data and pk->asy.datalen from long to octet */
msg_send_async(sock, pk->asy.bus, pk->asy.node,
pk->asy.offset_high << 32 | pk->asy.offset_low,
pk->tcode, pk->asy.tLabel, pk->asy.datalen, pk->asy.data);
return sdNET_ERR_TIMEOUT;
}
export LONG sdNET_SendIsochPacket(PHANDLE hDevice, PsdNET_Packet_t pk) {
fputs(log, "Send Isoch\n");
dump_packet(pk);
return sdNET_ERR_TIMEOUT;
}
export LONG sdNET_ReceivePacket(PHANDLE hDevice, PsdNET_Packet_t pk) {
char buf[512];
fputs(log, "Receive One\n");
return sdNET_ERR_TIMEOUT;
}
export LONG sdNET_IOControl(PHANDLE hDevice, ULONG cmd, PVOID iodata) {
fputs(log, "IOControl\n");
return sdNET_ERR_IOCTL_FAILED;
}
export LONG sdNET_MultiReceive(PHANDLE hDevice, PsdNET_MultiPk_t multiPk) {
fputs(log, "Recv many\n");
return sdNET_ERR_TIMEOUT;
}