📄 serial.c
字号:
/* 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 + -