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

📄 serial.c

📁 Libnet is a cross-platform library aimed at game developers. It has an abstract high level API, whic
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Close a port and free it.  */static void free_port (struct hl_port *hl_port){    __libnet_internal__serial_close (hl_port->port);    free (hl_port);}/* serial_detect: *  This function returns one of the following: *  - NET_DETECT_YES    (if the network driver can definitely work) *  - NET_DETECT_MAYBE  (if the network driver might be able to work) *  - NET_DETECT_NO     (if the network driver definitely cannot work) */static int serial_detect (void){    return (disable_driver) ? NET_DETECT_NO : NET_DETECT_MAYBE;}/* serial_init: *  Initialises the driver.  Return zero if successful, non-zero if not. */static int serial_init (void){    int i;    init_list (hl_port_list);    init_list (channel_data_list);    if (__libnet_internal__serial_init ())	return -1;    for (i = 0; i < MAX_PORT; i++)  	if (autoports[i]) open_port (i);        return 0;}/* serial_exit: *  Shuts down the driver, freeing allocated resources, etc.  All channels *  will already have been destroyed by the `destroy_channel' function, so  *  normally all this needs to do is tidy up anything `init' left untidy. *  Return zero if successful, non-zero otherwise. */static int serial_exit (void){    free_list (hl_port_list, free_port);    return __libnet_internal__serial_exit ();}/* serial_init_channel: *  This function will be called when a channel is created, before any  *  data is sent.  It should at least set the channel's return address to *  something meaningful or at least to a valid string if the driver can't *  supply a return address.  It can allocate memory, pointed to by the *  `data' field of the channel struct.  Return zero if successful, non-zero *  otherwise. */static int serial_init_channel (NET_CHANNEL *chan, const char *addr){    int port_nr;    int slot;    struct channel_data *data;    if (decode_binding (addr, &port_nr, &slot))	return -1;        if (((port_nr != ALL) && (port_nr < 0)) || (port_nr >= MAX_PORT))	return -1;    if ((port_unopened (port_nr)) && (open_port (port_nr) < 0))	return -1;    data = malloc (sizeof *data);    if (!data) return -1;    data->port_nr = port_nr;    data->local_slot = slot;    init_list (data->packet_list);    chan->data = data;    add_to_list (channel_data_list, data);    if (data->port_nr == ALL)	sprintf (chan->local_addr, ":%d", data->local_slot);    else	sprintf (chan->local_addr, "%d:%d", data->port_nr, data->local_slot);    return 0;}/* serial_destroy_channel: *  Called when a channel is being closed.  This should tidy up anything  *  that init_channel or subsequent functions have left messy, for example  *  it should free any data block that has been allocated.  Return zero if  *  successful, non-zero otherwise. */static int serial_destroy_channel (NET_CHANNEL *chan){    struct channel_data *data = chan->data;    del_from_list (data);    free_list (data->packet_list, free_packet);    free (data);    /* If the channel was using a port listed in autoports and is     * the last channel using that port, should we close the port?  */    return 0;}/* serial_update_target: *  This will be called if the target_addr for the channel changes.  *  If necessary, the address could be converted into network format here. *  Return zero if any conversion was possible, but don't bother checking *  whether or not the target is reachable. */static int serial_update_target (NET_CHANNEL *chan){    struct channel_data *data = chan->data;    int port_nr, slot;    /* This should probably not allow NULL and "" through.  */    if (decode_binding (chan->target_addr, &port_nr, &slot))	return -1;        if (((port_nr != ALL) && (port_nr < 0)) || (port_nr >= MAX_PORT))	return -1;    if (port_unopened (port_nr))	if (open_port (port_nr) < 0) return -1;    data->port_nr = port_nr;    data->remote_slot = slot;    return 0;}/* serial_send: *  Send the given data block down the channel.  `size' is in bytes. *  Return zero if successful, otherwise return non-zero.  Don't bother *  checking that the packet arrived at the destination though. */static void serial_send_all(struct port *port,			    const unsigned char *buf, int size){    int sent;    while (size) {	sent = __libnet_internal__serial_send(port, buf, size);	buf += sent;	size -= sent;    }}static inline void do_send (struct port *port, const void *header,			    const void *buf, int size,                            const void *checksum){    serial_send_all (port, header, 12);    serial_send_all (port, buf, size);    serial_send_all (port, checksum, 4);}static int serial_send (NET_CHANNEL *chan, const void *buf, int size){    /* Packets are sent in the following format:     * - 4 PACKET_MARKER     * - 2 remote_slot (as seen by sender)     * - 2 local_slot (as seen by sender)     * - 2 length of packet (n, in bytes, data only)     * - 2 checksum for remote_slot, local_slot and length     * - n packet data     * - 4 checksum for packet data     */    struct channel_data *data = chan->data;    struct hl_port *hl_port;    unsigned char header[12];    unsigned char checksum[4];    int chk;    header[0] = (unsigned char) (PACKET_MARKER >> 24);    header[1] = (unsigned char) (PACKET_MARKER >> 16);    header[2] = (unsigned char) (PACKET_MARKER >> 8 );    header[3] = (unsigned char) (PACKET_MARKER      );    header[4] = data->remote_slot >> 8;    header[5] = data->remote_slot;    header[6] = data->local_slot >> 8;    header[7] = data->local_slot;    header[8] = size >> 8;    header[9] = size;    chk = rls_checksum (data->remote_slot, data->local_slot, size);    header[10] = chk >> 8;    header[11] = chk;    chk = data_checksum_l (buf, size);    checksum[0] = chk >> 24;    checksum[1] = chk >> 16;    checksum[2] = chk >> 8;    checksum[3] = chk;    if (data->port_nr == ALL) {	foreach (hl_port, hl_port_list)	    do_send (hl_port->port, header, buf, size, checksum);	return 0;    }        foreach (hl_port, hl_port_list)        if (hl_port->port_nr == data->port_nr) {	    do_send (hl_port->port, header, buf, size, checksum);	    return 0;	}    return -1;}/* serial_recv: *  Receive a packet into the memory block given.  `size' is the maximum *  number of bytes to receive.  The sender's address will be put in `from'. *  Return the number of bytes received, or -1 if an error occured.  A zero *  return value means there was no data to receive. */static int serial_recv (NET_CHANNEL *chan, void *buf, int size, char *from){    struct channel_data *data = chan->data;    struct packet *packet;    poll_ports ();    if (list_empty (data->packet_list))	return 0;    packet = data->packet_list.next;    if (packet->size < size)	size = packet->size;    memcpy (buf, packet->data, size);    if (from)	sprintf (from, "%i:%i", packet->from_port_nr, packet->from_slot);    del_from_list (packet);    free_packet (packet);    return size;}/* serial_query: *  Returns non-zero if there is data waiting to be read from the channel. */static int serial_query (NET_CHANNEL *chan){    poll_ports ();    return !(list_empty (((struct channel_data *) chan->data)->packet_list));}/* serial_load_config: *  This will be called once when the library is initialised, inviting the *  driver to load configuration information from the passed text file. */static void parse_autoports (char *value){    int i;    char *endptr;            for (i = 0; i < MAX_PORT; i++)	autoports[i] = 0;        while (1) {	i = strtol (value, &endptr, 10);	if (endptr == value) break;	if ((i >= 0) && (i < MAX_PORT))	    autoports[i] = 1;	value = endptr;    }}static void serial_load_config (NET_DRIVER *drv, FILE *fp){    char section[] = "serial port #", *p;    char *option, *value;    int i;    /* [serial port #] */    p = strchr (section, '#');    for (i = 0; i < MAX_PORT; i++) {	*p = '0' + i;	if (__libnet_internal__seek_section (fp, section))	    continue;	while (!__libnet_internal__get_setting (fp, &option, &value))	    __libnet_internal__serial_load_config (i, option, value);    }    /* [serial] */    if (!__libnet_internal__seek_section (fp, "serial")) {	while (!__libnet_internal__get_setting (fp, &option, &value)) {	    if (!strcmp (option, "autoports"))		parse_autoports (value);	    else if (!strcmp (option, "slot"))		default_slot = atoi (value);	    else if (!strcmp (option, "disable"))		disable_driver = (atoi (value) || (value[0] == 'y'));	}    }    if (drv->load_conn_config)	drv->load_conn_config (drv, fp, "serial");}#endif/* NET_DRIVER structures.  */static int dummy_detect (void) { return NET_DETECT_NO; }static void dummy_load_config (NET_DRIVER *drv, FILE *fp) { }#define MAKE_REAL_SERIAL_DRIVER(drv, name)		\NET_DRIVER drv = {					\    name,						\    "Serial driver",					\    NET_CLASS_SERIAL,					\							\    serial_detect,					\    serial_init,					\    serial_exit,					\							\    NULL, NULL,						\							\    serial_init_channel,				\    serial_destroy_channel,				\							\    serial_update_target,				\    serial_send,					\    serial_recv,					\    serial_query,					\							\    NULL, NULL,						\    NULL, NULL, NULL, NULL,				\    NULL, NULL, NULL, NULL, NULL,			\							\    serial_load_config,					\    NULL, NULL						\};#define MAKE_DUMMY_SERIAL_DRIVER(drv, name)		\NET_DRIVER drv = {					\    name, "Dummy driver",				\    NET_CLASS_SERIAL,					\    dummy_detect,					\    NULL, NULL,						\    NULL, NULL,						\    NULL, NULL,						\    NULL, NULL, NULL, NULL,				\    NULL, NULL, NULL, NULL, NULL, NULL,			\    NULL, NULL, NULL, NULL, NULL,			\    dummy_load_config,					\    NULL, NULL						\};#ifdef __USE_REAL_SERIAL_DOS__    MAKE_REAL_SERIAL_DRIVER (net_driver_serial_dos, "Serial ports in DOS");#else    MAKE_DUMMY_SERIAL_DRIVER (net_driver_serial_dos, "Serial ports in DOS");#endif#ifdef __USE_REAL_SERIAL_LINUX__    MAKE_REAL_SERIAL_DRIVER (net_driver_serial_linux, "Serial ports in Linux");#else    MAKE_DUMMY_SERIAL_DRIVER (net_driver_serial_linux, "Serial ports in Linux");#endif#ifdef __USE_REAL_SERIAL_BEOS__    MAKE_REAL_SERIAL_DRIVER (net_driver_serial_beos, "Serial ports in BeOS");#else    MAKE_DUMMY_SERIAL_DRIVER (net_driver_serial_beos, "Serial ports in BeOS");#endif

⌨️ 快捷键说明

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