From 35f90c3d350100d85afca7cd18f27d7b07ebe6a1 Mon Sep 17 00:00:00 2001 From: Riccardo Gaiati <riccardo@cs.lth.se> Date: Tue, 13 Dec 2011 13:43:51 +0100 Subject: [PATCH] working ethernet test --- examples/simple_java/Encoder.java | 5 +- examples/simple_java/simple.lc | 5 + examples/simple_java/thr_compile.sh | 3 + examples/simple_java/thr_decoder.c | 56 ++++ examples/simple_java/thr_encoder.c | 43 ++++ lib/c/ThrottleDrv/display.h | 7 + lib/c/ThrottleDrv/ethernet_drv.c | 223 ++++++++++++++++ lib/c/ThrottleDrv/ethernet_drv.h | 12 + lib/c/ThrottleDrv/throttle_drv.c | 385 ++++++++++++++++++++++++++++ lib/c/ThrottleDrv/throttle_drv.h | 17 ++ lib/c/labcomm.c | 76 +++--- lib/c/labcomm_thr_reader_writer.c | 141 ++++++++++ lib/c/labcomm_thr_reader_writer.h | 5 + 13 files changed, 941 insertions(+), 37 deletions(-) create mode 100644 examples/simple_java/thr_compile.sh create mode 100644 examples/simple_java/thr_decoder.c create mode 100644 examples/simple_java/thr_encoder.c create mode 100644 lib/c/ThrottleDrv/display.h create mode 100644 lib/c/ThrottleDrv/ethernet_drv.c create mode 100644 lib/c/ThrottleDrv/ethernet_drv.h create mode 100644 lib/c/ThrottleDrv/throttle_drv.c create mode 100644 lib/c/ThrottleDrv/throttle_drv.h create mode 100644 lib/c/labcomm_thr_reader_writer.c create mode 100644 lib/c/labcomm_thr_reader_writer.h diff --git a/examples/simple_java/Encoder.java b/examples/simple_java/Encoder.java index 6a05792..3209f7a 100644 --- a/examples/simple_java/Encoder.java +++ b/examples/simple_java/Encoder.java @@ -4,6 +4,9 @@ import java.io.OutputStream; import se.lth.control.labcomm.LabCommEncoderChannel; +/** + * Simple encoder + */ public class Encoder { @@ -35,7 +38,7 @@ public class Encoder public static void main(String[] arg) throws Exception { - FileOutputStream fos = new FileOutputStream(new File(arg[0])); + FileOutputStream fos = new FileOutputStream(arg[0]); Encoder example = new Encoder(fos); example.doEncode(); fos.close(); diff --git a/examples/simple_java/simple.lc b/examples/simple_java/simple.lc index b83c63a..2da6c48 100644 --- a/examples/simple_java/simple.lc +++ b/examples/simple_java/simple.lc @@ -7,3 +7,8 @@ sample struct { int x; string s; } IntString; + +sample struct { + double x; + double y; +} TwoDoubles; diff --git a/examples/simple_java/thr_compile.sh b/examples/simple_java/thr_compile.sh new file mode 100644 index 0000000..53b9865 --- /dev/null +++ b/examples/simple_java/thr_compile.sh @@ -0,0 +1,3 @@ +gcc -o thr_encoder -L ../../lib/c -I . -I ../../lib/c thr_encoder.c gen/simple.c ../../lib/c/labcomm_thr_reader_writer.c ../../lib/c/ThrottleDrv/*.c -llabcomm + +gcc -o thr_decoder -L ../../lib/c -I . -I ../../lib/c thr_decoder.c gen/simple.c ../../lib/c/labcomm_thr_reader_writer.c ../../lib/c/ThrottleDrv/*.c -llabcomm diff --git a/examples/simple_java/thr_decoder.c b/examples/simple_java/thr_decoder.c new file mode 100644 index 0000000..de5907c --- /dev/null +++ b/examples/simple_java/thr_decoder.c @@ -0,0 +1,56 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <labcomm_thr_reader_writer.h> +#include "gen/simple.h" +#include "ThrottleDrv/throttle_drv.h" + +static void handle_simple_TwoInts(simple_TwoInts *v,void *context) { + printf("Got TwoInts. a=%d, b=%d\n", v->a, v->b); +} + +static void handle_simple_IntString(simple_IntString *v,void *context) { + printf("Got IntString. x=%d, s=%s\n", v->x, v->s); +} + +int main(int argc, char *argv[]) { + struct thr_chn_t *p_thr_chn = NULL; + struct labcomm_decoder *decoder; + void *context = NULL; + int ret = 0; + unsigned char dest_mac[ETH_ADR_SIZE] = {0x06, 0x05, 0x04, 0x03, 0x02, 0x01}; /* other host MAC address, hardcoded...... :-( */ + unsigned char chn_id = 0x01; + unsigned short frag_size = 60; + unsigned short freq = 1000; /* milliseconds */ + unsigned char data[200]; + + char *filename = argv[1]; + if (-1 == thr_init("eth2")) + { + printf("Throttle Init failure."); + } + else + { + p_thr_chn = thr_open_chn(dest_mac, chn_id, frag_size, freq, labcomm_decoder_decode_one); + decoder = labcomm_decoder_new(labcomm_thr_reader, p_thr_chn); + if (!decoder) + { + printf("Failed to allocate decoder %s:%d\n", __FUNCTION__, __LINE__); + return 1; + } + labcomm_decoder_register_simple_TwoInts(decoder, handle_simple_TwoInts, context); + labcomm_decoder_register_simple_IntString(decoder, handle_simple_IntString, context); + + printf("Decoding:\n"); + do { + ret = thr_receive(p_thr_chn, data, decoder); + } while(-1 != ret); + { + printf("Throttle Send receive failure."); + } + printf("--- End Of File ---:\n"); + labcomm_decoder_free(decoder); + + //server_exit(fd); + } +} diff --git a/examples/simple_java/thr_encoder.c b/examples/simple_java/thr_encoder.c new file mode 100644 index 0000000..6466175 --- /dev/null +++ b/examples/simple_java/thr_encoder.c @@ -0,0 +1,43 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <labcomm_thr_reader_writer.h> +#include "gen/simple.h" +#include "ThrottleDrv/throttle_drv.h" + + +int main(int argc, char *argv[]) { + struct thr_chn_t *p_thr_chn = NULL; + struct labcomm_encoder *encoder; + int i, j; + unsigned char dest_mac[ETH_ADR_SIZE] = {0x00, 0x09, 0x6b, 0x10, 0xf3, 0x80}; /* other host MAC address, hardcoded...... :-( */ + unsigned char chn_id = 0x01; + unsigned short frag_size = 60; + unsigned short freq = 1000; /* milliseconds */ + + char *filename = argv[1]; + if (-1 == thr_init("eth0")) + { + printf("Throttle Init failure."); + } + else + { + p_thr_chn = thr_open_chn(dest_mac, chn_id, frag_size, freq, NULL); + encoder = labcomm_encoder_new(labcomm_thr_writer, p_thr_chn); + labcomm_encoder_register_simple_TwoInts(encoder); + labcomm_encoder_register_simple_IntString(encoder); + simple_IntString is; + is.x = 24; + is.s = "Hello, LabComm!"; + printf("Encoding IntString, x=%d, s=%s\n", is.x, is.s); + labcomm_encode_simple_IntString(encoder, &is); + + simple_TwoInts ti; + ti.a = 13; + ti.b = 37; + printf("Encoding TwoInts, a=%d, b=%d\n", ti.a, ti.b); + labcomm_encode_simple_TwoInts(encoder, &ti); + + //client_exit(fd); + } +} diff --git a/lib/c/ThrottleDrv/display.h b/lib/c/ThrottleDrv/display.h new file mode 100644 index 0000000..f8bed75 --- /dev/null +++ b/lib/c/ThrottleDrv/display.h @@ -0,0 +1,7 @@ +#define PC_MODE +#ifdef PC_MODE +#include <stdio.h> +#define DISPLAY_ERR(s) perror(s); +#else +#define DISPLAY_ERR(s) ; +#endif diff --git a/lib/c/ThrottleDrv/ethernet_drv.c b/lib/c/ThrottleDrv/ethernet_drv.c new file mode 100644 index 0000000..d0f5f02 --- /dev/null +++ b/lib/c/ThrottleDrv/ethernet_drv.c @@ -0,0 +1,223 @@ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <linux/if_ether.h> +#include <linux/if_packet.h> +#include <linux/if_arp.h> +#include <netinet/in.h> +#include "ethernet_drv.h" +#include "display.h" + + +/** LOCAL FUNCTIONS **/ + +/* local type for the ethernet interface */ +struct eth_int_t +{ + unsigned char mac_adr[ETH_ALEN]; /* MAC address */ + int socket_id; /* socket file descriptor */ + int index; /* index of the eth interface */ + unsigned char validity; +}; + +/*** +Open an Ethernet Raw packet connection +***/ +struct eth_int_t* eth_open(const char* eth_int_name) +{ + struct eth_int_t* tmp_eth = NULL; /* pointer to ethernet interface struct */ + struct ifreq ifr; /* struct used by ioctl function */ + + /* TO-DO: check if a ethernet socket has already been created for eth_int_name interface */ + + /* Ethernet interface name pointer valid ? */ + if (NULL == eth_int_name) + { + errno = EINVAL; + DISPLAY_ERR("Input parameter NULL"); + } + else + { + /* allocate memory for the Ethernet Interface */ + tmp_eth = (struct eth_int_t*)malloc(sizeof(struct eth_int_t)); + if (NULL == tmp_eth) + { + DISPLAY_ERR("Error allocating memory!"); + } + else + { + /* creates a Packet Socket, raw delivery, accept all protocol */ + tmp_eth->socket_id = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (-1 == tmp_eth->socket_id) /* error occurred during socket creation ? */ + { + free(tmp_eth); /* deallocate the memory */ + tmp_eth = NULL; + DISPLAY_ERR("Error in creating socket"); + } + else + { + /* retrieve the Ethernet card MAC address */ + strcpy(ifr.ifr_name, eth_int_name); + if (ioctl(tmp_eth->socket_id, SIOCGIFHWADDR, &ifr) == -1) /* error during the retrieve of MAC address ? */ + { + close(tmp_eth->socket_id); /* close the socket */ + free(tmp_eth); /* deallocate the memory */ + tmp_eth = NULL; + DISPLAY_ERR("ioctl error SIOCGIFHWADDR"); + } + else + { + /* copy the MAC address into the eth interface struct */ + memcpy(tmp_eth->mac_adr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); + + /*retrieve the Ethernet interface index*/ + if (ioctl(tmp_eth->socket_id, SIOCGIFINDEX, &ifr) == -1)/* error during the retrieve of index */ + { + close(tmp_eth->socket_id); /* close the socket */ + free(tmp_eth); /* deallocate the memory */ + tmp_eth = NULL; + DISPLAY_ERR("ioctl error SIOCGIFINDEX"); + } + else + { + /* copy the interface index into the eth interface struct */ + tmp_eth->index = ifr.ifr_ifindex; + printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", + tmp_eth->mac_adr[0],tmp_eth->mac_adr[1],tmp_eth->mac_adr[2],tmp_eth->mac_adr[3],tmp_eth->mac_adr[4],tmp_eth->mac_adr[5]); + printf("Successfully got interface index for %s: %i\n",eth_int_name, tmp_eth->index); + } + } + } + } + } + return(tmp_eth); +} + +/*** +Close the Ethernet Raw packet connection +***/ +int eth_close(struct eth_int_t* eth_int) +{ + int ret = 0; + + /* Ethernet interface pointer valid ? */ + if (NULL == eth_int) + { + ret = -1; + errno = EINVAL; + DISPLAY_ERR("Input parameter NULL"); + } + else + { + if (-1 == close(eth_int->socket_id)) /* error during the closure of the socket ? */ + { + ret = -1; + DISPLAY_ERR("Socket closure error"); + } + else + { + free(eth_int); /* deallocate the memory */ + eth_int = NULL; + } + } + return(ret); +} + +/*** +Returns the MAC address of the Ethernet Interface +***/ +int eth_getMACadr(const struct eth_int_t* eth_int, unsigned char* mac_adr) +{ + int ret = 0; + + if ((NULL == eth_int) || (NULL == mac_adr)) /* Input parameters valid ? */ + { + ret = -1; + errno = EINVAL; + DISPLAY_ERR("Input parameter(s) NULL"); + } + else + { + /* TO-DO: introduce a validity flag to be check before accessing to eth_int (better a crc) */ + memcpy(mac_adr, eth_int->mac_adr, ETH_ALEN); + } + return(ret); +} + + +/*** +send a complete Ethernet Raw Packet +***/ +int eth_send(const struct eth_int_t* eth_int, const unsigned char* eth_frame, unsigned short length) +{ + struct ethhdr *eth_header = NULL; /* Pointer to Ethernet frame header (Dest,Source,Type) */ + struct sockaddr_ll socket_address; + int ret; + + if ((NULL == eth_int) || (NULL == eth_frame)) + { + ret = -1; + errno = EINVAL; + DISPLAY_ERR("Input parameter(s) Null!"); + } + else + { + eth_header = (struct ethhdr*)eth_frame; + + /*prepare sockaddr_ll (address structure for PACKET_SOCKET) */ + socket_address.sll_family = AF_PACKET; + socket_address.sll_protocol = htons(ETH_P_IP); /* Physical layer protocol */ + socket_address.sll_ifindex = eth_int->index; /* Ethernet Interface index */ + socket_address.sll_hatype = ARPHRD_ETHER; /* ARP hardware identifier: Ethernet */ + socket_address.sll_pkttype = PACKET_OTHERHOST; /* Packet type: Another host */ + socket_address.sll_halen = ETH_ALEN; /* Length of the MAC address */ + socket_address.sll_addr[0] = eth_header->h_dest[0]; + socket_address.sll_addr[1] = eth_header->h_dest[1]; + socket_address.sll_addr[2] = eth_header->h_dest[2]; + socket_address.sll_addr[3] = eth_header->h_dest[3]; + socket_address.sll_addr[4] = eth_header->h_dest[4]; + socket_address.sll_addr[5] = eth_header->h_dest[5]; + socket_address.sll_addr[6] = 0x00; /* not used */ + socket_address.sll_addr[7] = 0x00; /* not used */ + + /*send the Ethernet frame */ + ret = sendto(eth_int->socket_id, eth_frame, length, 0, (struct sockaddr*)&socket_address, sizeof(socket_address)); + if (ret == -1) /* error during the trasmission of the Ethernet frame ? */ + { + DISPLAY_ERR("sendto error!"); + } + } + return(ret); +} + +/*** +receive a complete Ethernet Raw Packet +***/ +int eth_receive (const struct eth_int_t* eth_int, unsigned char* eth_frame, unsigned short length) +{ + int ret; + + if ((NULL == eth_int) || (NULL == eth_frame)) + { + ret = -1; + errno = EINVAL; + DISPLAY_ERR("Input parameter(s) Null!"); + } + else + { + /*Wait for incoming packet...*/ + ret = recvfrom(eth_int->socket_id, (void*)eth_frame, length, 0, NULL, NULL); + if (ret == -1) /* error during the reception of the Ethernet frame ? */ + { + DISPLAY_ERR("recvfrom error!"); + } + } + return(ret); +} + + + diff --git a/lib/c/ThrottleDrv/ethernet_drv.h b/lib/c/ThrottleDrv/ethernet_drv.h new file mode 100644 index 0000000..1dc786e --- /dev/null +++ b/lib/c/ThrottleDrv/ethernet_drv.h @@ -0,0 +1,12 @@ +#ifndef _ETHERNET_DRV_H_ +#define _ETHERNET_DRV_H_ + +struct eth_int_t; + +struct eth_int_t* eth_open(const char* eth_int_name); +int eth_close(struct eth_int_t* eth_int); +int eth_getMACadr(const struct eth_int_t* eth_int, unsigned char* mac_adr); +int eth_send(const struct eth_int_t* eth_int, const unsigned char* eth_frame, unsigned short length); +int eth_receive (const struct eth_int_t* eth_int, unsigned char* eth_frame, unsigned short length); + +#endif diff --git a/lib/c/ThrottleDrv/throttle_drv.c b/lib/c/ThrottleDrv/throttle_drv.c new file mode 100644 index 0000000..7cece88 --- /dev/null +++ b/lib/c/ThrottleDrv/throttle_drv.c @@ -0,0 +1,385 @@ +#include "throttle_drv.h" +#include "ethernet_drv.h" +#include <errno.h> +#include "display.h" +#include "stdlib.h" +#include <string.h> +#include <time.h> +#include <arpa/inet.h> + +#define THROTTLENET_PROTO 0x544e +#define ETH_ADR_LEN 6 + +#define THR_DST_ADR_POS 0 +#define THR_SRC_ADR_POS (THR_DST_ADR_POS + sizeof(((thr_header_t*)0)->dst_adr)) //6 +#define THR_ETH_TYP_POS (THR_SRC_ADR_POS + sizeof(((thr_header_t*)0)->src_adr)) //12 +#define THR_CHN_ID_POS (THR_ETH_TYP_POS + sizeof(((thr_header_t*)0)->eth_type)) //14 +#define THR_FRAG_NUM_POS (THR_CHN_ID_POS + sizeof(((thr_header_t*)0)->chn_id)) //15 +#define THR_FRAG_TOT_NUM_POS (THR_FRAG_NUM_POS + sizeof(((thr_header_t*)0)->frag_num)) //17 +#define THR_FRAG_LEN_POS (THR_FRAG_TOT_NUM_POS + sizeof(((thr_header_t*)0)->frag_num_tot)) //19 +#define THR_PAYLOAD_POS (THR_FRAG_LEN_POS + sizeof(((thr_header_t*)0)->frag_len)) //21 +#define THR_MSG_HEADER_LEN THR_PAYLOAD_POS + +#define THR_MSG_DST_ADR (unsigned char*)(&thr_msg[THR_DST_ADR_POS]) +#define THR_MSG_SRC_ADR (unsigned char*)(&thr_msg[THR_SRC_ADR_POS]) +#define THR_MSG_ETH_TYP *(unsigned short*)(&thr_msg[THR_ETH_TYP_POS]) +#define THR_MSG_CHN_ID *(unsigned char*)(&thr_msg[THR_CHN_ID_POS]) +#define THR_MSG_FRAG_NUM *(unsigned short*)(&thr_msg[THR_FRAG_NUM_POS]) +#define THR_MSG_FRAG_TOT_NUM *(unsigned short*)(&thr_msg[THR_FRAG_TOT_NUM_POS]) +#define THR_MSG_FRAG_LEN *(unsigned short*)(&thr_msg[THR_FRAG_LEN_POS]) +#define THR_MSG_PAYLOAD (unsigned char*)(&thr_msg[THR_PAYLOAD_POS]) + + +/* local type for the Throttle Channel structure */ +struct thr_chn_t +{ + unsigned char dst_adr[ETH_ADR_LEN];/* destination MAC address */ + unsigned char id; /* Channel id */ + unsigned short frag_size; /* Fragment size */ + unsigned short freq; /* Message transmission frequency */ + thr_msg_handler_t funct; /* Callback function invoked at the reception */ + unsigned short msg_length; + unsigned short* p_msg; +}; + +/* Type for the Throttle message */ +typedef struct +{ + unsigned char dst_adr[ETH_ADR_LEN]; /* destination MAC address */ + unsigned char src_adr[ETH_ADR_LEN]; /* source MAC address */ + unsigned short eth_type; /* ethernet packet type */ + unsigned char chn_id; /* channel identification */ + unsigned short frag_num; /* fragment number */ + unsigned short frag_num_tot; /* total fragment number */ + unsigned short frag_len; /* fragment length */ +}thr_header_t; + +/* Local functions */ +static int thr_msg_check(const unsigned char* thr_msg, unsigned short chn_id, unsigned short length); + +static struct eth_int_t* eth_int = NULL; + +/** +* @fn int thr_init(const char* eth_int_name) +* +* @brief Initializes the Throttle Net Driver, enabling the Ethernet Raw communication for the eth_int_name interface. +* +* @param [in] eth_int_name: ethernet interface name (e.g. "eth0","eth1") +* +* @retval int: 0 on success; -1 on error and errno is set appropriately +* +*******************************************************************************/ +int thr_init(const char* eth_int_name) +{ + int ret = 0; + + if (NULL == eth_int_name) + { + ret = -1; + errno = EINVAL; + DISPLAY_ERR("Input parameter NULL"); + } + else + { + eth_int = eth_open(eth_int_name); /* open the Ethernet socket */ + if (NULL == eth_int) + { + ret = -1; + } + } + return(ret); +} + +/** +* @fn struct thr_chn_t* thr_open_chn(const char* dst_adr, unsigned char chn_id, unsigned char frag_size, unsigned short freq, const thr_msg_handler_t funct); +* +* @brief Open a logic channel +* +* @param [in] dst_adr: destination MAC address; +* @param [in] chn_id: identification of the channel; +* @param [in] frag_size: fragment size; +* @param [in] freq: frequency of trasmission for each fragment; +* @param [in] msg_handler: callback invoked when a message is completely received; +* +* @retval struct thr_chn_t*: pointer to the Channel structure. NULL on error and errno is set appropriately. +* +*******************************************************************************/ +struct thr_chn_t* thr_open_chn(const unsigned char* dst_adr, unsigned char chn_id, unsigned char frag_size, unsigned short freq, const thr_msg_handler_t funct) +{ + struct thr_chn_t* tmp_chn = NULL; /* pointer to Channel structure */ + + /* TO-DO: check if a similar channel has already been created */ + + /* Input parameters not valid ? */ + if ((NULL == dst_adr) || (0 == frag_size)) + { + errno = EINVAL; + DISPLAY_ERR("Input parameter(s) NULL"); + } + else + { + /* allocate memory for the Channel structure */ + tmp_chn = (struct thr_chn_t*)malloc(sizeof(struct thr_chn_t)); + if (NULL == tmp_chn) + { + DISPLAY_ERR("Error allocating memory!"); + } + else + { + /* Update the Channel structure */ + memcpy(tmp_chn->dst_adr, dst_adr, sizeof(tmp_chn->dst_adr)); + tmp_chn->id = chn_id; + tmp_chn->frag_size = frag_size; + tmp_chn->freq = freq; + tmp_chn->funct = funct; + } + printf("thr_open_chn: callback = %x\n", tmp_chn->funct); + + } + + return(tmp_chn); +} + + +/** +* @fn int thr_send(const struct thr_chn_t* thr_chn, const char* data, unsigned int length) +* +* @brief Sends a Throttle message. A channel must be opened first. +* +* @param [in] thr_chn: pointer to the Throttle channel descriptor; +* @param [in] data: data buffer to be sent; +* @param [in] length: length of the data buffer; +* +* @retval int: number of byte sent, on success. -1 on error and errno is set appropriately. +* +*******************************************************************************/ +int thr_send(const struct thr_chn_t* thr_chn, const char* data, unsigned int length) +{ + unsigned char* thr_msg; + unsigned char i; + int ret = 0; + + /* Check the input parameters */ + if ((NULL == thr_chn) || (NULL == data) || (0 == length)) + { + ret = -1; + errno = EINVAL; + DISPLAY_ERR("Input parameter(s) NULL"); + } + else + { + if (0 == thr_chn->frag_size) + { + ret = -1; + errno = ERANGE; + DISPLAY_ERR("Division by zero"); + } + else + { + /* allocate memory for the Throttle Message */ + thr_msg = (unsigned char*)malloc(THR_MSG_HEADER_LEN + thr_chn->frag_size); + if (NULL == thr_msg) + { + ret = -1; + DISPLAY_ERR("Error allocating memory!"); + } + else + { + /* Compose the Ethernet Frame to be sent */ + memcpy(THR_MSG_DST_ADR, &thr_chn->dst_adr[0], ETH_ADR_LEN); /* Destiantion MAC Address */ + eth_getMACadr(eth_int, THR_MSG_SRC_ADR); /* Source MAC Address */ + THR_MSG_ETH_TYP = htons(THROTTLENET_PROTO); /* Ethernet Packet Type */ + THR_MSG_CHN_ID = thr_chn->id; /* Channel identification */ + THR_MSG_FRAG_TOT_NUM = ((length - 1) / thr_chn->frag_size) + 1; /* Total number of fragment */ + + struct timespec thr_time; + thr_time.tv_sec = thr_chn->freq / 1000; + thr_time.tv_nsec = (thr_chn->freq % 1000) * 1000000; + + /* Message is splitted into fragments and they are sent */ + for (i = 1; i <= THR_MSG_FRAG_TOT_NUM; i++) + { + THR_MSG_FRAG_NUM = i; /* fragment number */ + /* update the fragment length */ + if (length >= thr_chn->frag_size) + { + THR_MSG_FRAG_LEN = thr_chn->frag_size; + length -= thr_chn->frag_size; + } + else + { + THR_MSG_FRAG_LEN = length; + } + memcpy ((void*)THR_MSG_PAYLOAD, (void*)data, THR_MSG_FRAG_LEN); /* update the payload */ + ret = eth_send(eth_int, &thr_msg[0], (THR_MSG_HEADER_LEN + THR_MSG_FRAG_LEN)); /* send the message */ + if (-1 == ret) /*Error during the Ethernet trasmission ? */ + { + DISPLAY_ERR("Error during Throttle msg trasmission!"); + break; + } + else + { + data += THR_MSG_FRAG_LEN; + nanosleep(&thr_time, NULL); + } + } + /*deallocate the memory */ + free(thr_msg); + thr_msg = NULL; + } + } + } + return(ret); +} + +int thr_receive(struct thr_chn_t* thr_chn, unsigned char* data, void* param) +{ + unsigned char* thr_msg = NULL; + unsigned char* p_data = NULL; + unsigned short frag_index = 1; + short byte_rec = 0; + unsigned char msg_received = 0; + int ret; + + if ((NULL == thr_chn) || (NULL == data) || (NULL == thr_chn->funct) || (NULL == param)) + { + ret = -1; + errno = EINVAL; + DISPLAY_ERR("Input parameter(s) NULL"); + } + else + { + /* allocate memory for the Throttle Message */ + thr_msg = (unsigned char*)malloc(THR_MSG_HEADER_LEN + thr_chn->frag_size); + if (NULL == thr_msg) + { + ret = -1; + DISPLAY_ERR("Error allocating memory!"); + } + else + { + p_data = data; + do + { + byte_rec = eth_receive(eth_int, thr_msg, (THR_MSG_HEADER_LEN + thr_chn->frag_size)); /* receive the Ethernet Raw packet */ + if (-1 == byte_rec) + { + /* discard the message */ + DISPLAY_ERR("Error during Throttle msg reception: Fragment discarded."); + } + else + { + /* check if the Ethernet Raw message is correct (Ethernet protocol, Channel ID, length) */ + ret = thr_msg_check(thr_msg, thr_chn->id, byte_rec); + if (ret < 0) + { + //printf("Throttle msg mismatch: Fragment discarded.\n"); + } + else + { + printf("Message Index %d on %d. Actual Index %d\n", THR_MSG_FRAG_NUM, THR_MSG_FRAG_TOT_NUM, frag_index); + if (frag_index == THR_MSG_FRAG_NUM) /* The fragment is the one expected ? */ + { + /* Rebuild the original data linking the payloads of each fragment */ + memcpy((void*)p_data, (void*)THR_MSG_PAYLOAD, THR_MSG_FRAG_LEN); + p_data += THR_MSG_FRAG_LEN; /* update the pointer to the buffer */ + frag_index++; /* update the fragment index */ + ret = p_data - data; /* update the number of received byte */ + if (frag_index > THR_MSG_FRAG_TOT_NUM) + { + msg_received = 1; + } + } + else + { + printf("Fragment mismatch: Fragment discarded.\n"); + frag_index = 1; + p_data = data; + } + } + } + }while (msg_received != 1); + + thr_chn->p_msg = (unsigned char*)malloc(ret); + if (NULL == thr_chn->p_msg) + { + ret = -1; + DISPLAY_ERR("Error allocating memory!"); + } + else + { + printf("Number of byte receive %d\n",ret); + thr_chn->msg_length = ret; + memcpy(thr_chn->p_msg, data, ret); /* copy the msg into the thr structure */ + printf("calling %x\n", thr_chn->funct); + (thr_chn->funct)(param); + free(thr_chn->p_msg); + thr_chn->p_msg = NULL; + } + + /* deallocate memory for the Throttle Message */ + free(thr_msg); + thr_msg = NULL; + p_data = NULL; + } + } + return(ret); +} + + +static int thr_msg_check(const unsigned char* thr_msg, unsigned short chn_id, unsigned short length) +{ + int ret = 0; + + if (length > THR_MSG_HEADER_LEN) /* Ethernet Raw Packet contains a valid Payload ? */ + { + if (THROTTLENET_PROTO == ntohs(THR_MSG_ETH_TYP)) /* Is Ethernet Type THROTTLENET Protocol ? */ + { + if (THR_MSG_CHN_ID == chn_id) /* Is Channel identification correct ? */ + { + /* throttle message is correct */ + } + else + { + ret = -1; + } + } + else + { + /* discard the message */ + ret = -2; + } + } + else + { + /* discard the message */ + ret = -3; + } + return(ret); +} + + +int thr_read(struct thr_chn_t* thr_chn, unsigned char* data, int length) +{ + int ret = 0; + + if ((NULL == thr_chn) || (NULL == data)) + { + ret = -1; + errno = EINVAL; + DISPLAY_ERR("Input parameter(s) NULL"); + } + else + { + if (length > thr_chn->msg_length) + { + length = thr_chn->msg_length; + printf("thr_read: truncating length to %d\n", length); + } + printf("thr_read: calling memcpy(%x, %x, %d\n", data, thr_chn->p_msg, length); + memcpy(data, thr_chn->p_msg, length); /* copy the msg into the thr structure */ + ret = length; + thr_chn->msg_length = 0; + } + return(ret); +} diff --git a/lib/c/ThrottleDrv/throttle_drv.h b/lib/c/ThrottleDrv/throttle_drv.h new file mode 100644 index 0000000..567c36d --- /dev/null +++ b/lib/c/ThrottleDrv/throttle_drv.h @@ -0,0 +1,17 @@ +#ifndef _THROTTLE_DRV_H_ +#define _THROTTLE_DRV_H_ + +#define ETH_ADR_SIZE 6 + +/* typedef of the callback used to manage the received Ethernet Frame (the User Data)*/ +typedef int (*thr_msg_handler_t)(void* data); +struct thr_chn_t; + + +int thr_init(const char* eth_int); +struct thr_chn_t* thr_open_chn(const unsigned char* dst_adr, unsigned char chn_id, unsigned char frag_size, unsigned short freq, thr_msg_handler_t funct); +int thr_receive (struct thr_chn_t* thr_chn, unsigned char* data, void* param); +int thr_send(const struct thr_chn_t* thr_chn, const char* data, unsigned int length); +int thr_read(struct thr_chn_t* thr_chn, unsigned char* data, int length); + +#endif diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c index ee93aec..13aff96 100644 --- a/lib/c/labcomm.c +++ b/lib/c/labcomm.c @@ -41,7 +41,7 @@ static labcomm_sample_entry_t *get_sample_by_signature_address( { labcomm_sample_entry_t *p; for (p = head ; p && p->signature != signature ; p = p->next) { - + } return p; } @@ -55,7 +55,7 @@ static labcomm_sample_entry_t *get_sample_by_signature_value( if (p->signature->type == signature->type && p->signature->size == signature->size && strcmp(p->signature->name, signature->name) == 0 && - bcmp((void*)p->signature->signature, (void*)signature->signature, + bcmp((void*)p->signature->signature, (void*)signature->signature, signature->size) == 0) { break; } @@ -90,7 +90,7 @@ static int get_encoder_index( return result; } -static void do_encoder_register(struct labcomm_encoder *e, +static void do_encoder_register(struct labcomm_encoder *e, labcomm_signature_t *signature, labcomm_encode_typecast_t encode) { @@ -98,7 +98,7 @@ static void do_encoder_register(struct labcomm_encoder *e, if (get_encoder_index(e, signature) == 0) { int i; labcomm_encoder_context_t *context = e->context; - labcomm_sample_entry_t *sample = + labcomm_sample_entry_t *sample = (labcomm_sample_entry_t*)malloc(sizeof(labcomm_sample_entry_t)); sample->next = context->sample; sample->index = context->index; @@ -112,7 +112,7 @@ static void do_encoder_register(struct labcomm_encoder *e, labcomm_encode_type_index(e, signature); labcomm_encode_string(e, signature->name); for (i = 0 ; i < signature->size ; i++) { - if (e->writer.pos >= e->writer.count) { + if (e->writer.pos >= e->writer.count) { e->writer.write(&e->writer, labcomm_writer_continue); } e->writer.data[e->writer.pos] = signature->signature[i]; @@ -124,13 +124,13 @@ static void do_encoder_register(struct labcomm_encoder *e, } static void do_encode( - labcomm_encoder_t *encoder, - labcomm_signature_t *signature, + labcomm_encoder_t *encoder, + labcomm_signature_t *signature, void *value) { labcomm_encoder_context_t *context = encoder->context; labcomm_sample_entry_t *sample; - sample = get_sample_by_signature_address(context->sample, + sample = get_sample_by_signature_address(context->sample, signature); if (sample && sample->encode) { sample->encode(encoder, value); @@ -165,7 +165,7 @@ labcomm_encoder_t *labcomm_encoder_new( } void labcomm_internal_encoder_register( - labcomm_encoder_t *e, + labcomm_encoder_t *e, labcomm_signature_t *signature, labcomm_encode_typecast_t encode) { @@ -177,26 +177,26 @@ void labcomm_internal_encoder_register( } void labcomm_internal_encode( - labcomm_encoder_t *e, - labcomm_signature_t *signature, + labcomm_encoder_t *e, + labcomm_signature_t *signature, void *value) { if (e && e->do_encode) { e->do_encode(e, signature, value); } else { printf("Encoder is missing do_encode\n"); - } + } } - + void labcomm_internal_encoder_user_action(labcomm_encoder_t *e, int action) { e->writer.write(&e->writer, action); } -void labcomm_encoder_free(labcomm_encoder_t* e) +void labcomm_encoder_free(labcomm_encoder_t* e) { - + e->writer.write(&e->writer, labcomm_writer_free); free(e); } @@ -208,7 +208,7 @@ void labcomm_encode_type_index(labcomm_encoder_t *e, labcomm_signature_t *s) } static int signature_writer( - labcomm_writer_t *w, + labcomm_writer_t *w, labcomm_writer_action_t action) { switch (action) { @@ -219,13 +219,13 @@ static int signature_writer( w->pos = 0; } break; case labcomm_writer_start: { - w->data_size = 1000; + w->data_size = 1000; w->count = w->data_size; w->data = realloc(w->data, w->data_size); w->pos = 0; } break; case labcomm_writer_continue: { - w->data_size += 1000; + w->data_size += 1000; w->count = w->data_size; w->data = realloc(w->data, w->data_size); } break; @@ -257,7 +257,7 @@ static void collect_flat_signature( switch (type) { case LABCOMM_ARRAY: { int dimensions, i; - + dimensions = labcomm_decode_int(decoder); labcomm_encode_int(signature_writer, dimensions); for (i = 0 ; i < dimensions ; i++) { @@ -294,16 +294,16 @@ static void collect_flat_signature( } static void do_decoder_register( - labcomm_decoder_t *decoder, - labcomm_signature_t *signature, + labcomm_decoder_t *decoder, + labcomm_signature_t *signature, labcomm_decoder_typecast_t type_decoder, labcomm_handler_typecast_t handler, void *handler_context) { - + labcomm_decoder_context_t *context = decoder->context; labcomm_sample_entry_t *sample; - sample = get_sample_by_signature_address(context->sample, + sample = get_sample_by_signature_address(context->sample, signature); if (!sample) { sample = (labcomm_sample_entry_t*)malloc(sizeof(labcomm_sample_entry_t)); @@ -311,7 +311,7 @@ static void do_decoder_register( context->sample = sample; sample->index = 0; sample->signature = signature; - } + } sample->decoder = type_decoder; sample->handler = handler; sample->context = handler_context; @@ -323,7 +323,7 @@ static int do_decode_one(labcomm_decoder_t *d) do { result = d->reader.read(&d->reader, labcomm_reader_start); - if (result > 0) { + if (result > 0) { labcomm_decoder_context_t *context = d->context; result = labcomm_decode_int(d); @@ -332,7 +332,7 @@ static int do_decode_one(labcomm_decoder_t *d) labcomm_signature_t signature; labcomm_sample_entry_t *entry; int index; - + e->writer.write(&e->writer, labcomm_writer_start); signature.type = result; index = labcomm_decode_int(d); @@ -343,10 +343,10 @@ static int do_decode_one(labcomm_decoder_t *d) entry = get_sample_by_signature_value(context->sample, &signature); if (! entry) { // Unknown datatype, bail out - fprintf(stderr, "%s: unknown datatype '%s' (id=0x%x)\n", + fprintf(stderr, "%s: unknown datatype '%s' (id=0x%x)\n", __FUNCTION__, signature.name, index); } else if (entry->index && entry->index != index) { - fprintf(stderr, "%s: index mismatch '%s' (id=0x%x != 0x%x)\n", + fprintf(stderr, "%s: index mismatch '%s' (id=0x%x != 0x%x)\n", __FUNCTION__, signature.name, entry->index, index); } else { entry->index = index; @@ -360,10 +360,10 @@ static int do_decode_one(labcomm_decoder_t *d) labcomm_encoder_free(e); } else { labcomm_sample_entry_t *entry; - + entry = get_sample_by_index(context->sample, result); if (!entry) { - fprintf(stderr, "%s: type not found (id=0x%x)\n", + fprintf(stderr, "%s: type not found (id=0x%x)\n", __FUNCTION__, result); result = -ENOENT; } else { @@ -372,7 +372,7 @@ static int do_decode_one(labcomm_decoder_t *d) } } d->reader.read(&d->reader, labcomm_reader_end); - } while (result > 0 && result < LABCOMM_USER); + } while (result > 0 && result < LABCOMM_USER); return result; } @@ -400,8 +400,8 @@ labcomm_decoder_t *labcomm_decoder_new( } void labcomm_internal_decoder_register( - labcomm_decoder_t *d, - labcomm_signature_t *signature, + labcomm_decoder_t *d, + labcomm_signature_t *signature, labcomm_decoder_typecast_t type_decoder, labcomm_handler_typecast_t handler, void *handler_context) @@ -416,9 +416,13 @@ void labcomm_internal_decoder_register( int labcomm_decoder_decode_one(labcomm_decoder_t *d) { int result = -1; - if (d && d->do_decode_one) { + if (d && d->do_decode_one) + { + printf("labcomm decode 1\n"); result = d->do_decode_one(d); - } else { + } + else + { printf("Decoder is missing do_decode_one\n"); } return result; @@ -430,7 +434,7 @@ void labcomm_decoder_run(labcomm_decoder_t *d) } } -void labcomm_decoder_free(labcomm_decoder_t* d) +void labcomm_decoder_free(labcomm_decoder_t* d) { d->reader.read(&d->reader, labcomm_reader_free); free(d); diff --git a/lib/c/labcomm_thr_reader_writer.c b/lib/c/labcomm_thr_reader_writer.c new file mode 100644 index 0000000..4ba0147 --- /dev/null +++ b/lib/c/labcomm_thr_reader_writer.c @@ -0,0 +1,141 @@ +#include <errno.h> +#include <unistd.h> +#include "labcomm.h" +#include "ThrottleDrv/throttle_drv.h" + +#define BUFFER_SIZE 2048 + +int labcomm_thr_reader(labcomm_reader_t *r, labcomm_reader_action_t action) +{ + int result = -EINVAL; + struct thr_chn_t *ctx = r->context; + + switch (action) + { + case labcomm_reader_alloc: + { + r->data = malloc(BUFFER_SIZE); + if (r->data) + { + r->data_size = BUFFER_SIZE; + result = r->data_size; + } + else + { + r->data_size = 0; + result = -ENOMEM; + } + r->count = 0; + r->pos = 0; + } + break; + + case labcomm_reader_start: + case labcomm_reader_continue: + { + printf("labcomm_reader_start or continue...\n"); + if (r->pos < r->count) + { + result = r->count - r->pos; + } + else + { + int err; + r->pos = 0; + printf("labcomm_thr_reader_writer. calling thr_read: %x, %x, %d\n", ctx, r->data, r->data_size); + err = thr_read(ctx, r->data, r->data_size); + if (err <= 0) + { + r->count = 0; + result = -1; + } else + { + r->count = err; + result = r->count - r->pos; + } + } + } + break; + + case labcomm_reader_end: + { + result = 0; + } + break; + + case labcomm_reader_free: + { + free(r->data); + r->data = 0; + r->data_size = 0; + r->count = 0; + r->pos = 0; + result = 0; + } + break; + } + return result; +} + +int labcomm_thr_writer(labcomm_writer_t *w, labcomm_writer_action_t action) +{ + int result = 0; + struct thr_chn_t *ctx = w->context; + + switch (action) + { + case labcomm_writer_alloc: + { + w->data = malloc(BUFFER_SIZE); + if (! w->data) + { + result = -ENOMEM; + w->data_size = 0; + w->count = 0; + w->pos = 0; + } + else + { + w->data_size = BUFFER_SIZE; + w->count = BUFFER_SIZE; + w->pos = 0; + } + } break; + case labcomm_writer_free: + { + free(w->data); + w->data = 0; + w->data_size = 0; + w->count = 0; + w->pos = 0; + } + break; + + case labcomm_writer_start: + { + w->pos = 0; + } + break; + + case labcomm_writer_continue: + { + result = thr_send(ctx, w->data, w->pos); + w->pos = 0; + } + break; + + case labcomm_writer_end: + { + result = thr_send(ctx, w->data, w->pos); + w->pos = 0; + } + break; + + case labcomm_writer_available: + { + result = w->count - w->pos; + } + break; + } + return result; +} diff --git a/lib/c/labcomm_thr_reader_writer.h b/lib/c/labcomm_thr_reader_writer.h new file mode 100644 index 0000000..0adf36e --- /dev/null +++ b/lib/c/labcomm_thr_reader_writer.h @@ -0,0 +1,5 @@ +#include "labcomm.h" + +extern int labcomm_thr_reader(labcomm_reader_t *r, labcomm_reader_action_t action); + +extern int labcomm_thr_writer(labcomm_writer_t *r, labcomm_writer_action_t action); -- GitLab