1 // Copyright 2019 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #pragma once 15 16 #include "esp_eth_com.h" 17 #include "esp_eth_mac.h" 18 #include "esp_eth_phy.h" 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /** 25 * @brief Handle of Ethernet driver 26 * 27 */ 28 typedef void *esp_eth_handle_t; 29 30 /** 31 * @brief Configuration of Ethernet driver 32 * 33 */ 34 typedef struct { 35 /** 36 * @brief Ethernet MAC object 37 * 38 */ 39 esp_eth_mac_t *mac; 40 41 /** 42 * @brief Ethernet PHY object 43 * 44 */ 45 esp_eth_phy_t *phy; 46 47 /** 48 * @brief Period time of checking Ethernet link status 49 * 50 */ 51 uint32_t check_link_period_ms; 52 53 /** 54 * @brief Input frame buffer to user's stack 55 * 56 * @param[in] eth_handle: handle of Ethernet driver 57 * @param[in] buffer: frame buffer that will get input to upper stack 58 * @param[in] length: length of the frame buffer 59 * 60 * @return 61 * - ESP_OK: input frame buffer to upper stack successfully 62 * - ESP_FAIL: error occurred when inputting buffer to upper stack 63 * 64 */ 65 esp_err_t (*stack_input)(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv); 66 67 /** 68 * @brief Callback function invoked when lowlevel initialization is finished 69 * 70 * @param[in] eth_handle: handle of Ethernet driver 71 * 72 * @return 73 * - ESP_OK: process extra lowlevel initialization successfully 74 * - ESP_FAIL: error occurred when processing extra lowlevel initialization 75 */ 76 esp_err_t (*on_lowlevel_init_done)(esp_eth_handle_t eth_handle); 77 78 /** 79 * @brief Callback function invoked when lowlevel deinitialization is finished 80 * 81 * @param[in] eth_handle: handle of Ethernet driver 82 * 83 * @return 84 * - ESP_OK: process extra lowlevel deinitialization successfully 85 * - ESP_FAIL: error occurred when processing extra lowlevel deinitialization 86 */ 87 esp_err_t (*on_lowlevel_deinit_done)(esp_eth_handle_t eth_handle); 88 89 /** 90 * @brief Read PHY register 91 * 92 * @note Usually the PHY register read/write function is provided by MAC (SMI interface), 93 * but if the PHY device is managed by other interface (e.g. I2C), then user needs to 94 * implement the corresponding read/write. 95 * Setting this to NULL means your PHY device is managed by MAC's SMI interface. 96 * 97 * @param[in] eth_handle: handle of Ethernet driver 98 * @param[in] phy_addr: PHY chip address (0~31) 99 * @param[in] phy_reg: PHY register index code 100 * @param[out] reg_value: PHY register value 101 * 102 * @return 103 * - ESP_OK: read PHY register successfully 104 * - ESP_ERR_INVALID_ARG: read PHY register failed because of invalid argument 105 * - ESP_ERR_TIMEOUT: read PHY register failed because of timeout 106 * - ESP_FAIL: read PHY register failed because some other error occurred 107 */ 108 esp_err_t (*read_phy_reg)(esp_eth_handle_t eth_handle, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value); 109 110 /** 111 * @brief Write PHY register 112 * 113 * @note Usually the PHY register read/write function is provided by MAC (SMI interface), 114 * but if the PHY device is managed by other interface (e.g. I2C), then user needs to 115 * implement the corresponding read/write. 116 * Setting this to NULL means your PHY device is managed by MAC's SMI interface. 117 * 118 * @param[in] eth_handle: handle of Ethernet driver 119 * @param[in] phy_addr: PHY chip address (0~31) 120 * @param[in] phy_reg: PHY register index code 121 * @param[in] reg_value: PHY register value 122 * 123 * @return 124 * - ESP_OK: write PHY register successfully 125 * - ESP_ERR_INVALID_ARG: read PHY register failed because of invalid argument 126 * - ESP_ERR_TIMEOUT: write PHY register failed because of timeout 127 * - ESP_FAIL: write PHY register failed because some other error occurred 128 */ 129 esp_err_t (*write_phy_reg)(esp_eth_handle_t eth_handle, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value); 130 } esp_eth_config_t; 131 132 /** 133 * @brief Default configuration for Ethernet driver 134 * 135 */ 136 #define ETH_DEFAULT_CONFIG(emac, ephy) \ 137 { \ 138 .mac = emac, \ 139 .phy = ephy, \ 140 .check_link_period_ms = 2000, \ 141 .stack_input = NULL, \ 142 .on_lowlevel_init_done = NULL, \ 143 .on_lowlevel_deinit_done = NULL, \ 144 .read_phy_reg = NULL, \ 145 .write_phy_reg = NULL, \ 146 } 147 148 /** 149 * @brief Install Ethernet driver 150 * 151 * @param[in] config: configuration of the Ethernet driver 152 * @param[out] out_hdl: handle of Ethernet driver 153 * 154 * @return 155 * - ESP_OK: install esp_eth driver successfully 156 * - ESP_ERR_INVALID_ARG: install esp_eth driver failed because of some invalid argument 157 * - ESP_ERR_NO_MEM: install esp_eth driver failed because there's no memory for driver 158 * - ESP_FAIL: install esp_eth driver failed because some other error occurred 159 */ 160 esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_t *out_hdl); 161 162 /** 163 * @brief Uninstall Ethernet driver 164 * @note It's not recommended to uninstall Ethernet driver unless it won't get used any more in application code. 165 * To uninstall Ethernet driver, you have to make sure, all references to the driver are released. 166 * Ethernet driver can only be uninstalled successfully when reference counter equals to one. 167 * 168 * @param[in] hdl: handle of Ethernet driver 169 * 170 * @return 171 * - ESP_OK: uninstall esp_eth driver successfully 172 * - ESP_ERR_INVALID_ARG: uninstall esp_eth driver failed because of some invalid argument 173 * - ESP_ERR_INVALID_STATE: uninstall esp_eth driver failed because it has more than one reference 174 * - ESP_FAIL: uninstall esp_eth driver failed because some other error occurred 175 */ 176 esp_err_t esp_eth_driver_uninstall(esp_eth_handle_t hdl); 177 178 /** 179 * @brief Start Ethernet driver **ONLY** in standalone mode (i.e. without TCP/IP stack) 180 * 181 * @note This API will start driver state machine and internal software timer (for checking link status). 182 * 183 * @param[in] hdl handle of Ethernet driver 184 * 185 * @return 186 * - ESP_OK: start esp_eth driver successfully 187 * - ESP_ERR_INVALID_ARG: start esp_eth driver failed because of some invalid argument 188 * - ESP_ERR_INVALID_STATE: start esp_eth driver failed because driver has started already 189 * - ESP_FAIL: start esp_eth driver failed because some other error occurred 190 */ 191 esp_err_t esp_eth_start(esp_eth_handle_t hdl); 192 193 /** 194 * @brief Stop Ethernet driver 195 * 196 * @note This function does the oppsite operation of `esp_eth_start`. 197 * 198 * @param[in] hdl handle of Ethernet driver 199 * @return 200 * - ESP_OK: stop esp_eth driver successfully 201 * - ESP_ERR_INVALID_ARG: stop esp_eth driver failed because of some invalid argument 202 * - ESP_ERR_INVALID_STATE: stop esp_eth driver failed because driver has not started yet 203 * - ESP_FAIL: stop esp_eth driver failed because some other error occurred 204 */ 205 esp_err_t esp_eth_stop(esp_eth_handle_t hdl); 206 207 /** 208 * @brief Update Ethernet data input path (i.e. specify where to pass the input buffer) 209 * 210 * @note After install driver, Ethernet still don't know where to deliver the input buffer. 211 * In fact, this API registers a callback function which get invoked when Ethernet received new packets. 212 * 213 * @param[in] hdl handle of Ethernet driver 214 * @param[in] stack_input function pointer, which does the actual process on incoming packets 215 * @param[in] priv private resource, which gets passed to `stack_input` callback without any modification 216 * @return 217 * - ESP_OK: update input path successfully 218 * - ESP_ERR_INVALID_ARG: update input path failed because of some invalid argument 219 * - ESP_FAIL: update input path failed because some other error occurred 220 */ 221 esp_err_t esp_eth_update_input_path( 222 esp_eth_handle_t hdl, 223 esp_err_t (*stack_input)(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv), 224 void *priv); 225 226 /** 227 * @brief General Transmit 228 * 229 * @param[in] hdl: handle of Ethernet driver 230 * @param[in] buf: buffer of the packet to transfer 231 * @param[in] length: length of the buffer to transfer 232 * 233 * @return 234 * - ESP_OK: transmit frame buffer successfully 235 * - ESP_ERR_INVALID_ARG: transmit frame buffer failed because of some invalid argument 236 * - ESP_FAIL: transmit frame buffer failed because some other error occurred 237 */ 238 esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length); 239 240 /** 241 * @brief General Receive is deprecated and shall not be accessed from app code, 242 * as polling is not supported by Ethernet. 243 * 244 * @param[in] hdl: handle of Ethernet driver 245 * @param[out] buf: buffer to preserve the received packet 246 * @param[out] length: length of the received packet 247 * 248 * @note Before this function got invoked, the value of "length" should set by user, equals the size of buffer. 249 * After the function returned, the value of "length" means the real length of received data. 250 * @note This API was exposed by accident, users should not use this API in their applications. 251 * Ethernet driver is interrupt driven, and doesn't support polling mode. 252 * Instead, users should register input callback with ``esp_eth_update_input_path``. 253 * 254 * @return 255 * - ESP_OK: receive frame buffer successfully 256 * - ESP_ERR_INVALID_ARG: receive frame buffer failed because of some invalid argument 257 * - ESP_ERR_INVALID_SIZE: input buffer size is not enough to hold the incoming data. 258 * in this case, value of returned "length" indicates the real size of incoming data. 259 * - ESP_FAIL: receive frame buffer failed because some other error occurred 260 */ 261 esp_err_t esp_eth_receive(esp_eth_handle_t hdl, uint8_t *buf, uint32_t *length) __attribute__((deprecated("Ethernet driver is interrupt driven only, please register input callback with esp_eth_update_input_path"))); 262 263 /** 264 * @brief Misc IO function of Etherent driver 265 * 266 * @param[in] hdl: handle of Ethernet driver 267 * @param[in] cmd: IO control command 268 * @param[in, out] data: address of data for `set` command or address where to store the data when used with `get` command 269 * 270 * @return 271 * - ESP_OK: process io command successfully 272 * - ESP_ERR_INVALID_ARG: process io command failed because of some invalid argument 273 * - ESP_FAIL: process io command failed because some other error occurred 274 * 275 * The following IO control commands are supported: 276 * @li @c ETH_CMD_S_MAC_ADDR sets Ethernet interface MAC address. @c data argument is pointer to MAC address buffer with expected size of 6 bytes. 277 * @li @c ETH_CMD_G_MAC_ADDR gets Ethernet interface MAC address. @c data argument is pointer to a buffer to which MAC address is to be copied. The buffer size must be at least 6 bytes. 278 * @li @c ETH_CMD_S_PHY_ADDR sets PHY address in range of <0-31>. @c data argument is pointer to memory of uint32_t datatype from where the configuration option is read. 279 * @li @c ETH_CMD_G_PHY_ADDR gets PHY address. @c data argument is pointer to memory of uint32_t datatype to which the PHY address is to be stored. 280 * @li @c ETH_CMD_G_SPEED gets current Ethernet link speed. @c data argument is pointer to memory of eth_speed_t datatype to which the speed is to be stored. 281 * @li @c ETH_CMD_S_PROMISCUOUS sets/resets Ethernet interface promiscuous mode. @c data argument is pointer to memory of bool datatype from which the configuration option is read. 282 * @li @c ETH_CMD_S_FLOW_CTRL sets/resets Ethernet interface flow control. @c data argument is pointer to memory of bool datatype from which the configuration option is read. 283 * @li @c ETH_CMD_G_DUPLEX_MODE gets current Ethernet link duplex mode. @c data argument is pointer to memory of eth_duplex_t datatype to which the duplex mode is to be stored. 284 * @li @c ETH_CMD_S_PHY_LOOPBACK sets/resets PHY to/from loopback mode. @c data argument is pointer to memory of bool datatype from which the configuration option is read. 285 * 286 */ 287 esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data); 288 289 /** 290 * @brief Increase Ethernet driver reference 291 * @note Ethernet driver handle can be obtained by os timer, netif, etc. 292 * It's dangerous when thread A is using Ethernet but thread B uninstall the driver. 293 * Using reference counter can prevent such risk, but care should be taken, when you obtain Ethernet driver, 294 * this API must be invoked so that the driver won't be uninstalled during your using time. 295 * 296 * 297 * @param[in] hdl: handle of Ethernet driver 298 * @return 299 * - ESP_OK: increase reference successfully 300 * - ESP_ERR_INVALID_ARG: increase reference failed because of some invalid argument 301 */ 302 esp_err_t esp_eth_increase_reference(esp_eth_handle_t hdl); 303 304 /** 305 * @brief Decrease Ethernet driver reference 306 * 307 * @param[in] hdl: handle of Ethernet driver 308 * @return 309 * - ESP_OK: increase reference successfully 310 * - ESP_ERR_INVALID_ARG: increase reference failed because of some invalid argument 311 */ 312 esp_err_t esp_eth_decrease_reference(esp_eth_handle_t hdl); 313 314 #ifdef __cplusplus 315 } 316 #endif 317