bcm43362_driver.c
Go to the documentation of this file.
1 /**
2  * @file bcm43362_driver.c
3  * @brief BCM43362 Wi-Fi controller
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL NIC_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/net.h"
35 #include "debug.h"
36 
37 //WICED dependencies
38 #include "platform_init.h"
39 #include "platform_mcu_peripheral.h"
40 #include "wwd_constants.h"
41 #include "wwd_structures.h"
42 #include "wwd_buffer.h"
43 #include "wwd_events.h"
44 #include "wwd_management.h"
45 #include "wwd_poll.h"
46 #include "wwd_wifi.h"
47 #include "wwd_buffer_interface.h"
48 #include "wwd_bus_protocol_interface.h"
49 #include "wwd_network_constants.h"
50 #include "wwd_network_interface.h"
51 
52 //Underlying network interface
53 static NetInterface *bcm43362StaInterface = NULL;
54 static NetInterface *bcm43362ApInterface = NULL;
55 
56 //RX queue
57 QueueHandle_t wwdRxQueue;
58 
59 //Regitered Wi-Fi events
60 static const wwd_event_num_t app_wifi_events[] =
61 {
62  WLC_E_IF,
63  WLC_E_LINK,
64  WLC_E_ASSOC_IND,
65  WLC_E_DISASSOC_IND,
66  WLC_E_NONE
67 };
68 
69 //Forward declaration of functions
70 void *app_wifi_event_handler(const wwd_event_header_t *event_header,
71  const uint8_t *event_data, void *handler_user_data);
72 
73 
74 /**
75  * @brief BCM43362 driver (STA mode)
76  **/
77 
79 {
81  ETH_MTU,
89  NULL,
90  NULL,
91  NULL,
92  TRUE,
93  TRUE,
94  TRUE,
95  TRUE
96 };
97 
98 
99 /**
100  * @brief BCM43362 driver (AP mode)
101  **/
102 
104 {
106  ETH_MTU,
107  bcm43362Init,
108  bcm43362Tick,
114  NULL,
115  NULL,
116  NULL,
117  TRUE,
118  TRUE,
119  TRUE,
120  TRUE
121 };
122 
123 
124 /**
125  * @brief BCM43362 initialization
126  * @param[in] interface Underlying network interface
127  * @return Error code
128  **/
129 
131 {
132  wwd_result_t ret;
133  //MacAddr macAddr;
134 
135  //STA or AP mode?
136  if(interface->nicDriver == &bcm43362StaDriver)
137  {
138  //Debug message
139  TRACE_INFO("Initializing BCM43362 (STA mode)...\r\n");
140  }
141  else
142  {
143  //Debug message
144  TRACE_INFO("Initializing BCM43362 (AP mode)...\r\n");
145  }
146 
147  //Start of exception handling block
148  do
149  {
150  //Initialization sequence is performed once at startup
151  if(bcm43362StaInterface == NULL && bcm43362ApInterface == NULL)
152  {
153  platform_init_mcu_infrastructure();
154  wwd_buffer_init(NULL);
155 
156  //Create TX queue
157  wwdRxQueue = xQueueCreate(16, sizeof(wiced_buffer_t));
158 
159  //Initialize Wi-Fi controller
160  ret = wwd_management_wifi_on(WICED_COUNTRY_FRANCE);
161  TRACE_INFO("wwd_management_wifi_on=%d (0x%04X)\r\n", ret, ret);
162 
163  ret = wwd_management_set_event_handler(app_wifi_events, app_wifi_event_handler, NULL, WWD_AP_INTERFACE);
164  TRACE_INFO("wwd_management_set_event_handler=%d (0x%04X)\r\n", ret, ret);
165  }
166  else
167  {
168  //Initialization was already done
169  ret = WWD_SUCCESS;
170  }
171 
172  //STA or AP mode?
173  if(interface->nicDriver == &bcm43362StaDriver)
174  {
175  //Save underlying network interface (STA mode)
176  bcm43362StaInterface = interface;
177 
178  //Optionally set the station MAC address
179  //if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
180  {
181  //Use the factory preprogrammed station address
182  ret = wwd_wifi_get_mac_address((wiced_mac_t *) &interface->macAddr, WWD_STA_INTERFACE);
183  TRACE_INFO("wwd_wifi_get_mac_address=%d (0x%04X)\r\n", ret, ret);
184  TRACE_INFO("MAC=%s\r\n", macAddrToString(&interface->macAddr, NULL));
185 
186  //Generate the 64-bit interface identifier
187  macAddrToEui64(&interface->macAddr, &interface->eui64);
188  }
189  }
190  else
191  {
192  //Save underlying network interface (AP mode)
193  bcm43362ApInterface = interface;
194 
195  //Optionally set the station MAC address
196  //if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
197  {
198  //Use the factory preprogrammed station address
199  ret = wwd_wifi_get_mac_address((wiced_mac_t *) &interface->macAddr, WWD_STA_INTERFACE);
200  TRACE_INFO("wwd_wifi_get_mac_address=%d (0x%04X)\r\n", ret, ret);
201  TRACE_INFO("MAC=%s\r\n", macAddrToString(&interface->macAddr, NULL));
202 
203  //Generate the 64-bit interface identifier
204  macAddrToEui64(&interface->macAddr, &interface->eui64);
205  }
206  }
207 
208  //End of exception handling block
209  } while(0);
210 
211  //BCM43362 is now ready to send
212  osSetEvent(&interface->nicTxEvent);
213 
214  //Successful initialization
215  return NO_ERROR;
216 }
217 
218 
219 /**
220  * @brief BCM43362 timer handler
221  *
222  * This routine is periodically called by the TCP/IP stack to
223  * handle periodic operations such as polling the link state
224  *
225  * @param[in] interface Underlying network interface
226  **/
227 
228 void bcm43362Tick(NetInterface *interface)
229 {
230 }
231 
232 
233 /**
234  * @brief Enable interrupts
235  * @param[in] interface Underlying network interface
236  **/
237 
239 {
240 }
241 
242 
243 /**
244  * @brief Disable interrupts
245  * @param[in] interface Underlying network interface
246  **/
247 
249 {
250 }
251 
252 
253 /**
254  * @brief BCM43362 interrupt service routine
255  * @return TRUE if a higher priority task must be woken. Else FALSE is returned
256  **/
257 
259 {
260  bool_t flag;
261 
262  //This flag will be set if a higher priority task must be woken
263  flag = FALSE;
264 
265  //STA and/or AP mode?
266  if(bcm43362StaInterface != NULL)
267  bcm43362StaInterface->nicEvent = TRUE;
268  else if(bcm43362ApInterface != NULL)
269  bcm43362ApInterface->nicEvent = TRUE;
270 
271  //Notify the TCP/IP stack of the event
272  flag = osSetEventFromIsr(&netEvent);
273 
274  //A higher priority task must be woken?
275  return flag;
276 }
277 
278 
279 /**
280  * @brief BCM43362 event handler
281  * @param[in] interface Underlying network interface
282  **/
283 
285 {
286 }
287 
288 
289 /**
290  * @brief Send a packet
291  * @param[in] interface Underlying network interface
292  * @param[in] buffer Multi-part buffer containing the data to send
293  * @param[in] offset Offset to the first data byte
294  * @return Error code
295  **/
296 
298  const NetBuffer *buffer, size_t offset)
299 {
300  wwd_result_t ret;
301  wiced_buffer_t packet;
302  size_t length;
303  uint8_t *p;
304 
305  //Retrieve the length of the packet
306  length = netBufferGetLength(buffer) - offset;
307 
308  //Allocate a network buffer
309  ret = host_buffer_get(&packet, WWD_NETWORK_TX, length + WICED_LINK_OVERHEAD_BELOW_ETHERNET_FRAME_MAX, FALSE);
310 
311  //Check status code
312  if(ret == WWD_SUCCESS)
313  {
314  //Make room for additional headers
315  host_buffer_add_remove_at_front(&packet, WICED_LINK_OVERHEAD_BELOW_ETHERNET_FRAME_MAX);
316 
317  //Point to the data payload
318  p = host_buffer_get_current_piece_data_pointer(packet);
319 
320  //Copy user data
321  netBufferRead(p, buffer, offset, length);
322 
323  //Adjust the length of the buffer
324  host_buffer_set_size(packet, length);
325 
326  //STA or AP mode?
327  if(interface == bcm43362StaInterface)
328  {
329  //Send packet
330  wwd_network_send_ethernet_data(packet, WWD_STA_INTERFACE);
331  }
332  else
333  {
334  //Send packet
335  wwd_network_send_ethernet_data(packet, WWD_AP_INTERFACE);
336  }
337  }
338  else
339  {
340  TRACE_ERROR("##### bcm43362SendPacket ALLOC FAILED ####\r\n");
341  }
342 
343  //The transmitter can accept another packet
344  osSetEvent(&interface->nicTxEvent);
345 
346  //Return status code
347  if(ret == WWD_SUCCESS)
348  return NO_ERROR;
349  else
350  return ERROR_FAILURE;
351 }
352 
353 
354 /**
355  * @brief Configure MAC address filtering
356  * @param[in] interface Underlying network interface
357  * @return Error code
358  **/
359 
361 {
362  uint_t i;
363  wwd_result_t ret;
364  MacFilterEntry *entry;
365 
366  //Debug message
367  TRACE_INFO("Updating BCM43362 multicast filter...\r\n");
368 
369  //STA interface?
370  if(interface == bcm43362StaInterface)
371  {
372  //The MAC address filter contains the list of MAC addresses to accept
373  //when receiving an Ethernet frame
374  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
375  {
376  //Point to the current entry
377  entry = &interface->macAddrFilter[i];
378 
379  //Check whether the MAC filter table should be updated for the
380  //current multicast address
381  if(!macCompAddr(&entry->addr, &MAC_UNSPECIFIED_ADDR))
382  {
383  if(entry->addFlag)
384  {
385  //Add a new entry to the MAC filter table
386  //ret = wwd_wifi_register_multicast_address((wiced_mac_t *) entry->addr.b);
387  //TRACE_ERROR("wwd_wifi_register_multicast_address=%d (0x%04X)\r\n", ret, ret);
388  }
389  else if(entry->deleteFlag)
390  {
391  //Remove the current entry from the MAC filter table
392  //ret = wwd_wifi_unregister_multicast_address((wiced_mac_t *) entry->addr.b);
393  //TRACE_ERROR("wwd_wifi_unregister_multicast_address=%d (0x%04X)\r\n", ret, ret);
394  }
395  }
396  }
397  }
398 
399  //Successful processing
400  return NO_ERROR;
401 }
402 
403 
404 /**
405  * @brief Callback function that handles Wi-Fi events
406  **/
407 
408 void *app_wifi_event_handler(const wwd_event_header_t *event_header, const uint8_t *event_data, void *handler_user_data)
409 {
410  //Check event type
411  switch(event_header->event_type)
412  {
413  //I/F change?
414  case WLC_E_IF:
415  TRACE_INFO("### app_wifi_event_handler: WLC_E_IF\r\n");
416  break;
417 
418  //802.11 ASSOC indication?
419  case WLC_E_ASSOC_IND:
420  TRACE_INFO("### app_wifi_event_handler: WLC_E_ASSOC_IND\r\n");
421  break;
422 
423  //802.11 DISASSOC indication?
424  case WLC_E_DISASSOC_IND:
425  TRACE_INFO("### app_wifi_event_handler: WLC_E_DISASSOC_IND\r\n");
426  break;
427 
428  //Generic link indication?
429  case WLC_E_LINK:
430  //Debug message
431  TRACE_INFO("### app_wifi_event_handler: WLC_E_LINK\r\n");
432 
433  //STA interface?
434  if(event_header->interface == WWD_STA_INTERFACE)
435  {
436  if(bcm43362StaInterface != NULL)
437  {
438  //Check link state
439  if(event_header->flags & 0x01)
440  bcm43362StaInterface->linkState = TRUE;
441  else
442  bcm43362StaInterface->linkState = FALSE;
443 
444  //Get exclusive access
446  //Process link state change event
447  nicNotifyLinkChange(bcm43362StaInterface);
448  //Release exclusive access
450  }
451  }
452  //AP interface?
453  else if(event_header->interface == WWD_AP_INTERFACE)
454  {
455  if(bcm43362ApInterface != NULL)
456  {
457  //Check link state
458  if(event_header->flags & 0x01)
459  bcm43362ApInterface->linkState = TRUE;
460  else
461  bcm43362ApInterface->linkState = FALSE;
462 
463  //Get exclusive access
465  //Process link state change event
466  nicNotifyLinkChange(bcm43362ApInterface);
467  //Release exclusive access
469  }
470  }
471 
472  break;
473 
474  //Unknown event?
475  default:
476  TRACE_INFO("### app_wifi_event_handler: Unknown event\r\n");
477  break;
478  }
479 
480  return handler_user_data;
481 }
482 
483 
484 /**
485  * @brief Callback function that handles incoming packets
486  **/
487 
488 void host_network_process_ethernet_data(wiced_buffer_t buffer, wwd_interface_t interface)
489 {
490  size_t n;
491  uint8_t *p;
492 
493  //Point to the incoming packet
494  p = host_buffer_get_current_piece_data_pointer(buffer);
495  //Retrieve the length of the packet
496  n = host_buffer_get_current_piece_size(buffer);
497 
498  //Valid packet received?
499  if(p != NULL && n > 0)
500  {
501  if(interface == WWD_STA_INTERFACE)
502  {
503  if(bcm43362StaInterface != NULL)
504  {
505  //Get exclusive access
507  //Process link state change event
508  nicProcessPacket(bcm43362StaInterface, p, n);
509  //Release exclusive access
511  }
512  }
513  else if(interface == WWD_AP_INTERFACE)
514  {
515  if(bcm43362ApInterface != NULL)
516  {
517  //Get exclusive access
519  //Process link state change event
520  nicProcessPacket(bcm43362ApInterface, p, n);
521  //Release exclusive access
523  }
524  }
525  }
526 
527  //Release network buffer
528  host_buffer_release(buffer, WWD_NETWORK_RX);
529 }
530 
531 
532 //Miscellaneous WICED dependencies
533 signed int xTaskIsTaskFinished(void *xTask)
534 {
535  TRACE_INFO("### xTaskIsTaskFinished\r\n");
536  return pdTRUE;
537 }
538 
539 portBASE_TYPE vTaskFreeTerminated(TaskHandle_t xTask)
540 {
541  TRACE_INFO("### vTaskFreeTerminated\r\n");
542  return pdTRUE;
543 }
MacAddr addr
MAC address.
Definition: ethernet.h:210
void nicNotifyLinkChange(NetInterface *interface)
Process link state change event.
Definition: nic.c:298
const NicDriver bcm43362ApDriver
BCM43362 driver (AP mode)
bool_t addFlag
Definition: ethernet.h:212
TCP/IP stack core.
void bcm43362EventHandler(NetInterface *interface)
BCM43362 event handler.
Debugging facilities.
uint8_t p
Definition: ndp.h:295
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
Generic error code.
Definition: error.h:43
bool_t deleteFlag
Definition: ethernet.h:213
error_t bcm43362UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define TRACE_ERROR(...)
Definition: debug.h:70
#define TRUE
Definition: os_port.h:48
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:65
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:670
NIC driver.
Definition: nic.h:161
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
error_t bcm43362SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
Map a MAC address to the IPv6 modified EUI-64 identifier.
Definition: ethernet.c:1266
void host_network_process_ethernet_data(wiced_buffer_t buffer, wwd_interface_t interface)
Callback function that handles incoming packets.
#define TRACE_INFO(...)
Definition: debug.h:86
void * app_wifi_event_handler(const wwd_event_header_t *event_header, const uint8_t *event_data, void *handler_user_data)
Callback function that handles Wi-Fi events.
QueueHandle_t wwdRxQueue
#define ETH_MTU
Definition: ethernet.h:82
Ethernet interface.
Definition: nic.h:69
Success.
Definition: error.h:42
OsEvent netEvent
Definition: net.c:72
void nicProcessPacket(NetInterface *interface, void *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:239
BCM43362 Wi-Fi controller.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
void bcm43362Tick(NetInterface *interface)
BCM43362 timer handler.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void bcm43362EnableIrq(NetInterface *interface)
Enable interrupts.
void bcm43362DisableIrq(NetInterface *interface)
Disable interrupts.
#define NetInterface
Definition: net.h:34
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:95
const NicDriver bcm43362StaDriver
BCM43362 driver (STA mode)
bool_t bcm43362IrqHandler(void)
BCM43362 interrupt service routine.
char_t * macAddrToString(const MacAddr *macAddr, char_t *str)
Convert a MAC address to a dash delimited string.
Definition: ethernet.c:1243
OsMutex netMutex
Definition: net.c:70
portBASE_TYPE vTaskFreeTerminated(TaskHandle_t xTask)
signed int xTaskIsTaskFinished(void *xTask)
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
error_t bcm43362Init(NetInterface *interface)
BCM43362 initialization.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
MAC filter table entry.
Definition: ethernet.h:208