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