⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.c

📁 Libnet is a cross-platform library aimed at game developers. It has an abstract high level API, whic
💻 C
📖 第 1 页 / 共 2 页
字号:
/*---------------------------------------------------------------- * serial.c - serial network driver for libnet *---------------------------------------------------------------- *  libnet is (c) Copyright Chad Catlett and George Foot 1997-1999 * *  Please look in `docs' for details, documentation and *  distribution conditions. */#include "platdefs.h"#include "libnet.h"#include "internal.h"/* If we can use serial ports, do so.  */#ifdef __USE_REAL_SERIAL__#include <ctype.h>#include <stdlib.h>#include <string.h>#include <netinet/in.h>#include "config.h"#include "serial.h"/* Note: In the serial code we distinguish between physical serial  * "ports" and virtual "slots".  Normally the words "address" and  * "port" apply, but it's less confusing for me this way.  */#define MAX_PORT	8/* High level serial ports.  These are a layer above the platform * specific low level serial port routines and are shared between * channels.  */struct hl_port {    struct hl_port *next;    struct hl_port *prev;    int port_nr;    struct port *port;    struct queue recv;};static struct list_head hl_port_list;/* Private channel data.  */#define ALL	-1 struct channel_data {    struct channel_data *next;    struct channel_data *prev;    int port_nr;		/* port we use */    int local_slot;		/* slot we receive from */    int remote_slot;		/* slot we send to */    struct list_head packet_list;};static struct list_head channel_data_list;/* Packets.  These are like letters sitting in a mailbox (the channel)  * waiting to be collected.  Slots are then the names of recipients on * the envelope.  */struct packet {    struct packet *next;    struct packet *prev;    int from_port_nr;    int from_slot;    int size;    void *data;};/* Config variables.  */static int autoports[MAX_PORT] = { 0, 1 };static int default_slot = 0;static int disable_driver = 0;/* Find a slot unused by any channel and is not the default.  */static int unused_slot (void){    static int next_slot = 0;    struct channel_data *data;  next:    next_slot = (next_slot + 1) & 0xffff;    if (next_slot == default_slot)	goto next;    foreach (data, channel_data_list)	if (next_slot == data->local_slot)	    goto next;    return next_slot;}/* Return the port and slot numbers in a binding string.  */#define ERR	-0xffstatic int my_atoi (const char *s){    return (isdigit (*s)) ? atoi (s) : ERR;}static int decode_binding (const char *binding, int *port_nr, int *slot){    if (!binding) {			/* NULL */	*port_nr = ALL;	*slot = unused_slot ();    }    else if (!*binding) {		/* "" */	*port_nr = ALL;	*slot = default_slot;    }    else {	char *c = strchr (binding, ':');	if (c) {	    if (c != binding)		/* x:[y] */		*port_nr = my_atoi (binding);	    else			/* :[y] */		*port_nr = ALL;	    	    if (c[1])			/* [x]:y */		*slot = my_atoi (c+1);	    else			/* [x]: */		*slot = default_slot;	}	else {				/* x */	    *port_nr = my_atoi (binding);	    *slot = default_slot;	}    }    return ((*port_nr == ERR) || (*slot == ERR)) ? -1 : 0;}/* (see top of serial_send for packet format)  */#define PACKET_MARKER	0x94A3FE05l#define PACKET_SIZE	(4+2+2+2+2+4)/* Helpers for calculating the checksums.  */#define DATA_RLS_INIT	0x6FD3static int rls_checksum (int remote, int local, int size){    int chk = DATA_RLS_INIT;    chk ^= ((chk << 11) | (chk >> 5)) ^ remote; chk &= 0xFFFFl;    chk ^= ((chk << 11) | (chk >> 5)) ^ local;  chk &= 0xFFFFl;    chk ^= ((chk << 11) | (chk >> 5)) ^ size;   chk &= 0xFFFFl;    return chk;}#define DATA_CHK_INIT	0x1F25B79Clstatic int data_checksum_ex (int chk, const unsigned char *data, int size){    while (size--)        chk ^= ((chk << 19) | (chk >> 13)) ^ *data++;    return chk;}static int data_checksum_q (struct queue *q, int p, int size){    int chk = DATA_CHK_INIT;    int p_end = queue_wrap (p + size);    if (p_end < p) {        int br = QUEUE_SIZE - p;	chk = data_checksum_ex (chk, &q->data[p], br);        chk = data_checksum_ex (chk, q->data, p);    }    else {	chk = data_checksum_ex (chk, &q->data[p], size);    }    return chk;}#define data_checksum_l(data, size) \        data_checksum_ex(DATA_CHK_INIT, (data), (size))/* Retrieve the next packet from the bytestream.  */static struct packet *get_next_packet (struct hl_port *hl_port, int *to_slot){    struct queue *q = &hl_port->recv;    struct packet *packet;    int qtail = q->tail;    int qsize = queue_wrap (q->head - qtail);    int marker;    if (qsize < PACKET_SIZE) return 0;    /* Read the first int from the queue */    marker                = q->data[qtail]; qtail = queue_wrap (qtail + 1);    marker <<= 8; marker |= q->data[qtail]; qtail = queue_wrap (qtail + 1);    marker <<= 8; marker |= q->data[qtail]; qtail = queue_wrap (qtail + 1);    marker <<= 8; marker |= q->data[qtail]; qtail = queue_wrap (qtail + 1);    /* qtail now points to the first byte after the hypothetical     * PACKET_MARKER.  */    while (qsize >= PACKET_SIZE) {        if (marker == PACKET_MARKER) { 	    int p = qtail;	    int remote;	    int local;	    int size;	    int n;            remote                = q->data[p]; p = queue_wrap (p + 1);            remote <<= 8; remote |= q->data[p]; p = queue_wrap (p + 1);            local                 = q->data[p]; p = queue_wrap (p + 1);            local  <<= 8; local  |= q->data[p]; p = queue_wrap (p + 1);            size                  = q->data[p]; p = queue_wrap (p + 1);            size   <<= 8; size   |= q->data[p]; p = queue_wrap (p + 1);            /* Read checksum for packet header.  */            n                     = q->data[p]; p = queue_wrap (p + 1);            n      <<= 8; n      |= q->data[p]; p = queue_wrap (p + 1);            /* Is the checksum correct?  */            if (n == rls_checksum (remote, local, size)) {		/* If the packet isn't all there yet, then we return.                 * The packet will be read later when it is complete.  */		if (qsize < PACKET_SIZE + size) {                    q->tail = queue_wrap (qtail - 4);		    return 0;                }                /* Skip the header permanently. It is valid.  */                qtail = p;                /* Read data checksum.  */		p = queue_wrap (p + size);	        n           = q->data[p]; p = queue_wrap (p + 1);	        n <<= 8; n |= q->data[p]; p = queue_wrap (p + 1);	        n <<= 8; n |= q->data[p]; p = queue_wrap (p + 1);	        n <<= 8; n |= q->data[p]; p = queue_wrap (p + 1);                /* Is the checksum correct?  */                if (n == data_checksum_q (q, qtail, size)) {		    packet = malloc (sizeof *packet);                    /* Out of memory? Tut tut. Discard the packet.  */                    if (packet) {		        packet->size = size;		        packet->data = malloc (size);		        /* Store header information.  */                        *to_slot = remote;		        packet->from_slot = local;		        packet->from_port_nr = hl_port->port_nr;                    }		    /* p currently points to after the data checksum.  		     * Set q->tail accordinly, and set p to point to  		     * the end of the data themselves.  */		    q->tail = p;		    p = queue_wrap (p - 4);		    /* Read packet data.  */                    if (packet) {                        if (p < qtail) {                            int br = QUEUE_SIZE - qtail;			    memcpy (packet->data, &q->data[qtail], br);			    memcpy (packet->data + br, q->data, p);                        } else {                            memcpy (packet->data, &q->data[qtail], p - qtail);                        }                    }                    return packet;                }            }        }        /* Skip unidentified data.  */        marker <<= 8;        marker &= 0xFFFFFFFFl; /* Portable to 64-bit systems, NARF  */        marker |= q->data[qtail];        qtail = queue_wrap (qtail + 1);        qsize--;    }    /* No complete packet was present.  */    return 0;}/* Free a packet.  */static void free_packet (struct packet *p){    free (p->data);    free (p);}/* Check ports for new data.  If packets are available, fish them out * and distribute them to the appropriate channels.  */static void poll_ports (void){    struct hl_port *hl_port;    struct packet *packet;    int to_slot;    foreach (hl_port, hl_port_list) {	unsigned char buf[256];	int size, i;	/* Read byte stream from low level port.  */	size = __libnet_internal__serial_read (hl_port->port, buf, sizeof buf);	if (size <= 0) continue;	/* Stuff byte stream into queue.  */	for (i = 0; i < size; i++)	    queue_put (hl_port->recv, buf[i]);      next:	/* Get the next packet if available.  */	if ((packet = get_next_packet (hl_port, &to_slot))) {	    struct channel_data *data;	    /* Distribute it to channel.  */	    foreach (data, channel_data_list)		if (data->local_slot == to_slot) {		    append_to_list (data->packet_list, packet);		    goto next;		}	    /* No takers.  */	    free_packet (packet);	}    }}/* Return non-zero if port is not already opened.  */static int port_unopened (int port_nr){    struct hl_port *hl_port;    if ((port_nr == ALL) || (autoports[port_nr]))	return 0;    foreach (hl_port, hl_port_list)	if (hl_port->port_nr == port_nr) return 0;    return 1;}/* Open a port and add it to the list.  Return zero on success.  */static int open_port (int port_nr){    struct hl_port *hl_port;    struct port *port;        hl_port = malloc (sizeof *hl_port);    if (!hl_port) return -1;    port = __libnet_internal__serial_open (port_nr);    if (!port) {	free (hl_port);	return -1;    }    hl_port->port_nr = port_nr;    hl_port->port = port;    hl_port->recv.head = hl_port->recv.tail = 0;    add_to_list (hl_port_list, hl_port);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -