├── .gitignore ├── NET_API ├── inc │ ├── arp.h │ ├── dhcp.h │ ├── ethernet.h │ ├── icmp.h │ ├── ipv4.h │ ├── network_utilities.h │ ├── tcp.h │ └── udp.h └── src │ ├── arp.c │ ├── dhcp.c │ ├── ethernet.c │ ├── icmp.c │ ├── ipv4.c │ ├── network_utilities.c │ ├── tcp.c │ └── udp.c ├── README.md ├── enc28j60.c ├── enc28j60.h ├── main.c ├── tm4c123gh6pm.h ├── tm4c123gh6pm_startup_ccs.c ├── wait.c └── wait.h /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | Debug 3 | 4 | targetConfigs 5 | 6 | *.cmd 7 | 8 | .ccsproject 9 | .cproject 10 | .launches 11 | .project 12 | .settings 13 | -------------------------------------------------------------------------------- /NET_API/inc/arp.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file arp.h 4 | * @author Aditya Mall, 5 | * @brief arp protocol header file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | #ifndef ARP_H_ 43 | #define ARP_H_ 44 | 45 | 46 | /* 47 | * Standard header and api header files 48 | */ 49 | #include 50 | 51 | #include "ethernet.h" 52 | 53 | 54 | 55 | /******************************************************************************/ 56 | /* */ 57 | /* Defines */ 58 | /* */ 59 | /******************************************************************************/ 60 | 61 | /* Used by other protocols to resolve address */ 62 | #define ARP_FRAME_SIZE 28 63 | 64 | 65 | 66 | 67 | /******************************************************************************/ 68 | /* */ 69 | /* ARP Function Prototypes */ 70 | /* */ 71 | /******************************************************************************/ 72 | 73 | 74 | /******************************************************** 75 | * @brief Function to send arp request 76 | * @param *ethernet : reference to the Ethernet handle 77 | * @param *sender_ip : sender ip address 78 | * @param *target_ip : target ip address 79 | * @retval int16_t : Error = -1, Success = 0 80 | ********************************************************/ 81 | int16_t ether_send_arp_req(ethernet_handle_t *ethernet, uint8_t *sender_ip, uint8_t *target_ip); 82 | 83 | 84 | 85 | /********************************************************** 86 | * @brief Function to independently read ARP data 87 | * (Blocking Call) 88 | * @param *ethernet : reference to the Ethernet handle 89 | * @param *data : network_data 90 | * @param *data_length : length of data to be read 91 | * @retval uint8_t : Error = 0, Success = 1 92 | **********************************************************/ 93 | uint8_t ether_is_arp(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length); 94 | 95 | 96 | 97 | /****************************************************************** 98 | * @brief Function to handle ARP request and reply 99 | * sends ARP reply if ARP request received 100 | * @param *ethernet : reference to the Ethernet handle 101 | * @retval int16_t : Error = -2, -3 = reply ignore, Success = 0 102 | ******************************************************************/ 103 | int16_t ether_handle_arp_resp_req(ethernet_handle_t *ethernet); 104 | 105 | 106 | 107 | 108 | /*********************************************************************** 109 | * @brief Function to get MAC address from destination IP address 110 | * by searching local ARP table 111 | * @param *ethernet : reference to the Ethernet handle 112 | * @param *mac_address : device mac_address 113 | * @param *ip_address : device ip address 114 | * @retval int8_t : Success = 1 device found else 0 for not found 115 | ***********************************************************************/ 116 | uint8_t ether_arp_resolve_address(ethernet_handle_t *ethernet, uint8_t *destination_mac, uint8_t *destination_ip); 117 | 118 | 119 | 120 | 121 | #endif /* ARP_H_ */ 122 | -------------------------------------------------------------------------------- /NET_API/inc/dhcp.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file dhcp.h 4 | * @author Aditya Mall, 5 | * @brief DHCP protocol header file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | #ifndef DHCP_H_ 43 | #define DHCP_H_ 44 | 45 | 46 | 47 | /* 48 | * Standard header and api header files 49 | */ 50 | #include 51 | 52 | #include "ethernet.h" 53 | 54 | 55 | 56 | /******************************************************************************/ 57 | /* */ 58 | /* Data Structures and Defines */ 59 | /* */ 60 | /******************************************************************************/ 61 | 62 | 63 | 64 | 65 | /* DHCP states */ 66 | typedef enum _dhcp_state_values 67 | { 68 | DHCP_INIT_STATE = 1, 69 | DHCP_SELECTING_STATE = 2, 70 | DHCP_READ_STATE = 3, 71 | DHCP_REQUESTING_STATE = 4, 72 | DHCP_ACK_STATE = 5, 73 | DHCP_BOUND_STATE = 6, 74 | 75 | }dhcp_states; 76 | 77 | 78 | 79 | 80 | /******************************************************************************/ 81 | /* */ 82 | /* DHCP Functions Prototypes */ 83 | /* */ 84 | /******************************************************************************/ 85 | 86 | 87 | 88 | /************************************************************** 89 | * @brief Function Send DHCP Discover 90 | * @param *ethernet : reference to the Ethernet handle 91 | * @param transaction_id : random transaction ID 92 | * 93 | * @param seconds_elapsed : number of seconds elapsed 94 | * @retval uint8_t : Error = -1, Success = 0 95 | **************************************************************/ 96 | int8_t ether_dhcp_send_discover(ethernet_handle_t *ethernet, uint32_t transaction_id, uint8_t *mac_address, 97 | uint16_t seconds_elapsed); 98 | 99 | 100 | 101 | 102 | /************************************************************ 103 | * @brief Function read DHCP offer 104 | * @param *ethernet : reference to the Ethernet handle 105 | * @param *network_data : network_data from PHY 106 | * @param *your_ip : 'your IP' address 107 | * 108 | * @param *dhcp_options : DHCP options data 109 | * @retval uint8_t : Error = 0, Success = DHCP type 110 | ************************************************************/ 111 | int8_t ether_dhcp_read(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *your_ip, uint32_t client_transac_id, uint8_t *dhcp_options); 112 | 113 | 114 | 115 | 116 | /************************************************************ 117 | * @brief Function read DHCP offer (Depreciated) 118 | * @param *ethernet : reference to the Ethernet handle 119 | * @param *network_data : network_data from PHY 120 | * @param *your_ip : 'your IP' address 121 | * @param *server_ip : server IP address 122 | * @param *subnet_mask : SUBNET mask 123 | * @param *lease_time : IP address lease time 124 | * @retval uint8_t : Error = 0, Success = 1 125 | ************************************************************/ 126 | int8_t ether_dhcp_read_offer(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *your_ip, uint8_t *server_ip, 127 | uint8_t *subnet_mask, uint8_t *lease_time); 128 | 129 | 130 | 131 | 132 | /************************************************************* 133 | * @brief Function Send DHCP Request 134 | * @param *ethernet : reference to the Ethernet handle 135 | * @param transaction_id : random transaction ID 136 | * @param seconds_elapsed : number of seconds elapsed 137 | * @param *server_ip : DHCP server IP 138 | * @param *requested_ip : IP request to the server 139 | * @param *lease_time : Lease time 140 | * @retval uint8_t : Error = -1, Success = 0 141 | *************************************************************/ 142 | int8_t ether_dhcp_send_request(ethernet_handle_t *ethernet, uint32_t transaction_id, uint16_t seconds_elapsed, 143 | uint8_t *server_ip, uint8_t *requested_ip, uint32_t lease_time); 144 | 145 | 146 | 147 | 148 | /************************************************************* 149 | * @brief Function to get IP though DHCP state machine 150 | * @param *ethernet : reference to the Ethernet handle 151 | * @param *network_data : network data from PHY 152 | * 153 | * @param dhcp_state : DHCP state machine states 154 | * @retval uint8_t : Error = NA, Success = NA 155 | *************************************************************/ 156 | int8_t ether_get_dhcp_ip(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *mac_address, 157 | dhcp_states dhcp_state); 158 | 159 | 160 | 161 | 162 | #endif /* DHCP_H_ */ 163 | -------------------------------------------------------------------------------- /NET_API/inc/ethernet.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file ethernet.h 4 | * @author Aditya Mall, 5 | * @brief ethernet layer header file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | #ifndef ETHERNET_H_ 43 | #define ETHERNET_H_ 44 | 45 | 46 | 47 | /* 48 | * Standard header and api header files 49 | */ 50 | #include 51 | 52 | 53 | 54 | /******************************************************************************/ 55 | /* */ 56 | /* Macros and Defines */ 57 | /* */ 58 | /******************************************************************************/ 59 | 60 | /* structure padding */ 61 | #define pragma pack(1) 62 | 63 | 64 | #define ETHER_PHY_DATA_OFFSET 4 65 | 66 | #define ETHER_MAC_SIZE 6 /*!< Size of MAC address */ 67 | #define ETHER_FRAME_SIZE 14 /*!< Ethernet Frame size */ 68 | #define ETHER_IPV4_SIZE 4 /*!< IP protocol version 4 size */ 69 | #define ARP_TABLE_SIZE 5 /*!< ARP Table size define */ 70 | #define ETHER_MTU_SIZE 1460 /*!< MAX MTU size */ 71 | #define APP_BUFF_SIZE 500 /*!< Application buffer size */ 72 | 73 | 74 | /* Function define for random number generator function */ 75 | #define get_unique_id get_random_port 76 | #define get_unique_id_l get_random_port_l 77 | 78 | 79 | /******************************************************************************/ 80 | /* */ 81 | /* Data Structures */ 82 | /* */ 83 | /******************************************************************************/ 84 | 85 | 86 | 87 | /* Ethernet Frame structure (14 Bytes) */ 88 | typedef struct _ether_frame 89 | { 90 | uint8_t destination_mac_addr[6]; /*!< Destination MAC address */ 91 | uint8_t source_mac_addr[6]; /*!< Source MAC address */ 92 | uint16_t type; /*!< Ethernet frame type */ 93 | uint8_t data; /*!< Ethernet data/payload */ 94 | 95 | }ether_frame_t; 96 | 97 | 98 | 99 | /* Ethernet Handle type defined */ 100 | typedef struct _ethernet_handle ethernet_handle_t; 101 | 102 | 103 | /* ARP Table */ 104 | typedef struct _arp_table 105 | { 106 | uint8_t ip_address[ETHER_IPV4_SIZE]; /*!< Device IP address */ 107 | uint8_t mac_address[ETHER_MAC_SIZE]; /*!< Device MAC address */ 108 | 109 | }arp_table_t; 110 | 111 | 112 | /* */ 113 | typedef struct _network_timer_operations 114 | { 115 | uint8_t (*open)(void); 116 | uint8_t (*start)(uint8_t timer_type, uint32_t seconds); 117 | uint8_t (*stop)(void); 118 | uint8_t (*reset)(void); 119 | 120 | }net_timer_ops_t; 121 | 122 | 123 | /* Ethernet/Network Operations handle */ 124 | typedef struct _ethernet_operations 125 | { 126 | uint8_t function_lock; /*!< Function Lock for exclusive access of functions (experimental ) */ 127 | uint8_t (*open)(uint8_t *mac_address); /*!< Function initialize network/ETHER PHY, takes MAC address as parameter */ 128 | uint8_t (*network_interface_status)(void); /*!< Network / Ethernet module packet receive status / trigger */ 129 | uint16_t (*random_gen_seed)(void); /*!< Seed value return function for random number generation */ 130 | int16_t (*ether_send_packet)(uint8_t *data, uint16_t length); /*!< Callback function to send Ethernet packet */ 131 | uint16_t (*ether_recv_packet)(uint8_t *data, uint16_t length); /*!< Callback function to receive Ethernet packet */ 132 | 133 | }ether_operations_t; 134 | 135 | 136 | /* Ethernet status fields */ 137 | typedef struct _network_status 138 | { 139 | uint8_t mode_static : 1; 140 | uint8_t mode_dynamic : 1; 141 | uint8_t mode_dhcp_init : 1; 142 | uint8_t mode_dhcp_bound : 1; 143 | uint8_t mode_read_blocking : 1; 144 | uint8_t net_app_data_rdy : 1; 145 | uint8_t reserved : 2; 146 | 147 | }net_status_t; 148 | 149 | 150 | 151 | /* Ethernet/Network Handle */ 152 | struct _ethernet_handle 153 | { 154 | ether_frame_t *ether_obj; /*!< Ethernet frame object */ 155 | net_status_t status; /*!< Ethernet status fields */ 156 | ether_operations_t *ether_commands; /*!< Network Operations */ 157 | arp_table_t arp_table[ARP_TABLE_SIZE]; /*!< ARP Table */ 158 | 159 | uint16_t ip_identifier; /*!< */ 160 | uint16_t source_port; /*!< Ethernet source port, gets random source port value */ 161 | char *net_application_data; /*!< Network application data, allocated by create handle */ 162 | uint16_t net_app_data_length; /*!< */ 163 | uint8_t host_mac[ETHER_MAC_SIZE]; /*!< Host MAC address, given by handle */ 164 | uint8_t host_ip[ETHER_IPV4_SIZE]; /*!< Host IP address, static or dynamic */ 165 | uint8_t broadcast_mac[ETHER_MAC_SIZE]; /*!< Broadcast MAC address */ 166 | uint8_t broadcast_ip[ETHER_IPV4_SIZE]; /*!< Broadcast IP address */ 167 | uint8_t subnet_mask[ETHER_IPV4_SIZE]; /*!< SUBNET mask, gets value from DHCP sever */ 168 | uint8_t gateway_ip[ETHER_IPV4_SIZE]; /*!< Gateway or DHCP Server IP, from DHCP server */ 169 | uint32_t lease_time; /*!< IP lease time, from DHCP server */ 170 | 171 | }; 172 | 173 | 174 | /**/ 175 | typedef enum _ether_control_modes 176 | { 177 | ETHER_READ_NONBLOCK = 0, 178 | ETHER_READ_BLOCK = 1, 179 | ETHER_IP_STATIC = 2, 180 | ETHER_IP_DYNAMIC = 3, 181 | 182 | }ether_control_t; 183 | 184 | 185 | 186 | /* Ethernet source address fields, used for raw transport layer protocol functions */ 187 | typedef struct _ethernet_source_addr 188 | { 189 | uint8_t source_mac[ETHER_MAC_SIZE]; /*!< Source MAC address */ 190 | uint8_t source_ip[ETHER_IPV4_SIZE]; /*!< Source IP address */ 191 | uint16_t source_port; /*!< Source port */ 192 | uint16_t identifier; /*!< Protocol Message ID */ 193 | 194 | }ether_source_t; 195 | 196 | 197 | 198 | /* Ethernet type values */ 199 | typedef enum _ether_type 200 | { 201 | ETHER_IPV4 = 0x0800, /*!< IP protocol version 4 Ethernet type value */ 202 | ETHER_ARP = 0x0806, /*!< ARP protocol Ethernet type value */ 203 | ETHER_RARP = 0x8035, /*!< RARP protocol Ethernet type value */ 204 | 205 | }ether_type_t; 206 | 207 | 208 | 209 | /* Network error codes protocol functions */ 210 | typedef enum _network_error_codes 211 | { 212 | NET_ARP_REQ_ERROR = -1, /*!< */ 213 | NET_ARP_RESP_ERROR = -2, /*!< */ 214 | NET_ARP_RESP_IGNORE = -3, /*!< */ 215 | NET_IP_GET_ERROR = -4, /*!< */ 216 | NET_IP_CHECKSUM_ERROR = -5, /*!< */ 217 | NET_ICMP_RESP_ERROR = -6, /*!< */ 218 | NET_ICMP_RESP_IGNORE = -7, /*!< */ 219 | NET_ICMP_REQ_ERROR = -8, /*!< */ 220 | NET_UDP_RAW_SEND_ERROR = -9, /*!< */ 221 | NET_UDP_SEND_ERROR = -10, /*!< */ 222 | NET_TCP_CONNECT_ERROR = -11, /*!< */ 223 | NET_TCP_SEND_ERROR = -12, /*!< */ 224 | NET_TCP_READ_ERROR = -13, /*!< */ 225 | NET_FUNC_NO_RDWR = -14, /*!< */ 226 | 227 | }network_erro_codes_t; 228 | 229 | 230 | 231 | 232 | 233 | /******************************************************************************/ 234 | /* */ 235 | /* Ethernet Function Prototypes */ 236 | /* */ 237 | /******************************************************************************/ 238 | 239 | 240 | 241 | /****************************************************** 242 | * @brief Function to sum the data in network packet 243 | * @param *sum : Total 32 bit sum 244 | * @param *data : data to be summed 245 | * @param size_in_bytes : size of the data 246 | * @retval uint16_t : Error = -1, Success = 0 247 | ******************************************************/ 248 | int8_t ether_sum_words(uint32_t *sum, void *data, uint16_t size_in_bytes); 249 | 250 | 251 | 252 | /****************************************************** 253 | * @brief Function to get checksum of network packet 254 | * @param *sum : Total 32 bit sum 255 | * @retval uint16_t : checksum value 256 | ******************************************************/ 257 | uint16_t ether_get_checksum(uint32_t sum); 258 | 259 | 260 | 261 | 262 | /****************************************************** 263 | * @brief Function to get random number above a bound 264 | * @param *ethernet : reference to Ethernet handle 265 | * @param lower_bound : lower bound value 266 | * @retval uint16_t : Error = -1, Success = 0 267 | ******************************************************/ 268 | int16_t get_random_port(ethernet_handle_t *ethernet, uint16_t lower_bound); 269 | 270 | 271 | 272 | 273 | /****************************************************** 274 | * @brief Function to get random number above a bound 275 | * (32 bit) 276 | * @param *ethernet : reference to Ethernet handle 277 | * @param lower_bound : lower bound value 278 | * @retval uint32_t : Error = -1, Success = 0 279 | ******************************************************/ 280 | int32_t get_random_port_l(ethernet_handle_t *ethernet, uint32_t lower_bound); 281 | 282 | 283 | 284 | 285 | /************************************************************************** 286 | * @brief constructor function to create Ethernet handle 287 | * (Multiple exit points) 288 | * @param *network_data : reference to the network data buffer 289 | * @param *mac_address : MAC address (string) 290 | * @param *ip_address : ip address (string) 291 | * @param *ether_ops : reference to the Ethernet operations structure 292 | * @retval int8_t : Error = NULL, Success = Ethernet object 293 | **************************************************************************/ 294 | ethernet_handle_t* create_ethernet_handle(uint8_t *network_data, char *mac_address, char *ip_address, ether_operations_t *ether_ops); 295 | 296 | 297 | 298 | 299 | 300 | uint8_t ether_control(ethernet_handle_t *ethernet, ether_control_t ether_mode); 301 | 302 | 303 | 304 | /********************************************************** 305 | * @brief Function to get the Ethernet device status 306 | * @param *ethernet : reference to the Ethernet Handle 307 | * @retval uint8_t : Error = 0, Success = 1 308 | *********************************************************/ 309 | uint8_t ether_module_status(ethernet_handle_t *ethernet); 310 | 311 | 312 | 313 | /*********************************************************** 314 | * @brief Function get Ethernet network data 315 | * @param *ethernet : reference to the Ethernet handle 316 | * @param *data : network data 317 | * @param *data_length : source MAC address 318 | * @retval uint8_t : Error = 0, Success = 1 319 | ***********************************************************/ 320 | uint8_t ether_get_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length); 321 | 322 | 323 | 324 | /*********************************************************** 325 | * @brief Function send Ethernet network data 326 | * @param *ethernet : reference to the Ethernet handle 327 | * @param *data : network data 328 | * @param *data_length : source MAC address 329 | * @retval uint8_t : Error = 0, Success = 1 330 | ***********************************************************/ 331 | uint8_t ether_send_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length); 332 | 333 | 334 | 335 | /********************************************************************** 336 | * @brief Function to fill the Ethernet frame 337 | * @param *ethernet : reference to the Ethernet handle 338 | * @param *destination_mac_address : destination MAC address 339 | * @param *source_mac_address : source MAC address 340 | * @param frame type : Ethernet frame type 341 | * @retval int8_t : Error = -1, Success = 0 342 | **********************************************************************/ 343 | int8_t fill_ether_frame(ethernet_handle_t *ethernet, uint8_t *destination_mac_addr, uint8_t *source_mac_addr, ether_type_t frame_type); 344 | 345 | 346 | 347 | /*********************************************************** 348 | * @brief Function get ethernet protocol type 349 | * @param *ethernet : reference to the Ethernet handle 350 | * @retval ether_type_t : Error = 0, Success = 1 351 | ***********************************************************/ 352 | ether_type_t get_ether_protocol_type(ethernet_handle_t *ethernet); 353 | 354 | 355 | 356 | #endif /* ETHERNET_H_ */ 357 | -------------------------------------------------------------------------------- /NET_API/inc/icmp.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file icmp.h 4 | * @author Aditya Mall, 5 | * @brief ICMP (for IPV4) header file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | 43 | #ifndef ICMP_H_ 44 | #define ICMP_H_ 45 | 46 | 47 | 48 | 49 | /* 50 | * Standard header and api header files 51 | */ 52 | #include 53 | 54 | #include "ethernet.h" 55 | 56 | 57 | /******************************************************************************/ 58 | /* */ 59 | /* Data Structures and Defines */ 60 | /* */ 61 | /******************************************************************************/ 62 | 63 | 64 | /* ICMP message types */ 65 | typedef enum _icmp_type 66 | { 67 | ICMP_ECHOREPLY = 0, /*!< ICMP Echo reply code */ 68 | ICMP_UNREACHABLE = 3, /*!< ICMP destination unreachable code */ 69 | ICMP_ECHOREQUEST = 8, /*!< ICMP Echo request code */ 70 | ICMP_TRACEROUTE = 30, /*!< ICMP Trace route code */ 71 | 72 | }icmp_type_t; 73 | 74 | 75 | 76 | 77 | /******************************************************************************/ 78 | /* */ 79 | /* ICMP Function Prototypes */ 80 | /* */ 81 | /******************************************************************************/ 82 | 83 | 84 | 85 | 86 | /****************************************************************** 87 | * @brief Function to send ICMP reply packet 88 | * @param *ethernet : reference to the Ethernet handle 89 | * @retval int16_t : Error = -6, -7 = reply ignore, Success = 0 90 | ******************************************************************/ 91 | int8_t ether_send_icmp_reply(ethernet_handle_t *ethernet); 92 | 93 | 94 | 95 | /***************************************************************** 96 | * @brief Function to send ICMP request 97 | * @param *ethernet : Reference to the Ethernet structure 98 | * @param icmp_type : ICMP request type 99 | * @param *destination_ip : Destination IP address 100 | * @param sequence_no : ICMP packet sequence Number 101 | * @param *destination_mac : Destination MAC address 102 | * @param *source_mac : Source MAC address 103 | * @retval int8_t : Error = -8, Success = 0. 104 | ****************************************************************/ 105 | int8_t ether_send_icmp_req(ethernet_handle_t *ethernet, icmp_type_t icmp_type, uint8_t *destination_ip, 106 | uint8_t *sequence_no, uint8_t* destination_mac, uint8_t *source_mac); 107 | 108 | 109 | #endif /* ICMP_H_ */ 110 | -------------------------------------------------------------------------------- /NET_API/inc/ipv4.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file ipv4.h 4 | * @author Aditya Mall, 5 | * @brief IP version 4 protocol header file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | #ifndef IPV4_H_ 43 | #define IPV4_H_ 44 | 45 | 46 | /* 47 | * Standard header and api header files 48 | */ 49 | #include 50 | 51 | #include "ethernet.h" 52 | 53 | 54 | 55 | 56 | /******************************************************************************/ 57 | /* */ 58 | /* Data Structures and Defines */ 59 | /* */ 60 | /******************************************************************************/ 61 | 62 | 63 | #define IP_VERSION 4 /*!< IP protocol version */ 64 | #define IP_HEADER_LENGTH 5 /*!< IP header length value (not header size) */ 65 | #define IP_DF_SET 0x4000 /*!< Don't Fragment set value */ 66 | #define IP_TTL_VALUE 64 /*!< Time to Live value */ 67 | #define IP_HEADER_SIZE 20 /*!< IP header size */ 68 | 69 | /* IP version and header length fields */ 70 | typedef struct _ip_ver_size 71 | { 72 | uint8_t header_length : 4; /*!< Header length value */ 73 | uint8_t version : 4; /*!< IP version value */ 74 | 75 | }ip_ver_size_t; 76 | 77 | 78 | /* IP Frame structure (20 Bytes in current implementation) */ 79 | typedef struct _net_ip 80 | { 81 | ip_ver_size_t version_length; /*!< IP version and header length */ 82 | uint8_t service_type; /*!< IP quality of service type */ 83 | uint16_t total_length; /*!< IP packet total length */ 84 | uint16_t id; /*!< IP packet ID */ 85 | uint16_t flags_offset; /*!< IP fragmentation flags and offset */ 86 | uint8_t ttl; /*!< Time to Live value */ 87 | uint8_t protocol; /*!< IP protocol type */ 88 | uint16_t header_checksum; /*!< IP header checksum */ 89 | uint8_t source_ip[4]; /*!< Source IP address */ 90 | uint8_t destination_ip[4]; /*!< Destination IP address */ 91 | 92 | }net_ip_t; 93 | 94 | 95 | /* IP protocol type values */ 96 | typedef enum _ip_protocol_type 97 | { 98 | IP_ICMP = 0x01, 99 | IP_TCP = 0x06, 100 | IP_UDP = 0x11, 101 | 102 | }ip_protocol_type_t; 103 | 104 | 105 | 106 | 107 | /******************************************************************************/ 108 | /* */ 109 | /* IPV4 Function Prototypes */ 110 | /* */ 111 | /******************************************************************************/ 112 | 113 | 114 | 115 | /************************************************************** 116 | * @brief Function to get IP data for current host device 117 | * validates IP Checksum, (Only handles UNICAST) 118 | * @param *ethernet : reference to the Ethernet handle 119 | * @retval int16_t : Error = -4, -5, 120 | * Success = 1 (UNICAST), 121 | * = 2 (BROADCAST) 122 | **************************************************************/ 123 | int16_t get_ip_communication_type(ethernet_handle_t *ethernet); 124 | 125 | 126 | 127 | 128 | /**************************************************************** 129 | * @brief Function to get IP protocol type 130 | * @param *ethernet : reference to the Ethernet handle 131 | * @retval int16_t : Error = -4, -5, Success = protocol type 132 | ***************************************************************/ 133 | ip_protocol_type_t get_ip_protocol_type(ethernet_handle_t *ethernet); 134 | 135 | 136 | 137 | 138 | /********************************************************** 139 | * @brief Function to fill the IP frame 140 | * @param *ip : reference to the IP structure 141 | * @param *id : reference to IP identifier 142 | * @param *destination_ip : destination IP address 143 | * @param *source_ip : source IP address 144 | * @param protocol : IP protocol type 145 | * @param data_size : size of payload 146 | * @retval int8_t : Error = NULL 147 | **********************************************************/ 148 | int8_t fill_ip_frame(net_ip_t *ip, uint16_t *id, uint8_t *destination_ip, uint8_t *source_ip, ip_protocol_type_t protocol, uint16_t data_size); 149 | 150 | 151 | 152 | 153 | #endif /* IPV4_H_ */ 154 | -------------------------------------------------------------------------------- /NET_API/inc/network_utilities.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file network_utilities.h 4 | * @author Aditya Mall, 5 | * @brief Network utility header file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | #ifndef NETWORK_UTILITIES_H_ 43 | #define NETWORK_UTILITIES_H_ 44 | 45 | 46 | 47 | 48 | /* 49 | * Standard header and api header files 50 | */ 51 | #include 52 | 53 | 54 | 55 | 56 | 57 | /******************************************************************************/ 58 | /* */ 59 | /* Data Structures and Defines */ 60 | /* */ 61 | /******************************************************************************/ 62 | 63 | 64 | /* defines network to host order function */ 65 | #define ntohs htons 66 | 67 | #define ntohl htonl 68 | 69 | 70 | /******************************************************************************/ 71 | /* */ 72 | /* Network Utility Function Prototypes */ 73 | /* */ 74 | /******************************************************************************/ 75 | 76 | 77 | 78 | /************************************************************************ 79 | * @brief Function to convert from host to network order and vice versa 80 | * (For 16 bit data) 81 | * @retval uint16_t : host to network or network to host converted data 82 | ************************************************************************/ 83 | uint16_t htons(uint16_t value); 84 | 85 | 86 | 87 | /************************************************************************ 88 | * @brief Function to convert from host to network order and vice versa 89 | * (For 32 bit data) 90 | * Copyright (C) 1997-2019 Free Software Foundation, Inc. 91 | * 92 | * @retval uint32_t : host to network or network to host converted data 93 | ************************************************************************/ 94 | uint32_t htonl(uint32_t x); 95 | 96 | 97 | 98 | /******************************************************** 99 | * @brief Function to set mac address 100 | * @param *device_mac : device mac address (Hex) 101 | * @param *mac_address : mac address (string) 102 | * @retval int8_t : Error = -1, Success = 0 103 | ********************************************************/ 104 | int8_t set_mac_address(uint8_t *device_mac, char *mac_address); 105 | 106 | 107 | 108 | /******************************************************** 109 | * @brief function to set ip address 110 | * @param *host_ip : host ip address (integer) 111 | * @param *ip_address : ip address (string) 112 | * @retval int8_t : Error = -1, Success = 0 113 | ********************************************************/ 114 | int8_t set_ip_address(uint8_t *host_ip, char *ip_address); 115 | 116 | 117 | 118 | 119 | /*********************************************** 120 | * @brief Function to swap network address 121 | * (used in response messages) 122 | * @param *l_address : address value LHS 123 | * @param *r_address : address value RHS 124 | * @param size : size of address 125 | * @retval int8_t : Error = -1, Success = 0 126 | ***********************************************/ 127 | int8_t net_swap_address(uint8_t* l_address, uint8_t *r_address, uint8_t size); 128 | 129 | 130 | 131 | 132 | /********************************************************* 133 | * @brief Function to set broadcast address 134 | * @param *destination_address : destination address 135 | * @param size : size of address 136 | * @retval int8_t : Error = -1, Success = 0 137 | *********************************************************/ 138 | int8_t set_broadcast_address(uint8_t *destination_address, uint8_t size); 139 | 140 | 141 | 142 | #endif /* NETWORK_UTILITIES_H_ */ 143 | -------------------------------------------------------------------------------- /NET_API/inc/tcp.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file TCP.h 4 | * @author Aditya Mall, 5 | * @brief TCP protocol header file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | 43 | #ifndef TCP_H_ 44 | #define TCP_H_ 45 | 46 | 47 | /* 48 | * Standard header and API header files 49 | */ 50 | #include 51 | #include "ethernet.h" 52 | 53 | 54 | /******************************************************************************/ 55 | /* */ 56 | /* Data Structures and Defines */ 57 | /* */ 58 | /******************************************************************************/ 59 | 60 | /* TCP ACK flags */ 61 | typedef enum _tcp_control_flags 62 | { 63 | 64 | TCP_FIN = 0x01, 65 | TCP_SYN = 0x02, 66 | TCP_RST = 0x04, 67 | TCP_PSH = 0x08, 68 | TCP_ACK = 0x10, 69 | TCP_FIN_ACK = 0x11, 70 | TCP_SYN_ACK = 0x12, 71 | TCP_RST_ACK = 0x14, 72 | TCP_PSH_ACK = 0x18, 73 | TCP_FIN_PSH_ACK = 0x19, 74 | 75 | }tcp_ctl_flags_t; 76 | 77 | 78 | typedef enum _tcp_read_state 79 | { 80 | TCP_READ_BLOCKING = 1, 81 | TCP_READ_NONBLOCK = 2, 82 | 83 | }tcp_read_state_t; 84 | 85 | 86 | /* TCP client handle flags */ 87 | typedef struct _tcp_client_flags 88 | { 89 | uint8_t connect_request : 1; 90 | uint8_t connect_established : 1; 91 | uint8_t server_tcp_reset : 1; 92 | uint8_t server_close : 1; 93 | uint8_t client_close : 1; 94 | uint8_t client_blocking : 1; 95 | uint8_t reserved : 2; 96 | 97 | }tcp_client_flags_t; 98 | 99 | 100 | /* TCP client handle */ 101 | typedef struct _tcp_handle 102 | { 103 | uint16_t source_port; 104 | uint16_t destination_port; 105 | uint32_t sequence_number; 106 | uint32_t acknowledgement_number; 107 | uint8_t server_ip[4]; 108 | 109 | tcp_client_flags_t client_flags; 110 | 111 | 112 | }tcp_handle_t; 113 | 114 | 115 | 116 | /******************************************************************************/ 117 | /* */ 118 | /* TCP Functions Prototypes */ 119 | /* */ 120 | /******************************************************************************/ 121 | 122 | 123 | 124 | /******************************************************************** 125 | * @brief Function to create TCP client object (STATIC) 126 | * @param source_port : TCP source port 127 | * @param destination_port : TCP destination port 128 | * @param *server_ip : Server IP 129 | * @retval int8_t : Error = 0, Success = TCP client object 130 | ********************************************************************/ 131 | tcp_handle_t* ether_tcp_create_client(ethernet_handle_t *ethernet, 132 | uint8_t *network_data, 133 | uint16_t source_port, 134 | uint16_t destination_port, 135 | uint8_t *server_ip); 136 | 137 | 138 | 139 | 140 | /***************************************************************** 141 | * @brief Function to initialize TCP values to TCP client object 142 | * @param *client : Reference to TCP client handle 143 | * @param source_port : TCP source port 144 | * @param destination_port : TCP destination port 145 | * @param *server_ip : Server IP 146 | * @retval int8_t : Error = 0, Success = 1 147 | *****************************************************************/ 148 | uint8_t tcp_init_client(tcp_handle_t *client, 149 | uint16_t source_port, 150 | uint16_t destination_port, 151 | uint8_t *server_ip); 152 | 153 | 154 | 155 | 156 | /********************************************************** 157 | * @brief Function to establish connection to TCP server 158 | * @param *ethernet : Reference to Ethernet handle 159 | * @param *network_data : Network data 160 | * @param *client : reference to TCP client handle 161 | * @retval int8_t : Error = -11, Success = 1 162 | **********************************************************/ 163 | int8_t ether_tcp_connect(ethernet_handle_t *ethernet, uint8_t *network_data ,tcp_handle_t *client); 164 | 165 | 166 | 167 | 168 | /***************************************************************** 169 | * @brief Function to control TCP read behavior 170 | * @param *client : Reference to TCP handle 171 | * @param app_state : TCP read type (blocking or non blocking) 172 | * @retval int8_t : Error = 0, Success = 1 173 | ****************************************************************/ 174 | int8_t tcp_control(tcp_handle_t *client, tcp_read_state_t app_state); 175 | 176 | 177 | 178 | 179 | 180 | /*************************************************************** 181 | * @brief Function for sending TCP data 182 | * @param *ethernet : Reference to the Ethernet Handle 183 | * @param *network_data : Network data 184 | * @param *client : Reference to TCP client handle 185 | * @param *application_data : application_data 186 | * @param data_length : application data length 187 | * @retval int8_t : Error = -12, 188 | * Success = 1 189 | * -14(Connection closed) 190 | ***************************************************************/ 191 | int32_t ether_tcp_send_data(ethernet_handle_t *ethernet, 192 | uint8_t *network_data, 193 | tcp_handle_t *client, 194 | char *application_data, 195 | uint16_t data_length); 196 | 197 | 198 | 199 | 200 | 201 | /************************************************************************ 202 | * @brief helper function for reading TCP data 203 | * @param *ethernet : Reference to the Ethernet Handle 204 | * @param *network_data : Network data 205 | * @param *client : Reference to TCP client handle 206 | * @param *application_data : application_data 207 | * @param data_length : application data length 208 | * @retval uint16_t : Error = 0, Success = number of bytes read 209 | * 1 = ACK received 210 | ************************************************************************/ 211 | int32_t ether_tcp_read_data(ethernet_handle_t *ethernet, 212 | uint8_t *network_data, 213 | tcp_handle_t *client, 214 | char *tcp_data, 215 | uint16_t data_length); 216 | 217 | 218 | 219 | 220 | /*************************************************************** 221 | * @brief Function for close socket 222 | * @param *ethernet : Reference to the Ethernet Handle 223 | * @param *network_data : Network data 224 | * @param *client : Reference to TCP handle 225 | * @retval uint16_t : Error = 0, Success = 1; 226 | ***************************************************************/ 227 | uint8_t ether_tcp_close(ethernet_handle_t *ethernet, uint8_t *network_data, tcp_handle_t *client); 228 | 229 | 230 | 231 | 232 | #endif /* TCP_H_ */ 233 | -------------------------------------------------------------------------------- /NET_API/inc/udp.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file udp.h 4 | * @author Aditya Mall, 5 | * @brief UDP protocol header file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | 43 | #ifndef _UDP_H 44 | #define _UDP_H 45 | 46 | 47 | 48 | /* 49 | * Standard header and api header files 50 | */ 51 | #include 52 | 53 | #include "ethernet.h" 54 | 55 | 56 | 57 | 58 | /******************************************************************************/ 59 | /* */ 60 | /* UDP Functions Prototypes */ 61 | /* */ 62 | /******************************************************************************/ 63 | 64 | 65 | 66 | /************************************************************** 67 | * @brief Function get calculate UDP checksum 68 | * (UDP Headers + UDP data) 69 | * @param *ip : Reference to IP frame structure 70 | * @param *udp : Reference to UDP frame structure 71 | * @param data_length : Length of UDP data 72 | * @retval uint8_t : Error = 0, Success = checksum value 73 | **************************************************************/ 74 | uint8_t ether_get_udp_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length); 75 | 76 | 77 | 78 | 79 | /******************************************************************* 80 | * @brief Raw Function to send UPD packets 81 | * UDP data dependent upon total data allocated to 82 | * ethernet object 83 | * @param *ethernet : Reference to the Ethernet handle 84 | * @param *source_addr : Reference to source address structure 85 | * @param *destination_ip : Destination IP address 86 | * @param *destination_mac : Destination MAC address 87 | * @param destination_port : UDP destination port 88 | * @param *data : UDP data 89 | * @param data_length : Length of UDP data 90 | * @retval int8_t : Error = -9, Success = 0 91 | *******************************************************************/ 92 | int8_t ether_send_udp_raw(ethernet_handle_t *ethernet, ether_source_t *source_addr, uint8_t *destination_ip, 93 | uint8_t *destination_mac, uint16_t destination_port, uint8_t *data, uint16_t data_length); 94 | 95 | 96 | 97 | 98 | /**************************************************************** 99 | * @brief Function detect UDP packet, state machine independent 100 | * @param *ethernet : Reference to the Ethernet handle 101 | * @param *network_data : network data from PHY 102 | * @param network_data_length : network data length to be read 103 | * @retval uint8_t : Error = 0, 104 | * Success = 1 (UNICAST) 105 | * = 2 (BROADCAST) 106 | ****************************************************************/ 107 | uint8_t ether_is_udp(ethernet_handle_t *ethernet, uint8_t *network_data, uint16_t network_data_length); 108 | 109 | 110 | 111 | 112 | 113 | /***************************************************************** 114 | * @brief Function to read UPD packets 115 | * @param *ethernet : Reference to the Ethernet handle 116 | * @param *network_data : network data from PHY 117 | * @param *application_data : UDP data 118 | * @param app_data_length : Length of UDP data 119 | * @retval int8_t : Error = 0, Success = 1 120 | *****************************************************************/ 121 | uint8_t ether_read_udp(ethernet_handle_t *ethernet, uint8_t *network_data, char *application_data, uint16_t app_data_length); 122 | 123 | 124 | 125 | /************************************************************** 126 | * @brief Function to send UPD packets 127 | * UDP data dependent upon total data allocated to 128 | * ethernet object 129 | * @param *ethernet : Reference to the Ethernet handle 130 | * @param *destination_ip : Destination IP address 131 | * @param destination_port : UDP destination port 132 | * @param *application_data : UDP data 133 | * @param data_length : Length of UDP data 134 | * @retval int8_t : Error = -10, Success = 0 135 | **************************************************************/ 136 | int8_t ether_send_udp(ethernet_handle_t *ethernet, uint8_t *destination_ip, uint16_t destination_port, 137 | char *application_data, uint16_t data_length); 138 | 139 | 140 | 141 | 142 | 143 | /************************************************************** 144 | * @brief Function to read UDP packet 145 | * @param *ethernet : reference to the Ethernet handle 146 | * @param *network_data : network data from the ether PHY 147 | * @param net_data_length : network data length 148 | * @param *source_port : UDP source port 149 | * @param *destination_port : UDP destination port 150 | * @param *application_data : UDP data 151 | * @param data_length : Length of UDP data 152 | * @param app_data_length : 153 | * @retval uint16_t : Error = 0, Success = bytes read 154 | **************************************************************/ 155 | uint16_t ether_read_udp_raw(ethernet_handle_t *ethernet, uint8_t *network_data, uint16_t net_data_length, 156 | uint16_t *source_port, uint16_t *destination_port, char *application_data, uint16_t app_data_length); 157 | 158 | 159 | 160 | 161 | #endif /* UDP_H_ */ 162 | -------------------------------------------------------------------------------- /NET_API/src/arp.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file arp.c 4 | * @author Aditya Mall, 5 | * @brief ARP Protocol source file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | 43 | /* 44 | * Standard header and api header files 45 | */ 46 | #include 47 | #include 48 | 49 | 50 | #include "arp.h" 51 | #include "network_utilities.h" 52 | 53 | 54 | 55 | /******************************************************************************/ 56 | /* */ 57 | /* Data Structures and Defines */ 58 | /* */ 59 | /******************************************************************************/ 60 | 61 | 62 | 63 | /* ARP protocol structure */ 64 | typedef struct _net_arp 65 | { 66 | uint16_t hardware_type; /*!< Network hardware type */ 67 | uint16_t protocol_type; /*!< Network protocol type */ 68 | uint8_t hardware_size; /*!< Hardware address (MAC) length */ 69 | uint8_t protocol_size; /*!< Protocol address (IP) length */ 70 | uint16_t opcode; /*!< Opcode */ 71 | uint8_t sender_hw_addr[6]; /*!< Source hardware address */ 72 | uint8_t sender_ip[4]; /*!< Source IP address */ 73 | uint8_t target_hw_addr[6]; /*!< Destination hardware address */ 74 | uint8_t target_ip[4]; /*!< Source hardware address */ 75 | 76 | }net_arp_t; 77 | 78 | 79 | /* ARP protocol constant values */ 80 | typedef enum _arp_protocol_constants 81 | { 82 | ARP_HRD_ETHERNET = 1, /*!< Value for hardware type (Ethernet) */ 83 | ARP_PRO_IPV4 = 0x0800, /*!< Value for IPV4 protocol type */ 84 | ARP_HLN = 6, /*!< Length of hardware address */ 85 | ARP_PLN = 4 /*!< Length of IP address */ 86 | 87 | }arp_protocol_constants_t; 88 | 89 | 90 | 91 | /* ARP protocol opcode values */ 92 | typedef enum _arp_opcodes 93 | { 94 | ARP_REQUEST = 1, 95 | ARP_REPLY = 2, 96 | RARP_REQUEST = 3, 97 | RARP_REPLY = 4, 98 | 99 | }arp_opcodes_t; 100 | 101 | 102 | 103 | 104 | 105 | /******************************************************************************/ 106 | /* */ 107 | /* Private Functions */ 108 | /* */ 109 | /******************************************************************************/ 110 | 111 | 112 | 113 | /******************************************************** 114 | * @brief Static function to set broadcast mac address 115 | * @param *mac address : mac address to be configured 116 | * @retval int16_t : Error = -1, Success = 0 117 | ********************************************************/ 118 | static int8_t set_broadcast_mac_addr(uint8_t *mac_address) 119 | { 120 | int8_t func_retval = 0; 121 | 122 | int8_t index = 0; 123 | 124 | if(mac_address == NULL) 125 | { 126 | func_retval = -1; 127 | } 128 | else 129 | { 130 | for(index = 0; index < 6; index++ ) 131 | { 132 | mac_address[index] = 0xFF; 133 | } 134 | } 135 | 136 | return func_retval; 137 | } 138 | 139 | 140 | 141 | 142 | /****************************************************************************** 143 | * @brief Static Function to update ARP table 144 | * @param *ethernet : reference to the Ethernet handle 145 | * @param *ip_address : device ip address 146 | * @param *mac_address : device mac_address 147 | * @retval int8_t : Success = 0 (device added), 1(device already exists) 148 | ******************************************************************************/ 149 | static uint8_t update_arp_table(ethernet_handle_t *ethernet, uint8_t *ip_address, uint8_t *mac_address) 150 | { 151 | 152 | uint8_t func_retval = 0; 153 | 154 | uint8_t index = 0; 155 | uint8_t copy_index = 0; 156 | 157 | uint8_t found = 0; 158 | 159 | if(ethernet->ether_obj == NULL) 160 | { 161 | func_retval = 0; 162 | } 163 | else 164 | { 165 | 166 | for(index = 0; index < ARP_TABLE_SIZE; index++) 167 | { 168 | if( (memcmp(ethernet->arp_table[index].ip_address, ip_address, ETHER_IPV4_SIZE) == 0) ) 169 | { 170 | found = 1; 171 | 172 | break; 173 | } 174 | else if( (strncmp((char*)ethernet->arp_table[index].ip_address, 0, ETHER_IPV4_SIZE) == 0) ) 175 | { 176 | found = 0; 177 | 178 | /* Copy IP address */ 179 | for(copy_index = 0; copy_index < ETHER_IPV4_SIZE; copy_index++) 180 | { 181 | ethernet->arp_table[index].ip_address[copy_index] = ip_address[copy_index]; 182 | } 183 | 184 | /* Copy MAC address */ 185 | for(copy_index = 0; copy_index < ETHER_MAC_SIZE; copy_index++) 186 | { 187 | ethernet->arp_table[index].mac_address[copy_index] = mac_address[copy_index]; 188 | } 189 | 190 | break; 191 | } 192 | } 193 | 194 | func_retval = found; 195 | } 196 | 197 | return func_retval; 198 | } 199 | 200 | 201 | 202 | 203 | /****************************************************************************** 204 | * @brief Static Function to search ARP table 205 | * @param *ethernet : reference to the Ethernet handle 206 | * @param *mac_address : device mac_address 207 | * @param *ip_address : device ip address 208 | * @retval int8_t : Success = 1 (address found) 209 | * Error = 0 (address not found) 210 | ******************************************************************************/ 211 | static int8_t search_arp_table(ethernet_handle_t *ethernet, uint8_t *mac_address, uint8_t *ip_address) 212 | { 213 | 214 | int8_t func_retval = 0; 215 | 216 | uint8_t index = 0; 217 | uint8_t found = 0; 218 | 219 | 220 | for(index=0; index < ARP_TABLE_SIZE; index++) 221 | { 222 | 223 | if(memcmp(ethernet->arp_table[index].ip_address, ip_address , ETHER_IPV4_SIZE) == 0) 224 | { 225 | 226 | memcpy(mac_address, ethernet->arp_table[index].mac_address, ETHER_MAC_SIZE); 227 | 228 | found = 1; 229 | 230 | func_retval = found; 231 | 232 | break; 233 | } 234 | 235 | } 236 | 237 | return func_retval; 238 | } 239 | 240 | 241 | 242 | 243 | 244 | /******************************************************************************/ 245 | /* */ 246 | /* ARP Functions */ 247 | /* */ 248 | /******************************************************************************/ 249 | 250 | 251 | 252 | /******************************************************** 253 | * @brief Function to send arp request 254 | * @param *ethernet : reference to the Ethernet handle 255 | * @param *sender_ip : sender ip address 256 | * @param *target_ip : target ip address 257 | * @retval int16_t : Error = -1, Success = 0 258 | ********************************************************/ 259 | int16_t ether_send_arp_req(ethernet_handle_t *ethernet, uint8_t *sender_ip, uint8_t *target_ip) 260 | { 261 | int16_t func_retval = 0; 262 | 263 | net_arp_t *arp; 264 | 265 | uint8_t broadcast_mac_addr[6] = {0}; 266 | uint8_t i = 0; 267 | 268 | if(ethernet->ether_obj == NULL) 269 | { 270 | func_retval = NET_ARP_REQ_ERROR; 271 | } 272 | else 273 | { 274 | /* Link network object data */ 275 | arp = (void*)ðernet->ether_obj->data; 276 | 277 | 278 | /* Set Broadcast MAC */ 279 | set_broadcast_mac_addr(broadcast_mac_addr); 280 | 281 | 282 | /* Fill Ethernet frame */ 283 | fill_ether_frame(ethernet, broadcast_mac_addr, ethernet->host_mac, ETHER_ARP); 284 | 285 | 286 | /* Fill ARP frame */ 287 | arp->hardware_type = htons(ARP_HRD_ETHERNET); 288 | arp->protocol_type = htons(ARP_PRO_IPV4); 289 | arp->hardware_size = ARP_HLN; 290 | arp->protocol_size = ARP_PLN; 291 | arp->opcode = htons(ARP_REQUEST); 292 | 293 | for (i = 0; i < 6; i++) 294 | { 295 | arp->sender_hw_addr[i] = ethernet->host_mac[i]; 296 | arp->target_hw_addr[i] = broadcast_mac_addr[i]; 297 | } 298 | 299 | for (i = 0; i < 4; i++) 300 | { 301 | arp->sender_ip[i] = sender_ip[i]; 302 | arp->target_ip[i] = target_ip[i]; 303 | } 304 | 305 | /* Send packet (uses callback) */ 306 | ether_send_data(ethernet, (uint8_t*)ethernet->ether_obj, ETHER_FRAME_SIZE + ARP_FRAME_SIZE); 307 | } 308 | 309 | return func_retval; 310 | } 311 | 312 | 313 | 314 | 315 | /********************************************************** 316 | * @brief Function to independently read ARP data 317 | * (Blocking Call) 318 | * @param *ethernet : reference to the Ethernet handle 319 | * @param *data : network_data 320 | * @param *data_length : length of data to be read 321 | * @retval uint8_t : Error = 0, Success = 1 322 | **********************************************************/ 323 | uint8_t ether_is_arp(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length) 324 | { 325 | uint8_t func_retval = 0; 326 | uint8_t block_loop = 0; 327 | 328 | net_arp_t *arp; 329 | 330 | if(ethernet->ether_obj == NULL || data == NULL || data_length == 0 || data_length > UINT16_MAX) 331 | { 332 | func_retval = 0; 333 | } 334 | else 335 | { 336 | /* Wait for data */ 337 | block_loop = 1; 338 | 339 | do 340 | { 341 | if(ether_get_data(ethernet, data, data_length)) 342 | { 343 | /* Check if protocol is ARP */ 344 | if(ntohs(ethernet->ether_obj->type) == ETHER_ARP) 345 | { 346 | arp = (void*)ðernet->ether_obj->data; 347 | 348 | if(memcmp(arp->target_hw_addr, ethernet->host_mac, ETHER_MAC_SIZE) == 0) 349 | { 350 | 351 | func_retval = 1; 352 | 353 | break; 354 | } 355 | } 356 | } 357 | 358 | }while(block_loop); 359 | 360 | } 361 | 362 | return func_retval; 363 | } 364 | 365 | 366 | 367 | 368 | /****************************************************************** 369 | * @brief Function to handle ARP request and reply 370 | * sends ARP reply if ARP request received 371 | * @param *ethernet : reference to the Ethernet handle 372 | * @retval int16_t : Error = -2, -3 = reply ignore, Success = 0 373 | ******************************************************************/ 374 | int16_t ether_handle_arp_resp_req(ethernet_handle_t *ethernet) 375 | { 376 | int16_t func_retval = 0; 377 | 378 | net_arp_t *arp; 379 | 380 | uint8_t i = 0; 381 | 382 | if(ethernet->ether_obj == NULL || ethernet->ether_obj->type != ntohs(ETHER_ARP)) 383 | { 384 | func_retval = NET_ARP_RESP_ERROR; 385 | } 386 | else 387 | { 388 | 389 | arp = (void*)ðernet->ether_obj->data; 390 | 391 | /* Check if ARP request is for host IP */ 392 | if( (strncmp((char*)arp->target_ip, (char*)ethernet->host_ip, 4) == 0) ) 393 | { 394 | /* Handle APR request */ 395 | if(arp->opcode == ntohs(ARP_REQUEST)) 396 | { 397 | 398 | /* Get data into ARP Table */ 399 | update_arp_table(ethernet, arp->sender_ip, arp->sender_hw_addr); 400 | 401 | /* Swap Ethernet MAC Address */ 402 | for (i = 0; i < 6; i++) 403 | { 404 | ethernet->ether_obj->destination_mac_addr[i] = ethernet->ether_obj->source_mac_addr[i]; 405 | ethernet->ether_obj->source_mac_addr[i] = ethernet->host_mac[i]; 406 | } 407 | 408 | /* Fill ARP frame */ 409 | arp->hardware_type = htons(ARP_HRD_ETHERNET); 410 | arp->protocol_type = htons(ARP_PRO_IPV4); 411 | arp->hardware_size = ARP_HLN; 412 | arp->protocol_size = ARP_PLN; 413 | 414 | arp->opcode = htons(ARP_REPLY); 415 | 416 | /* Swap ARP hardware/MAC address */ 417 | for (i = 0; i < 6; i++) 418 | { 419 | arp->target_hw_addr[i] = arp->sender_hw_addr[i]; 420 | arp->sender_hw_addr[i] = ethernet->host_mac[i]; 421 | } 422 | 423 | /* Swap ARP IP address */ 424 | for (i = 0; i < 4; i++) 425 | { 426 | arp->target_ip[i] = arp->sender_ip[i]; 427 | arp->sender_ip[i] = ethernet->host_ip[i]; 428 | } 429 | 430 | /* Send packet (uses callback) */ 431 | ether_send_data(ethernet, (uint8_t*)ethernet->ether_obj, ETHER_FRAME_SIZE + 28); 432 | } 433 | 434 | /* Handle APR reply */ 435 | else if(arp->opcode == ntohs(ARP_REPLY)) 436 | { 437 | update_arp_table(ethernet, arp->sender_ip, arp->sender_hw_addr); 438 | } 439 | 440 | } 441 | else 442 | { 443 | func_retval = NET_ARP_RESP_IGNORE; 444 | } 445 | 446 | } 447 | 448 | return func_retval; 449 | } 450 | 451 | 452 | 453 | 454 | 455 | /*********************************************************************** 456 | * @brief Function to get MAC address from destination IP address 457 | * by searching local ARP table 458 | * @param *ethernet : reference to the Ethernet handle 459 | * @param *mac_address : device mac_address 460 | * @param *ip_address : device ip address 461 | * @retval int8_t : Success = 1 device found else 0 for not found 462 | ***********************************************************************/ 463 | uint8_t ether_arp_resolve_address(ethernet_handle_t *ethernet, uint8_t *destination_mac, uint8_t *destination_ip) 464 | { 465 | 466 | uint8_t func_retval = 0; 467 | 468 | /* Search arp table to find MAC address of the associated IP */ 469 | func_retval = search_arp_table(ethernet, destination_mac, destination_ip); 470 | 471 | 472 | return func_retval; 473 | } 474 | 475 | 476 | 477 | 478 | 479 | -------------------------------------------------------------------------------- /NET_API/src/dhcp.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file dhcp.c 4 | * @author Aditya Mall, 5 | * @brief DHCP protocol source file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | 43 | 44 | 45 | /* 46 | * Standard header and api header files 47 | */ 48 | 49 | #include 50 | #include 51 | 52 | #include "udp.h" 53 | #include "network_utilities.h" 54 | #include "dhcp.h" 55 | #include "arp.h" 56 | 57 | 58 | 59 | /******************************************************************************/ 60 | /* */ 61 | /* Data Structures and Defines */ 62 | /* */ 63 | /******************************************************************************/ 64 | 65 | 66 | #pragma pack(1) 67 | 68 | #define DHCP_FRAME_SIZE 240 69 | #define DHCP_DISCOVER_OPTS_SIZE 18 70 | #define DHCP_REQUEST_OPTS_SIZE 36 71 | 72 | 73 | 74 | /* DHCP UDP port */ 75 | typedef enum _network_ports 76 | { 77 | DHCP_DESTINATION_PORT = 67, 78 | DHCP_SOURCE_PORT = 68, 79 | 80 | }network_ports_t; 81 | 82 | 83 | 84 | /* DHCP FRAME (240 bytes), options variable data */ 85 | typedef struct _net_dhcp 86 | { 87 | uint8_t op_code; /*!< Operation code or message type */ 88 | uint8_t hw_type; /*!< Hardware type */ 89 | uint8_t hw_length; /*!< Hardware length */ 90 | uint8_t hops; /*!< Number of Hops */ 91 | uint32_t transaction_id; /*!< */ 92 | uint16_t seconds; /*!< */ 93 | uint16_t flags; /*!< */ 94 | uint8_t client_ip[4]; /*!< */ 95 | uint8_t your_ip[4]; /*!< */ 96 | uint8_t server_ip[4]; /*!< */ 97 | uint8_t gateway_ip[4]; /*!< */ 98 | uint8_t client_hw_addr[6]; /*!< */ 99 | uint8_t client_hw_addr_pad[10]; /*!< */ 100 | uint8_t server_name[64]; /*!< */ 101 | uint8_t boot_filename[128]; /*!< */ 102 | uint8_t magic_cookie[4]; /*!< */ 103 | uint8_t options; 104 | 105 | }net_dhcp_t ; 106 | 107 | 108 | 109 | 110 | /************* DHCP Discover options structures **************/ 111 | 112 | /* DHCP Option message type */ 113 | typedef struct _opts_53 114 | { 115 | uint8_t option_number; 116 | uint8_t length; 117 | uint8_t dhcp; 118 | 119 | }dhcp_option_53_t; 120 | 121 | 122 | /* DHCP Option parameter request list */ 123 | typedef struct _opts_55 124 | { 125 | uint8_t option_number; 126 | uint8_t length; 127 | uint8_t req_item[3]; 128 | 129 | }dhcp_option_55_t; 130 | 131 | 132 | /* DHCP Option client identifier */ 133 | typedef struct _opts_61 134 | { 135 | uint8_t option_number; 136 | uint8_t length; 137 | uint8_t hw_type; 138 | uint8_t client_mac[ETHER_MAC_SIZE]; 139 | 140 | }dhcp_option_61_t; 141 | 142 | 143 | 144 | /* DHCP Discover options (18 bytes) */ 145 | typedef struct _dhcp_discover_options 146 | { 147 | dhcp_option_53_t message_type; 148 | dhcp_option_55_t param_request_list; 149 | dhcp_option_61_t client_identifier; 150 | uint8_t options_end; 151 | 152 | }dhcp_discover_opts_t; 153 | 154 | 155 | 156 | /************* DHCP Offer options structures **************/ 157 | 158 | /* */ 159 | typedef struct _opts_54 160 | { 161 | uint8_t option_number; 162 | uint8_t length; 163 | uint8_t server_ip[ETHER_IPV4_SIZE]; 164 | 165 | }dhcp_option_54_t; 166 | 167 | /* */ 168 | typedef struct _opts_51 169 | { 170 | uint8_t option_number; 171 | uint8_t length; 172 | uint32_t lease_time; 173 | 174 | }dhcp_option_51_t; 175 | 176 | /* */ 177 | typedef struct _opts_1 178 | { 179 | uint8_t option_number; 180 | uint8_t length; 181 | uint8_t subnet_mask[ETHER_IPV4_SIZE]; 182 | 183 | }dhcp_option_1_t; 184 | 185 | /* */ 186 | typedef struct _opts_3 187 | { 188 | uint8_t option_number; 189 | uint8_t length; 190 | uint8_t router[ETHER_IPV4_SIZE]; 191 | 192 | }dhcp_option_3_t; 193 | 194 | 195 | 196 | /* DHCP Offer options */ 197 | typedef struct _dhcp_offer_options 198 | { 199 | dhcp_option_53_t message_type; 200 | dhcp_option_54_t server_identifier; 201 | dhcp_option_51_t lease_time; 202 | dhcp_option_1_t subnet_mask; 203 | dhcp_option_3_t router; 204 | uint8_t options_end; 205 | 206 | }dhcp_offer_opts_t; 207 | 208 | 209 | /************* DHCP Offer Request structures **************/ 210 | 211 | 212 | /* */ 213 | typedef struct _opts_50 214 | { 215 | uint8_t option_number; 216 | uint8_t length; 217 | uint8_t requested_ip[ETHER_IPV4_SIZE]; 218 | 219 | }dhcp_option_50_t; 220 | 221 | 222 | 223 | /* DHCP Request options */ 224 | typedef struct _dhcp_request_options 225 | { 226 | dhcp_option_51_t lease_time; 227 | dhcp_option_53_t message_type; 228 | dhcp_option_55_t param_request_list; 229 | dhcp_option_61_t client_identifier; 230 | dhcp_option_50_t requested_ip; 231 | dhcp_option_54_t server_identifier; 232 | uint8_t options_end; 233 | 234 | }dhcp_request_opts_t; 235 | 236 | 237 | 238 | /* */ 239 | typedef enum _dhcp_boot_message 240 | { 241 | DHCP_BOOT_REQ = 1, 242 | DHCP_BOOT_REPLY = 2, 243 | DHCP_DISCOVER = 1, 244 | DHCP_OFFER = 2, 245 | DHCP_REQUEST = 3, 246 | DHCP_ACK = 5, 247 | 248 | }dhcp_boot_msg_t; 249 | 250 | 251 | 252 | /* */ 253 | typedef enum _dhcp_option_types 254 | { 255 | DHCP_SUBNET_MASK = 1, 256 | DHCP_ROUTER = 3, 257 | DHCP_REQUESTED_IP = 50, 258 | DHCP_ADDR_LEASE_TIME = 51, 259 | DHCP_MESSAGE_TYPE = 53, 260 | DHCP_SERVER_IDENTIFIER = 54, 261 | DHCP_PARAM_REQ_LIST = 55, 262 | DHCP_CLIENT_IDENTIFIER = 61, 263 | DHCP_OPTION_END = 255, 264 | 265 | }dhcp_options_types_t; 266 | 267 | 268 | 269 | /******************************************************************************/ 270 | /* */ 271 | /* DHCP Functions */ 272 | /* */ 273 | /******************************************************************************/ 274 | 275 | 276 | 277 | 278 | /*************************************************************** 279 | * @brief Function Send DHCP Discover 280 | * @param *ethernet : reference to the Ethernet handle 281 | * @param transaction_id : random transaction ID 282 | * 283 | * @param seconds_elapsed : number of seconds elapsed 284 | * @retval uint8_t : Error = -1, Success = 0 285 | ***************************************************************/ 286 | int8_t ether_dhcp_send_discover(ethernet_handle_t *ethernet, uint32_t transaction_id, uint8_t *mac_address, 287 | uint16_t seconds_elapsed) 288 | { 289 | 290 | int8_t func_retval = 0; 291 | 292 | net_dhcp_t *dhcp_discover; 293 | dhcp_discover_opts_t *discover_opts; 294 | ether_source_t dhcp_client; 295 | 296 | uint8_t destination_ip[4] = {0}; 297 | uint8_t destination_mac[6] = {0}; 298 | 299 | char data[258] = {0}; 300 | 301 | if(ethernet == NULL) 302 | { 303 | func_retval = -1; 304 | } 305 | else 306 | { 307 | /* Configure DHCP fields */ 308 | dhcp_discover = (net_dhcp_t*)data; 309 | 310 | dhcp_discover->op_code = DHCP_BOOT_REQ; 311 | dhcp_discover->hw_type = 1; 312 | dhcp_discover->hw_length = ETHER_MAC_SIZE; 313 | dhcp_discover->hops = 0; 314 | dhcp_discover->transaction_id = htonl(transaction_id); 315 | dhcp_discover->seconds = htons(seconds_elapsed); 316 | dhcp_discover->flags = htons(0x8000); 317 | 318 | /* client IP address = 0 */ 319 | /* your IP address = 0 */ 320 | /* server IP address = 0 */ 321 | /* gateway IP address = 0 */ 322 | 323 | /* client hardware address */ 324 | memcpy((char*)dhcp_discover->client_hw_addr, (char*)ethernet->host_mac, ETHER_MAC_SIZE); 325 | 326 | /* Client hardware address padding = 0 */ 327 | /* Client Server host name = 0 */ 328 | /* Client file name = 0 */ 329 | 330 | /* Configure magic cookie value */ 331 | dhcp_discover->magic_cookie[0] = 0x63; 332 | dhcp_discover->magic_cookie[1] = 0x82; 333 | dhcp_discover->magic_cookie[2] = 0x53; 334 | dhcp_discover->magic_cookie[3] = 0x63; 335 | 336 | 337 | /* Configure DHCP options */ 338 | discover_opts = (void*)&dhcp_discover->options; 339 | 340 | /* option (53) */ 341 | discover_opts->message_type.option_number = DHCP_MESSAGE_TYPE; 342 | discover_opts->message_type.length = 1; 343 | discover_opts->message_type.dhcp = DHCP_DISCOVER; 344 | 345 | /* option (55) */ 346 | discover_opts->param_request_list.option_number = DHCP_PARAM_REQ_LIST; 347 | discover_opts->param_request_list.length = 3; 348 | discover_opts->param_request_list.req_item[0] = DHCP_SUBNET_MASK; 349 | discover_opts->param_request_list.req_item[1] = DHCP_ROUTER; 350 | discover_opts->param_request_list.req_item[2] = DHCP_ADDR_LEASE_TIME; 351 | 352 | /* option (61) */ 353 | discover_opts->client_identifier.option_number = DHCP_CLIENT_IDENTIFIER; 354 | discover_opts->client_identifier.length = 7; 355 | discover_opts->client_identifier.hw_type = 1; 356 | 357 | memcpy((char*)discover_opts->client_identifier.client_mac, (char*)ethernet->host_mac, ETHER_MAC_SIZE); 358 | 359 | /* option end */ 360 | discover_opts->options_end = DHCP_OPTION_END; 361 | 362 | /* Configure sources */ 363 | memset(&dhcp_client, 0, sizeof(ether_source_t)); 364 | 365 | dhcp_client.identifier = 1; 366 | dhcp_client.source_port = DHCP_SOURCE_PORT; 367 | 368 | memcpy((char*)dhcp_client.source_mac, (char*)mac_address, ETHER_MAC_SIZE); 369 | 370 | /* Configure destination address */ 371 | memcpy((char*)destination_ip, (char*)ethernet->broadcast_ip, ETHER_IPV4_SIZE); 372 | memcpy((char*)destination_mac, (char*)ethernet->broadcast_mac, ETHER_MAC_SIZE); 373 | 374 | 375 | /* Send DHCP packet as UPD message */ 376 | ether_send_udp_raw(ethernet, &dhcp_client, destination_ip, destination_mac, DHCP_DESTINATION_PORT, 377 | (uint8_t*)dhcp_discover, (DHCP_FRAME_SIZE + DHCP_DISCOVER_OPTS_SIZE)); 378 | } 379 | 380 | return func_retval; 381 | } 382 | 383 | 384 | 385 | 386 | /************************************************************ 387 | * @brief Function read DHCP offer 388 | * @param *ethernet : reference to the Ethernet handle 389 | * @param *network_data : network_data from PHY 390 | * @param *your_ip : 'your IP' address 391 | * 392 | * @param *dhcp_options : DHCP options data 393 | * @retval uint8_t : Error = 0, Success = DHCP type 394 | ************************************************************/ 395 | int8_t ether_dhcp_read(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *your_ip, uint32_t client_transac_id, uint8_t *dhcp_options) 396 | { 397 | int8_t func_retval = 0; 398 | uint16_t udp_message_length = 0; 399 | 400 | net_dhcp_t *dhcp_reply; 401 | dhcp_offer_opts_t *dhcp_opts; 402 | 403 | uint16_t udp_src_port = 0; 404 | uint16_t udp_dest_port = 0; 405 | 406 | char dhcp_data[APP_BUFF_SIZE] = {0}; 407 | 408 | if(ethernet == NULL || network_data == NULL) 409 | { 410 | func_retval = 0; 411 | } 412 | else 413 | { 414 | /* read UDP packet */ 415 | udp_message_length = ether_read_udp_raw(ethernet, network_data, ETHER_MTU_SIZE, &udp_src_port, &udp_dest_port, dhcp_data, APP_BUFF_SIZE); 416 | 417 | 418 | /* Check if UDP source ports = DHCP destination port */ 419 | if(udp_src_port == DHCP_DESTINATION_PORT && udp_dest_port == DHCP_SOURCE_PORT && udp_message_length) 420 | { 421 | dhcp_reply = (void*)dhcp_data; 422 | 423 | if(client_transac_id == ntohl(dhcp_reply->transaction_id)) 424 | { 425 | 426 | /* Get your_ip from DHCP standard header*/ 427 | strncpy((char*)your_ip, (char*)dhcp_reply->your_ip, ETHER_IPV4_SIZE); 428 | 429 | /* Get server_ip, SUBNET mask, lease time from DHCP offer options */ 430 | dhcp_opts = (void*)&dhcp_reply->options; 431 | 432 | func_retval = dhcp_opts->message_type.dhcp; 433 | 434 | memcpy(dhcp_options, (uint8_t*)dhcp_opts, (udp_message_length - DHCP_FRAME_SIZE)); 435 | } 436 | 437 | } 438 | 439 | } 440 | 441 | return func_retval; 442 | } 443 | 444 | 445 | 446 | 447 | 448 | 449 | /************************************************************ 450 | * @brief Function read DHCP offer (Depreciated) 451 | * @param *ethernet : reference to the Ethernet handle 452 | * @param *network_data : network_data from PHY 453 | * @param *your_ip : 'your IP' address 454 | * @param *server_ip : server IP address 455 | * @param *subnet_mask : SUBNET mask 456 | * @param *lease_time : IP address lease time 457 | * @retval uint8_t : Error = 0, Success = 1 458 | ************************************************************/ 459 | int8_t ether_dhcp_read_offer(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *your_ip, uint8_t *server_ip, 460 | uint8_t *subnet_mask, uint8_t *lease_time) 461 | { 462 | int8_t func_retval = 0; 463 | uint8_t api_retval = 0; 464 | 465 | net_dhcp_t *dhcp_offer; 466 | dhcp_offer_opts_t *offer_opts; 467 | 468 | uint16_t udp_src_port = 0; 469 | uint16_t udp_dest_port = 0; 470 | 471 | char dhcp_data[300] = {0}; 472 | 473 | if(ethernet == NULL || network_data == NULL) 474 | { 475 | func_retval = 0; 476 | } 477 | else 478 | { 479 | /* read UDP packet */ 480 | api_retval = ether_read_udp_raw(ethernet, network_data, 350, &udp_src_port, &udp_dest_port, dhcp_data, 300); 481 | 482 | 483 | /* Check if UDP source ports = DHCP destination port */ 484 | if(udp_src_port == DHCP_DESTINATION_PORT && udp_dest_port == DHCP_SOURCE_PORT && api_retval) 485 | { 486 | dhcp_offer = (void*)dhcp_data; 487 | 488 | /* Get your_ip from DHCP standard header*/ 489 | memcpy((char*)your_ip, (char*)dhcp_offer->your_ip, ETHER_IPV4_SIZE); 490 | 491 | 492 | /* Get server_ip, SUBNET mask, lease time from DHCP offer options */ 493 | offer_opts = (void*)&dhcp_offer->options; 494 | 495 | memcpy((char*)server_ip, (char*)offer_opts->server_identifier.server_ip, ETHER_IPV4_SIZE); 496 | 497 | memcpy((char*)lease_time, (char*)offer_opts->lease_time.lease_time, ETHER_IPV4_SIZE); 498 | 499 | memcpy((char*)subnet_mask, (char*)offer_opts->subnet_mask.subnet_mask, ETHER_IPV4_SIZE); 500 | 501 | 502 | func_retval = 1; 503 | } 504 | 505 | } 506 | 507 | return func_retval; 508 | } 509 | 510 | 511 | 512 | 513 | 514 | /************************************************************* 515 | * @brief Function Send DHCP Request 516 | * @param *ethernet : reference to the Ethernet handle 517 | * @param transaction_id : random transaction ID 518 | * @param seconds_elapsed : number of seconds elapsed 519 | * @param *server_ip : DHCP server IP 520 | * @param *requested_ip : IP request to the server 521 | * @param *lease_time : Lease time 522 | * @retval uint8_t : Error = -1, Success = 0 523 | *************************************************************/ 524 | int8_t ether_dhcp_send_request(ethernet_handle_t *ethernet, uint32_t transaction_id, uint16_t seconds_elapsed, 525 | uint8_t *server_ip, uint8_t *requested_ip, uint32_t lease_time) 526 | { 527 | 528 | int8_t func_retval = 0; 529 | 530 | net_dhcp_t *dhcp_request; 531 | dhcp_request_opts_t *request_opts; 532 | ether_source_t dhcp_client; 533 | 534 | uint8_t destination_ip[4] = {0}; 535 | uint8_t destination_mac[6] = {0}; 536 | 537 | char data[280] = {0}; 538 | 539 | if(ethernet == NULL) 540 | { 541 | func_retval = -1; 542 | } 543 | else 544 | { 545 | /* Configure DHCP fields */ 546 | dhcp_request = (net_dhcp_t*)data; 547 | 548 | dhcp_request->op_code = DHCP_BOOT_REQ; 549 | dhcp_request->hw_type = 1; 550 | dhcp_request->hw_length = ETHER_MAC_SIZE; 551 | dhcp_request->hops = 0; 552 | dhcp_request->transaction_id = htonl(transaction_id); 553 | dhcp_request->seconds = htons(seconds_elapsed); 554 | dhcp_request->flags = htons(0x8000); 555 | 556 | /* client IP address = 0 */ 557 | /* your IP address = 0 */ 558 | /* server IP address = 0 */ 559 | /* gateway IP address = 0 */ 560 | 561 | /* client hardware address */ 562 | strncpy((char*)dhcp_request->client_hw_addr, (char*)ethernet->host_mac, ETHER_MAC_SIZE); 563 | 564 | /* Client hardware address padding = 0 */ 565 | /* Client Server host name = 0 */ 566 | /* Client file name = 0 */ 567 | 568 | /* Configure magic cookie value */ 569 | dhcp_request->magic_cookie[0] = 0x63; 570 | dhcp_request->magic_cookie[1] = 0x82; 571 | dhcp_request->magic_cookie[2] = 0x53; 572 | dhcp_request->magic_cookie[3] = 0x63; 573 | 574 | 575 | /* Configure DHCP options */ 576 | request_opts = (void*)&dhcp_request->options; 577 | 578 | 579 | /* options (51) */ 580 | request_opts->lease_time.option_number = DHCP_ADDR_LEASE_TIME; 581 | request_opts->lease_time.length = 4; 582 | //memcpy((char*)request_opts->lease_time.lease_time, (char*)lease_time, 4); 583 | request_opts->lease_time.lease_time = htonl(lease_time); 584 | 585 | 586 | /* option (53) */ 587 | request_opts->message_type.option_number = DHCP_MESSAGE_TYPE; 588 | request_opts->message_type.length = 1; 589 | request_opts->message_type.dhcp = DHCP_REQUEST; 590 | 591 | /* option (55) */ 592 | request_opts->param_request_list.option_number = DHCP_PARAM_REQ_LIST; 593 | request_opts->param_request_list.length = 3; 594 | request_opts->param_request_list.req_item[0] = DHCP_SUBNET_MASK; 595 | request_opts->param_request_list.req_item[1] = DHCP_ROUTER; 596 | request_opts->param_request_list.req_item[2] = DHCP_ADDR_LEASE_TIME; 597 | 598 | /* option (61) */ 599 | request_opts->client_identifier.option_number = DHCP_CLIENT_IDENTIFIER; 600 | request_opts->client_identifier.length = 7; 601 | request_opts->client_identifier.hw_type = 1; 602 | memcpy((char*)request_opts->client_identifier.client_mac, (char*)ethernet->host_mac, ETHER_MAC_SIZE); 603 | 604 | 605 | /* options (50) */ 606 | request_opts->requested_ip.option_number = DHCP_REQUESTED_IP; 607 | request_opts->requested_ip.length = 4; 608 | memcpy((char*)request_opts->requested_ip.requested_ip, (char*)requested_ip, ETHER_IPV4_SIZE); 609 | 610 | 611 | /* options (54) */ 612 | request_opts->server_identifier.option_number = DHCP_SERVER_IDENTIFIER; 613 | request_opts->server_identifier.length = 4; 614 | memcpy((char*)request_opts->server_identifier.server_ip, (char*)server_ip, ETHER_IPV4_SIZE); 615 | 616 | 617 | /* option end */ 618 | request_opts->options_end = DHCP_OPTION_END; 619 | 620 | 621 | /* Configure sources */ 622 | memset(&dhcp_client, 0, sizeof(ether_source_t)); 623 | 624 | dhcp_client.identifier = 1; 625 | dhcp_client.source_port = DHCP_SOURCE_PORT; 626 | 627 | memcpy((char*)dhcp_client.source_mac, (char*)ethernet->host_mac, ETHER_MAC_SIZE); 628 | 629 | /* Configure destination address */ 630 | memcpy((char*)destination_ip, (char*)ethernet->broadcast_ip, ETHER_IPV4_SIZE); 631 | memcpy((char*)destination_mac, (char*)ethernet->broadcast_mac, ETHER_MAC_SIZE); 632 | 633 | 634 | /* Send DHCP packet as UPD message */ 635 | ether_send_udp_raw(ethernet, &dhcp_client, destination_ip, destination_mac, DHCP_DESTINATION_PORT, 636 | (uint8_t*)dhcp_request, (DHCP_FRAME_SIZE + DHCP_REQUEST_OPTS_SIZE)); 637 | } 638 | 639 | return func_retval; 640 | } 641 | 642 | 643 | 644 | 645 | 646 | /************************************************************* 647 | * @brief Function to get IP though DHCP state machine 648 | * @param *ethernet : reference to the Ethernet handle 649 | * @param *network_data : network data from PHY 650 | * 651 | * @param dhcp_state : DHCP state machine states 652 | * @retval uint8_t : Error = NA, Success = NA 653 | *************************************************************/ 654 | int8_t ether_get_dhcp_ip(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *mac_address, 655 | dhcp_states dhcp_state) 656 | { 657 | 658 | dhcp_offer_opts_t *offer_options; 659 | 660 | uint8_t your_ip[4] = {0}; 661 | uint8_t server_ip[4] = {0}; 662 | uint8_t subnet_mask[4] = {0}; 663 | uint8_t dhcp_options[60] = {0}; 664 | 665 | int8_t dhcp_type = 0; 666 | uint8_t dhcp_request_flag = 0; 667 | uint8_t dhcp_loop = 1; 668 | 669 | uint32_t dhcp_transac_id = get_random_port_l(ethernet, 65535); 670 | 671 | dhcp_state = DHCP_INIT_STATE; 672 | 673 | uint32_t lease_time = 0; 674 | 675 | while(dhcp_loop) 676 | { 677 | switch(dhcp_state) 678 | { 679 | 680 | case DHCP_INIT_STATE: 681 | 682 | ethernet->status.mode_dhcp_init = 1; 683 | 684 | dhcp_state = DHCP_SELECTING_STATE; 685 | 686 | break; 687 | 688 | 689 | case DHCP_SELECTING_STATE: 690 | 691 | ether_dhcp_send_discover(ethernet, dhcp_transac_id, mac_address, 0); 692 | 693 | dhcp_state = DHCP_READ_STATE; 694 | 695 | break; 696 | 697 | 698 | case DHCP_READ_STATE: 699 | 700 | dhcp_type = ether_dhcp_read(ethernet, (uint8_t*)network_data, your_ip, dhcp_transac_id, dhcp_options); 701 | 702 | /* Handle DHCP offer */ 703 | if(dhcp_type == DHCP_OFFER && ethernet->status.mode_dhcp_init == 1 && dhcp_request_flag == 0) 704 | { 705 | /* Get server_ip, SUBNET mask, lease time from DHCP offer options */ 706 | offer_options = (void*)dhcp_options; 707 | 708 | memcpy(server_ip, offer_options->server_identifier.server_ip, ETHER_IPV4_SIZE); 709 | memcpy(subnet_mask, offer_options->subnet_mask.subnet_mask, ETHER_IPV4_SIZE); 710 | 711 | lease_time = ntohl(offer_options->lease_time.lease_time); 712 | 713 | dhcp_state = DHCP_REQUESTING_STATE; 714 | break; 715 | 716 | } 717 | /* Handle DHCP ACK */ 718 | else if(dhcp_type == DHCP_ACK && dhcp_request_flag == 1) 719 | { 720 | dhcp_state = DHCP_ACK_STATE; 721 | break; 722 | } 723 | /* Handle DHCP offer or request not received conditions */ 724 | else if(dhcp_request_flag == 1) 725 | { 726 | dhcp_state = DHCP_REQUESTING_STATE; 727 | break; 728 | } 729 | else if(ethernet->status.mode_dhcp_init == 1) 730 | { 731 | dhcp_state = DHCP_SELECTING_STATE; 732 | } 733 | 734 | 735 | break; 736 | 737 | 738 | case DHCP_REQUESTING_STATE: 739 | 740 | ether_dhcp_send_request(ethernet, dhcp_transac_id, 1, server_ip, your_ip, lease_time); 741 | 742 | dhcp_request_flag = 1; 743 | 744 | dhcp_state = DHCP_READ_STATE; 745 | 746 | break; 747 | 748 | 749 | case DHCP_ACK_STATE: 750 | 751 | dhcp_request_flag = 0; 752 | 753 | memcpy((char*)ethernet->host_ip, (char*)your_ip, 4); 754 | 755 | memcpy((char*)ethernet->gateway_ip, (char*)server_ip, 4); 756 | 757 | memcpy((char*)ethernet->subnet_mask, (char*)subnet_mask, 4); 758 | 759 | ethernet->lease_time = lease_time; 760 | 761 | dhcp_state = DHCP_BOUND_STATE; 762 | 763 | break; 764 | 765 | 766 | case DHCP_BOUND_STATE: 767 | 768 | ethernet->status.mode_dhcp_init = 0; 769 | ethernet->status.mode_dhcp_bound = 1; 770 | ethernet->status.mode_dynamic = 1; 771 | 772 | dhcp_loop = 0; 773 | 774 | ether_send_arp_req(ethernet, ethernet->host_ip, ethernet->gateway_ip); 775 | 776 | if(ether_is_arp(ethernet, (uint8_t*)network_data, 128)) 777 | { 778 | 779 | ether_handle_arp_resp_req(ethernet); 780 | 781 | } 782 | 783 | 784 | break; 785 | 786 | 787 | default: 788 | 789 | dhcp_loop = 0; 790 | 791 | break; 792 | 793 | } 794 | 795 | } 796 | 797 | 798 | return 0; 799 | } 800 | 801 | 802 | 803 | 804 | -------------------------------------------------------------------------------- /NET_API/src/ethernet.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file ethernet.c 4 | * @author Aditya Mall, 5 | * @brief ethernet layer source file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | 43 | 44 | /* 45 | * Standard header and api header files 46 | */ 47 | 48 | #include 49 | #include 50 | #include 51 | 52 | #include "ethernet.h" 53 | #include "network_utilities.h" 54 | 55 | 56 | 57 | 58 | /******************************************************************************/ 59 | /* */ 60 | /* Ethernet Functions */ 61 | /* */ 62 | /******************************************************************************/ 63 | 64 | 65 | 66 | /* Weak implementations of Ethernet operation functions */ 67 | 68 | __attribute__((weak))int16_t ethernet_send_packet(uint8_t *data, uint16_t length) 69 | { 70 | 71 | return 0; 72 | } 73 | 74 | 75 | 76 | __attribute__((weak))uint16_t ethernet_recv_packet(uint8_t *data, uint16_t length) 77 | { 78 | 79 | return 0; 80 | } 81 | 82 | 83 | 84 | __attribute__((weak))uint16_t random_seed(void) 85 | { 86 | 87 | return 0; 88 | } 89 | 90 | 91 | 92 | 93 | /****************************************************** 94 | * @brief Function to sum the data in network packet 95 | * @param *sum : Total 32 bit sum 96 | * @param *data : data to be summed 97 | * @param size_in_bytes : size of the data 98 | * @retval uint16_t : Error = -1, Success = 0 99 | ******************************************************/ 100 | int8_t ether_sum_words(uint32_t *sum, void *data, uint16_t size_in_bytes) 101 | { 102 | 103 | int8_t func_retval = 0; 104 | 105 | uint8_t *data_ptr = (uint8_t *)data; 106 | 107 | uint16_t data_temp; 108 | uint8_t phase = 0; 109 | 110 | uint16_t i = 0; 111 | 112 | if(data == NULL) 113 | { 114 | func_retval = -1; 115 | } 116 | else 117 | { 118 | for(i = 0; i < size_in_bytes; i++) 119 | { 120 | if(phase) 121 | { 122 | data_temp = *data_ptr; 123 | 124 | *sum += data_temp << 8; 125 | } 126 | else 127 | { 128 | *sum += *data_ptr; 129 | } 130 | 131 | phase = 1 - phase; 132 | 133 | data_ptr++; 134 | } 135 | } 136 | 137 | return func_retval; 138 | } 139 | 140 | 141 | 142 | 143 | /****************************************************** 144 | * @brief Function to get checksum of network packet 145 | * @param *sum : Total 32 bit sum 146 | * @retval uint16_t : checksum value 147 | ******************************************************/ 148 | uint16_t ether_get_checksum(uint32_t sum) 149 | { 150 | uint16_t checksum = 0; 151 | 152 | while ((sum >> 16) > 0) 153 | { 154 | /* this is based on rfc1071 */ 155 | sum = (sum & 0xFFFF) + (sum >> 16); 156 | } 157 | 158 | checksum = sum & 0xFFFF; 159 | 160 | checksum = ~checksum; 161 | 162 | /* return 1s complement */ 163 | return checksum; 164 | } 165 | 166 | 167 | 168 | 169 | /****************************************************** 170 | * @brief Function to get random number above a bound 171 | * @param *ethernet : reference to Ethernet handle 172 | * @param lower_bound : lower bound value 173 | * @retval uint16_t : Error = -1, Success = 0 174 | ******************************************************/ 175 | int16_t get_random_port(ethernet_handle_t *ethernet, uint16_t lower_bound) 176 | { 177 | int16_t func_retval = 0; 178 | 179 | uint16_t random_seed = 0; 180 | uint16_t random_number = 0; 181 | 182 | if(ethernet->ether_obj == NULL) 183 | { 184 | func_retval = -1; 185 | } 186 | else 187 | { 188 | 189 | random_seed = ethernet->ether_commands->random_gen_seed(); 190 | 191 | srand(random_seed); 192 | 193 | lower_bound += random_seed; 194 | 195 | random_number = ( rand() % (UINT16_MAX - lower_bound) ) + lower_bound; 196 | 197 | random_number += ethernet->ether_commands->random_gen_seed(); 198 | 199 | func_retval = random_number; 200 | } 201 | 202 | return func_retval; 203 | } 204 | 205 | 206 | 207 | 208 | /****************************************************** 209 | * @brief Function to get random number above a bound 210 | * (32 bit) 211 | * @param *ethernet : reference to Ethernet handle 212 | * @param lower_bound : lower bound value 213 | * @retval uint32_t : Error = -1, Success = 0 214 | ******************************************************/ 215 | int32_t get_random_port_l(ethernet_handle_t *ethernet, uint32_t lower_bound) 216 | { 217 | int32_t func_retval = 0; 218 | 219 | uint16_t random_seed = 0; 220 | uint32_t random_number = 0; 221 | 222 | if(ethernet->ether_obj == NULL) 223 | { 224 | func_retval = -1; 225 | } 226 | else 227 | { 228 | random_seed = ethernet->ether_commands->random_gen_seed(); 229 | 230 | srand(ethernet->ether_commands->random_gen_seed()); 231 | 232 | lower_bound += (uint32_t)random_seed; 233 | 234 | random_number = ( rand() % (UINT32_MAX - lower_bound) ) + lower_bound; 235 | 236 | func_retval = random_number; 237 | } 238 | 239 | return func_retval; 240 | } 241 | 242 | 243 | 244 | 245 | /************************************************************************** 246 | * @brief constructor function to create Ethernet handle 247 | * (Multiple exit points) 248 | * @param *network_data : reference to the network data buffer 249 | * @param *mac_address : MAC address (string) 250 | * @param *ip_address : ip address (string) 251 | * @param *ether_ops : reference to the Ethernet operations structure 252 | * @retval int8_t : Error = NULL, Success = Ethernet object 253 | **************************************************************************/ 254 | ethernet_handle_t* create_ethernet_handle(uint8_t *network_data, char *mac_address, char *ip_address, ether_operations_t *ether_ops) 255 | { 256 | 257 | static ethernet_handle_t ethernet; 258 | 259 | static char application_buffer[APP_BUFF_SIZE] = {0}; 260 | 261 | int8_t api_retval = 0; 262 | 263 | if(network_data == NULL) 264 | { 265 | return NULL; 266 | } 267 | else 268 | { 269 | /* Give starting address of network data to*/ 270 | ethernet.ether_obj = (void*)network_data; 271 | 272 | /* Set source addresses */ 273 | api_retval = set_mac_address(ethernet.host_mac, mac_address); 274 | 275 | api_retval = set_ip_address(ethernet.host_ip, ip_address); 276 | 277 | /* Set default modes */ 278 | ethernet.status.mode_static = 1; 279 | ethernet.status.mode_dynamic = 0; 280 | ethernet.status.mode_dhcp_init = 0; 281 | ethernet.status.mode_read_blocking = ETHER_READ_BLOCK; 282 | 283 | /* Configure broadcast addresses */ 284 | set_broadcast_address(ethernet.broadcast_mac, ETHER_MAC_SIZE); 285 | 286 | set_broadcast_address(ethernet.broadcast_ip, ETHER_IPV4_SIZE); 287 | 288 | 289 | if(api_retval < 0) 290 | return NULL; 291 | 292 | 293 | /* Configure application buffer */ 294 | ethernet.net_application_data = application_buffer; 295 | 296 | /* Configure network operations and weak linking of default functions */ 297 | ethernet.ether_commands = ether_ops; 298 | 299 | if(ethernet.ether_commands->open == NULL) 300 | return NULL; 301 | 302 | if(ethernet.ether_commands->network_interface_status == NULL) 303 | return NULL; 304 | 305 | if(ethernet.ether_commands->random_gen_seed == NULL) 306 | ethernet.ether_commands->random_gen_seed = random_seed; 307 | 308 | if(ethernet.ether_commands->ether_send_packet == NULL) 309 | ethernet.ether_commands->ether_send_packet = ethernet_send_packet; 310 | 311 | if(ethernet.ether_commands->ether_recv_packet == NULL) 312 | ethernet.ether_commands->ether_recv_packet = ethernet_recv_packet; 313 | 314 | 315 | /* Functions called after linking */ 316 | 317 | /* configure sources */ 318 | ethernet.ip_identifier = get_unique_id(ðernet, 2000); 319 | ethernet.source_port = get_random_port(ðernet, 2000); 320 | 321 | 322 | /* Initialize Ethernet */ 323 | ethernet.ether_commands->open(ethernet.host_mac); 324 | 325 | 326 | } 327 | 328 | return ðernet; 329 | } 330 | 331 | 332 | 333 | uint8_t ether_control(ethernet_handle_t *ethernet, ether_control_t ether_mode) 334 | { 335 | 336 | if(ether_mode == ETHER_READ_NONBLOCK) 337 | { 338 | ethernet->status.mode_read_blocking = ETHER_READ_NONBLOCK; 339 | } 340 | 341 | 342 | return 0; 343 | } 344 | 345 | 346 | 347 | 348 | 349 | /********************************************************** 350 | * @brief Function to get the Ethernet device status 351 | * @param *ethernet : reference to the Ethernet Handle 352 | * @retval uint8_t : Error = 0, Success = 1 353 | *********************************************************/ 354 | uint8_t ether_module_status(ethernet_handle_t *ethernet) 355 | { 356 | uint8_t func_retval = 0; 357 | 358 | if(ethernet->ether_obj == NULL) 359 | { 360 | func_retval = 0; 361 | } 362 | else 363 | { 364 | if(ethernet->ether_commands->function_lock == 0) 365 | { 366 | ethernet->ether_commands->function_lock = 1; 367 | 368 | func_retval = ethernet->ether_commands->network_interface_status(); 369 | 370 | ethernet->ether_commands->function_lock = 0; 371 | } 372 | } 373 | 374 | return func_retval; 375 | } 376 | 377 | 378 | 379 | /*********************************************************** 380 | * @brief Function Ethernet network data 381 | * @param *ethernet : reference to the Ethernet handle 382 | * @param *data : network data 383 | * @param *data_length : source MAC address 384 | * @retval uint8_t : Error = 0, Success = 1 385 | ***********************************************************/ 386 | uint8_t ether_get_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length) 387 | { 388 | 389 | uint8_t func_retval = 0; 390 | 391 | if(ethernet->ether_obj == NULL || data == NULL || data_length == 0 || data_length > UINT16_MAX) 392 | { 393 | func_retval = 0; 394 | } 395 | else 396 | { 397 | if(ether_module_status(ethernet)) 398 | { 399 | ethernet->ether_commands->function_lock = 1; 400 | 401 | /* get data from network including PHY module frame */ 402 | ethernet->ether_commands->ether_recv_packet(data, data_length); 403 | 404 | func_retval = 1; 405 | 406 | ethernet->ether_commands->function_lock = 0; 407 | } 408 | 409 | } 410 | 411 | return func_retval; 412 | } 413 | 414 | 415 | 416 | /*********************************************************** 417 | * @brief Function send Ethernet network data 418 | * @param *ethernet : reference to the Ethernet handle 419 | * @param *data : network data 420 | * @param *data_length : source MAC address 421 | * @retval uint8_t : Error = 0, Success = 1 422 | ***********************************************************/ 423 | uint8_t ether_send_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length) 424 | { 425 | 426 | uint8_t func_retval = 0; 427 | 428 | if(ethernet->ether_obj == NULL || data == NULL || data_length == 0 || data_length > UINT16_MAX) 429 | { 430 | func_retval = 0; 431 | } 432 | else 433 | { 434 | ethernet->ether_commands->function_lock = 1; 435 | 436 | ethernet->ether_commands->ether_send_packet(data, data_length); 437 | 438 | func_retval = 1; 439 | 440 | ethernet->ether_commands->function_lock = 0; 441 | 442 | } 443 | 444 | return func_retval; 445 | } 446 | 447 | 448 | 449 | /********************************************************************** 450 | * @brief Function to fill the Ethernet frame 451 | * @param *ethernet : reference to the Ethernet handle 452 | * @param *destination_mac_address : destination MAC address 453 | * @param *source_mac_address : source MAC address 454 | * @param frame type : Ethernet frame type 455 | * @retval int8_t : Error = -1, Success = 0 456 | **********************************************************************/ 457 | int8_t fill_ether_frame(ethernet_handle_t *ethernet, uint8_t *destination_mac_addr, uint8_t *source_mac_addr, ether_type_t frame_type) 458 | { 459 | int8_t func_retval = 0; 460 | 461 | uint8_t index = 0; 462 | 463 | if(ethernet->ether_obj == NULL || destination_mac_addr == NULL || source_mac_addr == NULL) 464 | { 465 | func_retval = -1; 466 | } 467 | else 468 | { 469 | /* Fill MAC address */ 470 | for(index = 0; index < 6; index++) 471 | { 472 | ethernet->ether_obj->destination_mac_addr[index] = destination_mac_addr[index]; 473 | ethernet->ether_obj->source_mac_addr[index] = source_mac_addr[index]; 474 | } 475 | 476 | ethernet->ether_obj->type = htons(frame_type); 477 | } 478 | 479 | return func_retval; 480 | } 481 | 482 | 483 | 484 | 485 | /*********************************************************** 486 | * @brief Function get ethernet protocol type 487 | * @param *ethernet : reference to the Ethernet handle 488 | * @retval ether_type_t : Error = 0, Success = 1 489 | ***********************************************************/ 490 | ether_type_t get_ether_protocol_type(ethernet_handle_t *ethernet) 491 | { 492 | 493 | ether_type_t func_retval; 494 | 495 | if(ethernet == NULL || ethernet->ether_obj == NULL) 496 | { 497 | func_retval = (ether_type_t)0; 498 | } 499 | else 500 | { 501 | func_retval = (ether_type_t)(ntohs(ethernet->ether_obj->type)); 502 | } 503 | 504 | return func_retval; 505 | 506 | } 507 | 508 | 509 | 510 | 511 | 512 | -------------------------------------------------------------------------------- /NET_API/src/icmp.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file icmp.c 4 | * @author Aditya Mall, 5 | * @brief ICMP (for IPV4) source file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | 43 | 44 | 45 | /* 46 | * Standard header and api header files 47 | */ 48 | #include 49 | #include 50 | 51 | #include "icmp.h" 52 | #include "ipv4.h" 53 | #include "network_utilities.h" 54 | 55 | #include 56 | 57 | /******************************************************************************/ 58 | /* */ 59 | /* Data Structures and Defines */ 60 | /* */ 61 | /******************************************************************************/ 62 | 63 | 64 | #define ICMP_FRAME_SIZE 8 65 | 66 | 67 | 68 | /* ICMP Frame (8 bytes) */ 69 | typedef struct _net_icmp 70 | { 71 | uint8_t type; /*!< ICMP message type */ 72 | uint8_t code; /*!< ICMP code for subtype messages */ 73 | uint16_t checksum; /*!< ICMP message checksum */ 74 | uint16_t id; /*!< ICMP message ID */ 75 | uint16_t sequence_no; /*!< ICMP message sequence number */ 76 | uint8_t data; /*!< ICMP message data */ 77 | 78 | } net_icmp_t; 79 | 80 | 81 | 82 | 83 | /******************************************************************************/ 84 | /* */ 85 | /* ICMP Functions */ 86 | /* */ 87 | /******************************************************************************/ 88 | 89 | 90 | 91 | 92 | /****************************************************************** 93 | * @brief Function to send ICMP reply packet 94 | * @param *ethernet : reference to the Ethernet handle 95 | * @retval int16_t : Error = -6, -7 = reply ignore, Success = 0 96 | ******************************************************************/ 97 | int8_t ether_send_icmp_reply(ethernet_handle_t *ethernet) 98 | { 99 | int8_t func_retval = 0; 100 | 101 | net_ip_t *ip; 102 | net_icmp_t *icmp; 103 | 104 | uint32_t sum = 0; 105 | uint16_t ip_header_size = 0; 106 | uint16_t ip_packet_length = 0; 107 | uint16_t icmp_remaining_size = 0; 108 | 109 | if(ethernet->ether_obj == NULL) 110 | { 111 | func_retval = NET_ICMP_RESP_ERROR; 112 | } 113 | else 114 | { 115 | ip = (void*)ðernet->ether_obj->data; 116 | 117 | ip_header_size = ip->version_length.header_length * 4; 118 | 119 | icmp = (void*)( (uint8_t*)ip + ip_header_size); 120 | 121 | /* Send ECHO reply */ 122 | if(icmp->type == ICMP_ECHOREQUEST) 123 | { 124 | /* Swap MAC address in Ethernet Frame */ 125 | net_swap_address(ethernet->ether_obj->destination_mac_addr, ethernet->ether_obj->source_mac_addr, 6); 126 | 127 | /* Swap IP address in IP Frame */ 128 | net_swap_address(ip->destination_ip, ip->source_ip, 4); 129 | 130 | /* Fill ICMP frame */ 131 | icmp->type = ICMP_ECHOREPLY; 132 | 133 | /*** Calculate ICMP Checksum ***/ 134 | 135 | ether_sum_words(&sum, &icmp->type, 2); 136 | 137 | /* get total length of IP packet */ 138 | ip_packet_length = ntohs(ip->total_length); 139 | 140 | /* ICMP Remaining packet size = IP Length - (ICMP type+code+checksum size) */ 141 | icmp_remaining_size = ip_packet_length - (ip_header_size + 4); 142 | 143 | ether_sum_words(&sum, &icmp->id, icmp_remaining_size); 144 | 145 | /* Get checksum */ 146 | icmp->checksum = ether_get_checksum(sum); 147 | 148 | /* Send ICMP response packet(uses callback) */ 149 | ether_send_data(ethernet, (uint8_t*)ethernet->ether_obj, ip_packet_length + ETHER_FRAME_SIZE); 150 | 151 | } 152 | else 153 | { 154 | func_retval = NET_ICMP_RESP_IGNORE; 155 | } 156 | 157 | } 158 | 159 | return func_retval; 160 | } 161 | 162 | 163 | 164 | 165 | 166 | /***************************************************************** 167 | * @brief Function to send ICMP request 168 | * @param *ethernet : Reference to the Ethernet structure 169 | * @param icmp_type : ICMP request type 170 | * @param *destination_ip : Destination IP address 171 | * @param sequence_no : ICMP packet sequence Number 172 | * @param *destination_mac : Destination MAC address 173 | * @param *source_mac : Source MAC address 174 | * @retval int8_t : Error = -8, Success = 0. 175 | ****************************************************************/ 176 | int8_t ether_send_icmp_req(ethernet_handle_t *ethernet, icmp_type_t icmp_type, uint8_t *destination_ip, 177 | uint8_t *sequence_no, uint8_t* destination_mac, uint8_t *source_mac) 178 | { 179 | int8_t func_retval = 0; 180 | 181 | net_ip_t *ip; 182 | net_icmp_t *icmp; 183 | 184 | uint32_t sum = 0; 185 | uint16_t icmp_packet_size = 0; 186 | uint16_t ip_id = 0; 187 | 188 | if(ethernet->ether_obj == NULL) 189 | { 190 | func_retval = NET_ICMP_REQ_ERROR; 191 | } 192 | else 193 | { 194 | 195 | /* Fill ICMP frame */ 196 | ip = (void*)ðernet->ether_obj->data; 197 | 198 | icmp = (void*)( (uint8_t*)ip + IP_HEADER_SIZE ); 199 | 200 | icmp->type = ICMP_ECHOREQUEST; 201 | 202 | icmp->code = 0; 203 | 204 | /* Currently fixed */ 205 | icmp->id = 15625; 206 | 207 | icmp->sequence_no = htons(*sequence_no); 208 | 209 | (*sequence_no)++; 210 | 211 | /* Calculate ICMP checksum */ 212 | sum = 0; 213 | ether_sum_words(&sum, &icmp->type, 2); 214 | 215 | ether_sum_words(&sum, &icmp->id, 5); 216 | 217 | icmp->checksum = ether_get_checksum(sum); 218 | 219 | icmp_packet_size = ICMP_FRAME_SIZE; 220 | 221 | 222 | /* Fill IP frame */ 223 | fill_ip_frame(ip, &ip_id, destination_ip, ethernet->host_ip, IP_ICMP, icmp_packet_size); 224 | 225 | 226 | /* Fill Ethernet frame */ 227 | fill_ether_frame(ethernet, destination_mac, source_mac, ETHER_IPV4); 228 | 229 | 230 | /* Send ICMP data */ 231 | ether_send_data(ethernet, (uint8_t*)ethernet->ether_obj, ETHER_FRAME_SIZE + htons(ip->total_length)); 232 | 233 | } 234 | 235 | 236 | return func_retval; 237 | } 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | -------------------------------------------------------------------------------- /NET_API/src/ipv4.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file ipv4.c 4 | * @author Aditya Mall, 5 | * @brief IP version 4 protocol source file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | 43 | /* 44 | * Standard header and api header files 45 | */ 46 | #include 47 | 48 | #include "ipv4.h" 49 | 50 | #include "network_utilities.h" 51 | 52 | 53 | 54 | /******************************************************************************/ 55 | /* */ 56 | /* Data Structures and Defines */ 57 | /* */ 58 | /******************************************************************************/ 59 | 60 | 61 | 62 | 63 | 64 | /******************************************************************************/ 65 | /* */ 66 | /* IPV4 Functions */ 67 | /* */ 68 | /******************************************************************************/ 69 | 70 | 71 | 72 | /************************************************************** 73 | * @brief Function to get IP data for current host device 74 | * validates IP Checksum, (Only handles UNICAST) 75 | * @param *ethernet : reference to the Ethernet handle 76 | * @retval int16_t : Error = -4, -5, 77 | * Success = 1 (UNICAST), 78 | * = 2 (BROADCAST) 79 | **************************************************************/ 80 | int16_t get_ip_communication_type(ethernet_handle_t *ethernet) 81 | { 82 | int16_t func_retval = 0; 83 | 84 | net_ip_t *ip; 85 | 86 | uint32_t sum = 0; 87 | 88 | if(ethernet->ether_obj == NULL) 89 | { 90 | func_retval = NET_IP_GET_ERROR; 91 | } 92 | else 93 | { 94 | ip = (void*)ðernet->ether_obj->data; 95 | 96 | /* Validate IP header checksum */ 97 | ether_sum_words(&sum, ip, (ip->version_length.header_length) * 4); 98 | 99 | if( (ether_get_checksum(sum) == 0) ) 100 | { 101 | /* Check if UNICAST (temporarily make UNICAST unaccessible when requesting IP through DHCP, dynamic IP) */ 102 | /* mode_dhcp_req bit is cleared by DHCP state machine, done for better throughput during requesting. */ 103 | if( (strncmp((char*)ip->destination_ip, (char*)ethernet->host_ip, 4) == 0) && ethernet->status.mode_dhcp_init != 1 ) 104 | { 105 | func_retval = 1; 106 | } 107 | /* Check if BROADCAST */ 108 | else if( strncmp((char*)ip->destination_ip, (char*)ethernet->broadcast_ip, 4) == 0 ) 109 | { 110 | func_retval = 2; 111 | } 112 | 113 | } 114 | else 115 | { 116 | func_retval = NET_IP_CHECKSUM_ERROR; 117 | } 118 | 119 | } 120 | 121 | return func_retval; 122 | } 123 | 124 | 125 | 126 | /**************************************************************** 127 | * @brief Function to get IP protocol type 128 | * @param *ethernet : reference to the Ethernet handle 129 | * @retval int16_t : Error = -4, -5, Success = protocol type 130 | ***************************************************************/ 131 | ip_protocol_type_t get_ip_protocol_type(ethernet_handle_t *ethernet) 132 | { 133 | ip_protocol_type_t protocol; 134 | 135 | net_ip_t *ip; 136 | 137 | ip = (void*)ðernet->ether_obj->data; 138 | 139 | protocol = (ip_protocol_type_t)ip->protocol; 140 | 141 | return protocol; 142 | } 143 | 144 | 145 | 146 | /********************************************************** 147 | * @brief Function to fill the IP frame 148 | * @param *ip : reference to the IP structure 149 | * @param *id : reference to IP identifier 150 | * @param *destination_ip : destination IP address 151 | * @param *source_ip : source IP address 152 | * @param protocol : IP protocol type 153 | * @param data_size : size of payload 154 | * @retval int8_t : Error = NULL 155 | **********************************************************/ 156 | int8_t fill_ip_frame(net_ip_t *ip, uint16_t *id, uint8_t *destination_ip, uint8_t *source_ip, ip_protocol_type_t protocol, uint16_t data_size) 157 | { 158 | int8_t func_retval = 0; 159 | 160 | uint8_t i = 0; 161 | 162 | uint32_t sum = 0; 163 | 164 | if(ip == NULL || destination_ip == NULL || source_ip == NULL || data_size == 0 || data_size > UINT16_MAX) 165 | { 166 | func_retval = -1; 167 | } 168 | else 169 | { 170 | 171 | ip->version_length.version = IP_VERSION; 172 | ip->version_length.header_length = IP_HEADER_LENGTH; 173 | 174 | ip->service_type = 0; 175 | 176 | /* Get identifier and increment it for next message */ 177 | ip->id = htons(*id); 178 | 179 | (*id)++; 180 | 181 | /* Don't Fragment set condition */ 182 | ip->flags_offset = htons(IP_DF_SET); 183 | 184 | ip->ttl = IP_TTL_VALUE; 185 | 186 | ip->protocol = protocol; 187 | 188 | ip->total_length = htons(IP_HEADER_SIZE + data_size); 189 | 190 | for(i=0; i < 4; i++) 191 | { 192 | ip->destination_ip[i] = destination_ip[i]; 193 | ip->source_ip[i] = source_ip[i]; 194 | } 195 | 196 | /* Calculate checksum */ 197 | sum = 0; 198 | ether_sum_words(&sum, &ip->version_length, 10); 199 | 200 | ether_sum_words(&sum, ip->source_ip, 8); 201 | 202 | ip->header_checksum = ether_get_checksum(sum); 203 | } 204 | 205 | 206 | return func_retval; 207 | } 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /NET_API/src/network_utilities.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file network_utilities.c 4 | * @author Aditya Mall, 5 | * @brief Network utility source file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | 43 | 44 | /* 45 | * Standard header and api header files 46 | */ 47 | #include 48 | #include 49 | #include 50 | 51 | #include "network_utilities.h" 52 | 53 | 54 | 55 | /******************************************************************************/ 56 | /* */ 57 | /* Private Functions */ 58 | /* */ 59 | /******************************************************************************/ 60 | 61 | 62 | /* Implementation of glibc reentrant strtok Copyright (C) 1991-2019 GNU C Library */ 63 | 64 | static char *api_strtok_r (char *s, const char *delim, char **save_ptr) 65 | { 66 | char *end; 67 | if (s == NULL) 68 | s = *save_ptr; 69 | if (*s == '\0') 70 | { 71 | *save_ptr = s; 72 | return NULL; 73 | } 74 | /* Scan leading delimiters. */ 75 | s += strspn (s, delim); 76 | if (*s == '\0') 77 | { 78 | *save_ptr = s; 79 | return NULL; 80 | } 81 | /* Find the end of the token. */ 82 | end = s + strcspn (s, delim); 83 | if (*end == '\0') 84 | { 85 | *save_ptr = end; 86 | return s; 87 | } 88 | /* Terminate the token and make *SAVE_PTR point past it. */ 89 | *end = '\0'; 90 | *save_ptr = end + 1; 91 | return s; 92 | } 93 | 94 | 95 | 96 | 97 | /******************************************************************************/ 98 | /* */ 99 | /* Network Utility Functions */ 100 | /* */ 101 | /******************************************************************************/ 102 | 103 | 104 | 105 | /************************************************************************ 106 | * @brief Function to convert from host to network order and vice versa 107 | * (For 16 bit data) 108 | * @retval uint16_t : host to network or network to host converted data 109 | ************************************************************************/ 110 | uint16_t htons(uint16_t value) 111 | { 112 | /* Ignore byte swap for 8 bit variables */ 113 | if((value << 8) == 0) 114 | return value; 115 | else 116 | return ((value & 0xFF00) >> 8) + ((value & 0x00FF) << 8); 117 | } 118 | 119 | 120 | 121 | 122 | /************************************************************************ 123 | * @brief Function to convert from host to network order and vice versa 124 | * (For 32 bit data) 125 | * Copyright (C) 1997-2019 Free Software Foundation, Inc. 126 | * 127 | * @retval uint32_t : host to network or network to host converted data 128 | ************************************************************************/ 129 | 130 | 131 | /* Swap bytes in 32-bit value. */ 132 | #define __bswap_constant_32(x) \ 133 | ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) \ 134 | | (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) 135 | 136 | 137 | uint32_t htonl(uint32_t x) 138 | { 139 | return (uint32_t)__bswap_constant_32 (x); 140 | } 141 | 142 | 143 | 144 | 145 | 146 | 147 | /******************************************************** 148 | * @brief Function to set mac address 149 | * @param *device_mac : device mac address (Hex) 150 | * @param *mac_address : mac address (string) 151 | * @retval int8_t : Error = -1, Success = 0 152 | ********************************************************/ 153 | int8_t set_mac_address(uint8_t *device_mac, char *mac_address) 154 | { 155 | int8_t func_retval = 0; 156 | 157 | char mac_address_copy[18] = {0}; /*!< Copy variable */ 158 | char *rest_ptr; /*!< Tracking pointer */ 159 | char *token; /*!< token */ 160 | 161 | 162 | /* Copy mac address to copy variable for null termination (required for string function) */ 163 | strncpy(mac_address_copy, mac_address, 18); /* Size of mac address entered as string with null at index 18 */ 164 | 165 | uint8_t index = 0; 166 | 167 | if(mac_address_copy[17] != 0) 168 | { 169 | func_retval = -1; 170 | } 171 | else 172 | { 173 | rest_ptr = mac_address_copy; 174 | 175 | /* strtok_r function for non glibc compliant code */ 176 | while( (token = api_strtok_r(rest_ptr, ":", &rest_ptr)) ) 177 | { 178 | /* Convert to hex */ 179 | device_mac[index] = strtol(token, NULL, 16); 180 | 181 | index++; 182 | } 183 | 184 | } 185 | 186 | 187 | return func_retval; 188 | } 189 | 190 | 191 | 192 | /******************************************************** 193 | * @brief function to set ip address 194 | * @param *host_ip : host ip address (integer) 195 | * @param *ip_address : ip address (string) 196 | * @retval int8_t : Error = -1, Success = 0 197 | ********************************************************/ 198 | int8_t set_ip_address(uint8_t *host_ip, char *ip_address) 199 | { 200 | 201 | int8_t func_retval = 0; 202 | 203 | char ip_address_copy[16] = {0}; /*!< Copy variable */ 204 | char *rest_ptr; /*!< Tracking pointer */ 205 | char *token; /*!< token */ 206 | 207 | 208 | /* Copy ip address to copy variable for null termination (required for string function) */ 209 | strncpy(ip_address_copy, ip_address, 16); /* Size of ip address entered as string with null at index 18 */ 210 | 211 | uint8_t index = 0; 212 | 213 | if(ip_address_copy[15] != 0) 214 | { 215 | func_retval = -1; 216 | } 217 | else 218 | { 219 | rest_ptr = ip_address_copy; 220 | 221 | /* strtok_r function for non glibc compliant code */ 222 | while( (token = api_strtok_r(rest_ptr, ".", &rest_ptr)) ) 223 | { 224 | /* Convert to hex */ 225 | host_ip[index] = strtol(token, NULL, 10); 226 | 227 | index++; 228 | } 229 | 230 | } 231 | 232 | return func_retval; 233 | 234 | 235 | } 236 | 237 | 238 | 239 | /*********************************************** 240 | * @brief Function to swap network address 241 | * (used in response messages) 242 | * @param *l_address : address value LHS 243 | * @param *r_address : address value RHS 244 | * @param size : size of address 245 | * @retval int8_t : Error = -1, Success = 0 246 | ***********************************************/ 247 | int8_t net_swap_address(uint8_t* l_address, uint8_t *r_address, uint8_t size) 248 | { 249 | int8_t func_retval = 0; 250 | int8_t index = 0; 251 | 252 | if(l_address == NULL || r_address == NULL || size == 0 || size > 6) 253 | { 254 | func_retval = -1; 255 | } 256 | else 257 | { 258 | for(index = 0; index < size; index++) 259 | { 260 | l_address[index] = l_address[index] ^ r_address[index]; 261 | r_address[index] = l_address[index] ^ r_address[index]; 262 | l_address[index] = l_address[index] ^ r_address[index]; 263 | } 264 | 265 | } 266 | 267 | return func_retval; 268 | } 269 | 270 | 271 | 272 | 273 | 274 | /********************************************************* 275 | * @brief Function to set broadcast address 276 | * @param *destination_address : destination address 277 | * @param size : size of address 278 | * @retval int8_t : Error = -1, Success = 0 279 | *********************************************************/ 280 | int8_t set_broadcast_address(uint8_t *destination_address, uint8_t size) 281 | { 282 | int8_t func_retval = 0; 283 | int8_t index = 0; 284 | 285 | if(destination_address == NULL || size == 0) 286 | { 287 | func_retval = -1; 288 | } 289 | else 290 | { 291 | switch(size) 292 | { 293 | 294 | case 4: /* For IP address length */ 295 | 296 | for(index = 0; index < 4; index++) 297 | { 298 | destination_address[index] = 0xFF; 299 | } 300 | 301 | break; 302 | 303 | 304 | case 6: /* For MAC address length */ 305 | 306 | for(index = 0; index < 6; index++) 307 | { 308 | destination_address[index] = 0xFF; 309 | } 310 | 311 | break; 312 | 313 | 314 | default: 315 | 316 | func_retval = -1; 317 | 318 | break; 319 | } 320 | 321 | } 322 | 323 | return func_retval; 324 | } 325 | 326 | 327 | 328 | 329 | 330 | -------------------------------------------------------------------------------- /NET_API/src/udp.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file udp.c 4 | * @author Aditya Mall, 5 | * @brief UDP protocol source file 6 | * 7 | * Info 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

13 | * 14 | * MIT License 15 | * 16 | * Copyright (c) 2019 Aditya Mall 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | ****************************************************************************** 40 | */ 41 | 42 | 43 | 44 | /* 45 | * Standard header and api header files 46 | */ 47 | #include 48 | 49 | #include "ipv4.h" 50 | #include "udp.h" 51 | #include "arp.h" 52 | 53 | #include "network_utilities.h" 54 | 55 | 56 | 57 | 58 | /******************************************************************************/ 59 | /* */ 60 | /* Data Structures and Defines */ 61 | /* */ 62 | /******************************************************************************/ 63 | 64 | 65 | #define UDP_FRAME_SIZE 8 66 | 67 | #pragma pack(1) 68 | 69 | /* UDP Frame (8 Bytes) */ 70 | typedef struct _net_udp 71 | { 72 | uint16_t source_port; /*!< UDP source port */ 73 | uint16_t destination_port; /*!< UDP destination port */ 74 | uint16_t length; /*!< UDP packet length */ 75 | uint16_t checksum; /*!< UDP checksum (pseudo header + packet) */ 76 | uint8_t data; /*!< UDP data */ 77 | 78 | }net_udp_t; 79 | 80 | 81 | 82 | /******************************************************************************/ 83 | /* */ 84 | /* Private Functions */ 85 | /* */ 86 | /******************************************************************************/ 87 | 88 | 89 | 90 | /******************************************************* 91 | * @brief Static function to validate UDP checksum 92 | * @param *ip : Reference to IP frame structure 93 | * @param *udp : Reference to UDP frame structure 94 | * @retval uint8_t : Error = 0, Success = 1 95 | ******************************************************/ 96 | static uint8_t validate_udp_checksum(net_ip_t *ip, net_udp_t *udp) 97 | { 98 | uint8_t func_retval = 0; 99 | 100 | uint32_t sum = 0; 101 | uint16_t pseudo_protocol = 0; 102 | 103 | if(ip == NULL || udp == NULL) 104 | { 105 | func_retval = 0; 106 | } 107 | else 108 | { 109 | 110 | /* validate UDP checksum */ 111 | sum = 0; 112 | 113 | ether_sum_words(&sum, &ip->source_ip, 8); 114 | 115 | pseudo_protocol = ip->protocol; 116 | 117 | sum += ( (pseudo_protocol & 0xFF) << 8 ); 118 | 119 | ether_sum_words(&sum, &udp->length, 2); 120 | 121 | ether_sum_words(&sum, udp, ntohs(udp->length)); 122 | 123 | func_retval = (ether_get_checksum(sum) == 0); 124 | } 125 | 126 | return func_retval; 127 | } 128 | 129 | 130 | 131 | 132 | /************************************************************** 133 | * @brief Function get calculate UDP checksum 134 | * (UDP Headers + UDP data) 135 | * @param *ip : Reference to IP frame structure 136 | * @param *udp : Reference to UDP frame structure 137 | * @param data_length : Length of UDP data 138 | * @retval uint8_t : Error = 0, Success = checksum value 139 | **************************************************************/ 140 | static uint16_t get_udp_checksum(net_ip_t *ip, net_udp_t *udp, uint16_t data_length) 141 | { 142 | 143 | uint16_t func_retval = 0; 144 | uint32_t sum = 0; 145 | uint16_t pseudo_protocol = 0; 146 | 147 | if(ip == NULL || udp == NULL) 148 | { 149 | func_retval = 0; 150 | } 151 | else 152 | { 153 | 154 | /* UDP Pseudo Header checksum calculation */ 155 | sum = 0; 156 | 157 | ether_sum_words(&sum, ip->source_ip, 8); 158 | 159 | pseudo_protocol = ip->protocol; 160 | 161 | /* create space for reserved bits */ 162 | sum += ( (pseudo_protocol & 0xFF) << 8 ); 163 | 164 | ether_sum_words(&sum, &udp->length, 2); 165 | 166 | /* UDP Fixed header checksum calculation, excluding checksum field */ 167 | ether_sum_words(&sum, udp, UDP_FRAME_SIZE - 2); 168 | 169 | /* Add UPD data sum */ 170 | ether_sum_words(&sum, &udp->data, data_length); 171 | 172 | func_retval = ether_get_checksum(sum); 173 | } 174 | 175 | return func_retval; 176 | 177 | } 178 | 179 | 180 | 181 | /******************************************************************************/ 182 | /* */ 183 | /* UDP Functions */ 184 | /* */ 185 | /******************************************************************************/ 186 | 187 | 188 | 189 | 190 | 191 | /***************************************************************** 192 | * @brief Function to get UDP data inside network state machine 193 | * @param *ethernet : Reference to the Ethernet handle 194 | * @param *data : UDP data 195 | * @param data_length : Length of UDP data 196 | * @retval uint8_t : Error = 0, Success = 1 197 | *****************************************************************/ 198 | uint8_t ether_get_udp_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length) 199 | { 200 | uint8_t func_retval = 0; 201 | 202 | net_ip_t *ip; 203 | net_udp_t *udp; 204 | 205 | uint8_t validate = 0; 206 | 207 | uint16_t udp_packet_length = 0; 208 | uint16_t udp_data_length = 0; 209 | 210 | ip = (void*)ðernet->ether_obj->data; 211 | 212 | udp = (void*)( (uint8_t*)ip + IP_HEADER_SIZE ); 213 | 214 | 215 | if(ethernet->ether_obj == NULL || data == NULL) 216 | { 217 | func_retval = 0; 218 | } 219 | else 220 | { 221 | udp_packet_length = ntohs(udp->length); 222 | udp_data_length = udp_packet_length - UDP_FRAME_SIZE; 223 | 224 | /* Check and Truncate UDP data length */ 225 | if(data_length > udp_data_length) 226 | data_length = udp_data_length; 227 | 228 | /* validate UDP checksum */ 229 | validate = validate_udp_checksum(ip, udp); 230 | 231 | /* Get UDP data */ 232 | if(validate) 233 | { 234 | memcpy((char*)data, (char*)&udp->data, data_length); 235 | } 236 | 237 | func_retval = validate; 238 | } 239 | 240 | 241 | return func_retval; 242 | } 243 | 244 | 245 | 246 | 247 | 248 | /******************************************************************* 249 | * @brief Raw Function to send UPD packets 250 | * UDP data dependent upon total data allocated to 251 | * ethernet object 252 | * @param *ethernet : Reference to the Ethernet handle 253 | * @param *source_addr : Reference to source address structure 254 | * @param *destination_ip : Destination IP address 255 | * @param *destination_mac : Destination MAC address 256 | * @param destination_port : UDP destination port 257 | * @param *data : UDP data 258 | * @param data_length : Length of UDP data 259 | * @retval int8_t : Error = -9, Success = 0 260 | *******************************************************************/ 261 | int8_t ether_send_udp_raw(ethernet_handle_t *ethernet, ether_source_t *source_addr, uint8_t *destination_ip, 262 | uint8_t *destination_mac, uint16_t destination_port, uint8_t *data, uint16_t data_length) 263 | { 264 | 265 | int8_t func_retval = 0; 266 | 267 | net_ip_t *ip; 268 | net_udp_t *udp; 269 | 270 | uint16_t index = 0; 271 | 272 | uint8_t *data_copy; 273 | uint16_t udp_packet_size = 0; 274 | 275 | 276 | if(ethernet->ether_obj == NULL || source_addr == NULL || destination_ip == NULL || destination_mac == NULL \ 277 | || destination_port == 0 || data == NULL || data_length == 0 || data_length > UINT16_MAX) 278 | { 279 | func_retval = NET_UDP_RAW_SEND_ERROR; 280 | } 281 | else 282 | { 283 | 284 | ip = (void*)ðernet->ether_obj->data; 285 | 286 | udp = (void*)( (uint8_t*)ip + IP_HEADER_SIZE ); 287 | 288 | 289 | /* Fill UDP frame */ 290 | udp->source_port = htons(source_addr->source_port); 291 | udp->destination_port = htons(destination_port); 292 | 293 | udp->length = htons(UDP_FRAME_SIZE + data_length); 294 | 295 | 296 | /* Add UDP data */ 297 | data_copy = &udp->data; 298 | 299 | for(index = 0; index < data_length; index++) 300 | { 301 | data_copy[index] = data[index]; 302 | } 303 | 304 | 305 | /* Fill IP frame before UDP checksum calculation */ 306 | udp_packet_size = UDP_FRAME_SIZE + data_length; 307 | 308 | fill_ip_frame(ip, &source_addr->identifier, destination_ip, source_addr->source_ip, IP_UDP, udp_packet_size); 309 | 310 | 311 | /* get UDP checksum */ 312 | udp->checksum = get_udp_checksum(ip, udp, data_length); 313 | 314 | 315 | /* Fill Ethernet frame */ 316 | fill_ether_frame(ethernet, destination_mac, source_addr->source_mac, ETHER_IPV4); 317 | 318 | 319 | /* Send UPD data */ 320 | ether_send_data(ethernet,(uint8_t*)ethernet->ether_obj, ETHER_FRAME_SIZE + htons(ip->total_length)); 321 | } 322 | 323 | return func_retval; 324 | } 325 | 326 | 327 | 328 | 329 | 330 | /**************************************************************** 331 | * @brief Function detect UDP packet, state machine independent 332 | * @param *ethernet : Reference to the Ethernet handle 333 | * @param *network_data : network data from PHY 334 | * @param network_data_length : network data length to be read 335 | * @retval uint8_t : Error = 0, 336 | * Success = 1 (UNICAST) 337 | * = 2 (BROADCAST) 338 | ****************************************************************/ 339 | uint8_t ether_is_udp(ethernet_handle_t *ethernet, uint8_t *network_data, uint16_t network_data_length) 340 | { 341 | uint8_t func_retval = 0; 342 | uint8_t block_loop = 0; 343 | 344 | int16_t comm_type = 0; 345 | 346 | if(ethernet->ether_obj == NULL || network_data == NULL || network_data_length == 0 || network_data_length > UINT16_MAX) 347 | { 348 | func_retval = 0; 349 | } 350 | else 351 | { 352 | /* Wait for data */ 353 | block_loop = ethernet->status.mode_read_blocking; 354 | 355 | do 356 | { 357 | if(ether_get_data(ethernet, network_data, network_data_length)) 358 | { 359 | /* Check if protocol is IPV4 */ 360 | if(get_ether_protocol_type(ethernet) == ETHER_IPV4) 361 | { 362 | 363 | /* Checks if UNICAST, validates checksum */ 364 | comm_type = get_ip_communication_type(ethernet); 365 | 366 | /* UNICAST */ 367 | if(comm_type == 1) 368 | { 369 | /* Check if protocol is UDP */ 370 | if(get_ip_protocol_type(ethernet) == IP_UDP) 371 | { 372 | func_retval = 1; 373 | 374 | break; 375 | } 376 | 377 | } 378 | /* BROADCAST */ 379 | else if(comm_type == 2) 380 | { 381 | /* Check if protocol is UDP */ 382 | if(get_ip_protocol_type(ethernet) == IP_UDP) 383 | { 384 | func_retval = 2; 385 | 386 | break; 387 | } 388 | 389 | 390 | } 391 | 392 | } 393 | 394 | } 395 | 396 | }while(block_loop); 397 | 398 | } 399 | 400 | return func_retval; 401 | } 402 | 403 | 404 | 405 | 406 | 407 | /***************************************************************** 408 | * @brief Function to read UPD packets 409 | * @param *ethernet : Reference to the Ethernet handle 410 | * @param *network_data : network data from PHY 411 | * @param *application_data : UDP data 412 | * @param app_data_length : Length of UDP data 413 | * @retval int8_t : Error = 0, Success = 1 414 | *****************************************************************/ 415 | uint8_t ether_read_udp(ethernet_handle_t *ethernet, uint8_t *network_data, char *application_data, uint16_t app_data_length) 416 | { 417 | uint8_t func_retval = 0; 418 | uint8_t api_retval = 0; 419 | 420 | 421 | if(ethernet->ether_obj == NULL || network_data == NULL || app_data_length == 0 || app_data_length > UINT16_MAX) 422 | { 423 | func_retval = 0; 424 | } 425 | else 426 | { 427 | api_retval = ether_is_udp(ethernet, network_data, ETHER_MTU_SIZE); 428 | 429 | if(api_retval) 430 | { 431 | func_retval = ether_get_udp_data(ethernet, (uint8_t*)application_data, app_data_length); 432 | 433 | } 434 | } 435 | 436 | return func_retval; 437 | } 438 | 439 | 440 | 441 | 442 | /************************************************************** 443 | * @brief Function to send UPD packets 444 | * UDP data dependent upon total data allocated to 445 | * ethernet object 446 | * @param *ethernet : Reference to the Ethernet handle 447 | * @param *destination_ip : Destination IP address 448 | * @param destination_port : UDP destination port 449 | * @param *application_data : UDP data 450 | * @param data_length : Length of UDP data 451 | * @retval int8_t : Error = -10, Success = 0 452 | **************************************************************/ 453 | int8_t ether_send_udp(ethernet_handle_t *ethernet, uint8_t *destination_ip, uint16_t destination_port, char *application_data, uint16_t data_length) 454 | { 455 | 456 | int8_t func_retval = 0; 457 | 458 | net_ip_t *ip; 459 | net_udp_t *udp; 460 | 461 | /* UDP related variables */ 462 | uint16_t index = 0; 463 | uint8_t *data_copy; 464 | uint16_t udp_packet_size = 0; 465 | 466 | /*IP related variables */ 467 | uint16_t ip_identfier = 0; 468 | 469 | /* Ethernet Frame related variables */ 470 | uint8_t destination_mac[ETHER_MAC_SIZE] = {0}; 471 | 472 | 473 | if(ethernet->ether_obj == NULL || destination_ip == NULL || destination_port == 0 \ 474 | || application_data == NULL || data_length == 0 || data_length > UINT16_MAX) 475 | { 476 | func_retval = NET_UDP_SEND_ERROR; 477 | } 478 | else 479 | { 480 | 481 | ip = (void*)ðernet->ether_obj->data; 482 | 483 | udp = (void*)( (uint8_t*)ip + IP_HEADER_SIZE ); 484 | 485 | 486 | /* Fill UDP frame */ 487 | udp->source_port = htons(ethernet->source_port); 488 | udp->destination_port = htons(destination_port); 489 | 490 | udp->length = htons(UDP_FRAME_SIZE + data_length); 491 | 492 | 493 | /* Add UDP data */ 494 | data_copy = &udp->data; 495 | 496 | for(index = 0; index < data_length; index++) 497 | { 498 | data_copy[index] = application_data[index]; 499 | } 500 | 501 | 502 | /* Fill IP frame */ 503 | ip_identfier = get_unique_id(ethernet, 2000); 504 | 505 | udp_packet_size = UDP_FRAME_SIZE + data_length; 506 | 507 | fill_ip_frame(ip, &ip_identfier, destination_ip, ethernet->host_ip, IP_UDP, udp_packet_size); 508 | 509 | 510 | /* get UDP checksum */ 511 | udp->checksum = get_udp_checksum(ip, udp, data_length); 512 | 513 | 514 | /* Get MAC address from ARP table */ 515 | ether_arp_resolve_address(ethernet, destination_mac, destination_ip); 516 | 517 | /* Fill Ethernet frame */ 518 | fill_ether_frame(ethernet, destination_mac, ethernet->host_mac, ETHER_IPV4); 519 | 520 | 521 | /* Send UPD data */ 522 | ether_send_data(ethernet,(uint8_t*)ethernet->ether_obj, ETHER_FRAME_SIZE + htons(ip->total_length)); 523 | 524 | } 525 | 526 | return func_retval; 527 | 528 | 529 | } 530 | 531 | 532 | 533 | 534 | /************************************************************** 535 | * @brief Function to read UDP packet 536 | * @param *ethernet : reference to the Ethernet handle 537 | * @param *network_data : network data from the ether PHY 538 | * @param net_data_length : network data length 539 | * @param *source_port : UDP source port 540 | * @param *destination_port : UDP destination port 541 | * @param *application_data : UDP data 542 | * @param data_length : Length of UDP data 543 | * @param app_data_length : 544 | * @retval uint16_t : Error = 0, Success = bytes read 545 | **************************************************************/ 546 | uint16_t ether_read_udp_raw(ethernet_handle_t *ethernet, uint8_t *network_data, uint16_t net_data_length, 547 | uint16_t *source_port, uint16_t *destination_port, char *application_data, uint16_t app_data_length) 548 | { 549 | uint16_t func_retval = 0; 550 | 551 | net_ip_t *ip; 552 | net_udp_t *udp; 553 | 554 | uint8_t api_retval = 0; 555 | uint8_t validate = 0; 556 | 557 | uint16_t udp_packet_length = 0; 558 | uint16_t udp_data_length = 0; 559 | 560 | 561 | if(ethernet->ether_obj == NULL || network_data == NULL || net_data_length == 0 || net_data_length > UINT16_MAX) 562 | { 563 | func_retval = 0; 564 | } 565 | else 566 | { 567 | api_retval = ether_is_udp(ethernet, network_data, net_data_length); 568 | 569 | if(api_retval) 570 | { 571 | ip = (void*)ðernet->ether_obj->data; 572 | 573 | udp = (void*)( (uint8_t*)ip + IP_HEADER_SIZE ); 574 | 575 | /* get source and destination port */ 576 | *source_port = ntohs(udp->source_port); 577 | *destination_port = ntohs(udp->destination_port); 578 | 579 | /* Get UDP packet length and data length from header */ 580 | udp_packet_length = ntohs(udp->length); 581 | udp_data_length = udp_packet_length - UDP_FRAME_SIZE; 582 | 583 | /* Check and Truncate UDP data length */ 584 | if(app_data_length > udp_data_length) 585 | app_data_length = udp_data_length; 586 | 587 | /* validate UDP checksum */ 588 | validate = validate_udp_checksum(ip, udp); 589 | 590 | /* Get UDP header */ 591 | if(validate) 592 | { 593 | memcpy((char*)application_data, (char*)&udp->data, app_data_length); 594 | 595 | func_retval = app_data_length; 596 | } 597 | 598 | } 599 | } 600 | 601 | return func_retval; 602 | } 603 | 604 | 605 | 606 | 607 | 608 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minimal-TCP-IP-Stack 2 | 3 | ### Minimal-TCP/IP stack for enc28j60 module. 4 | 5 | ![Version:1.0](https://img.shields.io/badge/Version-1.0-green) 6 | ![IDE:CCStudio](https://img.shields.io/badge/IDE-CCStudio-red) 7 | ![Terminal:Putty](https://img.shields.io/badge/Teminal-puTTY-blue) 8 | 9 | ![License:MIT](https://img.shields.io/github/license/adimalla/MQTT-3.1-C?label=License) 10 |
11 |
12 | 13 | ## Description 14 | **minimal-TCP/IP stack** is a portable network stack API using the enc28j60 ethernet module on ARM-cortex M4 architecture based board for non OS enviornment. Tested on (Texas Instruments TM4c123gh series processor), developed as a part of course projects (EE6314) at the University of Texas at Arlington. This API was used to provide a network layer interface for the home automation project and MQTT gateway project for low power sensor network. 15 |
16 | 17 | ## Features 18 | 19 | ##### Current:- 20 | * Simple and easy to use API. 21 | * Implements Ethernet layer, ARP, ICMP, TCP and UDP protocols. 22 | * Supports Dynamic IP through DHCP. 23 | * API based layers for raw TCP and UDP sockets. 24 | * Supports max MTU of 1500 bytes. 25 | * Lightweight stack usage of approximate 4096 bytes for medium scale MCU based embedded systems. 26 | * Portable, can be ported to other platforms. 27 | * Extensively tested as TCP and UDP clients and also as clients with application layer protocols like MQTT. 28 | 29 | ##### Future Version:- 30 | * Linux Sockets like API. 31 | * Support for multiple sockets. 32 | * RTOS based testing and support. 33 | 34 | ## Testing 35 | 36 | **The API is tested on TIVA Launcpad by Texas Instruments and enc28j60 module.** 37 |
38 | 39 | ##### Hardware Configuration 40 | 41 | ENC28J60 Ethernet controller connected on the following pins :-
42 | * MOSI (SSI2Tx) on PB7
43 | * MISO (SSI2Rx) on PB6
44 | * SCLK (SSI2Clk) on PB4
45 | * ~CS (GPIO) on PB1
46 | 47 | ##### Dependencies 48 | 49 | Test code is dependent on the following APIs:-
50 | * Clone "clterm" Repo from : https://github.com/adimalla/clTerm 51 | * Clone "MQTT-3.1-C" Repo from : https://github.com/adimalla/MQTT-3.1-C 52 | 53 | 54 | ## Disclaimer 55 | If you are a student at The University of Texas at Arlington, please take prior permissions from Dr.Jason Losh and author of this repository before using any part of the source code in your project, in order to abide by the academic integrity of the university. 56 | 57 | ## Contact 58 | 59 | * aditya.mall1990@gmail.com 60 | * aditya.mall@mavs.uta.edu 61 | 62 |
63 | 64 | -------------------------------------------------------------------------------- /enc28j60.c: -------------------------------------------------------------------------------- 1 | // ENC28J60 Driver 2 | // Author: Jason Losh 3 | // Modifications: Aditya Mall 4 | // The University of Texas at Arlington 5 | 6 | //----------------------------------------------------------------------------- 7 | // Hardware Target 8 | //----------------------------------------------------------------------------- 9 | 10 | // Target uC: TM4C123GH6PM 11 | // System Clock: 40 MHz 12 | 13 | //----------------------------------------------------------------------------- 14 | // Device includes, defines, and assembler directives 15 | //----------------------------------------------------------------------------- 16 | 17 | #include 18 | #include 19 | #include "tm4c123gh6pm.h" 20 | #include "enc28j60.h" 21 | #include "wait.h" 22 | 23 | #include 24 | 25 | 26 | #pragma pack(1) 27 | 28 | // ------------------------------------------------------------------------------ 29 | // Globals 30 | // ------------------------------------------------------------------------------ 31 | 32 | uint8_t nextPacketLsb = 0x00; 33 | uint8_t nextPacketMsb = 0x00; 34 | 35 | 36 | 37 | //----------------------------------------------------------------------------- 38 | // Subroutines 39 | //----------------------------------------------------------------------------- 40 | 41 | void spiWrite(uint8_t data) 42 | { 43 | #if IOT_COURSE_TEST 44 | 45 | SSI0_DR_R = data; 46 | while (SSI0_SR_R & SSI_SR_BSY); 47 | 48 | #else 49 | SSI2_DR_R = data; 50 | while (SSI2_SR_R & SSI_SR_BSY); 51 | #endif 52 | } 53 | 54 | uint8_t spiRead() 55 | { 56 | #if IOT_COURSE_TEST 57 | 58 | return SSI0_DR_R; 59 | 60 | #else 61 | return SSI2_DR_R; 62 | #endif 63 | } 64 | 65 | void etherCsOn() 66 | { 67 | PIN_ETHER_CS = 0; 68 | __asm (" NOP"); // allow line to settle 69 | __asm (" NOP"); 70 | __asm (" NOP"); 71 | __asm (" NOP"); 72 | } 73 | 74 | void etherCsOff() 75 | { 76 | PIN_ETHER_CS = 1; 77 | } 78 | 79 | void etherWriteReg(uint8_t reg, uint8_t data) 80 | { 81 | etherCsOn(); 82 | spiWrite(0x40 | (reg & 0x1F)); 83 | spiRead(); 84 | spiWrite(data); 85 | spiRead(); 86 | etherCsOff(); 87 | } 88 | 89 | uint8_t etherReadReg(uint8_t reg) 90 | { 91 | uint8_t data; 92 | etherCsOn(); 93 | spiWrite(0x00 | (reg & 0x1F)); 94 | spiRead(); 95 | spiWrite(0); 96 | data = spiRead(); 97 | etherCsOff(); 98 | return data; 99 | } 100 | 101 | void etherSetReg(uint8_t reg, uint8_t mask) 102 | { 103 | etherCsOn(); 104 | spiWrite(0x80 | (reg & 0x1F)); 105 | spiRead(); 106 | spiWrite(mask); 107 | spiRead(); 108 | etherCsOff(); 109 | } 110 | 111 | void etherClearReg(uint8_t reg, uint8_t mask) 112 | { 113 | etherCsOn(); 114 | spiWrite(0xA0 | (reg & 0x1F)); 115 | spiRead(); 116 | spiWrite(mask); 117 | spiRead(); 118 | etherCsOff(); 119 | } 120 | 121 | void etherSetBank(uint8_t reg) 122 | { 123 | etherClearReg(ECON1, 0x03); 124 | etherSetReg(ECON1, reg >> 5); 125 | } 126 | 127 | void etherWritePhy(uint8_t reg, uint16_t data) 128 | { 129 | etherSetBank(MIREGADR); 130 | etherWriteReg(MIREGADR, reg); 131 | etherWriteReg(MIWRL, data & 0xFF); 132 | etherWriteReg(MIWRH, (data >> 8) & 0xFF); 133 | } 134 | 135 | uint16_t etherReadPhy(uint8_t reg) 136 | { 137 | uint16_t data, data2; 138 | etherSetBank(MIREGADR); 139 | etherWriteReg(MIREGADR, reg); 140 | etherWriteReg(MICMD, etherReadReg(MICMD) | MIIRD); 141 | waitMicrosecond(50); 142 | while ((etherReadReg(MISTAT) | MIBUSY) != 0); 143 | etherWriteReg(MICMD, etherReadReg(MICMD) & ~MIIRD); 144 | data = etherReadReg(MIRDL); 145 | data2 = etherReadReg(MIRDH); 146 | data |= (data2 << 8); 147 | return data; 148 | } 149 | 150 | void etherWriteMemStart() 151 | { 152 | etherCsOn(); 153 | spiWrite(0x7A); 154 | spiRead(); 155 | } 156 | 157 | void etherWriteMem(uint8_t data) 158 | { 159 | spiWrite(data); 160 | spiRead(); 161 | } 162 | 163 | void etherWriteMemStop() 164 | { 165 | etherCsOff(); 166 | } 167 | 168 | void etherReadMemStart() 169 | { 170 | etherCsOn(); 171 | spiWrite(0x3A); 172 | spiRead(); 173 | } 174 | 175 | uint8_t etherReadMem() 176 | { 177 | spiWrite(0); 178 | return spiRead(); 179 | } 180 | 181 | void etherReadMemStop() 182 | { 183 | etherCsOff(); 184 | } 185 | 186 | 187 | void setPhyMacAddr(uint8_t *macAddr) 188 | { 189 | // setup mac address 190 | etherSetBank(MAADR0); 191 | etherWriteReg(MAADR5, macAddr[0]); 192 | etherWriteReg(MAADR4, macAddr[1]); 193 | etherWriteReg(MAADR3, macAddr[2]); 194 | etherWriteReg(MAADR2, macAddr[3]); 195 | etherWriteReg(MAADR1, macAddr[4]); 196 | etherWriteReg(MAADR0, macAddr[5]); 197 | 198 | } 199 | 200 | 201 | // Initializes ethernet device 202 | // Uses order suggested in Chapter 6 of datasheet except 6.4 OST which is first here 203 | void etherInit(uint8_t mode, uint8_t *macAddress) 204 | { 205 | // make sure that oscillator start-up timer has expired 206 | while ((etherReadReg(ESTAT) & CLKRDY) == 0) {} 207 | 208 | // disable transmission and reception of packets 209 | etherClearReg(ECON1, RXEN); 210 | etherClearReg(ECON1, TXRTS); 211 | 212 | // initialize receive buffer space 213 | etherSetBank(ERXSTL); 214 | etherWriteReg(ERXSTL, LOBYTE(0x0000)); 215 | etherWriteReg(ERXSTH, HIBYTE(0x0000)); 216 | etherWriteReg(ERXNDL, LOBYTE(0x1A09)); 217 | etherWriteReg(ERXNDH, HIBYTE(0x1A09)); 218 | 219 | // initialize receiver write and read ptrs 220 | // at startup, will write from 0 to 1A08 only and will not overwrite rd ptr 221 | etherWriteReg(ERXWRPTL, LOBYTE(0x0000)); 222 | etherWriteReg(ERXWRPTH, HIBYTE(0x0000)); 223 | etherWriteReg(ERXRDPTL, LOBYTE(0x1A09)); 224 | etherWriteReg(ERXRDPTH, HIBYTE(0x1A09)); 225 | etherWriteReg(ERDPTL, LOBYTE(0x0000)); 226 | etherWriteReg(ERDPTH, HIBYTE(0x0000)); 227 | 228 | // setup receive filter 229 | // always check CRC, use OR mode 230 | etherSetBank(ERXFCON); 231 | etherWriteReg(ERXFCON, (mode | 0x20) & 0xBF); 232 | // bring mac out of reset 233 | etherSetBank(MACON2); 234 | etherWriteReg(MACON2, 0); 235 | 236 | // enable mac rx, enable pause control for full duplex 237 | etherWriteReg(MACON1, TXPAUS | RXPAUS | MARXEN); 238 | 239 | // enable padding to 60 bytes (no runt packets) 240 | // add crc to tx packets, set full or half duplex 241 | if ((mode & ETHER_FULLDUPLEX) != 0) 242 | etherWriteReg(MACON3, FULDPX | FRMLNEN | TXCRCEN | PAD60); 243 | else 244 | etherWriteReg(MACON3, FRMLNEN | TXCRCEN | PAD60); 245 | 246 | // leave MACON4 as reset 247 | 248 | // set maximum rx packet size 249 | etherWriteReg(MAMXFLL, LOBYTE(1518)); 250 | etherWriteReg(MAMXFLH, HIBYTE(1518)); 251 | 252 | // set back-to-back uint8_ter-packet gap to 9.6us 253 | if ((mode & ETHER_FULLDUPLEX) != 0) 254 | etherWriteReg(MABBIPG, 0x15); 255 | else 256 | etherWriteReg(MABBIPG, 0x12); 257 | 258 | // set non-back-to-back uint8_ter-packet gap registers 259 | etherWriteReg(MAIPGL, 0x12); 260 | etherWriteReg(MAIPGH, 0x0C); 261 | 262 | // leave collision window MACLCON2 as reset 263 | 264 | setPhyMacAddr(macAddress); 265 | 266 | // initialize phy duplex 267 | if ((mode & ETHER_FULLDUPLEX) != 0) 268 | etherWritePhy(PHCON1, PDPXMD); 269 | else 270 | etherWritePhy(PHCON1, 0); 271 | 272 | // disable phy loopback if in half-duplex mode 273 | etherWritePhy(PHCON2, HDLDIS); 274 | 275 | // set LEDA (link status) and LEDB (tx/rx activity) 276 | // stretch LED on to 40ms (default) 277 | etherWritePhy(PHLCON, 0x0472); 278 | 279 | // enable reception 280 | etherSetReg(ECON1, RXEN); 281 | } 282 | 283 | // Returns TRUE if packet received 284 | uint8_t etherKbhit() 285 | { 286 | return ((etherReadReg(EIR) & PKTIF) != 0); 287 | } 288 | 289 | // Returns up to max_size characters in data buffer 290 | // Returns number of bytes copied to buffer 291 | // Contents written are 16-bit size, 16-bit status, payload excl crc 292 | uint16_t etherGetPacket(uint8_t data[], uint16_t max_size) 293 | { 294 | uint16_t i = 0, size, tmp; 295 | 296 | // enable read from FIFO buffers 297 | etherReadMemStart(); 298 | 299 | // get next pckt information 300 | nextPacketLsb = etherReadMem(); 301 | nextPacketMsb = etherReadMem(); 302 | 303 | // calc size 304 | // don't return crc, instead return size + status, so size is correct 305 | size = etherReadMem(); 306 | data[i++] = size; 307 | tmp = etherReadMem(); 308 | data[i++] = tmp; 309 | size |= (tmp << 8); 310 | 311 | // copy status + data 312 | if (size > max_size) 313 | size = max_size; 314 | while (i < size) 315 | data[i++] = etherReadMem(); 316 | 317 | // end read from FIFO buffers 318 | etherReadMemStop(); 319 | 320 | // advance read ptr 321 | etherSetBank(ERXRDPTL); 322 | etherWriteReg(ERXRDPTL, nextPacketLsb); // hw ptr 323 | etherWriteReg(ERXRDPTH, nextPacketMsb); 324 | etherWriteReg(ERDPTL, nextPacketLsb); // dma rd ptr 325 | etherWriteReg(ERDPTH, nextPacketMsb); 326 | 327 | // decrement packet counter so that PKTIF is maintained correctly 328 | etherSetReg(ECON2, PKTDEC); 329 | 330 | return size; 331 | } 332 | 333 | // Returns TRUE is rx buffer overflowed after correcting the problem 334 | uint8_t etherIsOverflow() 335 | { 336 | uint8_t err; 337 | err = (etherReadReg(EIR) & RXERIF) != 0; 338 | if (err) 339 | etherClearReg(EIR, RXERIF); 340 | return err; 341 | } 342 | 343 | // Writes a packet 344 | int16_t etherPutPacket(uint8_t data[], uint16_t size) 345 | { 346 | uint16_t i; 347 | 348 | // clear out any tx errors 349 | if ((etherReadReg(EIR) & TXERIF) != 0) 350 | { 351 | etherClearReg(EIR, TXERIF); 352 | etherSetReg(ECON1, TXRTS); 353 | etherClearReg(ECON1, TXRTS); 354 | } 355 | 356 | // set DMA start address 357 | etherSetBank(EWRPTL); 358 | etherWriteReg(EWRPTL, LOBYTE(0x1A0A)); 359 | etherWriteReg(EWRPTH, HIBYTE(0x1A0A)); 360 | 361 | // start FIFO buffer write 362 | etherWriteMemStart(); 363 | 364 | // write control byte 365 | etherWriteMem(0); 366 | 367 | // write data 368 | for (i = 0; i < size; i++) 369 | etherWriteMem(data[i]); 370 | 371 | // stop write 372 | etherWriteMemStop(); 373 | 374 | // request transmit 375 | etherWriteReg(ETXSTL, LOBYTE(0x1A0A)); 376 | etherWriteReg(ETXSTH, HIBYTE(0x1A0A)); 377 | etherWriteReg(ETXNDL, LOBYTE(0x1A0A+size)); 378 | etherWriteReg(ETXNDH, HIBYTE(0x1A0A+size)); 379 | etherClearReg(EIR, TXIF); 380 | etherSetReg(ECON1, TXRTS); 381 | 382 | // wait for completion 383 | while ((etherReadReg(ECON1) & TXRTS) != 0); 384 | 385 | // determine success 386 | return ((etherReadReg(ESTAT) & TXABORT) == 0); 387 | } 388 | 389 | 390 | 391 | 392 | -------------------------------------------------------------------------------- /enc28j60.h: -------------------------------------------------------------------------------- 1 | // ENC28J60 Driver 2 | // Jason Losh 3 | 4 | //----------------------------------------------------------------------------- 5 | // Hardware Target 6 | //----------------------------------------------------------------------------- 7 | 8 | // Target uC: TM4C123GH6PM 9 | // System Clock: 40 MHz 10 | 11 | #ifndef ENC28J60_H_ 12 | #define ENC28J60_H_ 13 | 14 | 15 | #include "ethernet.h" 16 | #include "network_utilities.h" 17 | #include "ipv4.h" 18 | 19 | #define IOT_COURSE_TEST 0 20 | 21 | 22 | //----------------------------------------------------------------------------- 23 | // Subroutines 24 | //----------------------------------------------------------------------------- 25 | 26 | // Buffer is configured as follows 27 | // Receive buffer starts at 0x0000 (bottom 6666 bytes of 8K space) 28 | // Transmit buffer at 01A0A (top 1526 bytes of 8K space) 29 | 30 | // ------------------------------------------------------------------------------ 31 | // Defines 32 | // ------------------------------------------------------------------------------ 33 | 34 | // Pins 35 | #if IOT_COURSE_TEST 36 | 37 | #define PIN_ETHER_CS (*((volatile uint32_t *)(0x42000000 + (0x400043FC-0x40000000)*32 + 3*4))) 38 | 39 | //#define PIN_ETHER_CS (*((volatile uint32_t *)(0x42000000 + (0x400073FC-0x40000000)*32 + 1*4))) 40 | 41 | 42 | #else 43 | #define PIN_ETHER_CS (*((volatile uint32_t *)(0x42000000 + (0x400053FC-0x40000000)*32 + 5*4))) 44 | 45 | #endif 46 | 47 | #define ETHER_UNICAST 0x80 48 | #define ETHER_BROADCAST 0x01 49 | #define ETHER_MULTICAST 0x02 50 | #define ETHER_HASHTABLE 0x04 51 | #define ETHER_MAGICPACKET 0x08 52 | #define ETHER_PATTERNMATCH 0x10 53 | 54 | #define ETHER_HALFDUPLEX 0x00 55 | #define ETHER_FULLDUPLEX 0x40 56 | 57 | // Ether registers 58 | #define ERDPTL 0x00 59 | #define ERDPTH 0x01 60 | #define EWRPTL 0x02 61 | #define EWRPTH 0x03 62 | #define ETXSTL 0x04 63 | #define ETXSTH 0x05 64 | #define ETXNDL 0x06 65 | #define ETXNDH 0x07 66 | #define ERXSTL 0x08 67 | #define ERXSTH 0x09 68 | #define ERXNDL 0x0A 69 | #define ERXNDH 0x0B 70 | #define ERXRDPTL 0x0C 71 | #define ERXRDPTH 0x0D 72 | #define ERXWRPTL 0x0E 73 | #define ERXWRPTH 0x0F 74 | #define EIE 0x1B 75 | #define EIR 0x1C 76 | #define RXERIF 0x01 77 | #define TXERIF 0x02 78 | #define TXIF 0x08 79 | #define PKTIF 0x40 80 | #define ESTAT 0x1D 81 | #define CLKRDY 0x01 82 | #define TXABORT 0x02 83 | #define ECON2 0x1E 84 | #define PKTDEC 0x40 85 | #define ECON1 0x1F 86 | #define RXEN 0x04 87 | #define TXRTS 0x08 88 | #define ERXFCON 0x38 89 | #define EPKTCNT 0x39 90 | #define MACON1 0x40 91 | #define MARXEN 0x01 92 | #define RXPAUS 0x04 93 | #define TXPAUS 0x08 94 | #define MACON2 0x41 95 | #define MARST 0x80 96 | #define MACON3 0x42 97 | #define FULDPX 0x01 98 | #define FRMLNEN 0x02 99 | #define TXCRCEN 0x10 100 | #define PAD60 0x20 101 | #define MACON4 0x43 102 | #define MABBIPG 0x44 103 | #define MAIPGL 0x46 104 | #define MAIPGH 0x47 105 | #define MACLCON1 0x48 106 | #define MACLCON2 0x49 107 | #define MAMXFLL 0x4A 108 | #define MAMXFLH 0x4B 109 | #define MICMD 0x52 110 | #define MIIRD 0x01 111 | #define MIREGADR 0x54 112 | #define MIWRL 0x56 113 | #define MIWRH 0x57 114 | #define MIRDL 0x58 115 | #define MIRDH 0x59 116 | #define MAADR1 0x60 117 | #define MAADR0 0x61 118 | #define MAADR3 0x62 119 | #define MAADR2 0x63 120 | #define MAADR5 0x64 121 | #define MAADR4 0x65 122 | #define MISTAT 0x6A 123 | #define MIBUSY 0x01 124 | #define ECOCON 0x75 125 | 126 | // Ether phy registers 127 | #define PHCON1 0x00 128 | #define PDPXMD 0x0100 129 | #define PHCON2 0x10 130 | #define HDLDIS 0x0100 131 | #define PHLCON 0x14 132 | 133 | // ------------------------------------------------------------------------------ 134 | // Macros 135 | // ------------------------------------------------------------------------------ 136 | 137 | #define LOBYTE(x) ((x) & 0xFF) 138 | #define HIBYTE(x) (((x) >> 8) & 0xFF) 139 | 140 | 141 | 142 | 143 | typedef struct enc28j60Frame // 4-bytes 144 | { 145 | uint16_t size; 146 | uint16_t status; 147 | uint8_t data; 148 | 149 | }enc28j60_frame_t; 150 | 151 | enc28j60_frame_t *enc28j60; 152 | 153 | 154 | 155 | 156 | // ------------------------------------------------------------------------------ 157 | // Functions 158 | // ------------------------------------------------------------------------------ 159 | 160 | void etherInit(uint8_t mode, uint8_t *macAddress); 161 | 162 | void setPhyMacAddr(uint8_t *macAddr); 163 | 164 | void etherWritePhy(uint8_t reg, uint16_t data); 165 | uint16_t etherReadPhy(uint8_t reg); 166 | uint8_t etherKbhit(); 167 | uint16_t etherGetPacket(uint8_t data[], uint16_t max_size); 168 | uint8_t etherIsOverflow(); 169 | int16_t etherPutPacket(uint8_t data[], uint16_t size); 170 | 171 | 172 | 173 | 174 | #endif 175 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file main.c 4 | * @author Aditya Mall, 5 | * @brief Network API test app file 6 | * 7 | * Info 8 | * Target Platform : EK-TM4C123GXL w/ ENC28J60 9 | * Target uC : TM4C123GH6PM 10 | * System Clock : 40 MHz 11 | * 12 | * Hardware configuration :- 13 | * ENC28J60 Ethernet controller 14 | * MOSI (SSI2Tx) on PB7 15 | * MISO (SSI2Rx) on PB6 16 | * SCLK (SSI2Clk) on PB4 17 | * ~CS connected to PB1 18 | * 19 | ****************************************************************************** 20 | * @attention 21 | * 22 | *

