wf200_driver.c
Go to the documentation of this file.
1 /**
2  * @file wf200_driver.c
3  * @brief WF200 Wi-Fi controller
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "sl_wfx.h"
36 #include "sl_wfx_host.h"
37 #include "sl_wfx_host_api.h"
38 #include "core/net.h"
40 #include "debug.h"
41 
42 //Underlying network interface
43 static NetInterface *wf200StaInterface = NULL;
44 static NetInterface *wf200ApInterface = NULL;
45 
46 //WF200 context
47 static sl_wfx_context_t wf200Context;
48 
49 //Forward declaration of functions
50 sl_status_t sl_wfx_host_init_pins(void);
51 
52 
53 /**
54  * @brief WF200 driver (STA mode)
55  **/
56 
58 {
60  ETH_MTU,
61  wf200Init,
62  wf200Tick,
68  NULL,
69  NULL,
70  NULL,
71  TRUE,
72  TRUE,
73  TRUE,
74  TRUE
75 };
76 
77 
78 /**
79  * @brief WF200 driver (AP mode)
80  **/
81 
83 {
85  ETH_MTU,
86  wf200Init,
87  wf200Tick,
93  NULL,
94  NULL,
95  NULL,
96  TRUE,
97  TRUE,
98  TRUE,
99  TRUE
100 };
101 
102 
103 /**
104  * @brief WF200 initialization
105  * @param[in] interface Underlying network interface
106  * @return Error code
107  **/
108 
110 {
111  sl_status_t status;
112  sl_wfx_mac_address_t macAddr;
113 
114  //STA or AP mode?
115  if(interface->nicDriver == &wf200StaDriver)
116  {
117  //Debug message
118  TRACE_INFO("Initializing WF200 (STA mode)...\r\n");
119  //Save underlying network interface
120  wf200StaInterface = interface;
121  }
122  else
123  {
124  //Debug message
125  TRACE_INFO("Initializing WF200 (AP mode)...\r\n");
126  //Save underlying network interface
127  wf200ApInterface = interface;
128  }
129 
130  //Initialization sequence is performed once
131  if(wf200StaInterface == NULL || wf200ApInterface == NULL)
132  {
133  //Initialize WF200 pins
135 
136  //Initialize WF200 controller
137  status = sl_wfx_init(&wf200Context);
138  }
139  else
140  {
141  //Initialization was already done
142  status = SL_STATUS_OK;
143  }
144 
145  //Check status code
146  if(status == SL_STATUS_OK)
147  {
148  //Optionally set the MAC address
149  if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
150  {
151  //Use the factory preprogrammed MAC address
152  if(interface == wf200StaInterface)
153  {
154  macCopyAddr(&interface->macAddr, wf200Context.mac_addr_0.octet);
155  }
156  else
157  {
158  macCopyAddr(&interface->macAddr, wf200Context.mac_addr_1.octet);
159  }
160 
161  //Generate the 64-bit interface identifier
162  macAddrToEui64(&interface->macAddr, &interface->eui64);
163  }
164  else
165  {
166  //Override the factory preprogrammed address
167  macCopyAddr(&macAddr, &interface->macAddr);
168 
169  //Assign MAC addresses
170  if(interface == wf200StaInterface)
171  {
172  status = sl_wfx_set_mac_address(&macAddr, SL_WFX_STA_INTERFACE);
173  }
174  else
175  {
176  status = sl_wfx_set_mac_address(&macAddr, SL_WFX_SOFTAP_INTERFACE);
177  }
178  }
179  }
180 
181  //WF200 is now ready to send
182  osSetEvent(&interface->nicTxEvent);
183 
184  //Return status code
185  if(status == SL_STATUS_OK)
186  {
187  return NO_ERROR;
188  }
189  else
190  {
191  return ERROR_FAILURE;
192  }
193 }
194 
195 
196 /**
197  * @brief WF200 timer handler
198  *
199  * This routine is periodically called by the TCP/IP stack to handle periodic
200  * operations such as polling the link state
201  *
202  * @param[in] interface Underlying network interface
203  **/
204 
205 void wf200Tick(NetInterface *interface)
206 {
207 }
208 
209 
210 /**
211  * @brief Enable interrupts
212  * @param[in] interface Underlying network interface
213  **/
214 
215 void wf200EnableIrq(NetInterface *interface)
216 {
217 }
218 
219 
220 /**
221  * @brief Disable interrupts
222  * @param[in] interface Underlying network interface
223  **/
224 
226 {
227 }
228 
229 
230 /**
231  * @brief WF200 event handler
232  * @param[in] interface Underlying network interface
233  **/
234 
236 {
237 }
238 
239 
240 /**
241  * @brief Send a packet
242  * @param[in] interface Underlying network interface
243  * @param[in] buffer Multi-part buffer containing the data to send
244  * @param[in] offset Offset to the first data byte
245  * @param[in] ancillary Additional options passed to the stack along with
246  * the packet
247  * @return Error code
248  **/
249 
251  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
252 {
253  size_t n;
254  size_t length;
255  sl_status_t status;
256  sl_wfx_send_frame_req_t *req;
257 
258  //Retrieve the length of the packet
259  length = netBufferGetLength(buffer) - offset;
260 
261  //Make sure the link is up before transmitting the frame
262  if(!interface->linkState)
263  {
264  //The transmitter can accept another packet
265  osSetEvent(&interface->nicTxEvent);
266  //Drop current packet
267  return NO_ERROR;
268  }
269 
270  //Get the length of the packet
271  n = SL_WFX_ROUND_UP(length, 2);
272 
273  //Allocate a memory buffer to hold the request
274  sl_wfx_allocate_command_buffer((sl_wfx_generic_message_t **) &req,
275  SL_WFX_SEND_FRAME_REQ_ID, SL_WFX_TX_FRAME_BUFFER,
276  n + sizeof(sl_wfx_send_frame_req_t));
277 
278  //Successful memory allocation?
279  if(req != NULL)
280  {
281  //Copy user data to the transmit buffer
282  netBufferRead(req->body.packet_data, buffer, offset, length);
283 
284  //Send packet
285  if(interface == wf200StaInterface)
286  {
287  status = sl_wfx_send_ethernet_frame(req, length, SL_WFX_STA_INTERFACE, 0);
288  }
289  else
290  {
291  status = sl_wfx_send_ethernet_frame(req, length, SL_WFX_SOFTAP_INTERFACE, 0);
292  }
293 
294  //Release previously allocated memory
295  sl_wfx_free_command_buffer((sl_wfx_generic_message_t *) req,
296  SL_WFX_SEND_FRAME_REQ_ID, SL_WFX_TX_FRAME_BUFFER);
297  }
298  else
299  {
300  //Failed to allocate memory
301  status = SL_STATUS_ALLOCATION_FAILED;
302  }
303 
304  //The transmitter can accept another packet
305  osSetEvent(&interface->nicTxEvent);
306 
307  //Return status code
308  if(status == SL_STATUS_OK)
309  {
310  return NO_ERROR;
311  }
312  else
313  {
314  return ERROR_FAILURE;
315  }
316 }
317 
318 
319 /**
320  * @brief Configure MAC address filtering
321  * @param[in] interface Underlying network interface
322  * @return Error code
323  **/
324 
326 {
327  uint_t i;
328  MacFilterEntry *entry;
329  sl_status_t status;
330  sl_wfx_mac_address_t macAddr;
331 
332  //Debug message
333  TRACE_INFO("Updating WF200 multicast filter...\r\n");
334 
335  //Initialize status code
336  status = SL_STATUS_OK;
337 
338  //The MAC address filter contains the list of MAC addresses to accept
339  //when receiving an Ethernet frame
340  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
341  {
342  //Point to the current entry
343  entry = &interface->macAddrFilter[i];
344 
345  //Valid entry?
346  if(!macCompAddr(&entry->addr, &MAC_UNSPECIFIED_ADDR))
347  {
348  //Copy the MAC address
349  macCopyAddr(&macAddr, &entry->addr);
350 
351  //Update MAC filter table only if necessary
352  if(entry->addFlag)
353  {
354  //Add a new entry to the MAC filter table
355  if(interface == wf200StaInterface)
356  {
357  status = sl_wfx_add_multicast_address(&macAddr,
358  SL_WFX_STA_INTERFACE);
359  }
360  else
361  {
362  status = sl_wfx_add_multicast_address(&macAddr,
363  SL_WFX_SOFTAP_INTERFACE);
364  }
365  }
366  else if(entry->deleteFlag)
367  {
368  //Remove the current entry from the MAC filter table
369  if(interface == wf200StaInterface)
370  {
371  status = sl_wfx_remove_multicast_address(&macAddr,
372  SL_WFX_STA_INTERFACE);
373  }
374  else
375  {
376  status = sl_wfx_remove_multicast_address(&macAddr,
377  SL_WFX_SOFTAP_INTERFACE);
378  }
379  }
380  }
381  }
382 
383  //Return status code
384  if(status == SL_STATUS_OK)
385  {
386  return NO_ERROR;
387  }
388  else
389  {
390  return ERROR_FAILURE;
391  }
392 }
393 
394 
395 /**
396  * @brief Station connected callback
397  **/
398 
400 {
401  //Valid STA interface?
402  if(wf200StaInterface != NULL)
403  {
404  //Link is up
405  wf200StaInterface->linkState = TRUE;
406 
407  //Get exclusive access
409  //Process link state change event
410  nicNotifyLinkChange(wf200StaInterface);
411  //Release exclusive access
413  }
414 }
415 
416 
417 /**
418  * @brief Station disconnected callback
419  **/
420 
422 {
423  //Valid STA interface?
424  if(wf200StaInterface != NULL)
425  {
426  //Link is down
427  wf200StaInterface->linkState = FALSE;
428 
429  //Get exclusive access
431  //Process link state change event
432  nicNotifyLinkChange(wf200StaInterface);
433  //Release exclusive access
435  }
436 }
437 
438 
439 /**
440  * @brief Station connected callback
441  **/
442 
444 {
445  //Valid AP interface?
446  if(wf200ApInterface != NULL)
447  {
448  //Link is up
449  wf200ApInterface->linkState = TRUE;
450 
451  //Get exclusive access
453  //Process link state change event
454  nicNotifyLinkChange(wf200ApInterface);
455  //Release exclusive access
457  }
458 }
459 
460 
461 /**
462  * @brief Station disconnected callback
463  **/
464 
466 {
467  //Valid AP interface?
468  if(wf200ApInterface != NULL)
469  {
470  //Link is down
471  wf200ApInterface->linkState = FALSE;
472 
473  //Get exclusive access
475  //Process link state change event
476  nicNotifyLinkChange(wf200ApInterface);
477  //Release exclusive access
479  }
480 }
481 
482 
483 /**
484  * @brief Callback function that handles incoming packets
485  * @param[in] ind Pointer to the received indication
486  **/
487 
488 void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t *ind)
489 {
490  NetInterface *interface;
491  NetRxAncillary ancillary;
492 
493  //STA or AP interface?
494  if((ind->header.info & SL_WFX_MSG_INFO_INTERFACE_MASK) ==
495  (SL_WFX_STA_INTERFACE << SL_WFX_MSG_INFO_INTERFACE_OFFSET))
496  {
497  interface = wf200StaInterface;
498  }
499  else
500  {
501  interface = wf200ApInterface;
502  }
503 
504  //Valid interface?
505  if(interface != NULL)
506  {
507  //Get exclusive access
509 
510  //Additional options can be passed to the stack along with the packet
511  ancillary = NET_DEFAULT_RX_ANCILLARY;
512 
513  //Pass the packet to the upper layer
514  nicProcessPacket(interface, ind->body.frame + ind->body.frame_padding,
515  ind->body.frame_length, &ancillary);
516 
517  //Release exclusive access
519  }
520 }
unsigned int uint_t
Definition: compiler_port.h:50
Debugging facilities.
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
Map a MAC address to the IPv6 modified EUI-64 identifier.
Definition: ethernet.c:944
#define ETH_MTU
Definition: ethernet.h:116
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
#define macCopyAddr(destMacAddr, srcMacAddr)
Definition: ethernet.h:127
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netMutex
Definition: net_legacy.h:195
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:674
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:101
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:391
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:548
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
MAC filter table entry.
Definition: ethernet.h:262
bool_t addFlag
Definition: ethernet.h:265
MacAddr addr
MAC address.
Definition: ethernet.h:263
bool_t deleteFlag
Definition: ethernet.h:266
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
NIC driver.
Definition: nic.h:283
uint8_t length
Definition: tcp.h:368
void wf200EventHandler(NetInterface *interface)
WF200 event handler.
Definition: wf200_driver.c:235
void wf200ConnectCallback(void)
Station connected callback.
Definition: wf200_driver.c:399
void wf200DisconnectCallback(void)
Station disconnected callback.
Definition: wf200_driver.c:421
sl_status_t sl_wfx_host_init_pins(void)
void wf200Tick(NetInterface *interface)
WF200 timer handler.
Definition: wf200_driver.c:205
void wf200EnableIrq(NetInterface *interface)
Enable interrupts.
Definition: wf200_driver.c:215
void wf200StartApCallback(void)
Station connected callback.
Definition: wf200_driver.c:443
void wf200DisableIrq(NetInterface *interface)
Disable interrupts.
Definition: wf200_driver.c:225
void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t *ind)
Callback function that handles incoming packets.
Definition: wf200_driver.c:488
const NicDriver wf200ApDriver
WF200 driver (AP mode)
Definition: wf200_driver.c:82
void wf200StopApCallback(void)
Station disconnected callback.
Definition: wf200_driver.c:465
const NicDriver wf200StaDriver
WF200 driver (STA mode)
Definition: wf200_driver.c:57
error_t wf200UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
Definition: wf200_driver.c:325
error_t wf200SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
Definition: wf200_driver.c:250
error_t wf200Init(NetInterface *interface)
WF200 initialization.
Definition: wf200_driver.c:109
WF200 Wi-Fi controller.