Changes between Initial Version and Version 1 of 802.11/wlan_exp/HowToAddCommand


Ignore:
Timestamp:
Nov 25, 2015, 12:14:42 AM (8 years ago)
Author:
welsh
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • 802.11/wlan_exp/HowToAddCommand

    v1 v1  
     1{{{#!comment
     2[[Include(wiki:802.11/beta-note)]]
     3}}}
     4
     5[[TracNav(802.11/TOC)]]
     6
     7= WLAN Exp: How to add a Command =
     8
     9This tutorial will explain how to add a new command to the WLAN Exp framework.  This will allow a user to create a custom command that can be called via the WLAN Experiments Framework.
     10
     11
     12== 802.11 Reference Design v1.3 and prior ==
     13
     14'''Overview:'''
     15
     16  1. Edit wlan_exp/cmds.py with:
     17    - Create new non-overlapping CMDID_ value
     18    - Create new message.Cmd subclass, probably by copy/paste of existing simple command
     19    - Add new subclass to __all__
     20  1. Edit wlan_exp/node.py (or a subclass) with new command-specific node method
     21  1. Add new CMDID_ value to wlan_mac_high_framework/include/wlan_exp_node.h
     22  1. Edit wlan_mac_high_framework/wlan_exp_node.c with new case in giant node_processCmd() switch statement
     23  1. Possibly edit wlan_mac_[ap,sta,ibss].[c,h] for any MAC-specific responses to the new command
     24
     25
     26'''Edit wlan_exp/cmds.py:'''
     27
     28Add a new Command ID (CMDID_) value that does not overlap with any existing Command ID value.  For example, we can add "CMDID_NODE_USER_CMD" to the file:
     29
     30{{{
     31CMDID_NODE_WLAN_MAC_ADDR                         = 0x001018
     32CMDID_NODE_LOW_PARAM                             = 0x001020
     33CMDID_NODE_USER_INFO_CMD                         = 0x001030
     34
     35CMD_PARAM_WRITE                                  = 0x00000000
     36CMD_PARAM_READ                                   = 0x00000001
     37}}}
     38
     39
     40Create a new message.Cmd sub-class.  For example, this new class will take in an array of values and send them to the node.  It will also take any values returned by the node and return them to the user:
     41
     42{{{
     43class NodeUserInfoCommand(message.Cmd):
     44    """Command to pass user information to/from the node
     45   
     46    Attributes:
     47        values    -- Scalar or list of u32 values to pass to the node
     48
     49    """
     50    def __init__(self, values=None):
     51        super(NodeUserCommand, self).__init__()       
     52       
     53        self.command    = _CMD_GROUP_NODE + CMDID_NDOE_USER_INFO_CMD
     54
     55        # Caluculate the size in words of the values argument
     56        size = 0
     57       
     58        if values is not None:
     59            size += len(values)
     60
     61        # Add the size in words of the values arguments to the message
     62        self.add_args(size)
     63
     64        # Add the values to the message
     65        if values is not None:
     66            try:
     67                for v in values:
     68                    self.add_args(v)
     69            except TypeError:
     70                self.add_args(values)
     71           
     72    def process_resp(self, resp):
     73        """ Message format:
     74                respArgs32[0]   Status
     75                respArgs32[1]   Size in words of return values
     76                respArgs32[2:N] Values
     77        """
     78        # Create a hash of all possible error codes with respective error messages
     79        error_code_base         = CMD_PARAM_ERROR
     80
     81        status_errors = { error_code_base      : "Error Processing User Command" }
     82
     83        # Get the arguments from the response
     84        args = resp.get_args()
     85       
     86        # If the response is valid, then return the size and any values from the node
     87        if resp.resp_is_valid(num_args=(args[1] + 2), status_errors=status_errors, name='from User Command command'):
     88            return args[1:]
     89        else:
     90            return None
     91
     92# End Class
     93}}}
     94
     95
     96Add new subclass to __all__:
     97
     98
     99{{{
     100__all__ = [# Log command classes
     101           'LogGetEvents', 'LogConfigure', 'LogGetStatus', 'LogGetCapacity', 'LogAddExpInfoEntry',
     102           'LogAddCountsTxRx',
     103           # Counts command classes
     104           'CountsConfigure', 'CountsGetTxRx',
     105           # LTG classes
     106           'LTGConfigure', 'LTGStart', 'LTGStop', 'LTGRemove', 'LTGStatus',
     107           # Node command classes
     108           'NodeResetState', 'NodeConfigure', 'NodeProcWLANMACAddr', 'NodeProcTime',
     109           'NodeSetLowToHighFilter', 'NodeProcChannel', 'NodeProcRandomSeed', 'NodeLowParam', 'NodeUserInfoCommand',
     110...
     111}}}
     112
     113
     114'''Edit wlan_exp/node.py (or a subclass)'''
     115
     116Add new command specific method to the node (or a subclass):
     117
     118{{{
     119    def send_user_cmd(self, values=None):
     120        """Send information to / Receive information from a node
     121 
     122        Args:
     123            values (list of int): Value(s) to send to the node
     124           
     125        Returns:
     126            values (list of int): Value(s) received from the node
     127        """
     128        if values is not None:
     129            try:
     130                v0 = values[0]
     131            except TypeError:
     132                v0 = values
     133           
     134            if ((type(v0) is not int) and (type(v0) is not long)) or (v0 >= 2**32):
     135                raise Exception('ERROR: values must be scalar or iterable of ints in [0,2^32-1]!') 
     136               
     137        try:
     138            vals = list(values)
     139        except TypeError:
     140            vals = [values]
     141
     142        return self.send_cmd(cmds.NodeUserInfoCommand(values=vals))
     143}}}
     144
     145
     146'''Edit wlan_mac_high_framework/include/wlan_exp_node.h'''
     147
     148Add new Command ID (CMDID_) value to the C code.  This value should be the same as the CMDID_ value defined in the Python code:
     149
     150{{{
     151#define CMDID_NODE_WLAN_MAC_ADDR                           0x001018
     152#define CMDID_NODE_LOW_PARAM                               0x001020
     153#define CMDID_NODE_USER_INFO_CMD                           0x001030
     154
     155#define CMD_PARAM_WRITE_VAL                                0x00000000
     156#define CMD_PARAM_READ_VAL                                 0x00000001
     157}}}
     158
     159
     160'''Edit wlan_mac_high_framework/wlan_exp_node.c'''
     161
     162Add command implementation with new case in the node_processCmd() switch statement:
     163
     164{{{
     165        //---------------------------------------------------------------------
     166        case CMDID_NODE_USER_INFO_CMD:
     167            // Receive information from user / Send information to user
     168            //
     169            // Message format:
     170            //     cmd_args_32[0]    Size in words of received values
     171            //     cmd_args_32[1:N]  Values
     172            //
     173            // Response format:
     174            //     resp_args_32[0]    Status
     175            //     resp_args_32[1]    Size in words of values to send
     176            //     resp_args_32[3:M]  Values
     177            //
     178            status  = CMD_PARAM_SUCCESS;
     179            size    = Xil_Ntohl(cmd_args_32[0]);
     180            temp    = 0;
     181
     182            // Byte swap all the value words in the message (in place)
     183            for (i = 1; i < (size + 1); i++) {
     184                cmd_args_32[i] = Xil_Ntohl(cmd_args_32[i]);
     185            }
     186
     187
     188            //
     189            // ADD PROCESSING FOR COMMAND VALUES
     190            //
     191            // NOTE:  The user can define any message structure needed.  Modify the 'status' variable
     192            //     if there is an error (use CMD_PARAM_ERROR or any additional error codes the user adds).
     193            //     Modify the 'temp' variable to indicate the number of return values.  Additional
     194            //     variables can be declared at the beginning of the function.
     195            //
     196
     197            // In this example, the command merely echos the values sent to the node.
     198            //
     199            // NOTE:  Need to make sure the indexing is correct since the response values start at a different
     200            //     word than the received values.
     201            //
     202            for (i = 1; i < (size + 1); i++) {
     203                resp_args_32[i+1] = cmd_args_32[i];
     204            }
     205
     206
     207            // Send response
     208            resp_args_32[0] = Xil_Htonl(status);
     209            resp_args_32[1] = Xil_Htonl(temp);
     210
     211            // Byte swap all the value words in the return message (in place)
     212            for (i = 2; i < (temp + 2); i++) {
     213                resp_args_32[i] = Xil_Htonl(resp_args_32[i]);
     214            }
     215
     216            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
     217            resp_hdr->num_args = resp_index;
     218        break;
     219}}}
     220
     221
     222