© COPYRIGHT(c) 2019 Aditya Mall, MIT License

23 | * 24 | * Copyright (c) 2019 Aditya Mall 25 | * 26 | * Please Take prior permission from Dr. Jason Losh and Respective Owners of the, 27 | * API Libraries if you are a student at The University of Texas at Arlington and, 28 | * wish to use part of the code in your project. 29 | * 30 | * The above copyright notice and this permission notice shall be included in all 31 | * copies or substantial portions of the Software. 32 | * 33 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 36 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 37 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 38 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 39 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 40 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 41 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 42 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 | * 44 | ****************************************************************************** 45 | */ 46 | 47 | 48 | /* 49 | ****************************************************************************** 50 | * 51 | * Repository Information :- 52 | * 53 | * Clone "clterm" Repo from : https://github.com/adimalla/clTerm 54 | * Clone "MQTT-3.1-C" Repo from : https://github.com/adimalla/MQTT-3.1-C 55 | * 56 | ****************************************************************************** 57 | */ 58 | 59 | 60 | /* 61 | * Standard header and API header files 62 | */ 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include "tm4c123gh6pm.h" 68 | #include "enc28j60.h" 69 | #include "wait.h" 70 | 71 | #include "ethernet.h" 72 | #include "network_utilities.h" 73 | #include "arp.h" 74 | #include "ipv4.h" 75 | #include "icmp.h" 76 | #include "udp.h" 77 | #include "dhcp.h" 78 | #include "tcp.h" 79 | 80 | #include "cl_term.h" 81 | #include "mqtt_client.h" 82 | 83 | 84 | 85 | /******************************************************************************/ 86 | /* */ 87 | /* Data Structures and Defines */ 88 | /* */ 89 | /******************************************************************************/ 90 | 91 | 92 | #define STATIC 1 93 | #define ICMP_TEST 1 94 | #define UDP_TEST 0 95 | #define TCP_TEST 0 96 | #define MQTT_TEST 1 97 | 98 | 99 | #define RED_LED (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 1*4))) 100 | #define GREEN_LED (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 3*4))) 101 | #define BLUE_LED (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 2*4))) 102 | #define PUSH_BUTTON (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 4*4))) 103 | 104 | 105 | 106 | typedef enum _app_state 107 | { 108 | APP_INIT = 0, 109 | APP_READ = 1, 110 | APP_WRITE = 2, 111 | USER_INPUT = 3, 112 | 113 | }app_state_t; 114 | 115 | 116 | 117 | /******************************************************************************/ 118 | /* */ 119 | /* Functions Implementations */ 120 | /* */ 121 | /******************************************************************************/ 122 | 123 | 124 | void initHw() 125 | { 126 | // Configure HW to work with 16 MHz XTAL, PLL enabled, system clock of 40 MHz 127 | SYSCTL_RCC_R = SYSCTL_RCC_XTAL_16MHZ | SYSCTL_RCC_OSCSRC_MAIN | SYSCTL_RCC_USESYSDIV | (4 << SYSCTL_RCC_SYSDIV_S); 128 | 129 | // Set GPIO ports to use APB (not needed since default configuration -- for clarity) 130 | // Note UART on port A must use APB 131 | SYSCTL_GPIOHBCTL_R = 0; 132 | 133 | // Enable GPIO port B and E peripherals 134 | SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOB | SYSCTL_RCGC2_GPIOD | SYSCTL_RCGC2_GPIOF | SYSCTL_RCGC2_GPIOA | SYSCTL_RCGC2_GPIOE; 135 | 136 | // Configure LED and pushbutton pins 137 | GPIO_PORTF_DIR_R = 0x0E; // bits 1-3 are outputs, other pins are inputs 138 | GPIO_PORTF_DR2R_R = 0x0E; // set drive strength to 2mA (not needed since default configuration -- for clarity) 139 | GPIO_PORTF_DEN_R = 0x1E; // enable LEDs and pushbuttons 140 | GPIO_PORTF_PUR_R = 0x1E; // enable internal pull-up for push button 141 | 142 | #if IOT_COURSE_TEST /* IOT Networking Student Hardware check */ 143 | 144 | // Configure ~CS for ENC28J60 145 | GPIO_PORTA_DIR_R = (1 << 3); // make bit 1 an output 146 | GPIO_PORTA_DEN_R = (1 << 3); // enable bits 1 for digital 147 | 148 | // GPIO_PORTD_DIR_R = (1 << 1); // make bit 1 an output 149 | // GPIO_PORTD_DEN_R = (1 << 1); // enable bits 1 for digital 150 | 151 | SYSCTL_RCGCSSI_R |= SYSCTL_RCGCSSI_R0; 152 | GPIO_PORTA_DIR_R |= ( 1 << 2) | (1 << 3) | (1 << 5); 153 | GPIO_PORTA_DR2R_R |= ( 1 << 2) | (1 << 4) | (1 << 5); 154 | GPIO_PORTA_AFSEL_R |= ( 1 << 2) | (1 << 4) | (1 << 5); 155 | GPIO_PORTA_PCTL_R = GPIO_PCTL_PA5_SSI0TX | GPIO_PCTL_PA4_SSI0RX | GPIO_PCTL_PA2_SSI0CLK; 156 | GPIO_PORTA_DEN_R |= ( 1<< 2) | (1 << 4) | (1 << 5); 157 | 158 | SSI0_CR1_R &= ~SSI_CR1_SSE; 159 | SSI0_CR1_R = 0; // select master mode 160 | SSI0_CC_R = 0; // select system clock as the clock source 161 | SSI0_CPSR_R = 20; // set bit rate to 1 MHz (if SR=0 in CR0) 162 | SSI0_CR0_R = SSI_CR0_FRF_MOTO | SSI_CR0_DSS_8; // set SR=0, mode 0 (SPH=0, SPO=0), 8-bit 163 | SSI0_CR1_R |= SSI_CR1_SSE; 164 | 165 | #else 166 | 167 | // Configure ~CS for ENC28J60 168 | GPIO_PORTB_DIR_R = (1 << 5); // make bit 1 an output 169 | GPIO_PORTB_DEN_R = (1 << 5); // enable bits 1 for digital 170 | 171 | // Configure SSI2 pins for SPI configuration 172 | SYSCTL_RCGCSSI_R |= SYSCTL_RCGCSSI_R2; // turn-on SSI2 clocking 173 | GPIO_PORTB_DIR_R |= 0x90; // make bits 4 and 7 outputs 174 | GPIO_PORTB_DR2R_R |= 0x90; // set drive strength to 2mA 175 | GPIO_PORTB_AFSEL_R |= 0xD0; // select alternative functions for MOSI, MISO, SCLK pins 176 | GPIO_PORTB_PCTL_R = GPIO_PCTL_PB7_SSI2TX | \ 177 | GPIO_PCTL_PB6_SSI2RX | \ 178 | GPIO_PCTL_PB4_SSI2CLK; // map alt fns to SSI2 179 | GPIO_PORTB_DEN_R |= 0xD0; // enable digital operation on TX, RX, CLK pins 180 | 181 | // Configure the SSI2 as a SPI master, mode 3, 8bit operation, 1 MHz bit rate 182 | SSI2_CR1_R &= ~SSI_CR1_SSE; // turn off SSI2 to allow re-configuration 183 | SSI2_CR1_R = 0; // select master mode 184 | SSI2_CC_R = 0; // select system clock as the clock source 185 | SSI2_CPSR_R = 40; // set bit rate to 1 MHz (if SR=0 in CR0) 186 | SSI2_CR0_R = SSI_CR0_FRF_MOTO | SSI_CR0_DSS_8; // set SR=0, mode 0 (SPH=0, SPO=0), 8-bit 187 | SSI2_CR1_R |= SSI_CR1_SSE; // turn on SSI2 188 | 189 | #endif 190 | 191 | } 192 | 193 | 194 | void init_uart0(void) 195 | { 196 | // Enable GPIO port F peripherals 197 | SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOA; 198 | 199 | // Configure UART0 pins 200 | SYSCTL_RCGCUART_R |= SYSCTL_RCGCUART_R0; // Turn-on UART0, leave other uarts in same status 201 | GPIO_PORTA_DEN_R |= 3; // Turn on Digital Operations on PA0 and PA1 202 | GPIO_PORTA_AFSEL_R |= 3; // Select Alternate Functionality on PA0 and PA1 203 | GPIO_PORTA_PCTL_R |= GPIO_PCTL_PA1_U0TX | GPIO_PCTL_PA0_U0RX; // Select UART0 Module 204 | 205 | // Configure UART0 to 115200 baud, 8N1 format (must be 3 clocks from clock enable and config writes) 206 | UART0_CTL_R = 0; // turn-off UART0 to allow safe programming 207 | UART0_CC_R |= UART_CC_CS_SYSCLK; // use system clock (40 MHz) 208 | UART0_IBRD_R = 21; // r = 40 MHz / (Nx115.2kHz), set floor(r)=21, where N=16 209 | UART0_FBRD_R = 45; // round(fract(r)*64)=45 210 | UART0_LCRH_R |= UART_LCRH_WLEN_8 | UART_LCRH_FEN; // configure for 8N1 w/ 16-level FIFO 211 | UART0_CTL_R |= UART_CTL_TXE | UART_CTL_RXE | UART_CTL_UARTEN; // enable TX, RX, and module 212 | 213 | } 214 | 215 | 216 | // Blocking function that writes a serial character when the UART buffer is not full 217 | void putcUart0(const char c) 218 | { 219 | while(UART0_FR_R & UART_FR_TXFF); 220 | UART0_DR_R = c; 221 | 222 | } 223 | 224 | 225 | // Blocking function that returns with serial data once the buffer is not empty 226 | char getcUart0(void) 227 | { 228 | while (UART0_FR_R & UART_FR_RXFE); 229 | return UART0_DR_R & 0xFF; 230 | } 231 | 232 | 233 | 234 | // Blocking function that writes a string when the UART buffer is not full 235 | void putsUart0(const char* str) 236 | { 237 | uint8_t i; 238 | 239 | for (i = 0; i < strlen(str); i++) 240 | putcUart0(str[i]); 241 | } 242 | 243 | 244 | 245 | void init_adc(void) 246 | { 247 | 248 | // Enable GPIO port B and E peripherals 249 | 250 | // Configure AN0 as an analog input 251 | SYSCTL_RCGCADC_R |= SYSCTL_RCGCADC_R0; // turn on ADC module 0 clocking 252 | GPIO_PORTE_AFSEL_R |= (1 << 3); // select alternative functions for AN0 (PE3) 253 | GPIO_PORTE_DEN_R &= ~(1 << 3); // turn off digital operation on pin PE3 254 | GPIO_PORTE_AMSEL_R |= (1 << 3); // turn on analog operation on pin PE3 255 | ADC0_CC_R = ADC_CC_CS_SYSPLL; // select PLL as the time base (not needed, since default value) 256 | ADC0_ACTSS_R &= ~ADC_ACTSS_ASEN3; // disable sample sequencer 3 (SS3) for programming 257 | ADC0_EMUX_R = ADC_EMUX_EM3_PROCESSOR; // select SS3 bit in ADCPSSI as trigger 258 | ADC0_SSMUX3_R = 0; // set first sample to AN0 259 | ADC0_SSCTL3_R = ADC_SSCTL3_END0 | ADC_SSCTL3_TS0; // mark first sample as the end 260 | ADC0_ACTSS_R |= ADC_ACTSS_ASEN3; // enable SS3 for operation 261 | 262 | } 263 | 264 | 265 | uint16_t readAdc0Ss3() 266 | { 267 | ADC0_PSSI_R |= ADC_PSSI_SS3; // set start bit 268 | while (ADC0_ACTSS_R & ADC_ACTSS_BUSY); // wait until SS3 is not busy 269 | return ADC0_SSFIFO3_R & 0x0F; // get single result from the FIFO 270 | } 271 | 272 | 273 | 274 | /* wrapper Functions */ 275 | 276 | uint8_t ether_open(uint8_t *mac_address) 277 | { 278 | 279 | etherInit(ETHER_UNICAST | ETHER_BROADCAST | ETHER_HALFDUPLEX, mac_address); 280 | 281 | return 0; 282 | } 283 | 284 | 285 | uint8_t myUartOpen(uint32_t baud_rate) 286 | { 287 | init_uart0(); 288 | 289 | //return 1 for success, here 290 | return 1; 291 | } 292 | 293 | 294 | uint8_t myPutChar(char data) 295 | { 296 | putcUart0(data); 297 | 298 | return 0; 299 | } 300 | 301 | 302 | 303 | /* Link Console operation functions */ 304 | console_ops_t myUartOperations = 305 | { 306 | 307 | .open = myUartOpen, 308 | .print_char = myPutChar, 309 | .read_char = getcUart0, 310 | 311 | }; 312 | 313 | 314 | /* Link Network operation functions */ 315 | ether_operations_t ether_ops = 316 | { 317 | .open = ether_open, 318 | .network_interface_status = etherKbhit, 319 | .ether_send_packet = etherPutPacket, 320 | .ether_recv_packet = etherGetPacket, 321 | .random_gen_seed = readAdc0Ss3, 322 | }; 323 | 324 | 325 | 326 | /* Main */ 327 | int main(void) 328 | { 329 | 330 | enc28j60_frame_t *network_hardware; 331 | ethernet_handle_t *ethernet; 332 | 333 | uint8_t loop = 0; 334 | int16_t retval = 0; 335 | 336 | /* Network Data Buffer */ 337 | uint8_t data[ETHER_MTU_SIZE] = {0}; 338 | 339 | cl_term_t *my_console; 340 | char serial_buffer[MAX_INPUT_SIZE] = {0}; 341 | 342 | /* Point Network data */ 343 | network_hardware = (void*)data; 344 | 345 | /* init controller */ 346 | initHw(); 347 | 348 | init_adc(); 349 | 350 | /* Console Configurations */ 351 | my_console = console_open(&myUartOperations, 115200, serial_buffer, CONSOLE_STATIC); 352 | 353 | console_print(my_console, CONSOLE_CLEAR_SCREEN); 354 | 355 | /* Create Ethernet handle */ 356 | ethernet = create_ethernet_handle(&network_hardware->data, "02:03:04:50:60:48", "192.168.1.199", ðer_ops); 357 | 358 | /* flash PHY LEDS */ 359 | etherWritePhy(PHLCON, 0x0880); 360 | RED_LED = 1; 361 | waitMicrosecond(500000); 362 | etherWritePhy(PHLCON, 0x0990); 363 | RED_LED = 0; 364 | waitMicrosecond(500000); 365 | 366 | 367 | #if STATIC 368 | 369 | set_ip_address(ethernet->gateway_ip, "192.168.1.196"); 370 | 371 | #else 372 | 373 | /* test DHCP */ 374 | ether_get_dhcp_ip(ethernet, (uint8_t*)network_hardware, ethernet->host_mac, DHCP_INIT_STATE); 375 | 376 | #endif 377 | 378 | 379 | #if ICMP_TEST 380 | 381 | /* Test ICM, ARP packets */ 382 | uint8_t sequence_no = 1; 383 | 384 | ether_send_arp_req(ethernet, ethernet->host_ip, ethernet->gateway_ip); 385 | 386 | if(ether_is_arp(ethernet, (uint8_t*)network_hardware, 128)) 387 | { 388 | 389 | ether_handle_arp_resp_req(ethernet); 390 | 391 | GREEN_LED = 1; 392 | waitMicrosecond(50000); 393 | GREEN_LED = 0; 394 | } 395 | 396 | 397 | /* Test ICMP packets */ 398 | ether_send_icmp_req(ethernet, ICMP_ECHOREQUEST, ethernet->gateway_ip, &sequence_no, \ 399 | ethernet->arp_table[0].mac_address, ethernet->host_mac); 400 | #endif 401 | 402 | 403 | #if UDP_TEST 404 | 405 | ether_send_udp(ethernet, ethernet->gateway_ip, 8080, "Hello", 5); 406 | 407 | ether_read_udp(ethernet, (uint8_t*)network_hardware, udp_data, APP_BUFF_SIZE); 408 | 409 | if(strncmp(udp_data, "Hello from server", 18) == 0) 410 | ether_send_udp(ethernet, ethernet->gateway_ip, 8080, "Hello again", 11); 411 | 412 | #endif 413 | 414 | 415 | #if TCP_TEST 416 | /* Test TCP application */ 417 | uint16_t tcp_src_port = 0; 418 | uint16_t tcp_dest_port = 0; 419 | int32_t tcp_retval = 0; 420 | int16_t input_length = 0; 421 | 422 | uint16_t count = 0; 423 | 424 | 425 | char tcp_data[50] = {0}; 426 | uint8_t destination_ip[4] = {0}; 427 | 428 | set_ip_address(destination_ip, "192.168.1.13"); 429 | 430 | tcp_handle_t *test_client; 431 | 432 | /* APP state machine */ 433 | app_state_t app_state = APP_INIT; 434 | 435 | loop = 1 ; 436 | 437 | 438 | while(loop) 439 | { 440 | switch(app_state) 441 | { 442 | 443 | case APP_INIT: 444 | 445 | tcp_dest_port = 7788; 446 | 447 | tcp_src_port = get_random_port(ethernet, 6534); 448 | 449 | test_client = ether_tcp_create_client(ethernet, (uint8_t*)network_hardware, tcp_src_port, tcp_dest_port, destination_ip); 450 | 451 | ether_tcp_connect(ethernet, (uint8_t*)network_hardware, test_client); 452 | 453 | tcp_control(test_client, TCP_READ_NONBLOCK); 454 | 455 | app_state = APP_WRITE; 456 | 457 | break; 458 | 459 | 460 | case APP_READ: 461 | 462 | tcp_retval = 0; 463 | 464 | console_print(my_console, "Read State \n"); 465 | 466 | ether_tcp_read_data(ethernet, (uint8_t*)network_hardware, test_client, tcp_data, 50); 467 | 468 | app_state = APP_WRITE; 469 | 470 | console_print(my_console,tcp_data); 471 | console_print(my_console, "\n"); 472 | 473 | if(count > 100) 474 | { 475 | console_print(my_console,"Connection Closed"); 476 | 477 | ether_tcp_close(ethernet, (uint8_t*)network_hardware, test_client); 478 | loop = 0; 479 | count = 0; 480 | } 481 | 482 | if(test_client->client_flags.connect_established == 0) 483 | { 484 | loop = 0; 485 | } 486 | 487 | break; 488 | 489 | 490 | case APP_WRITE: 491 | 492 | console_print(my_console, "Write State \n"); 493 | #if 1 494 | input_length = 0; 495 | 496 | input_length = console_get_string(my_console, MAX_INPUT_SIZE); 497 | 498 | if(input_length) 499 | { 500 | tcp_retval = ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, serial_buffer, input_length); 501 | } 502 | #else 503 | 504 | tcp_retval = ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, "hey", 3); 505 | 506 | #endif 507 | 508 | if(tcp_retval > 0) 509 | count++; 510 | 511 | app_state = APP_READ; 512 | 513 | break; 514 | 515 | } 516 | 517 | } 518 | #endif 519 | 520 | 521 | #if MQTT_TEST 522 | 523 | /* Test MQTT application */ 524 | uint16_t tcp_src_port = 0; 525 | uint16_t tcp_dest_port = 0; 526 | int16_t input_length = 0; 527 | uint8_t destination_ip[4] = {0}; 528 | 529 | tcp_handle_t *test_client; 530 | mqtt_client_t publisher; 531 | 532 | /* Network API related variable initializations */ 533 | char message[200] = {0}; 534 | char read_buffer[150] = {0}; 535 | 536 | /* Client State machine related variable initializations */ 537 | size_t message_length = 0; 538 | int8_t message_status = 0; 539 | uint8_t loop_state = 0; 540 | uint8_t mqtt_message_state = 0; 541 | 542 | /* MQTT message buffers */ 543 | char *my_client_name = "Sender|1990-adityamall"; 544 | char user_name[] = "device1.sensor"; 545 | char pass_word[] = "4321"; 546 | char publish_topic[] = "device1/temp"; 547 | char publish_message[20] = "hello "; 548 | char copy_publish_message[20] = {0}; 549 | 550 | uint32_t count = 0; 551 | char count_buff[4] = {0}; 552 | 553 | /* Configure/Connect to MQTT broker */ 554 | set_ip_address(destination_ip, "192.168.1.196"); 555 | 556 | tcp_dest_port = 1883; 557 | tcp_src_port = get_random_port(ethernet, 6534); 558 | 559 | /* Create TCP object/socket */ 560 | test_client = ether_tcp_create_client(ethernet, (uint8_t*)network_hardware, tcp_src_port, tcp_dest_port, destination_ip); 561 | 562 | /*Connect to MQTT broker */ 563 | ether_tcp_connect(ethernet, (uint8_t*)network_hardware, test_client); 564 | 565 | /* Configure TCP Network IO control */ 566 | tcp_control(test_client, TCP_READ_NONBLOCK); 567 | 568 | 569 | /* MQTT State machine initializations */ 570 | loop_state = FSM_RUN; 571 | 572 | /* Update state to connect to send connect message */ 573 | mqtt_message_state = mqtt_connect_state; 574 | 575 | while(loop_state) 576 | { 577 | switch(mqtt_message_state) 578 | { 579 | 580 | case mqtt_idle_state: 581 | 582 | 583 | break; 584 | 585 | case mqtt_read_state: 586 | 587 | console_print(my_console, "READ \n"); 588 | 589 | memset(read_buffer, 0, sizeof(read_buffer)); 590 | 591 | while(ether_tcp_read_data(ethernet, (uint8_t*)network_hardware, test_client, read_buffer, 150) < 0); 592 | 593 | publisher.message = (void*)read_buffer; 594 | 595 | /* get MQTT message type and update state */ 596 | mqtt_message_state = get_mqtt_message_type(&publisher); 597 | if(!mqtt_message_state) 598 | { 599 | mqtt_message_state = mqtt_disconnect_state; 600 | } 601 | 602 | break; 603 | 604 | 605 | case mqtt_connect_state: 606 | 607 | console_print(my_console, "CONNECT \n"); 608 | 609 | /* Test connect message */ 610 | memset(message, '\0', sizeof(message)); 611 | 612 | publisher.connect_msg = (void*)message; 613 | 614 | /* Setup User name password (optional) */ 615 | mqtt_client_username_passwd(&publisher, user_name, pass_word); 616 | 617 | /* Set connect options */ 618 | mqtt_connect_options(&publisher, MQTT_CLEAN_SESSION, MQTT_MESSAGE_NO_RETAIN, MQTT_QOS_FIRE_FORGET); 619 | 620 | /* Setup MQTT CONNECT Message */ 621 | message_length = mqtt_connect(&publisher, my_client_name, 6000); 622 | 623 | /* Send connect message */ 624 | ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, (char*)publisher.connect_msg, message_length); 625 | 626 | /* Update state */ 627 | mqtt_message_state = mqtt_read_state; 628 | 629 | break; 630 | 631 | 632 | case mqtt_connack_state: 633 | 634 | console_print(my_console, "CONNACK \n"); 635 | 636 | /* Check return code of CONNACK message */ 637 | publisher.connack_msg = (void *)read_buffer; 638 | 639 | mqtt_message_state = get_connack_status(&publisher); 640 | 641 | if(!mqtt_message_state) 642 | mqtt_message_state = mqtt_publish_state; 643 | 644 | break; 645 | 646 | 647 | case mqtt_publish_state: 648 | 649 | console_print(my_console, "PUBLISH \n"); 650 | 651 | /* Fill MQTT PUBLISH message structure */ 652 | memset(message, '\0', sizeof(message)); 653 | 654 | publisher.publish_msg = (void *)message; 655 | 656 | /*Configure publish options */ 657 | mqtt_publish_options(&publisher, MQTT_MESSAGE_NO_RETAIN, MQTT_QOS_FIRE_FORGET); 658 | 659 | #if 0 660 | input_length = console_get_string(my_console, MAX_INPUT_SIZE); 661 | 662 | if(strcmp(serial_buffer,"exit") == 0 ) 663 | { 664 | mqtt_message_state = mqtt_disconnect_state; 665 | break; 666 | } 667 | 668 | if(input_length) 669 | { 670 | /* Configure publish message */ 671 | message_length = mqtt_publish(&publisher, "device1/temp", serial_buffer, input_length); 672 | 673 | /* Send publish message */ 674 | ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, (char*)publisher.publish_msg, message_length); 675 | } 676 | #else 677 | 678 | count++; 679 | 680 | ltoa(count, count_buff); 681 | 682 | console_print(my_console, count_buff); 683 | console_print(my_console, "\n"); 684 | 685 | strncpy(copy_publish_message, publish_message, strlen(publish_message)); 686 | 687 | strncat(copy_publish_message, count_buff, strlen(count_buff)); 688 | 689 | input_length = strlen(copy_publish_message); 690 | 691 | /* Configure publish message */ 692 | message_length = mqtt_publish(&publisher, publish_topic, copy_publish_message, input_length); 693 | 694 | /* Send publish message */ 695 | ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, (char*)publisher.publish_msg, message_length); 696 | 697 | memset(copy_publish_message, NULL, strlen(copy_publish_message)); 698 | memset(count_buff, NULL, strlen(count_buff)); 699 | 700 | if(count >= 10) 701 | { 702 | mqtt_message_state = mqtt_disconnect_state; 703 | break; 704 | } 705 | 706 | #endif 707 | 708 | mqtt_message_state = mqtt_publish_state; 709 | 710 | break; 711 | 712 | 713 | case mqtt_disconnect_state: 714 | 715 | console_print(my_console, "DISCONNECT \n"); 716 | 717 | /* Fill DISCONNECT structure */ 718 | memset(message,'\0',sizeof(message)); 719 | 720 | publisher.disconnect_msg = (void*)message; 721 | 722 | message_length = mqtt_disconnect(&publisher); 723 | 724 | /* Send Disconnect Message */ 725 | ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, (char*)publisher.disconnect_msg, message_length); 726 | 727 | /* Update State */ 728 | mqtt_message_state = mqtt_exit_state; 729 | 730 | break; 731 | 732 | 733 | case mqtt_exit_state: 734 | 735 | /* Close the client */ 736 | ether_tcp_close(ethernet, (uint8_t*)network_hardware, test_client); 737 | 738 | /* Suspend while loop */ 739 | loop_state = FSM_SUSPEND; 740 | 741 | break; 742 | 743 | 744 | default: 745 | 746 | break; 747 | 748 | } 749 | 750 | } 751 | 752 | /* Hold loop */ 753 | loop = 1; 754 | while(loop); 755 | 756 | #endif 757 | 758 | return 0; 759 | 760 | } 761 | -------------------------------------------------------------------------------- /tm4c123gh6pm_startup_ccs.c: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // 3 | // Startup code for use with TI's Code Composer Studio. 4 | // 5 | // Copyright (c) 2011-2014 Texas Instruments Incorporated. All rights reserved. 6 | // Software License Agreement 7 | // 8 | // Software License Agreement 9 | // 10 | // Texas Instruments (TI) is supplying this software for use solely and 11 | // exclusively on TI's microcontroller products. The software is owned by 12 | // TI and/or its suppliers, and is protected under applicable copyright 13 | // laws. You may not combine this software with "viral" open-source 14 | // software in order to form a larger program. 15 | // 16 | // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. 17 | // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT 18 | // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY 20 | // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL 21 | // DAMAGES, FOR ANY REASON WHATSOEVER. 22 | // 23 | //***************************************************************************** 24 | 25 | #include 26 | 27 | //***************************************************************************** 28 | // 29 | // Forward declaration of the default fault handlers. 30 | // 31 | //***************************************************************************** 32 | void ResetISR(void); 33 | static void NmiSR(void); 34 | static void FaultISR(void); 35 | static void IntDefaultHandler(void); 36 | 37 | //***************************************************************************** 38 | // 39 | // External declaration for the reset handler that is to be called when the 40 | // processor is started 41 | // 42 | //***************************************************************************** 43 | extern void _c_int00(void); 44 | 45 | //***************************************************************************** 46 | // 47 | // Linker variable that marks the top of the stack. 48 | // 49 | //***************************************************************************** 50 | extern uint32_t __STACK_TOP; 51 | 52 | //***************************************************************************** 53 | // 54 | // External declarations for the interrupt handlers used by the application. 55 | // 56 | //***************************************************************************** 57 | // To be added by user 58 | 59 | //***************************************************************************** 60 | // 61 | // The vector table. Note that the proper constructs must be placed on this to 62 | // ensure that it ends up at physical address 0x0000.0000 or at the start of 63 | // the program if located at a start address other than 0. 64 | // 65 | //***************************************************************************** 66 | #pragma DATA_SECTION(g_pfnVectors, ".intvecs") 67 | void (* const g_pfnVectors[])(void) = 68 | { 69 | (void (*)(void))((uint32_t)&__STACK_TOP), 70 | // The initial stack pointer 71 | ResetISR, // The reset handler 72 | NmiSR, // The NMI handler 73 | FaultISR, // The hard fault handler 74 | IntDefaultHandler, // The MPU fault handler 75 | IntDefaultHandler, // The bus fault handler 76 | IntDefaultHandler, // The usage fault handler 77 | 0, // Reserved 78 | 0, // Reserved 79 | 0, // Reserved 80 | 0, // Reserved 81 | IntDefaultHandler, // SVCall handler 82 | IntDefaultHandler, // Debug monitor handler 83 | 0, // Reserved 84 | IntDefaultHandler, // The PendSV handler 85 | IntDefaultHandler, // The SysTick handler 86 | IntDefaultHandler, // GPIO Port A 87 | IntDefaultHandler, // GPIO Port B 88 | IntDefaultHandler, // GPIO Port C 89 | IntDefaultHandler, // GPIO Port D 90 | IntDefaultHandler, // GPIO Port E 91 | IntDefaultHandler, // UART0 Rx and Tx 92 | IntDefaultHandler, // UART1 Rx and Tx 93 | IntDefaultHandler, // SSI0 Rx and Tx 94 | IntDefaultHandler, // I2C0 Master and Slave 95 | IntDefaultHandler, // PWM Fault 96 | IntDefaultHandler, // PWM Generator 0 97 | IntDefaultHandler, // PWM Generator 1 98 | IntDefaultHandler, // PWM Generator 2 99 | IntDefaultHandler, // Quadrature Encoder 0 100 | IntDefaultHandler, // ADC Sequence 0 101 | IntDefaultHandler, // ADC Sequence 1 102 | IntDefaultHandler, // ADC Sequence 2 103 | IntDefaultHandler, // ADC Sequence 3 104 | IntDefaultHandler, // Watchdog timer 105 | IntDefaultHandler, // Timer 0 subtimer A 106 | IntDefaultHandler, // Timer 0 subtimer B 107 | IntDefaultHandler, // Timer 1 subtimer A 108 | IntDefaultHandler, // Timer 1 subtimer B 109 | IntDefaultHandler, // Timer 2 subtimer A 110 | IntDefaultHandler, // Timer 2 subtimer B 111 | IntDefaultHandler, // Analog Comparator 0 112 | IntDefaultHandler, // Analog Comparator 1 113 | IntDefaultHandler, // Analog Comparator 2 114 | IntDefaultHandler, // System Control (PLL, OSC, BO) 115 | IntDefaultHandler, // FLASH Control 116 | IntDefaultHandler, // GPIO Port F 117 | IntDefaultHandler, // GPIO Port G 118 | IntDefaultHandler, // GPIO Port H 119 | IntDefaultHandler, // UART2 Rx and Tx 120 | IntDefaultHandler, // SSI1 Rx and Tx 121 | IntDefaultHandler, // Timer 3 subtimer A 122 | IntDefaultHandler, // Timer 3 subtimer B 123 | IntDefaultHandler, // I2C1 Master and Slave 124 | IntDefaultHandler, // Quadrature Encoder 1 125 | IntDefaultHandler, // CAN0 126 | IntDefaultHandler, // CAN1 127 | 0, // Reserved 128 | 0, // Reserved 129 | IntDefaultHandler, // Hibernate 130 | IntDefaultHandler, // USB0 131 | IntDefaultHandler, // PWM Generator 3 132 | IntDefaultHandler, // uDMA Software Transfer 133 | IntDefaultHandler, // uDMA Error 134 | IntDefaultHandler, // ADC1 Sequence 0 135 | IntDefaultHandler, // ADC1 Sequence 1 136 | IntDefaultHandler, // ADC1 Sequence 2 137 | IntDefaultHandler, // ADC1 Sequence 3 138 | 0, // Reserved 139 | 0, // Reserved 140 | IntDefaultHandler, // GPIO Port J 141 | IntDefaultHandler, // GPIO Port K 142 | IntDefaultHandler, // GPIO Port L 143 | IntDefaultHandler, // SSI2 Rx and Tx 144 | IntDefaultHandler, // SSI3 Rx and Tx 145 | IntDefaultHandler, // UART3 Rx and Tx 146 | IntDefaultHandler, // UART4 Rx and Tx 147 | IntDefaultHandler, // UART5 Rx and Tx 148 | IntDefaultHandler, // UART6 Rx and Tx 149 | IntDefaultHandler, // UART7 Rx and Tx 150 | 0, // Reserved 151 | 0, // Reserved 152 | 0, // Reserved 153 | 0, // Reserved 154 | IntDefaultHandler, // I2C2 Master and Slave 155 | IntDefaultHandler, // I2C3 Master and Slave 156 | IntDefaultHandler, // Timer 4 subtimer A 157 | IntDefaultHandler, // Timer 4 subtimer B 158 | 0, // Reserved 159 | 0, // Reserved 160 | 0, // Reserved 161 | 0, // Reserved 162 | 0, // Reserved 163 | 0, // Reserved 164 | 0, // Reserved 165 | 0, // Reserved 166 | 0, // Reserved 167 | 0, // Reserved 168 | 0, // Reserved 169 | 0, // Reserved 170 | 0, // Reserved 171 | 0, // Reserved 172 | 0, // Reserved 173 | 0, // Reserved 174 | 0, // Reserved 175 | 0, // Reserved 176 | 0, // Reserved 177 | 0, // Reserved 178 | IntDefaultHandler, // Timer 5 subtimer A 179 | IntDefaultHandler, // Timer 5 subtimer B 180 | IntDefaultHandler, // Wide Timer 0 subtimer A 181 | IntDefaultHandler, // Wide Timer 0 subtimer B 182 | IntDefaultHandler, // Wide Timer 1 subtimer A 183 | IntDefaultHandler, // Wide Timer 1 subtimer B 184 | IntDefaultHandler, // Wide Timer 2 subtimer A 185 | IntDefaultHandler, // Wide Timer 2 subtimer B 186 | IntDefaultHandler, // Wide Timer 3 subtimer A 187 | IntDefaultHandler, // Wide Timer 3 subtimer B 188 | IntDefaultHandler, // Wide Timer 4 subtimer A 189 | IntDefaultHandler, // Wide Timer 4 subtimer B 190 | IntDefaultHandler, // Wide Timer 5 subtimer A 191 | IntDefaultHandler, // Wide Timer 5 subtimer B 192 | IntDefaultHandler, // FPU 193 | 0, // Reserved 194 | 0, // Reserved 195 | IntDefaultHandler, // I2C4 Master and Slave 196 | IntDefaultHandler, // I2C5 Master and Slave 197 | IntDefaultHandler, // GPIO Port M 198 | IntDefaultHandler, // GPIO Port N 199 | IntDefaultHandler, // Quadrature Encoder 2 200 | 0, // Reserved 201 | 0, // Reserved 202 | IntDefaultHandler, // GPIO Port P (Summary or P0) 203 | IntDefaultHandler, // GPIO Port P1 204 | IntDefaultHandler, // GPIO Port P2 205 | IntDefaultHandler, // GPIO Port P3 206 | IntDefaultHandler, // GPIO Port P4 207 | IntDefaultHandler, // GPIO Port P5 208 | IntDefaultHandler, // GPIO Port P6 209 | IntDefaultHandler, // GPIO Port P7 210 | IntDefaultHandler, // GPIO Port Q (Summary or Q0) 211 | IntDefaultHandler, // GPIO Port Q1 212 | IntDefaultHandler, // GPIO Port Q2 213 | IntDefaultHandler, // GPIO Port Q3 214 | IntDefaultHandler, // GPIO Port Q4 215 | IntDefaultHandler, // GPIO Port Q5 216 | IntDefaultHandler, // GPIO Port Q6 217 | IntDefaultHandler, // GPIO Port Q7 218 | IntDefaultHandler, // GPIO Port R 219 | IntDefaultHandler, // GPIO Port S 220 | IntDefaultHandler, // PWM 1 Generator 0 221 | IntDefaultHandler, // PWM 1 Generator 1 222 | IntDefaultHandler, // PWM 1 Generator 2 223 | IntDefaultHandler, // PWM 1 Generator 3 224 | IntDefaultHandler // PWM 1 Fault 225 | }; 226 | 227 | //***************************************************************************** 228 | // 229 | // This is the code that gets called when the processor first starts execution 230 | // following a reset event. Only the absolutely necessary set is performed, 231 | // after which the application supplied entry() routine is called. Any fancy 232 | // actions (such as making decisions based on the reset cause register, and 233 | // resetting the bits in that register) are left solely in the hands of the 234 | // application. 235 | // 236 | //***************************************************************************** 237 | void 238 | ResetISR(void) 239 | { 240 | // 241 | // Jump to the CCS C initialization routine. This will enable the 242 | // floating-point unit as well, so that does not need to be done here. 243 | // 244 | __asm(" .global _c_int00\n" 245 | " b.w _c_int00"); 246 | } 247 | 248 | //***************************************************************************** 249 | // 250 | // This is the code that gets called when the processor receives a NMI. This 251 | // simply enters an infinite loop, preserving the system state for examination 252 | // by a debugger. 253 | // 254 | //***************************************************************************** 255 | static void 256 | NmiSR(void) 257 | { 258 | // 259 | // Enter an infinite loop. 260 | // 261 | while(1) 262 | { 263 | } 264 | } 265 | 266 | //***************************************************************************** 267 | // 268 | // This is the code that gets called when the processor receives a fault 269 | // interrupt. This simply enters an infinite loop, preserving the system state 270 | // for examination by a debugger. 271 | // 272 | //***************************************************************************** 273 | static void 274 | FaultISR(void) 275 | { 276 | // 277 | // Enter an infinite loop. 278 | // 279 | while(1) 280 | { 281 | } 282 | } 283 | 284 | //***************************************************************************** 285 | // 286 | // This is the code that gets called when the processor receives an unexpected 287 | // interrupt. This simply enters an infinite loop, preserving the system state 288 | // for examination by a debugger. 289 | // 290 | //***************************************************************************** 291 | static void 292 | IntDefaultHandler(void) 293 | { 294 | // 295 | // Go into an infinite loop. 296 | // 297 | while(1) 298 | { 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /wait.c: -------------------------------------------------------------------------------- 1 | // Wait functions 2 | // Jason Losh 3 | 4 | //----------------------------------------------------------------------------- 5 | // Hardware Target 6 | //----------------------------------------------------------------------------- 7 | 8 | // Target uC: TM4C123GH6PM 9 | // System Clock: 40 MHz 10 | 11 | //----------------------------------------------------------------------------- 12 | // Device includes, defines, and assembler directives 13 | //----------------------------------------------------------------------------- 14 | 15 | #include 16 | #include "tm4c123gh6pm.h" 17 | #include "wait.h" 18 | 19 | //----------------------------------------------------------------------------- 20 | // Subroutines 21 | //----------------------------------------------------------------------------- 22 | 23 | // Approximate busy waiting (in units of microseconds), given a 40 MHz system clock 24 | void waitMicrosecond(uint32_t us) 25 | { 26 | __asm("WMS_LOOP0: MOV R1, #6"); // 1 27 | __asm("WMS_LOOP1: SUB R1, #1"); // 6 28 | __asm(" CBZ R1, WMS_DONE1"); // 5+1*3 29 | __asm(" NOP"); // 5 30 | __asm(" NOP"); // 5 31 | __asm(" B WMS_LOOP1"); // 5*2 (speculative, so P=1) 32 | __asm("WMS_DONE1: SUB R0, #1"); // 1 33 | __asm(" CBZ R0, WMS_DONE0"); // 1 34 | __asm(" NOP"); // 1 35 | __asm(" B WMS_LOOP0"); // 1*2 (speculative, so P=1) 36 | __asm("WMS_DONE0:"); // --- 37 | // 40 clocks/us + error 38 | } 39 | -------------------------------------------------------------------------------- /wait.h: -------------------------------------------------------------------------------- 1 | // Wait functions 2 | // Jason Losh 3 | 4 | //----------------------------------------------------------------------------- 5 | // Hardware Target 6 | //----------------------------------------------------------------------------- 7 | 8 | // Target uC: TM4C123GH6PM 9 | // System Clock: 40 MHz 10 | 11 | #ifndef WAIT_H_ 12 | #define WAIT_H_ 13 | 14 | //----------------------------------------------------------------------------- 15 | // Subroutines 16 | //----------------------------------------------------------------------------- 17 | 18 | void waitMicrosecond(uint32_t us); 19 | 20 | #endif 21 | --------------------------------------------------------------------------------