370 lines
7.9 KiB
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;
|
|
}
|