source: ReferenceDesigns/w3_802.11/c/wlan_mac_high_ibss/wlan_mac_ibss.c

Last change on this file was 6319, checked in by chunter, 5 years ago

1.8.0 release wlan-mac-se

File size: 67.3 KB
Line 
1/** @file wlan_mac_ibss.c
2 *  @brief Station
3 *
4 *  This contains code for the 802.11 IBSS node (ad hoc).
5 *
6 *  @copyright Copyright 2014-2019, Mango Communications. All rights reserved.
7 *          Distributed under the Mango Communications Reference Design License
8 *              See LICENSE.txt included in the design archive or
9 *              at http://mangocomm.com/802.11/license
10 *
11 *  This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11)
12 */
13
14/***************************** Include Files *********************************/
15#include "wlan_mac_high_sw_config.h"
16
17// Xilinx SDK includes
18#include "stdio.h"
19#include "stdlib.h"
20#include "string.h"
21#include "xil_cache.h"
22
23// WLAN includes
24#include "wlan_platform_common.h"
25#include "wlan_platform_high.h"
26#include "wlan_mac_802_11_defs.h"
27#include "wlan_mac_queue.h"
28#include "wlan_mac_event_log.h"
29#include "wlan_mac_entries.h"
30#include "wlan_mac_ltg.h"
31#include "wlan_mac_high.h"
32#include "wlan_mac_packet_types.h"
33#include "wlan_mac_eth_util.h"
34#include "wlan_mac_scan.h"
35#include "ascii_characters.h"
36#include "wlan_mac_schedule.h"
37#include "wlan_mac_dl_list.h"
38#include "wlan_mac_network_info.h"
39#include "wlan_mac_station_info.h"
40#include "wlan_mac_ibss.h"
41#include "wlan_mac_mgmt_tags.h"
42#include "wlan_mac_common.h"
43#include "wlan_mac_pkt_buf_util.h"
44
45// WLAN Exp includes
46#include "wlan_exp.h"
47#include "wlan_exp_common.h"
48#include "wlan_exp_node.h"
49#include "wlan_exp_node_ibss.h"
50#include "wlan_exp_transport.h"
51#include "wlan_exp_user.h"
52
53
54/*************************** Constant Definitions ****************************/
55#define  WLAN_DEFAULT_BSS_CONFIG_CHANNEL 1
56#define  WLAN_DEFAULT_BSS_CONFIG_DTIM_PERIOD 2
57#define  WLAN_DEFAULT_BSS_CONFIG_BEACON_INTERVAL 100
58// The WLAN_DEFAULT_BSS_CONFIG_HT_CAPABLE define will set the default
59// unicast TX phy mode to:  1 --> HTMF  or  0 --> NONHT.
60#define  WLAN_DEFAULT_BSS_CONFIG_HT_CAPABLE 1
61
62#define  WLAN_DEFAULT_TX_PWR 15
63#define  WLAN_DEFAULT_TX_ANTENNA TX_ANTMODE_SISO_ANTA
64#define  WLAN_DEFAULT_RX_ANTENNA RX_ANTMODE_SISO_ANTA
65
66#define  WLAN_DEFAULT_SCAN_TIMEOUT_USEC_MIN 4000000
67#define  WLAN_DEFAULT_SCAN_TIMEOUT_USEC_MAX 8000000
68
69// WLAN_DEFAULT_USE_HT
70//
71// The WLAN_DEFAULT_USE_HT define will set the default unicast TX phy mode
72// to:  1 --> HTMF  or  0 --> NONHT.  It will also be used as the default
73// value for the HT_CAPABLE capability of the BSS in configure_bss() when
74// moving from a NULL to a non-NULL BSS and the ht_capable parameter is not
75// specified.  This parameter only affects how the MAC selects the phy_mode
76// value for transmissions. It does not affect the underlying PHY support for
77// Tx/Rx of HTMF waveforms.
78#define  WLAN_DEFAULT_USE_HT                     1
79
80
81/*********************** Global Variable Definitions *************************/
82
83
84// Static QIDs
85u16 mcast_qid;
86u16 mgmt_qid;
87
88// If you want this station to try to associate to a known IBSS at boot, type
89//   the string here. Otherwise, let it be an empty string.
90static char default_ssid[SSID_LEN_MAX + 1] = "MANGO-IBSS";
91// static char default_ssid[SSID_LEN_MAX + 1] = "";
92
93// Top level IBSS state
94network_info_t* active_network_info;
95
96// Tx queue variables;
97u32 max_queue_size;
98volatile u8 pause_data_queue;
99
100// MAC address
101static u8 wlan_mac_addr[MAC_ADDR_LEN];
102
103// Beacon configuration
104static  beacon_txrx_config_t gl_beacon_txrx_config;
105
106// Common Platform Device Info
107platform_common_dev_info_t platform_common_dev_info;
108
109
110/*************************** Functions Prototypes ****************************/
111
112#if WLAN_SW_CONFIG_ENABLE_WLAN_EXP
113int  wlan_exp_process_user_cmd(cmd_resp_hdr_t* cmd_hdr, eth_tx_queue_buffer_t* eth_tx_queue_buffer);
114#endif
115
116void send_probe_req();
117void ibss_set_beacon_ts_update_mode(u32 enable);
118
119
120/******************************** Functions **********************************/
121
122int main() {
123
124    // Call the platform-supplied cpu_init() first to setup any
125    //  processor-specific settings to enable sane execution
126    //  of the platform and framework code below
127    wlan_platform_cpu_high_init();
128
129    u64 scan_start_timestamp;
130    u64 scan_duration;
131    u8 locally_administered_addr[MAC_ADDR_LEN];
132    dl_list* ssid_match_list = NULL;
133    dl_entry* temp_dl_entry = NULL;
134    network_info_t* temp_network_info = NULL;
135    bss_config_t bss_config;
136    u32 update_mask;
137
138
139    // Print initial message to UART
140    xil_printf("\f");
141    xil_printf("----- Mango 802.11 Reference Design -----\n");
142    xil_printf("----- v1.8.0 ----------------------------\n");
143    xil_printf("----- wlan_mac_ibss ---------------------\n");
144    xil_printf("Compiled %s %s\n\n", __DATE__, __TIME__);
145
146    wlan_mac_common_malloc_init();
147
148    // Initialize the maximum TX queue size
149    max_queue_size = MAX_TX_QUEUE_LEN;
150
151    // Unpause the queue
152    pause_data_queue       = 0;
153
154    // Initialize beacon configuration
155    gl_beacon_txrx_config.ts_update_mode = FUTURE_ONLY_UPDATE;
156    bzero(gl_beacon_txrx_config.bssid_match, MAC_ADDR_LEN);
157    gl_beacon_txrx_config.beacon_tx_mode = NO_BEACON_TX;
158
159    // Initialize the utility library
160    wlan_mac_high_init();
161
162    // Open static queues
163    mcast_qid = queue_open((void*)wlan_null_callback, 0, max_queue_size);
164    mgmt_qid = queue_open((void*)wlan_null_callback, 0, max_queue_size);
165
166    // Get the device info
167    platform_common_dev_info = wlan_platform_common_get_dev_info();
168
169    // IBSS is not currently a member of BSS
170    configure_bss(NULL, 0);
171
172    wlan_platform_high_userio_disp_status(USERIO_DISP_STATUS_APPLICATION_ROLE, APPLICATION_ROLE_IBSS);
173
174    // Initialize hex display to "No BSS"
175    wlan_platform_high_userio_disp_status(USERIO_DISP_STATUS_MEMBER_LIST_UPDATE, 0xFF);
176
177    // Set default Tx params
178    // Set sane default Tx params. These will be overwritten by the user application
179    tx_params_t tx_params = { .phy = { .mcs = 3, .phy_mode = PHY_MODE_HTMF, .antenna_mode = WLAN_DEFAULT_TX_ANTENNA, .power = WLAN_DEFAULT_TX_PWR },
180                              .mac = { .flags = 0 } };
181
182    wlan_mac_set_default_tx_params(unicast_data, &tx_params);
183
184    tx_params.phy.mcs = 0;
185    tx_params.phy.phy_mode = PHY_MODE_NONHT;
186
187    wlan_mac_set_default_tx_params(unicast_mgmt, &tx_params);
188    wlan_mac_set_default_tx_params(mcast_data, &tx_params);
189    wlan_mac_set_default_tx_params(mcast_mgmt, &tx_params);
190
191    // Re-apply the defaults to any existing station_info_t structs that this AP
192    // knows about
193    wlan_mac_reapply_default_tx_params();
194
195    // Initialize callbacks
196#if WLAN_SW_CONFIG_ENABLE_ETH_BRIDGE
197    wlan_mac_util_set_eth_rx_callback((void*) ethernet_receive);
198#endif
199    wlan_mac_high_set_mpdu_rx_callback((void*) mpdu_rx_process);
200    wlan_mac_high_set_uart_rx_callback((void*) uart_rx);
201    wlan_mac_high_set_poll_tx_queues_callback((void*) poll_tx_queues);
202
203#if WLAN_SW_CONFIG_ENABLE_LTG
204    wlan_mac_ltg_sched_set_callback((void*) ltg_event);
205#endif //WLAN_SW_CONFIG_ENABLE_LTG
206    wlan_mac_scan_set_tx_probe_request_callback((void*) send_probe_req);
207    wlan_mac_scan_set_state_change_callback((void*) process_scan_state_change);
208    wlan_mac_high_set_cpu_low_reboot_callback((void*) handle_cpu_low_reboot);
209
210#if WLAN_SW_CONFIG_ENABLE_WLAN_EXP
211
212    // NOTE:  To use the WLAN Experiments Framework, it must be initialized after
213    //        CPU low has populated the hw_info structure in the MAC High framework.
214
215    // Initialize WLAN Exp
216    wlan_exp_node_init();
217
218    // Set WLAN Exp callbacks
219    wlan_exp_set_process_node_cmd_callback((void*) process_wlan_exp_app_cmd);
220    wlan_exp_set_purge_all_wireless_tx_queue_callback((void*) purge_all_wireless_tx_queue);
221    wlan_exp_set_process_user_cmd_callback((void*) wlan_exp_process_user_cmd);
222    wlan_exp_set_beacon_ts_update_mode_callback((void*) ibss_set_beacon_ts_update_mode);
223    wlan_exp_set_process_config_bss_callback((void*) configure_bss);
224    wlan_exp_set_active_network_info_getter_callback((void*) active_network_info_getter);
225
226    // Set CPU_HIGH Type in wlan_exp's node_info struct;
227    wlan_exp_node_set_type_high(APPLICATION_ROLE_IBSS,  __DATE__, __TIME__);
228#endif
229
230    // CPU Low will pass HW information to CPU High as part of the boot process
231    //   - Get necessary HW information
232    memcpy((void*) &(wlan_mac_addr[0]), (void*) get_mac_hw_addr_wlan(), MAC_ADDR_LEN);
233
234    // Set the at-boot MAC Time to 0 usec
235    set_mac_time_usec(0);
236
237    wlan_mac_high_set_radio_channel(WLAN_DEFAULT_BSS_CONFIG_CHANNEL);
238    wlan_mac_high_set_rx_ant_mode(WLAN_DEFAULT_RX_ANTENNA);
239    wlan_mac_high_set_tx_ctrl_power(WLAN_DEFAULT_TX_PWR);
240    wlan_mac_high_set_radio_tx_power(WLAN_DEFAULT_TX_PWR);
241
242#if WLAN_SW_CONFIG_ENABLE_LOGGING
243    // Reset the event log
244    event_log_reset();
245#endif //WLAN_SW_CONFIG_ENABLE_LOGGING
246
247
248    // Print Station information to the terminal
249    xil_printf("------------------------\n");
250    xil_printf("WLAN MAC IBSS boot complete.\n");
251
252#ifdef WLAN_USE_UART_MENU
253    xil_printf("\nPress the Esc key in your terminal to access the UART menu\n");
254#endif
255
256    // Start the interrupts
257    wlan_platform_intc_set_state(INTERRUPTS_ENABLED);
258
259    // If there is a default SSID and the DIP switch allows it, start an active scan
260    //     - Uses default scan parameters
261    if ((strlen(default_ssid) > 0) && ((wlan_platform_userio_get_state() & USERIO_INPUT_MASK_SW_3) == 0)) {
262
263        // To prevent multiple IBSS nodes from scanning and then all creating the same network simply
264        // because they were powered on at the same time, we randomize the amount of time spent scanning
265        // for a network between [WLAN_DEFAULT_SCAN_TIMEOUT_USEC_MIN, WLAN_DEFAULT_SCAN_TIMEOUT_USEC_MAX]
266        scan_duration = WLAN_DEFAULT_SCAN_TIMEOUT_USEC_MIN +
267                (( (1000*(u64)rand()) / ((u64)RAND_MAX) ) * (WLAN_DEFAULT_SCAN_TIMEOUT_USEC_MAX - WLAN_DEFAULT_SCAN_TIMEOUT_USEC_MIN)) / 1000;
268
269        scan_start_timestamp = get_system_time_usec();
270
271        wlan_mac_scan_start();
272
273        while (((get_system_time_usec() < (scan_start_timestamp + scan_duration))) &&
274                (temp_dl_entry == NULL)) {
275            // Only try to find a match if the IBSS has completed at least one full scan
276            if (wlan_mac_scan_get_num_scans() > 0) {
277                ssid_match_list = wlan_mac_high_find_network_info_SSID(default_ssid);
278
279                if (ssid_match_list->length > 0) {
280                    // Join the first entry in the list
281                    //     - This could be modified in the future to use some other selection,
282                    //       for example RX power.
283                    //
284                    temp_dl_entry = ssid_match_list->first;
285                }
286            }
287        }
288
289        wlan_mac_scan_stop();
290
291        // Set the BSSID / SSID / Channel based on whether the scan was successful
292        if (temp_dl_entry != NULL) {
293            // Found an existing network matching the default SSID. Adopt that network's BSS configuration
294            xil_printf("Found existing %s network. Matching BSS settings.\n", default_ssid);
295            temp_network_info = (network_info_t*)(temp_dl_entry->data);
296
297            bss_config = temp_network_info->bss_config;
298        } else {
299            // Did not find an existing network matching the default SSID.  Create default BSS configuration
300            xil_printf("Unable to find '%s' IBSS. Creating new network.\n", default_ssid);
301
302            // Use node's wlan_mac_addr as BSSID
303            //     - Raise the bit identifying this address as locally administered
304            memcpy(locally_administered_addr, wlan_mac_addr, MAC_ADDR_LEN);
305            locally_administered_addr[0] |= MAC_ADDR_MSB_MASK_LOCAL;
306
307            memcpy(bss_config.bssid, locally_administered_addr, MAC_ADDR_LEN);
308            strncpy(bss_config.ssid, default_ssid, SSID_LEN_MAX);
309
310            bss_config.chan_spec.chan_pri  = WLAN_DEFAULT_BSS_CONFIG_CHANNEL;
311            bss_config.chan_spec.chan_type = CHAN_TYPE_BW20;
312            bss_config.beacon_interval     = WLAN_DEFAULT_BSS_CONFIG_BEACON_INTERVAL;
313            bss_config.ht_capable          = WLAN_DEFAULT_BSS_CONFIG_HT_CAPABLE;
314        }
315
316        // Set the rest of the bss_config fields
317        update_mask     = (BSS_FIELD_MASK_BSSID           |
318                           BSS_FIELD_MASK_CHAN            |
319                           BSS_FIELD_MASK_SSID            |
320                           BSS_FIELD_MASK_BEACON_INTERVAL |
321                           BSS_FIELD_MASK_HT_CAPABLE);
322
323        // Set the BSS configuration
324        configure_bss(&bss_config, update_mask);
325    }
326
327    // Schedule Events
328    wlan_mac_schedule_add_event(SCHEDULE_ID_COARSE, ASSOCIATION_CHECK_INTERVAL_US, SCHEDULE_REPEAT_FOREVER, (void*)remove_inactive_station_infos);
329
330
331    while(1){
332        wlan_mac_poll();
333    }
334
335    // Unreachable, but non-void return keeps the compiler happy
336    return WLAN_FAILURE;
337}
338
339/*****************************************************************************/
340/**
341 * @brief Send probe requet
342 *
343 * This function is part of the scan infrastructure and will be called whenever
344 * the node needs to send a probe request.
345 *
346 * @param   None
347 * @return  None
348 *
349 *****************************************************************************/
350void send_probe_req(){
351    u16 tx_length;
352    dl_entry* tx_queue_entry;
353    tx_80211_queue_buffer_t* tx_queue_buffer;
354    volatile scan_parameters_t* scan_parameters = wlan_mac_scan_get_parameters();
355
356    // Check out queue element for packet
357    tx_queue_entry = queue_checkout();
358
359    // Create probe request
360    if(tx_queue_entry != NULL){
361        tx_queue_buffer = (tx_80211_queue_buffer_t*)(tx_queue_entry->data);
362
363        tx_length = wlan_create_probe_req_frame(tx_queue_buffer->pkt,
364                                                (u8*)bcast_addr,
365                                                wlan_mac_addr,
366                                                (u8*)bcast_addr,
367                                                scan_parameters->ssid);
368        // Fill in metadata
369        tx_queue_buffer->flags = 0;
370        tx_queue_buffer->length = tx_length;
371        tx_queue_buffer->seg0_len = tx_length;
372        tx_queue_buffer->seg1_len = 0;
373        tx_queue_buffer->seg1_offset = 0;
374        tx_queue_buffer->station_info = station_info_create((u8*)bcast_addr);
375
376        // Put the packet in the queue
377        wlan_mac_enqueue_wireless_tx(mgmt_qid, tx_queue_entry);
378
379        // Poll the TX queues to possibly send the packet
380        poll_tx_queues(PKT_BUF_GROUP_GENERAL);
381    }
382}
383
384
385
386/*****************************************************************************/
387/**
388 * @brief Handle state change in the network scanner
389 *
390 * This function is part of the scan infrastructure and will be called whenever
391 * the scanner is started, stopped, paused, or resumed. This allows the STA
392 * to revert the channel to a known-good state when the scanner has stopped and
393 * also serves as notification to the project that it should stop dequeueing data
394 * frames since it might be on a different channel than its intended recipient.
395 *
396 * @param   None
397 * @return  None
398 *
399 *****************************************************************************/
400void process_scan_state_change(scan_state_t scan_state){
401
402    // ------------------------------------------------------------------------
403    // Note on scanning:
404    //
405    //   Currently, scanning should only be done with active_bss_info = NULL, ie the
406    // node is not currently in a BSS.  This is to avoid any corner cases.  The
407    // IBSS needs to do the following things to make scanning safe when active_bss_info
408    // is not NULL:
409    //
410    //     - Pause outgoing data queues
411    //     - Pause beacon transmissions in CPU_LOW
412    //     - Refuse to enqueue probe responses when a probe request is received off channel
413    //     - Pause dequeue of probe responses when off channel
414    //       - Note: Currently, this is difficult because probe responses share a
415    //             queue with probe requests which are needed for active scans
416    //
417    // ------------------------------------------------------------------------
418
419    switch(scan_state){
420        case SCAN_IDLE:
421        case SCAN_PAUSED:
422            pause_data_queue = 0;
423            if(active_network_info != NULL){
424                wlan_mac_high_set_radio_channel(
425                        wlan_mac_high_bss_channel_spec_to_radio_chan(active_network_info->bss_config.chan_spec));
426            }
427        break;
428        case SCAN_RUNNING:
429            pause_data_queue = 1;
430        break;
431    }
432}
433
434
435
436/*****************************************************************************/
437/**
438 * @brief Poll Tx queues to select next available packet to transmit
439 *
440 *****************************************************************************/
441#define NUM_QUEUE_GROUPS 2
442typedef enum queue_group_t{
443    MGMT_QGRP,
444    DATA_QGRP
445} queue_group_t;
446
447/*****************************************************************************/
448/**
449 * @brief Poll Tx queues to select next available packet to transmit
450 *
451 * This function will attempt to completely fill all Tx packet buffers in the
452 * PKT_BUF_GROUP_GENERAL group. Dequeueing occurs with a nested round-robing policy:
453 *  1) The function will alternate between dequeueing management and data frames in order
454 *     to prioritize time-critical management responses probe responses.
455 *  2) Data frames will be dequeued round-robin for station for which packets are enqueued.
456 *     Multicast frames are treated like their own station for the purposes of this policy.
457 *
458 *****************************************************************************/
459void poll_tx_queues(){
460    interrupt_state_t curr_interrupt_state;
461    dl_entry* tx_queue_entry;
462    u32 i;
463
464    int num_pkt_bufs_avail;
465    int poll_loop_cnt;
466
467    // Remember the next group to poll between calls to this function
468    //   This implements the ping-pong poll between the MGMT_QGRP and DATA_QGRP groups
469    static queue_group_t next_queue_group = MGMT_QGRP;
470    queue_group_t curr_queue_group;
471
472    // Remember the last queue polled between calls to this function
473    //   This implements the round-robin poll of queues in the DATA_QGRP group
474    static station_info_entry_t* next_station_info_entry = NULL;
475    station_info_entry_t* curr_station_info_entry;
476
477    station_info_t* curr_station_info;
478
479    // Stop interrupts for all processing below - this avoids many possible race conditions,
480    //  like new packets being enqueued or stations joining/leaving the BSS
481    curr_interrupt_state = wlan_platform_intc_stop();
482
483    // First handle the general packet buffer group
484    num_pkt_bufs_avail = wlan_mac_num_tx_pkt_buf_available(PKT_BUF_GROUP_GENERAL);
485
486    // This loop will (at most) check every queue twice
487    //  This handles the case of a single non-empty queue needing to supply packets
488    //  for both GENERAL packet buffers
489    poll_loop_cnt = 0;
490    while((num_pkt_bufs_avail > 0) && (poll_loop_cnt < (2*NUM_QUEUE_GROUPS))) {
491        poll_loop_cnt++;
492        curr_queue_group = next_queue_group;
493
494        if(curr_queue_group == MGMT_QGRP) {
495            // Poll the management queue on this loop, data queues on next loop
496            next_queue_group = DATA_QGRP;
497            tx_queue_entry = queue_dequeue(mgmt_qid);
498            if(tx_queue_entry) {
499                // Update the packet buffer group
500                ((tx_80211_queue_buffer_t*)(tx_queue_entry->data))->tx_queue_details.pkt_buf_group = PKT_BUF_GROUP_GENERAL;
501                // Successfully dequeued a management packet - transmit and checkin
502                wlan_mac_transmit_wireless(tx_queue_entry);
503                //continue the loop
504                num_pkt_bufs_avail--;
505                continue;
506            }
507        } else {
508            // Poll the data queues on this loop, management queue on next loop
509            next_queue_group = MGMT_QGRP;
510
511            if(pause_data_queue) {
512                // Data queues are paused - skip any dequeue attempts and continue the loop
513                continue;
514            }
515
516            for(i = 0; i < (active_network_info->members.length + 1); i++) {
517                // Resume polling data queues from where we stopped on the previous call
518                curr_station_info_entry = next_station_info_entry;
519
520                // Loop through all associated stations' queues and the broadcast queue
521                if(curr_station_info_entry == NULL) {
522                    next_station_info_entry = (station_info_entry_t*)(active_network_info->members.first);
523
524                    tx_queue_entry = queue_dequeue(mcast_qid);
525                    if(tx_queue_entry) {
526                        // Update the packet buffer group
527                        ((tx_80211_queue_buffer_t*)(tx_queue_entry->data))->tx_queue_details.pkt_buf_group = PKT_BUF_GROUP_GENERAL;
528                        // Successfully dequeued a management packet - transmit and checkin
529                        wlan_mac_transmit_wireless(tx_queue_entry);
530                        // Successfully dequeued a multicast packet - end the DATA_QGRP loop
531                        num_pkt_bufs_avail--;
532                        break;
533                    }
534                } else {
535                    // Check the queue for an associated station
536                    curr_station_info = (station_info_t*)(curr_station_info_entry->data);
537
538                    if( station_info_is_member(&active_network_info->members, curr_station_info)) {
539                        if(curr_station_info_entry == (station_info_entry_t*)(active_network_info->members.last)){
540                            // We've reached the end of the table, so we wrap around to the beginning
541                            next_station_info_entry = NULL;
542                        } else {
543                            next_station_info_entry = dl_entry_next(curr_station_info_entry);
544                        }
545
546                        tx_queue_entry = queue_dequeue(curr_station_info->QID);
547                        if(tx_queue_entry) {
548                            // Update the packet buffer group
549                            ((tx_80211_queue_buffer_t*)(tx_queue_entry->data))->tx_queue_details.pkt_buf_group = PKT_BUF_GROUP_GENERAL;
550                            // Successfully dequeued a management packet - transmit and checkin
551                            wlan_mac_transmit_wireless(tx_queue_entry);
552                            // Successfully dequeued a unicast packet for this station - end the DATA_QGRP loop
553                            num_pkt_bufs_avail--;
554                            break;
555                        }
556
557                    } else {
558                        // This curr_station_info is invalid. Perhaps it was removed from
559                        // the association table before poll_tx_queues was called. We will
560                        // start the round robin checking back at broadcast.
561                        next_station_info_entry = NULL;
562                    } // END if(curr_station_info is BSS member)
563                } // END if(multicast queue or station queue)
564            } // END for loop over association table
565        } // END if(MGMT or DATA queue group)
566    } // END while(buffers available && keep polling)
567
568    wlan_platform_intc_set_state(curr_interrupt_state);
569}
570
571/*****************************************************************************/
572/**
573 * @brief Purges all packets from all Tx queues
574 *
575 * This function discards all currently en-queued packets awaiting transmission and returns all
576 * queue entries to the free pool.
577 *
578 * This function does not discard packets already submitted to the lower-level MAC for transmission
579 *
580 * @param None
581 * @return None
582 *****************************************************************************/
583void purge_all_wireless_tx_queue(){
584    station_info_entry_t* curr_station_info_entry;
585    station_info_t* curr_station_info;
586
587    int iter = active_network_info->members.length;
588
589    // Purge all data transmit queues
590    wlan_mac_purge_wireless_tx(mcast_qid); // Broadcast Queue
591    wlan_mac_purge_wireless_tx(mgmt_qid); // Unicast Management queue
592
593    if(active_network_info != NULL){
594        curr_station_info_entry = (station_info_entry_t*)(active_network_info->members.first);
595        while( (curr_station_info_entry != NULL) && (iter-- > 0) ){
596            curr_station_info = curr_station_info_entry->data;
597            wlan_mac_purge_wireless_tx(curr_station_info->QID); // Each unicast queue
598            curr_station_info_entry = dl_entry_next(curr_station_info_entry);
599        }
600    }
601}
602
603/*****************************************************************************/
604/**
605 * @brief Callback to handle insertion of an Ethernet reception into the corresponding wireless Tx queue
606 *
607 * This function is called when a new Ethernet packet is received that must be transmitted via the wireless interface.
608 * The packet must be encapsulated before it is passed to this function. Ethernet encapsulation is implemented in the mac_high framework.
609 *
610 *****************************************************************************/
611int ethernet_receive(eth_rx_queue_buffer_t* eth_rx_queue_buffer){
612    ethernet_header_t* eth_hdr;
613    tx_80211_queue_buffer_t* tx_queue_buffer;
614    station_info_t* station_info = NULL;
615    station_info_entry_t* station_info_entry;
616    u32 queue_id;
617
618    if(active_network_info != NULL){
619
620        eth_hdr = (ethernet_header_t*)eth_rx_queue_buffer->pkt;
621
622        if( (eth_hdr->ethertype != ETH_TYPE_ARP) && (eth_hdr->ethertype != ETH_TYPE_IP) ) return 0;
623
624        //Encapsulate the packet
625        // Note: the encapsulation function handles filling in the C0/C1 lengths and C1 offset for us
626        tx_queue_buffer = wlan_eth_encap( eth_rx_queue_buffer, WLAN_ETH_ENCAP_FLAGS_OVERWRITE_PYLD_ADDRS );
627        if(tx_queue_buffer){
628            tx_queue_buffer->flags = 0;
629
630            wlan_create_data_frame_header(tx_queue_buffer->pkt,
631                                          eth_hdr->dest_mac_addr,
632                                          wlan_mac_addr,
633                                          active_network_info->bss_config.bssid,
634                                          0);
635
636            if( wlan_addr_mcast(eth_hdr->dest_mac_addr) ){
637                // Fill in metadata
638                queue_id = mcast_qid;
639                tx_queue_buffer->flags = 0;
640
641                // Assign a station_info_t struct
642                //  Notes: (1) if one exists already, it will be adopted.
643                //         (2) if no heap exists for creating one, NULL is a valid
644                //             value for the station_info_t*
645                tx_queue_buffer->station_info = station_info_create(eth_hdr->dest_mac_addr);
646            } else {
647
648                station_info_entry = station_info_find_by_addr(eth_hdr->dest_mac_addr, &active_network_info->members);
649
650                if(station_info_entry != NULL){
651                    station_info = (station_info_t*)station_info_entry->data;
652                } else {
653                    // Add station info
654                    //     - Set ht_capable argument to the HT_CAPABLE capability of the BSS.  Given that the node does not know
655                    //       the HT capabilities of the new station, it is reasonable to assume that they are the same as the BSS.
656                    //
657                    station_info = network_info_add_member(active_network_info, eth_hdr->dest_mac_addr, max_queue_size);
658
659                    if(station_info != NULL){
660
661                        if(active_network_info->bss_config.ht_capable){
662                            station_info->capabilities |= STATION_INFO_CAPABILITIES_HT_CAPABLE;
663                        } else {
664                            station_info->capabilities &= ~STATION_INFO_CAPABILITIES_HT_CAPABLE;
665                        }
666
667                        station_info->flags |= STATION_INFO_FLAG_KEEP;
668                        time_hr_min_sec_t time_hr_min_sec = wlan_mac_time_to_hr_min_sec(get_system_time_usec());
669                        xil_printf("*%dh:%02dm:%02ds* IBSS 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x added to BSS\n",
670                                time_hr_min_sec.hr, time_hr_min_sec.min, time_hr_min_sec.sec,
671                                eth_hdr->dest_mac_addr[0], eth_hdr->dest_mac_addr[1], eth_hdr->dest_mac_addr[2],
672                                eth_hdr->dest_mac_addr[3], eth_hdr->dest_mac_addr[4], eth_hdr->dest_mac_addr[5]);
673                    }
674
675                    wlan_platform_high_userio_disp_status(USERIO_DISP_STATUS_MEMBER_LIST_UPDATE, active_network_info->members.length);
676                }
677
678                if( station_info == NULL ){
679                    queue_id = mcast_qid;
680                } else {
681                    queue_id = station_info->QID;
682                }
683
684                // Fill in metadata
685                tx_queue_buffer->flags = TX_80211_QUEUE_BUFFER_FLAGS_FILL_DURATION;
686                tx_queue_buffer->station_info = station_info;
687            }
688        } else {
689            // Ethernet encapsulation failed, so we have nothing to send
690            return 0;
691        }
692        if(queue_length(queue_id) < max_queue_size){
693            // Put the packet in the queue
694            wlan_mac_enqueue_wireless_tx(queue_id, tx_queue_buffer->pyld_queue_hdr.dle);
695        } else {
696            // Packet was not successfully enqueued
697            return 0;
698        }
699
700        // Packet was successfully enqueued
701        return 1;
702    } else {
703        // Packet was not successfully enqueued
704        return 0;
705    }
706}
707
708
709
710/*****************************************************************************/
711/**
712 * @brief Process received MPDUs
713 *
714 * This callback function will process all the received MPDUs..
715 *
716 * @param  void* pkt_buf_addr
717 *     - Packet buffer address;  Contains the contents of the MPDU as well as other packet information from CPU low
718 * @param  station_info_t * station_info
719 *     - Pointer to metadata about the station from which this frame was received
720 * @param  rx_common_entry* rx_event_log_entry
721 *     - Pointer to the log entry created for this reception by the MAC High Framework
722 * @return u32 flags
723 *
724 *****************************************************************************/
725u32 mpdu_rx_process(void* pkt_buf_addr, station_info_t* station_info, rx_common_entry* rx_event_log_entry)  {
726
727    rx_frame_info_t* rx_frame_info = (rx_frame_info_t*)pkt_buf_addr;
728    void* mac_payload = (u8*)pkt_buf_addr + PHY_RX_PKT_BUF_MPDU_OFFSET;
729    u8* mac_payload_ptr_u8 = (u8*)mac_payload;
730    mac_header_80211* rx_80211_header = (mac_header_80211*)((void *)mac_payload_ptr_u8);
731
732    u16 rx_seq;
733
734    dl_entry* tx_queue_entry;
735    tx_80211_queue_buffer_t* tx_queue_buffer;
736
737    u8 unicast_to_me;
738    u8 to_multicast;
739    u8 send_response = 0;
740    u32 tx_length;
741
742    u32 return_val = 0;
743    u16 length = rx_frame_info->phy_details.length;
744
745    // If this function was passed a CTRL frame (e.g., CTS, ACK), then we should just quit.
746    // The only reason this occured was so that it could be logged in the line above.
747    if((rx_80211_header->frame_control_1 & 0xF) == MAC_FRAME_CTRL1_TYPE_CTRL){
748        goto mpdu_rx_process_end;
749    }
750
751    // Determine destination of packet
752    unicast_to_me = wlan_addr_eq(rx_80211_header->address_1, wlan_mac_addr);
753    to_multicast  = wlan_addr_mcast(rx_80211_header->address_1);
754
755    // If the packet is good (ie good FCS) and it is destined for me, then process it
756    if( (rx_frame_info->flags & RX_FRAME_INFO_FLAGS_FCS_GOOD)){
757
758        // Sequence number is 12 MSB of seq_control field
759        rx_seq         = ((rx_80211_header->sequence_control) >> 4) & 0xFFF;
760
761        // Check if this was a duplicate reception
762        //   - Packet is unicast and directed towards me
763        //   - Packet has the RETRY bit set to 1 in the second frame control byte
764        //   - Received seq num matched previously received seq num for this STA
765        if( (station_info != NULL) && unicast_to_me ){
766            if( ((rx_80211_header->frame_control_2) & MAC_FRAME_CTRL2_FLAG_RETRY) && (station_info->latest_rx_seq == rx_seq) ) {
767                if(rx_event_log_entry != NULL){
768                    rx_event_log_entry->flags |= RX_FLAGS_DUPLICATE;
769                    return_val |= MAC_RX_CALLBACK_RETURN_FLAG_DUP;
770                }
771            } else {
772                station_info->latest_rx_seq = rx_seq;
773            }
774        }
775
776        // Update the association information
777        if(active_network_info != NULL){
778            if(wlan_addr_eq(rx_80211_header->address_3, active_network_info->bss_config.bssid)){
779                if( station_info != NULL && station_info_is_member(&active_network_info->members, station_info) == 0 ){
780                    // Add station info
781                    //     - Set ht_capable argument to the HT_CAPABLE capability of the BSS.  Given that the node does not know
782                    //       the HT capabilities of the new station, it is reasonable to assume that they are the same as the BSS.
783                    //
784                    // Note: we do not need the returned station_info_t* from this function since it is guaranteed to match
785                    //  the "station_info" argument to the mpdu_rx_process function
786                    network_info_add_member(active_network_info, rx_80211_header->address_2, max_queue_size);
787
788                    // Open a queue for this station for outgoing unicast DATA frames
789                    if(active_network_info->bss_config.ht_capable){
790                        station_info->capabilities |= STATION_INFO_CAPABILITIES_HT_CAPABLE;
791                    } else {
792                        station_info->capabilities &= ~STATION_INFO_CAPABILITIES_HT_CAPABLE;
793                    }
794                    station_info->flags |= STATION_INFO_FLAG_KEEP;
795                    time_hr_min_sec_t time_hr_min_sec = wlan_mac_time_to_hr_min_sec(get_system_time_usec());
796                    xil_printf("*%dh:%02dm:%02ds* IBSS 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x added to BSS\n",
797                            time_hr_min_sec.hr, time_hr_min_sec.min, time_hr_min_sec.sec,
798                            rx_80211_header->address_2[0], rx_80211_header->address_2[1], rx_80211_header->address_2[2],
799                            rx_80211_header->address_2[3], rx_80211_header->address_2[4], rx_80211_header->address_2[5]);
800
801                    wlan_platform_high_userio_disp_status(USERIO_DISP_STATUS_MEMBER_LIST_UPDATE, active_network_info->members.length);
802                }
803            }
804        }
805
806        if(station_info != NULL) {
807
808
809            // Check if this was a duplicate reception
810            //   - Received seq num matched previously received seq num for this STA
811            if( return_val & MAC_RX_CALLBACK_RETURN_FLAG_DUP) {
812                // Finish the function
813                goto mpdu_rx_process_end;
814            }
815        }
816
817        if(unicast_to_me || to_multicast){
818            // Process the packet
819            switch(rx_80211_header->frame_control_1) {
820
821                //---------------------------------------------------------------------
822                case MAC_FRAME_CTRL1_SUBTYPE_QOSDATA:
823                case (MAC_FRAME_CTRL1_SUBTYPE_DATA):
824                    // Data packet
825                    //   - If the STA is associated with the AP and this is from the DS, then transmit over the wired network
826                    //
827                    if(active_network_info != NULL){
828                        if(wlan_addr_eq(rx_80211_header->address_3, active_network_info->bss_config.bssid)) {
829                            // MPDU is flagged as destined to the DS - send it for de-encapsulation and Ethernet Tx (if appropriate)
830#if WLAN_SW_CONFIG_ENABLE_ETH_BRIDGE
831                            wlan_eth_decap_and_send(mac_payload,
832                                                    NULL,
833                                                    rx_80211_header->address_2,
834                                                    length,
835                                                    WLAN_ETH_ENCAP_FLAGS_OVERWRITE_PYLD_ADDRS);
836#endif
837                        }
838                    }
839                break;
840
841                //---------------------------------------------------------------------
842                case (MAC_FRAME_CTRL1_SUBTYPE_PROBE_REQ):
843                    if(active_network_info != NULL){
844                        if(wlan_addr_eq(rx_80211_header->address_3, bcast_addr)) {
845                            mac_payload_ptr_u8 += sizeof(mac_header_80211);
846
847                            // Loop through tagged parameters
848                            while(((u32)mac_payload_ptr_u8 -  (u32)mac_payload)<= (length - WLAN_PHY_FCS_NBYTES)){
849
850                                // What kind of tag is this?
851                                switch(mac_payload_ptr_u8[0]){
852                                    //-----------------------------------------------------
853                                    case MGMT_TAG_SSID:
854                                        // SSID parameter set
855                                        if((mac_payload_ptr_u8[1]==0) || (memcmp(mac_payload_ptr_u8+2, (u8*)default_ssid, mac_payload_ptr_u8[1])==0)) {
856                                            // Broadcast SSID or my SSID - send unicast probe response
857                                            send_response = 1;
858                                        }
859                                    break;
860
861                                    //-----------------------------------------------------
862                                    case MGMT_TAG_SUPPORTED_RATES:
863                                        // Supported rates
864                                    break;
865
866                                    //-----------------------------------------------------
867                                    case MGMT_TAG_EXTENDED_SUPPORTED_RATES:
868                                        // Extended supported rates
869                                    break;
870
871                                    //-----------------------------------------------------
872                                    case MGMT_TAG_DSSS_PARAMETER_SET:
873                                        // DS Parameter set (e.g. channel)
874                                    break;
875                                }
876
877                                // Move up to the next tag
878                                mac_payload_ptr_u8 += mac_payload_ptr_u8[1]+2;
879                            }
880
881                            if(send_response) {
882                                // Create a probe response frame
883                                tx_queue_entry = queue_checkout();
884
885                                if(tx_queue_entry != NULL){
886                                    tx_queue_buffer = (tx_80211_queue_buffer_t*)(tx_queue_entry->data);
887
888                                    tx_length = wlan_create_probe_resp_frame(tx_queue_buffer->pkt,
889                                                                             rx_80211_header->address_2,
890                                                                             wlan_mac_addr,
891                                                                             active_network_info->bss_config.bssid,
892                                                                             active_network_info);
893
894                                    // Fill in metadata
895                                    tx_queue_buffer->flags = TX_80211_QUEUE_BUFFER_FLAGS_FILL_DURATION | TX_80211_QUEUE_BUFFER_FLAGS_FILL_TIMESTAMP;
896                                    tx_queue_buffer->length = tx_length;
897                                    tx_queue_buffer->seg0_len = tx_length;
898                                    tx_queue_buffer->seg1_len = 0;
899                                    tx_queue_buffer->seg1_offset = 0;
900                                    tx_queue_buffer->station_info = station_info;
901
902                                    // Put the packet in the queue
903                                    wlan_mac_enqueue_wireless_tx(mgmt_qid, tx_queue_entry);
904                                }
905
906                                // Finish the function
907                                goto mpdu_rx_process_end;
908                            }
909                        }
910                    }
911                break;
912
913                //---------------------------------------------------------------------
914                default:
915                    //This should be left as a verbose print. It occurs often when communicating with mobile devices since they tend to send
916                    //null data frames (type: DATA, subtype: 0x4) for power management reasons.
917                    wlan_printf(PL_VERBOSE, "Received unknown frame control type/subtype %x\n",rx_80211_header->frame_control_1);
918                break;
919            }
920        }
921        // Finish the function
922        goto mpdu_rx_process_end;
923    } else {
924        // Process any Bad FCS packets
925        goto mpdu_rx_process_end;
926    }
927
928
929    // Finish any processing for the RX MPDU process
930    mpdu_rx_process_end:
931
932    return return_val;
933}
934
935
936
937/*****************************************************************************/
938/**
939 * @brief Check the time since the station has interacted with another station
940 *
941 *
942 * @param  None
943 * @return None
944 *****************************************************************************/
945void remove_inactive_station_infos() {
946
947    u64 time_since_last_activity;
948    station_info_t* curr_station_info;
949    station_info_entry_t* curr_station_info_entry;
950    station_info_entry_t* next_station_info_entry;
951
952    if(active_network_info != NULL){
953        next_station_info_entry = (station_info_entry_t*)active_network_info->members.first;
954
955        while(next_station_info_entry != NULL) {
956            curr_station_info_entry = next_station_info_entry;
957            next_station_info_entry = dl_entry_next(curr_station_info_entry);
958
959            curr_station_info        = (station_info_t*)(curr_station_info_entry->data);
960            time_since_last_activity = (get_system_time_usec() - curr_station_info->latest_rx_timestamp);
961
962            // De-authenticate the station if we have timed out and we have not disabled this check for the station
963            if((time_since_last_activity > ASSOCIATION_TIMEOUT_US) && ((curr_station_info->flags & STATION_INFO_FLAG_DISABLE_ASSOC_CHECK) == 0)){
964                wlan_mac_purge_wireless_tx(curr_station_info->QID);
965                network_info_remove_member( active_network_info, curr_station_info->addr );
966                wlan_platform_high_userio_disp_status(USERIO_DISP_STATUS_MEMBER_LIST_UPDATE, active_network_info->members.length);
967
968                time_hr_min_sec_t time_hr_min_sec = wlan_mac_time_to_hr_min_sec(get_system_time_usec());
969                xil_printf("*%dh:%02dm:%02ds* IBSS 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x removed from BSS\n",
970                        time_hr_min_sec.hr, time_hr_min_sec.min, time_hr_min_sec.sec,
971                        curr_station_info->addr[0], curr_station_info->addr[1], curr_station_info->addr[2],
972                        curr_station_info->addr[3], curr_station_info->addr[4], curr_station_info->addr[5]);
973
974                curr_station_info->flags &= ~STATION_INFO_FLAG_KEEP;
975
976            }
977        }
978    }
979}
980
981
982#if WLAN_SW_CONFIG_ENABLE_LTG
983/*****************************************************************************/
984/**
985 * @brief Callback to handle new Local Traffic Generator event
986 *
987 * This function is called when the LTG scheduler determines a traffic generator should create a new packet. The
988 * behavior of this function depends entirely on the LTG payload parameters.
989 *
990 * The reference implementation defines 3 LTG payload types:
991 *  - LTG_PYLD_TYPE_FIXED: generate 1 fixed-length packet to single destination; callback_arg is pointer to ltg_pyld_fixed_t struct
992 *  - LTG_PYLD_TYPE_UNIFORM_RAND: generate 1 random-length packet to single destination; callback_arg is pointer to ltg_pyld_uniform_rand_t struct
993 *  - LTG_PYLD_TYPE_ALL_ASSOC_FIXED: generate 1 fixed-length packet to each associated station; callback_arg is pointer to ltg_pyld_all_assoc_fixed_t struct
994 *
995 * @param u32 id
996 *  - Unique ID of the previously created LTG
997 * @param void* callback_arg
998 *  - Callback argument provided at LTG creation time; interpretation depends on LTG type
999 * @return None
1000 *****************************************************************************/
1001void ltg_event(u32 id, void* callback_arg){
1002
1003    u32 payload_length;
1004    u32 min_ltg_payload_length;
1005    station_info_entry_t* station_info_entry = NULL;
1006    station_info_t* station_info = NULL;
1007    u8* addr_da;
1008    u8 is_multicast;
1009    u8 queue_id;
1010    dl_entry* tx_queue_entry        = NULL;
1011    tx_80211_queue_buffer_t* tx_queue_buffer         = NULL;
1012    u8 continue_loop;
1013    u16 flags = TX_80211_QUEUE_BUFFER_FLAGS_FILL_UNIQ_SEQ;
1014    u8* addr_ra;
1015    u16 duration;
1016
1017    if(((ltg_pyld_hdr_t*)callback_arg)->type == LTG_PYLD_TYPE_CTRL_RESP){
1018
1019        tx_queue_entry = queue_checkout();
1020        if(tx_queue_entry != NULL){
1021            tx_queue_buffer = ((tx_80211_queue_buffer_t*)(tx_queue_entry->data));
1022
1023            addr_ra = ((ltg_pyld_ctrl_resp_t*)callback_arg)->addr_ra;
1024            duration = ((ltg_pyld_ctrl_resp_t*)callback_arg)->duration;
1025
1026            if(((ltg_pyld_ctrl_resp_t*)callback_arg)->subtype == LTG_PYLD_CTRL_RESP_SUBTYPE_CTS){
1027                payload_length = wlan_create_cts_frame(tx_queue_buffer->pkt,
1028                                                       addr_ra,
1029                                                       duration);
1030                tx_queue_buffer->flags = TX_80211_QUEUE_BUFFER_FLAGS_TYPE_CTS;
1031            } else { //LTG_PYLD_CTRL_RESP_SUBTYPE_ACK
1032                payload_length = wlan_create_ack_frame(tx_queue_buffer->pkt,
1033                                                       addr_ra);
1034                tx_queue_buffer->flags = TX_80211_QUEUE_BUFFER_FLAGS_TYPE_ACK;
1035            }
1036
1037            // Fill in metadata
1038            tx_queue_buffer->flags |= TX_80211_QUEUE_BUFFER_FLAGS_BYPASS_RECOVERY;
1039            tx_queue_buffer->length = payload_length;
1040
1041            // With LTG_PYLD_TYPE_CTRL_RESP, we will transmit to the receive address (addr_ra) regardless of
1042            // whether that address is an AP that we are associated to. To do that, we need to make sure that
1043            // a station_info_t exists for that address
1044            tx_queue_buffer->station_info = station_info_create(addr_ra);
1045
1046            wlan_mac_enqueue_wireless_tx(mgmt_qid, tx_queue_entry);
1047
1048        }
1049    } else {
1050
1051
1052        if(active_network_info != NULL){
1053            switch(((ltg_pyld_hdr_t*)callback_arg)->type){
1054                case LTG_PYLD_TYPE_FIXED:
1055                    payload_length = ((ltg_pyld_fixed_t*)callback_arg)->length;
1056                    addr_da = ((ltg_pyld_fixed_t*)callback_arg)->addr_da;
1057                    is_multicast = wlan_addr_mcast(addr_da);
1058                    if(is_multicast){
1059                        queue_id = mcast_qid;
1060                    } else {
1061                        flags |= TX_80211_QUEUE_BUFFER_FLAGS_FILL_DURATION;
1062                        station_info_entry = station_info_find_by_addr(addr_da, &active_network_info->members);
1063                        if(station_info_entry != NULL){
1064                            station_info = (station_info_t*)(station_info_entry->data);
1065                            queue_id = station_info->QID;
1066                        } else {
1067                            //Unlike the AP, this isn't necessarily a criteria for giving up on this LTG event.
1068                            //In the IBSS, it's possible that there simply wasn't room in the heap for a station_info,
1069                            //but we should still send it a packet. We'll use the multi-cast queue as a catch-all queue for these frames.
1070                            queue_id = mcast_qid;
1071                        }
1072                    }
1073                break;
1074
1075                case LTG_PYLD_TYPE_UNIFORM_RAND:
1076                    payload_length = (rand()%(((ltg_pyld_uniform_rand_t*)(callback_arg))->max_length - ((ltg_pyld_uniform_rand_t*)(callback_arg))->min_length))+((ltg_pyld_uniform_rand_t*)(callback_arg))->min_length;
1077                    addr_da = ((ltg_pyld_fixed_t*)callback_arg)->addr_da;
1078
1079                    is_multicast = wlan_addr_mcast(addr_da);
1080                    if(is_multicast){
1081                        queue_id = mcast_qid;
1082                    } else {
1083                        flags |= TX_80211_QUEUE_BUFFER_FLAGS_FILL_DURATION;
1084                        station_info_entry = station_info_find_by_addr(addr_da, &active_network_info->members);
1085                        if(station_info_entry != NULL){
1086                            station_info = (station_info_t*)(station_info_entry->data);
1087                            queue_id = station_info->QID;
1088                        } else {
1089                            //Unlike the AP, this isn't necessarily a criteria for giving up on this LTG event.
1090                            //In the IBSS, it's possible that there simply wasn't room in the heap for a station_info,
1091                            //but we should still send it a packet. We'll use the multi-cast queue as a catch-all queue for these frames.
1092                            queue_id = mcast_qid;
1093                        }
1094                    }
1095                break;
1096
1097                case LTG_PYLD_TYPE_ALL_ASSOC_FIXED:
1098                    if(active_network_info->members.length > 0){
1099                        flags |= TX_80211_QUEUE_BUFFER_FLAGS_FILL_DURATION;
1100                        station_info_entry = (station_info_entry_t*)(active_network_info->members.first);
1101                        station_info = (station_info_t*)station_info_entry->data;
1102                        addr_da = station_info->addr;
1103                        queue_id = station_info->QID;
1104                        is_multicast = 0;
1105                        payload_length = ((ltg_pyld_all_assoc_fixed_t*)callback_arg)->length;
1106                    } else {
1107                        return;
1108                    }
1109                break;
1110
1111                default:
1112                    xil_printf("ERROR ltg_event: Unknown LTG Payload Type! (%d)\n", ((ltg_pyld_hdr_t*)callback_arg)->type);
1113                    return;
1114                break;
1115            }
1116
1117            if(is_multicast == 0){
1118                station_info_entry = station_info_find_by_addr(addr_da, &active_network_info->members);
1119
1120                if(station_info_entry == NULL){
1121                    // Add station info
1122                    //     - Set ht_capable argument to the HT_CAPABLE capability of the BSS.  Given that the node does not know
1123                    //       the HT capabilities of the new station, it is reasonable to assume that they are the same as the BSS.
1124                    //
1125                    station_info = network_info_add_member(active_network_info, addr_da, max_queue_size);
1126                    if(station_info != NULL){
1127                        if(active_network_info->bss_config.ht_capable){
1128                            station_info->capabilities |= STATION_INFO_CAPABILITIES_HT_CAPABLE;
1129                        } else {
1130                            station_info->capabilities &= ~STATION_INFO_CAPABILITIES_HT_CAPABLE;
1131                        }
1132                        station_info->flags |= STATION_INFO_FLAG_KEEP;
1133                        time_hr_min_sec_t time_hr_min_sec = wlan_mac_time_to_hr_min_sec(get_system_time_usec());
1134                        xil_printf("*%dh:%02dm:%02ds* IBSS 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x added to BSS\n",
1135                                time_hr_min_sec.hr, time_hr_min_sec.min, time_hr_min_sec.sec,
1136                                addr_da[0], addr_da[1], addr_da[2],
1137                                addr_da[3], addr_da[4], addr_da[5]);
1138                    }
1139                    wlan_platform_high_userio_disp_status(USERIO_DISP_STATUS_MEMBER_LIST_UPDATE, active_network_info->members.length);
1140                }
1141            }
1142
1143
1144            do{
1145                continue_loop = 0;
1146
1147                if(queue_length(queue_id) < max_queue_size){
1148                    // Checkout 1 element from the queue;
1149                    tx_queue_entry = queue_checkout();
1150                    if(tx_queue_entry != NULL){
1151                        // Create LTG packet
1152                        tx_queue_buffer = ((tx_80211_queue_buffer_t*)(tx_queue_entry->data));
1153
1154                        min_ltg_payload_length = wlan_create_ltg_frame(tx_queue_buffer->pkt,
1155                                                                       addr_da,
1156                                                                       wlan_mac_addr,
1157                                                                       active_network_info->bss_config.bssid,
1158                                                                       0,
1159                                                                       id);
1160                        payload_length = WLAN_MAX(payload_length+sizeof(mac_header_80211)+WLAN_PHY_FCS_NBYTES, min_ltg_payload_length);
1161
1162                        // Fill in metadata
1163                        tx_queue_buffer->length = payload_length;
1164                        tx_queue_buffer->seg0_len = min_ltg_payload_length;
1165                        tx_queue_buffer->seg1_len = 0;
1166                        tx_queue_buffer->seg1_offset = 0;
1167                        tx_queue_buffer->station_info = station_info;
1168                        tx_queue_buffer->flags = flags;
1169
1170                        // Submit the new packet to the appropriate queue
1171                        wlan_mac_enqueue_wireless_tx(queue_id, tx_queue_entry);
1172
1173
1174                    } else {
1175                        // There aren't any free queue elements right now.
1176                        // As such, there probably isn't any point to continuing this callback.
1177                        // We'll return and try again once it is called the next time.
1178                        return;
1179                    }
1180                }
1181
1182                if(((ltg_pyld_hdr_t*)callback_arg)->type == LTG_PYLD_TYPE_ALL_ASSOC_FIXED){
1183                    station_info_entry = dl_entry_next(station_info_entry);
1184                    if(station_info_entry != NULL){
1185                        station_info = (station_info_t*)station_info_entry->data;
1186                        addr_da = station_info->addr;
1187                        queue_id = station_info->QID;
1188                        is_multicast = 0;
1189                        continue_loop = 1;
1190                    } else {
1191                        continue_loop = 0;
1192                    }
1193                } else {
1194                    continue_loop = 0;
1195                }
1196            } while(continue_loop == 1);
1197        }
1198    }
1199}
1200#endif //WLAN_SW_CONFIG_ENABLE_LTG
1201
1202/*****************************************************************************/
1203/**
1204 * @brief Handle a reboot of CPU_LOW
1205 *
1206 * If CPU_LOW reboots, any parameters we had previously set in it will be lost.
1207 * This function is called to tell us that we should re-apply any previous
1208 * parameters we had set.
1209 *
1210 * @param  u32 type - type of MAC running in CPU_LOW
1211 * @return None
1212 *****************************************************************************/
1213void handle_cpu_low_reboot(u32 type){
1214    if(active_network_info){
1215        // Re-apply any Beacon Tx configurations
1216        wlan_mac_high_config_txrx_beacon(&gl_beacon_txrx_config);
1217    }
1218}
1219
1220/*****************************************************************************/
1221/**
1222 *
1223 *****************************************************************************/
1224u32 configure_bss(bss_config_t* bss_config, u32 update_mask){
1225    u32 return_status = 0;
1226    u8 update_beacon_template = 0;
1227    u8 send_beacon_config_to_low = 0;
1228    u8 send_channel_switch_to_low = 0;
1229
1230    network_info_t* local_network_info;
1231    interrupt_state_t curr_interrupt_state;
1232    station_info_t* curr_station_info;
1233    dl_entry* next_station_info_entry;
1234    dl_entry* curr_station_info_entry;
1235    int iter;
1236    tx_params_t default_beacon_tx_params;
1237
1238    //---------------------------------------------------------
1239    // 1. Check for any invalid inputs or combination of inputs
1240    //      First verify the requested update to the BSS configuration before
1241    //      modifying anything. This will prevent a partial update of BSS
1242    //      configuration with valid parameters before discovering an invalid
1243    //      parameter.
1244
1245    if (bss_config != NULL) {
1246        if (update_mask & BSS_FIELD_MASK_BSSID) {
1247            if (wlan_addr_eq(bss_config->bssid, zero_addr) == 0) {
1248                if ((active_network_info != NULL) && wlan_addr_eq(bss_config->bssid, active_network_info->bss_config.bssid)) {
1249                    // The caller of this function claimed that it was updating the BSSID,
1250                    // but the new BSSID matches the one already specified in active_bss_info.
1251                    // Complete the rest of this function as if that bit in the update mask
1252                    // were not set
1253                    update_mask &= ~BSS_FIELD_MASK_BSSID;
1254                } else {
1255                    // Changing the BSSID, perform necessary argument checks
1256                    if ((bss_config->bssid[0] & MAC_ADDR_MSB_MASK_LOCAL ) == 0) {
1257                        // In the IBSS implementation, the BSSID provided must be locally generated
1258                        return_status |= BSS_CONFIG_FAILURE_BSSID_INVALID;
1259                    }
1260                    if (((update_mask & BSS_FIELD_MASK_SSID) == 0) ||
1261                        ((update_mask & BSS_FIELD_MASK_CHAN) == 0) ||
1262                        ((update_mask & BSS_FIELD_MASK_BEACON_INTERVAL) == 0)) {
1263                        return_status |= BSS_CONFIG_FAILURE_BSSID_INSUFFICIENT_ARGUMENTS;
1264                    }
1265                }
1266            }
1267        } else {
1268            if (active_network_info == NULL) {
1269                // Cannot update BSS without specifying BSSID
1270                return_status |= BSS_CONFIG_FAILURE_BSSID_INSUFFICIENT_ARGUMENTS;
1271            }
1272        }
1273        if (update_mask & BSS_FIELD_MASK_CHAN) {
1274            if (wlan_verify_channel(
1275                    wlan_mac_high_bss_channel_spec_to_radio_chan(bss_config->chan_spec)) != WLAN_SUCCESS) {
1276                return_status |= BSS_CONFIG_FAILURE_CHANNEL_INVALID;
1277            }
1278        }
1279        if (update_mask & BSS_FIELD_MASK_BEACON_INTERVAL) {
1280            if ((bss_config->beacon_interval != BEACON_INTERVAL_NO_BEACON_TX) &&
1281                (bss_config->beacon_interval <  10)) {
1282                return_status |= BSS_CONFIG_FAILURE_BEACON_INTERVAL_INVALID;
1283            }
1284        }
1285        if (update_mask & BSS_FIELD_MASK_HT_CAPABLE) {
1286            if (bss_config->ht_capable > 1) {
1287                return_status |= BSS_CONFIG_FAILURE_HT_CAPABLE_INVALID;
1288            }
1289        }
1290        if (update_mask & BSS_FIELD_MASK_DTIM_PERIOD) {
1291            //IBSS DTIM is not supported at this time. Any attempt to update this field
1292            //will return an error
1293            return_status |= BSS_CONFIG_FAILURE_DTIM_PERIOD_INVALID;
1294        }
1295    }
1296
1297    if (return_status == 0) {
1298        //---------------------------------------------------------
1299        // 2. Apply BSS configuration changes
1300        //      Now that the provided bss_config_t struct is valid, apply the changes.
1301
1302        // Disable interrupts around these modifications to prevent state
1303        // changing out from underneath this context while the new BSS
1304        // configuration parameters are only partially updated.
1305        curr_interrupt_state = wlan_platform_intc_stop();
1306
1307        if ((bss_config == NULL) || (update_mask & BSS_FIELD_MASK_BSSID)) {
1308            // Adopting a new BSSID. This could mean either
1309            //    1) Shutting the BSS down
1310            // or 2) Shutting the BSS down and then starting a new BSS.
1311            //
1312            // In either case, first remove any station_info structs
1313            // that are members of the current active_bss_info and return to
1314            // a NULL active_bss_info state.
1315            //
1316            // This will not result in any OTA transmissions to the stations.
1317
1318            if (active_network_info != NULL) {
1319                //Purge all tranmissions queues
1320                purge_all_wireless_tx_queue();
1321
1322                if ((bss_config == NULL) ||
1323                        ((update_mask & BSS_FIELD_MASK_BSSID) && wlan_addr_eq(bss_config->bssid, zero_addr)) ) {
1324                    xil_printf("Leaving BSS\n");
1325                }
1326
1327                // Remove all associations
1328                next_station_info_entry = active_network_info->members.first;
1329                iter = active_network_info->members.length;
1330
1331                while ((next_station_info_entry != NULL) && (iter-- > 0)) {
1332                    curr_station_info_entry = next_station_info_entry;
1333                    next_station_info_entry = dl_entry_next(curr_station_info_entry);
1334
1335                    curr_station_info = (station_info_t*)(curr_station_info_entry->data);
1336
1337                    // Remove the association
1338                    network_info_remove_member(active_network_info, curr_station_info->addr);
1339
1340                    time_hr_min_sec_t time_hr_min_sec = wlan_mac_time_to_hr_min_sec(get_system_time_usec());
1341                    xil_printf("*%dh:%02dm:%02ds* IBSS 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x removed from BSS\n",
1342                            time_hr_min_sec.hr, time_hr_min_sec.min, time_hr_min_sec.sec,
1343                            curr_station_info->addr[0], curr_station_info->addr[1], curr_station_info->addr[2],
1344                            curr_station_info->addr[3], curr_station_info->addr[4], curr_station_info->addr[5]);
1345
1346                    curr_station_info->flags &= ~STATION_INFO_FLAG_KEEP;
1347
1348                    // Update the hex display to show station was removed
1349                    wlan_platform_high_userio_disp_status(USERIO_DISP_STATUS_MEMBER_LIST_UPDATE, active_network_info->members.length);
1350                }
1351
1352                // Inform the MAC High Framework to no longer will keep this BSS Info. This will
1353                // allow it to be overwritten in the future to make space for new BSS Infos.
1354                active_network_info->flags &= ~NETWORK_FLAGS_KEEP;
1355
1356                // Set "active_bss_info" to NULL
1357                //     - All functions must be able to handle active_bss_info = NULL
1358                active_network_info = NULL;
1359
1360                // Disable beacons immediately
1361                ((tx_frame_info_t*)CALC_PKT_BUF_ADDR(platform_common_dev_info.tx_pkt_buf_baseaddr, TX_PKT_BUF_BEACON))->tx_pkt_buf_state = TX_PKT_BUF_HIGH_CTRL;
1362                gl_beacon_txrx_config.beacon_tx_mode = NO_BEACON_TX;
1363                bzero(gl_beacon_txrx_config.bssid_match, MAC_ADDR_LEN);
1364                wlan_mac_high_config_txrx_beacon(&gl_beacon_txrx_config);
1365
1366                // Set hex display to "No BSS"
1367                wlan_platform_high_userio_disp_status(USERIO_DISP_STATUS_MEMBER_LIST_UPDATE, 0xFF);
1368            }
1369
1370            // (bss_config_update == NULL) is one way to remove the BSS state of the node. This operation
1371            // was executed just above.  Rather that continuing to check non-NULLness of bss_config
1372            // throughout the rest of this function, just re-enable interrupts and return early.
1373
1374            if(bss_config == NULL){
1375                wlan_platform_intc_set_state(curr_interrupt_state);
1376                return return_status;
1377            }
1378
1379            // active_bss_info is guaranteed to be NULL at this point in the code
1380            // bss_config is guaranteed to be non-NULL at this point in the code
1381
1382            // Update BSS
1383            //     - BSSID must not be zero_addr (reserved address)
1384            if (wlan_addr_eq(bss_config->bssid, zero_addr) == 0) {
1385                // Stop the scan state machine if it is running
1386                if (wlan_mac_scan_is_scanning()) {
1387                    wlan_mac_scan_stop();
1388                }
1389
1390                // Create a new bss_info or overwrite an existing one with matching BSSID.
1391                //     Note:  The wildcard SSID and 0-valued channel arguments are temporary. Because
1392                //         of the error checking at the top of this function, the bss_config will
1393                //         contain a valid SSID as well as channel. These fields will be updated
1394                //         in step 3).
1395                local_network_info = wlan_mac_high_create_network_info(bss_config->bssid, "", 0);
1396
1397                if(local_network_info != NULL){
1398                    local_network_info->flags |= NETWORK_FLAGS_KEEP;
1399                    local_network_info->capabilities = (BSS_CAPABILITIES_IBSS);
1400                    active_network_info = local_network_info;
1401                }
1402
1403                // Set hex display
1404                wlan_platform_high_userio_disp_status(USERIO_DISP_STATUS_MEMBER_LIST_UPDATE, active_network_info->members.length);
1405            }
1406        }
1407
1408        //---------------------------------------------------------
1409        // 3. Clean up
1410        //      Now that active_bss_info has been updated, CPU_HIGH can communicate
1411        //      the changes to CPU_LOW so that the node is tuned to the correct channel,
1412        //      send beacons at the correct interval, and update the beacon
1413        //      template packet buffer.
1414        if (active_network_info != NULL) {
1415
1416            if (update_mask & BSS_FIELD_MASK_CHAN) {
1417                active_network_info->bss_config.chan_spec = bss_config->chan_spec;
1418                send_channel_switch_to_low = 1;
1419                update_beacon_template = 1;
1420            }
1421            if (update_mask & BSS_FIELD_MASK_SSID) {
1422                strncpy(active_network_info->bss_config.ssid, bss_config->ssid, SSID_LEN_MAX);
1423                update_beacon_template = 1;
1424            }
1425            if (update_mask & BSS_FIELD_MASK_BEACON_INTERVAL) {
1426                active_network_info->bss_config.beacon_interval = bss_config->beacon_interval;
1427                update_beacon_template = 1;
1428                send_beacon_config_to_low = 1;
1429            }
1430            if (update_mask & BSS_FIELD_MASK_HT_CAPABLE) {
1431                // In an IBSS network, the node does not know the HT capabilities of any of
1432                // the peer nodes in the BSS.  Therefore, when station infos are added to
1433                // track peer nodes, the node assumes that the peer node's HT capabilities
1434                // matches that of the BSS.  Given that changing the BSS capabilities does
1435                // not invalidate that assumption, the IBSS node does not update any station
1436                // info HT capabilities when the BSS capabilities change.  Therefore,
1437                // changing the BSS HT_CAPABLE capabilities only affects what is advertised in
1438                // the IBSS beacons.  Also, it should not change any of the default TX params
1439                // since the IBSS node is still capable of sending and receiving HT packets.
1440
1441                active_network_info->bss_config.ht_capable = bss_config->ht_capable;
1442
1443                // Update the beacon template to match capabilities
1444                update_beacon_template = 1;
1445            }
1446
1447            // Update the beacon template
1448            //     In the event that CPU_LOW currently has the beacon packet buffer locked,
1449            //     block for now until it unlocks.  This will guarantee that beacon are updated
1450            //     before the function returns.
1451            if (update_beacon_template) {
1452                default_beacon_tx_params = wlan_mac_get_default_tx_params(mcast_mgmt);
1453
1454                while( wlan_mac_high_configure_beacon_tx_template((u8*)bcast_addr,
1455                                                                  wlan_mac_addr,
1456                                                                  active_network_info->bss_config.bssid,
1457                                                                  active_network_info,
1458                                                                  &default_beacon_tx_params,
1459                                                                  TX_FRAME_INFO_FLAGS_FILL_TIMESTAMP | TX_FRAME_INFO_FLAGS_WAIT_FOR_LOCK) != 0 ){}
1460            }
1461
1462            // Update the channel
1463            if (send_channel_switch_to_low) {
1464                wlan_mac_high_set_radio_channel(
1465                        wlan_mac_high_bss_channel_spec_to_radio_chan(active_network_info->bss_config.chan_spec));
1466            }
1467
1468            // Update Beacon configuration
1469            if (send_beacon_config_to_low) {
1470
1471                memcpy(gl_beacon_txrx_config.bssid_match, active_network_info->bss_config.bssid, MAC_ADDR_LEN);
1472
1473                if ((active_network_info->bss_config.beacon_interval == BEACON_INTERVAL_NO_BEACON_TX) ||
1474                    (active_network_info->bss_config.beacon_interval == BEACON_INTERVAL_UNKNOWN)) {
1475                    ((tx_frame_info_t*)CALC_PKT_BUF_ADDR(platform_common_dev_info.tx_pkt_buf_baseaddr, TX_PKT_BUF_BEACON))->tx_pkt_buf_state = TX_PKT_BUF_HIGH_CTRL;
1476                    gl_beacon_txrx_config.beacon_tx_mode = NO_BEACON_TX;
1477                } else {
1478                    gl_beacon_txrx_config.beacon_tx_mode = IBSS_BEACON_TX;
1479                }
1480
1481                gl_beacon_txrx_config.beacon_interval_tu = active_network_info->bss_config.beacon_interval;
1482                gl_beacon_txrx_config.beacon_template_pkt_buf = TX_PKT_BUF_BEACON;
1483
1484                wlan_mac_high_config_txrx_beacon(&gl_beacon_txrx_config);
1485            }
1486
1487            // Print new IBSS information
1488            xil_printf("IBSS Details: \n");
1489            xil_printf("  BSSID           : %02x-%02x-%02x-%02x-%02x-%02x\n",active_network_info->bss_config.bssid[0],active_network_info->bss_config.bssid[1],
1490                                                                             active_network_info->bss_config.bssid[2],active_network_info->bss_config.bssid[3],
1491                                                                             active_network_info->bss_config.bssid[4],active_network_info->bss_config.bssid[5]);
1492            xil_printf("   SSID           : %s\n", active_network_info->bss_config.ssid);
1493            xil_printf("   Channel        : %d\n", wlan_mac_high_bss_channel_spec_to_radio_chan(active_network_info->bss_config.chan_spec));
1494            if (active_network_info->bss_config.beacon_interval == BEACON_INTERVAL_NO_BEACON_TX) {
1495                xil_printf("   Beacon Interval: No Beacon Tx\n");
1496            } else if (active_network_info->bss_config.beacon_interval == BEACON_INTERVAL_UNKNOWN) {
1497                xil_printf("   Beacon Interval: Unknown\n");
1498            } else {
1499                xil_printf("   Beacon Interval: %d TU (%d us)\n", active_network_info->bss_config.beacon_interval, active_network_info->bss_config.beacon_interval*1024);
1500            }
1501        }
1502
1503        // Restore interrupts after all BSS changes
1504        wlan_platform_intc_set_state(curr_interrupt_state);
1505    }
1506
1507    return return_status;
1508}
1509
1510
1511
1512/*****************************************************************************/
1513/**
1514 * @brief Callback to handle beacon MAC time update mode
1515 *
1516 * @param  u32 enable        - Enable / Disable MAC time update from beacons
1517 * @return None
1518 *
1519 *****************************************************************************/
1520void ibss_set_beacon_ts_update_mode(u32 enable){
1521    if (enable) {
1522        gl_beacon_txrx_config.ts_update_mode = FUTURE_ONLY_UPDATE;
1523    } else {
1524        gl_beacon_txrx_config.ts_update_mode = NEVER_UPDATE;
1525    }
1526
1527    // Push beacon configuration to CPU_LOW
1528    wlan_mac_high_config_txrx_beacon(&gl_beacon_txrx_config);
1529}
1530
1531
1532
1533/*****************************************************************************/
1534/**
1535 * @brief Accessor methods for global variables
1536 *
1537 * These functions will return pointers to global variables
1538 *
1539 * @param  None
1540 * @return None
1541 *****************************************************************************/
1542dl_list* get_network_member_list(){
1543    if(active_network_info != NULL){
1544        return &(active_network_info->members);
1545    } else {
1546        return NULL;
1547    }
1548}
1549
1550network_info_t * active_network_info_getter(){ return active_network_info; }
1551
1552
1553#if WLAN_SW_CONFIG_ENABLE_WLAN_EXP
1554
1555// ****************************************************************************
1556// Define MAC Specific User Commands
1557//
1558// NOTE:  All User Command IDs (CMDID_*) must be a 24 bit unique number
1559//
1560
1561//-----------------------------------------------
1562// MAC Specific User Commands
1563//
1564// #define CMDID_USER_<COMMAND_NAME>                       0x100000
1565
1566
1567//-----------------------------------------------
1568// MAC Specific User Command Parameters
1569//
1570// #define CMD_PARAM_USER_<PARAMETER_NAME>                 0x00000000
1571
1572
1573
1574/*****************************************************************************/
1575/**
1576 * Process User Commands
1577 *
1578 * This function is part of the WLAN Exp framework and will process the framework-
1579 * level user commands.  This function intentionally does not implement any user
1580 * commands and it is left to the user to implement any needed functionality.   By
1581 * default, any commands not processed in this function will print an error to the
1582 * UART.
1583 *
1584 * @return  int              - Status of the command:
1585 *                                 NO_RESP_SENT - No response has been sent
1586 *                                 RESP_SENT    - A response has been sent
1587 *
1588 * @note    See on-line documentation for more information:
1589 *          https://warpproject.org/trac/wiki/802.11/wlan_exp/Extending
1590 *
1591 *****************************************************************************/
1592int wlan_exp_process_user_cmd(cmd_resp_hdr_t* cmd_hdr, eth_tx_queue_buffer_t* eth_tx_queue_buffer) {
1593
1594    //
1595    // IMPORTANT ENDIAN NOTES:
1596    //     - command
1597    //         - header - Already endian swapped by the framework (safe to access directly)
1598    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the command)
1599    //     - response
1600    //         - header - Will be endian swapped by the framework (safe to write directly)
1601    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the response)
1602    //
1603
1604    // Standard variables
1605    //
1606    // Used for accessing command arguments and constructing the command response header/payload
1607    //
1608    // NOTE:  Some of the standard variables below have been commented out.  This was to remove
1609    //     compiler warnings for "unused variables" since the default implementation is empty.  As
1610    //     you add commands, you should un-comment the standard variables.
1611    //
1612    u32 resp_sent = NO_RESP_SENT;
1613
1614    u32 cmd_id = CMD_TO_CMDID(cmd_hdr->cmd);
1615#if 0
1616    // Segment 0 length includes a fully formed command response header
1617    //  because one was created with default values suitable for a responseless
1618    //  acknowledgment.
1619    cmd_resp_hdr_t* resp_hdr = (cmd_resp_hdr_t*)(eth_tx_queue_buffer->seg0
1620                                                 + eth_tx_queue_buffer->seg0_len
1621                                                 - sizeof(cmd_resp_hdr_t));
1622
1623    u32* cmd_args_32 = (u32*)((u8*)cmd_hdr + sizeof(cmd_resp_hdr_t));
1624#endif
1625
1626    switch(cmd_id){
1627
1628//-----------------------------------------------------------------------------
1629// MAC Specific User Commands
1630//-----------------------------------------------------------------------------
1631
1632        // Template framework for a Command
1633        //
1634        // NOTE:  The WLAN Exp framework assumes that the Over-the-Wire format of the data is
1635        //     big endian.  However, the node processes data using little endian.  Therefore,
1636        //     any data received from the host must be properly endian-swapped and similarly,
1637        //     any data sent to the host must be properly endian-swapped.  The built-in Xilinx
1638        //     functions:  Xil_Ntohl() (Network to Host) and Xil_Htonl() (Host to Network) are
1639        //     used for this.
1640        //
1641#if 0
1642        //---------------------------------------------------------------------
1643        case CMDID_USER_<COMMAND_NAME>: {
1644            // Command Description
1645            //
1646            // Message format:
1647            //     cmd_args_32[0:N]    Document command arguments from the host
1648            //
1649            // Response format:
1650            //     resp_args_32[0:M]   Document response arguments from the node
1651            //
1652            // NOTE:  Variables are declared above.
1653            // NOTE:  Please take care of the endianness of the arguments (see comment above)
1654            //
1655
1656            // Variables for template command
1657            int status;
1658            u32 arg_0;
1659            interrupt_state_t curr_interrupt_state;
1660
1661            // Initialize variables
1662            status      = CMD_PARAM_SUCCESS;
1663            arg_0       = Xil_Ntohl(cmd_args_32[0]);              // Swap endianness of command argument
1664
1665            // Do something with argument(s)
1666            xil_printf("Command argument 0: 0x%08x\n", arg_0);
1667
1668            // If necessary, disable interrupts before processing the command
1669            //  Interrupts must be disabled if the command implementation relies on any state that might
1670            //  change during an interrupt service routine. See the user guide for more details
1671            //  https://warpproject.org/trac/wiki/802.11/wlan_exp/Extending
1672            curr_interrupt_state = wlan_platform_intc_stop();
1673
1674            // Process command arguments and generate any response payload
1675            //     NOTE:  If interrupts were disabled above, take care to avoid any long-running code in this
1676            //         block (i.e. avoid xil_printf()). When interrupts are disabled, CPU High is unable to
1677            //         respond to CPU Low (ie CPU High will not send / receive packets) and execute scheduled
1678            //         tasks, such as LTGs.
1679
1680            // Re-enable interrupts before returning (only do this if wlan_platform_intc_stop() is called above)
1681            wlan_platform_intc_set_state(curr_interrupt_state);
1682
1683            // Send response
1684            //   NOTE:  It is good practice to send a status as the first argument of the response.
1685            //       This way it is easy to determine if the other data in the response is valid.
1686            //       Predefined status values are:  CMD_PARAM_SUCCESS, CMD_PARAM_ERROR
1687            //
1688            wlan_exp_add_u32_resp_arg(eth_tx_queue_buffer, resp_hdr, status);
1689        }
1690        break;
1691#endif
1692
1693
1694        //---------------------------------------------------------------------
1695        default: {
1696            wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_node, "Unknown IBSS user command: 0x%x\n", cmd_id);
1697        }
1698        break;
1699    }
1700
1701    return resp_sent;
1702}
1703
1704#endif
1705
Note: See TracBrowser for help on using the repository browser.