#include #include #include #include #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; }