📄 etherdrv.c
字号:
#endif}/* * Function: read_packet * Purpose: read a packet, and pass it back to higher levels * * Params: * In/Out: packet Holder for the read packet * * Returns: 1 - Packet is complete * 0 - No complete packet read * * Post-conditions: Will call panic() if something goes wrong with the OS */static int read_packet(struct data_packet *const packet){ struct sockaddr_in from; int nbytes, fromlen = sizeof(from); DevChanID devchan; /* * try to get the packet */ if ((nbytes = recvfrom(sock, (char *)(packet->data), packet->buf_len, 0, (struct sockaddr *)&from, &fromlen)) < 0) {#ifdef COMPILING_ON_WINDOWS if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) MessageBox(GetFocus(), "Error receiving packet\n", "Angel", MB_OK | MB_ICONSTOP);#else if (errno != EWOULDBLOCK) {# ifdef DEBUG perror("recv");# endif panic("ethernet recv failure"); }#endif return 0; }#ifdef COMPILING_ON_WINDOWS if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR) { progressInfo.nRead += nbytes; (*pfnProgressCallback)(&progressInfo); }#endif /* * work out where the packet was from */ if (from.sin_addr.s_addr != remote.sin_addr.s_addr) { /* * not from our target - ignore it */#ifdef DEBUG printf("read_packet: ignoring packet from %s\n", inet_ntoa(from.sin_addr));#endif return 0; } else if (ntohs(from.sin_port) == ports[DBUG_INDEX]) devchan = DC_DBUG; else if (ntohs(from.sin_port) == ports[APPL_INDEX]) devchan = DC_APPL; else { /* * unknown port number - ignore it */#ifdef DEBUG printf("read_packet: ignore packet from port %hd\n", htons(from.sin_port));#endif return 0; }#if defined(DEBUG) && !defined(DO_TRACE) printf("EthernetRead: %d bytes from %s channel\n", nbytes, (devchan == DC_DBUG) ? "DBUG" : "APPL");#endif#ifdef DO_TRACE printf("[%d on %d]\n", nbytes, devchan); { int i = 0; unsigned char *cptr = packet->data; while (i < nbytes) { printf("<%02X ", *(cptr++)); if (!(++i % 16)) printf("\n"); } if (i % 16) printf("\n"); }#endif /* * OK - fill in the details */ packet->type = devchan; packet->len = nbytes; return 1;}/**********************************************************************//* * Function: Ethernet_Open * Purpose: Open the Ethernet device. See the documentation for * DeviceOpen in drivers.h * * Post-conditions: Will have updated struct sockaddr_in remote (*ia) * with the address of the remote target. */static int EthernetOpen(const char *name, const char *arg){#ifdef COMPILING_ON_WINDOWS WORD wVersionRequested; WSADATA wsaData;#endif /* * name is passed as e=<blah>, so skip 1st two characters */ const char *etheraddr = name + 2;#ifdef DEBUG printf("EthernetOpen: name `%s'\n", name);#endif /* Check that the name is a valid one */ if (EthernetMatch(name, arg) != 0) return -1;#ifdef COMPILING_ON_WINDOWS wVersionRequested = MAKEWORD(1, 1); if (WSAStartup(wVersionRequested, &wsaData) != 0) /* * Couldn't find a useable winsock.dll. */ return -1; if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup(); /* * Couldn't find a winsock.dll with supported version. */ return -1; }#endif memset((char *)ia, 0, sizeof(*ia)); if (set_address(etheraddr, ia) < 0) {#ifdef COMPILING_ON_WINDOWS /* * SJ - I'm not sure that this is the correct way to handle this * as Fail calls remote_disable and exits, while panic just exits. * However at the time of writing remote_disable does nothing! */ /* Panic("EthernetOpen: bad name `%s'\n", etheraddr); */#else Fail("EthernetOpen: bad name `%s'\n", etheraddr);#endif return -1; } if ((sock = open_socket()) < 0) return -1; /* * fetch the port numbers assigned by the remote target * to its Debug and Application sockets */ fetch_ports(); return 0;}static int EthernetMatch(const char *name, const char *arg){ /* IGNORE arg */ if (0) arg = arg; if (name == NULL) return -1; if (tolower(name[0]) != 'e' || name[1] != '=') return -1; return 0;}static void EthernetClose(void){ if (sock >= 0) { closesocket(sock); sock = -1; }#ifdef COMPILING_ON_WINDOWS WSACleanup();#endif}static int EthernetRead(DriverCall *dc, bool block){ fd_set fdset; struct timeval tv; int err; FD_ZERO(&fdset); FD_SET(sock, &fdset);#ifdef COMPILING_ON_WINDOWS UNUSED(block); tv.tv_sec = tv.tv_usec = 0;#else tv.tv_sec = 0; tv.tv_usec = (block ? 10000 : 0);#endif err = select(sock + 1, &fdset, NULL, NULL, &tv); if (err < 0) { if (errno == EINTR) { return 0; } panic("ethernet select failure (errno=%i)",errno); return 0; } if (FD_ISSET(sock, &fdset)) return read_packet(&dc->dc_packet); else return 0;}static int EthernetWrite(DriverCall *dc){ int nbytes; struct data_packet *packet = &dc->dc_packet; if (packet->type == DC_DBUG) ia->sin_port = htons(ports[DBUG_INDEX]); else if (packet->type == DC_APPL) ia->sin_port = htons(ports[APPL_INDEX]); else { panic("EthernetWrite: unknown devchan"); return 0; }#if defined(DEBUG) && !defined(DO_TRACE) printf("EthernetWrite: %d bytes to %s channel\n", packet->len, (packet->type == DC_DBUG) ? "DBUG" : "APPL");#endif#ifdef DO_TRACE printf("[%d on %d]\n", packet->len, packet->type); { int i = 0; unsigned char *cptr = packet->data; while (i < packet->len) { printf(">%02X ", *(cptr++)); if (!(++i % 16)) printf("\n"); } if (i % 16) printf("\n"); }#endif if ((nbytes = sendto(sock, (char *)(packet->data), packet->len, 0, (struct sockaddr *)ia, sizeof(*ia))) != packet->len) {#ifdef COMPILING_ON_WINDOWS if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)#else if (nbytes < 0 && errno != EWOULDBLOCK)#endif {#ifdef DEBUG perror("sendto");#endif#ifdef COMPILING_ON_WINDOWS panic("ethernet send failure\n");#else /* might not work for Windows */ panic("ethernet send failure [%s]\n",#ifdef STDC_HEADERS strerror(errno));#else errno < sys_nerr ? sys_errlist[errno] : "unknown errno");#endif /* STDC_HEADERS */#endif }#ifdef DEBUG else if (nbytes >= 0) fprintf(stderr, "ethernet send: asked for %d, sent %d\n", packet->len, nbytes);#endif return 0; }#ifdef COMPILING_ON_WINDOWS if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR) { progressInfo.nWritten += nbytes; (*pfnProgressCallback)(&progressInfo); }#endif return 1;}static int EthernetIoctl(const int opcode, void *args){#ifdef DEBUG printf( "EthernetIoctl: op %d arg %x\n", opcode, args );#endif /* * IGNORE(opcode) */ if (0) { int dummy = opcode; UNUSED(dummy); } UNUSED(args); switch ( opcode ) { case DC_RESYNC: {#ifdef DEBUG printf( "EthernetIoctl: resync\n" );#endif fetch_ports(); return 0; } default: { return -1; } }}/* EOF etherdrv.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -