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

Last change on this file since 6225 was 6225, checked in by chunter, 6 years ago

updated year in comments

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