takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mac_commands.cpp Source File

mac_commands.cpp

00001 /*
00002  * Copyright (c) 2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #include "mac_commands.h"
00018 
00019 //Need to disable filtering until mac_filter_api.h in mbed-os is updated
00020 #define DISABLE_FILTERING
00021 
00022 #define TRACE_GROUP "MAC"
00023 
00024 #define MAN_MAC_START   "start <options> --- Starts a PAN\n"\
00025                         "   --pan_id <value>                PAN id in hex, default: 0x1234\n"\
00026                         "   --logical_channel <value>       Operated logical channel, default: 11 (0-26)\n"\
00027                         "   --channel_page <value>          Operated channel page, default: 0 (0-2)\n"\
00028                         "   --start_time <value>            Time at which to start sending beacons\n"\
00029                         "                                   default: 0\n"\
00030                         "   --beacon_order <value>          How often are beacons transmitted\n"\
00031                         "                                   default: 15 (0-15, 15 = never)\n"\
00032                         "   --super_frame_order <value>     Length of the superframe's active portion\n"\
00033                         "                                   if beacon_order is 15, this option is ignored\n"\
00034                         "                                   default: 15 (0-15)\n"\
00035                         "   --pan_coordinator <bool>        Is this device the PAN coordinator?\n"\
00036                         "                                   default: true\n"\
00037                         "   --battery_life_extension <bool> Disable beaconing device periodically\n"\
00038                         "                                   to save power? default: false\n"\
00039                         "   --coord_realignment <bool>      If true, coordinator realignment command\n"\
00040                         "                                   is sent prior to changing\n"\
00041                         "                                   the superframe configuration default: false\n"
00042 
00043 #define MAN_MAC_SCAN    "scan <options> --- Perform a scan\n"\
00044                         "   --scan_type <value>         What type of scan to perform, 0=ED, 1=active\n"\
00045                         "                               2=passive, 3=orphan, default: 1\n"\
00046                         "   --channel_page_enum <value> default: 0 (0-10)\n"\
00047                         "   --channel_mask <value>      Bitmap of the channels on which to perform\n"\
00048                         "                               the scan, lower 27-bits are used\n"\
00049                         "                               bit 0 corresponds to channel 0 and so forth\n"\
00050                         "                               default: 0x07FFF800 (channels 11-26)\n"\
00051                         "   --scan_duration <value>     How long to spend in each channel,\n"\
00052                         "                               aBaseSuperFrameDuration * (2^n + 1) symbols\n"\
00053                         "                               default: 5 (0-14)\n"\
00054                         "   --channel_page <value>      The channel page on which to perform the scan\n"\
00055                         "                               default: 0 (0-31)\n"\
00056                         MAN_MAC_SECURITY
00057 
00058 #define MAN_MAC_DATA    "data <options> --- Send arbitrary data\n"\
00059                         "   --src_addr_mode <value>     Source addressing mode, 0=no address, 1=reserved\n"\
00060                         "                               2=16-bit address, 3=64-bit address\n"\
00061                         "                               default: 3 (0-3)\n"\
00062                         "   --dst_addr_mode <value>     Destination addressing mode, same as above\n"\
00063                         "                               default: 3 (0-3)\n"\
00064                         "   --dst_pan_id <value>        Destination PAN id in hex\n"\
00065                         "                               default: 0x1234 (0x0-0xFFFF)\n"\
00066                         "   --dst_addr <bytes>          Destination address, default: 00:00:00:...\n"\
00067                         "   --msdu_length <value>       Length of the data to send, default: 0 (0-255)\n"\
00068                         "   --msdu <text>               Data to transmit, default: <NULL>\n"\
00069                         "   --msdu_handle <value>       Handle of this MSDU, default: 0 (0-255)\n"\
00070                         "   --tx_ack_req <bool>         Is ack required for this transmission?\n"\
00071                         "                               default: true\n"\
00072                         "   --indirect_tx <bool>        Transmit indirectly? default: false\n"\
00073                         "   --pending_bit <bool>        Specifies whether more fragments (higher layer)\n"\
00074                         "                               are to be sent, default: false\n"\
00075                         "   --wait_for_confirm <bool>   Should we block further commands until we have\n"\
00076                         "                               received a data confirmation, default: true\n"\
00077                         MAN_MAC_SECURITY
00078 
00079 #define MAN_MAC_POLL    "poll <options> --- Poll the coordinator for data\n"\
00080                         "   --coord_addr_mode <value>   Coordinator addressing mode, 2=16-bit address\n"\
00081                         "                               3=64-bit address, default: 3 (2-3)\n"\
00082                         "   --coord_pan_id <value>      Coordinator PAN id in hex\n"\
00083                         "                               default: 0x1234 (0x0-0xFFFF)\n"\
00084                         "   --coord_address <bytes>     Coordinator address, default 00:00:00:...\n"\
00085                         MAN_MAC_SECURITY
00086 
00087 #define MAN_MAC_PURGE   "purge <options> --- Remove a transmission from the queue\n"\
00088                         "   --msdu_handle <value>       Handle of the MSDU to be removed\n"\
00089                         "                               default: 0 (0-255)\n"\
00090 
00091 #define MAN_MAC_SET     "mlme-set <options> --- Set a specified PIB attribute\n"\
00092                         "   --attr <value>              ID of the attribute to set in hex (0x0-0xFF)\n"\
00093                         "   --attr_index <0-255>        Index of the attribute, default: 0 (0-255)\n"\
00094                         "   --value_ascii <text>        Specify the set value as an ASCII string\n"\
00095                         "   --value_bytes <bytes>       Value as a string of bytes\n"\
00096                         "   --value_uint8/16/32 <value> Value as a uint8, uint16, or uint32\n"\
00097                         "                               Max value for uint32 is the max value for int32\n"\
00098                         "   --value_size <value>        Size of the value in bytes (0-255)\n"
00099 
00100 #define MAN_MAC_GET     "mlme-get <options> --- Get a specified PIB attribute\n"\
00101                         "   --attr <value>          ID of the attribute we want to get in hex (0x0-0xFF)\n"\
00102                         "   --attr_index <value>    Index of the attribute, default: 0 (0-255)\n"
00103 
00104 #define MAN_MAC_RESET   "mlme-reset --- Reset the MAC sublayer\n"\
00105                         "   --set_default_pib <bool>    When set to true, PIB attributes are set to\n"\
00106                         "                               their default values\n"\
00107                         "                               If set to false, PIB attributes retain\n"\
00108                         "                               their values, default: true\n"
00109 
00110 #define MAN_MAC_ADDR    "addr <options> --- Configure 16/64-bit MAC addresses\n"\
00111                         "                   having no options will display the addresses\n"\
00112                         "   --16-bit <value>    16-bit MAC address in hex (0x0-0xFFFF)\n"\
00113                         "   --64-bit <bytes>    64-bit MAC address\n"
00114 
00115 #define MAN_MAC_SECURITY    "   --security_level <value>    0=no security, 1=MIC32, 2=MIC64, 3=MIC128,\n"\
00116                             "                               4=ENC, 5=ENC+MIC32, 6=ENC+MIC64, 7=ENC+MIC128\n"\
00117                             "                               default: 0\n"\
00118                             "   --key_id_mode <value>       0=implicit, 1=default key source\n"\
00119                             "                               2=2-byte key source\n"\
00120                             "                               3=8-byte key source, default: 0 (0-3)\n"\
00121                             "   --key_index <value>         Which key to use, default: 0 (0-255)\n"\
00122                             "   --key_source <AA:BB...>     The originator of the key to be used\n"
00123 
00124 #define MAN_MAC_KEY "key <cmd> <options> --- Configure or add key descriptors\n"\
00125                     "config --- Configure parameters for key descriptor\n"\
00126                     "   --key <bytes>                           Actual security key, 16 bytes\n"\
00127                     "                                           default: C0:C1:C2:...:CF\n"\
00128                     "   --key_id_lookup_list_entries <value>    Amount of entries in the key's lookup\n"\
00129                     "   --key_device_list_entries <value>       ...device...\n"\
00130                     "   --key_usage_list_entries <value>        and usage list, default: 2 (0-255)\n"\
00131                     "   --lookup_index <value>                  Which entry of the lookup list\n"\
00132                     "                                           are we accessing? default: 0 (0-255)\n"\
00133                     "   --lookup_data <bytes>                   The lookup data for this key\n"\
00134                     "                                           length is 9 bytes regardless of\n"\
00135                     "                                           the next option\n"\
00136                     "   --lookup_data_size <value>              How large is the lookup data? (0-1)\n"\
00137                     "                                           0=5 bytes, 1=9 bytes\n"\
00138                     "   --device_list_index <value>             Which entry of the device list\n"\
00139                     "                                           are we accessing, default: 0 (0-255)\n"\
00140                     "   --device_descriptor_handle <value>      Which entry in our neighbour table\n"\
00141                     "                                           do we want to use this key with\n"\
00142                     "                                           default: 0 (0-255)\n"\
00143                     "   --unique_device <bool>                  Is the device unique to the key?\n"\
00144                     "   --blacklisted <bool>                    Is the device blacklisted?\n"\
00145                     "   --usage_list_index <value>              Which entry of the usage list\n"\
00146                     "                                           are we accessing, default: 0 (0-255)\n"\
00147                     "   --frame_type <value>                    What type of frame do we want to\n"\
00148                     "                                           use this key with? (0-3)\n"\
00149                     "                                           0=beacon, 1=data, 2=ACK, 3=command\n"\
00150                     "   --command_frame_identifier <value>      Type of the command frame (1-9)\n"\
00151                     "                                           1=association request\n"\
00152                     "                                           2=association response\n"\
00153                     "                                           3=disassociation notification\n"\
00154                     "                                           4=data request\n"\
00155                     "                                           5=PAN id conflict notification\n"\
00156                     "                                           6=orphan notification\n"\
00157                     "                                           7=beacon request\n"\
00158                     "                                           8=coordinator realigment\n"\
00159                     "                                           9=GTS request\n"\
00160                     "add --- Add the key into the key descriptor table\n"\
00161                     "   --index <value>                         Index in the key table (0-255)\n"
00162 
00163 #define MAN_MAC_ADD_NEIGHBOUR   "add-neigh <options> --- Add an entry to the neighbour table\n"\
00164                                 "   --frame_ctr <value>     Frame counter for this neighbour\n"\
00165                                 "   --mac16 <value>         16-bit MAC address in hex (0x0-0xFFFF)\n"\
00166                                 "   --mac64 <bytes>         64-bit MAC address\n"\
00167                                 "   --pan_id <value>        PAN id (0x0-0xFFFF)\n"\
00168                                 "   --index <value>         Index in the neighbour table (0-255)\n"
00169 
00170 #define MAN_MAC_FILTER  "filter <cmd> <options> --- Configure MAC layer filtering\n"\
00171                         "start --- Start a generic filter in blacklist, whitelist or fixed mode\n"\
00172                         "   --mode <value>              Set the filtering mode, values: allow|block|fixed\n"\
00173                         "       --lqi_m <value>         LQI multiplier (fixed mode only)\n"\
00174                         "       --dbm_m <value>         dBm multiplier (fixed mode only)\n"\
00175                         "add --- Add a filter by manually supplying values, or using a preset mode\n"\
00176                         "   --lqi_m <value>             LQI multiplier\n"\
00177                         "   --lqi_add <value>           Value added to the LQI\n"\
00178                         "   --dbm_m <value>             dBm multiplier\n"\
00179                         "   --dbm_add <value>           Value added to the dBm\n"\
00180                         "   --mode <value>              Filtering mode, values: allow|block|fixed\n"\
00181                         "   --short <value>             16-bit address in hex to filter (0x0-0xFFFF)\n"\
00182                         "   --long <bytes>              64-bit address as bytes to filter\n"\
00183                         "remove --- Remove a filter\n"\
00184                         "   --short <value>             16-bit address to remove from filter (0x0-0xFFFF)\n"\
00185                         "   --long <bytes>              64-bit address to remove from filter\n"\
00186                         "clear --- Clear all filters excluding the default one\n"\
00187                         "stop --- Stop filtering completely\n"\
00188 
00189 #define MAN_MAC_CONFIG_STATUS   "config-status <options> --- Configure expected status codes\n"\
00190                                 "                            having no options will display configured statuses\n"\
00191                                 "                            default: 0 (MLME_SUCCESS) for all\n"\
00192                                 "   --data_conf <value>     MCPS-DATA.confirm (0-255)\n"\
00193                                 "   --data_ind <text>       MCPS-DATA.indication (0-255)\n"\
00194                                 "   --get <value>           MLME-GET.confirm (0-255)\n"\
00195                                 "   --scan <value>          MLME-SCAN.confirm (0-255)\n"\
00196                                 "   --poll <value>          MLME-POLL.confirm (0-255)\n"\
00197                                 "   --purge <value>         MCPS-PURGE.confirm (0-255)\n"\
00198                                 "   --comm_status <value>   MLME-COMM-STATUS.indication (0-255)\n"\
00199                                 "   --list                  List all statuses\n"\
00200                                 "   --reset                 Reset all statuses to default values\n"
00201 
00202 #define MAN_MAC_FIND_BEACON     "find-beacon <options> --- Search for a PAN in the\n"\
00203                                 "                          results of the last scan\n"\
00204                                 "   --data <text>   Beacon data transmitted in the beacon\n"
00205 
00206 #define MAN_MAC_WAIT    "wait <options> --- Wait for data sent directly for a\n"\
00207                         "                   specified amount of milliseconds\n"\
00208                         "   --timeout <value>   Milliseconds to wait, default: 1000\n"
00209 
00210 #define MAN_MAC_ED_ANALYZE  "analyze-ed <options --- Analyze the results of the last ED scan\n"\
00211                             "   --channel <value>   Channel to analyze (11-26)\n"\
00212                             "   --above <value>     Check if the ED value is above a given value\n"\
00213                             "   --below <value>     Check if the ED value is below a given value\n"
00214 
00215 #define MAN_RESET   "reset <options> --- Reset MCPS and MLME structures to default values\n"
00216 
00217 #define MAN_SILENT  "silent-mode <on/off> --- When enabled, doesn't print extended information\n"\
00218                     "                         of MCPS/MLME primitives\n"
00219 
00220 mac_api_s *mac_interface = NULL;
00221 static bool wait_for_confirm = true;
00222 static bool silent_mode = false;
00223 static volatile unsigned int data_count = 0;
00224 
00225 static mlme_start_t start_req = {
00226     0x1234, /*PANId*/
00227     11,     /*LogicalChannel*/
00228     0,      /*ChannelPage*/
00229     0,      /*StartTime*/
00230     15,     /*BeaconOrder*/
00231     15,     /*SuperframeOrder*/
00232     true,   /*PANCoordinator*/
00233     false,  /*BatteryLifeExtension*/
00234     false,  /*CoordRealignment*/
00235 };
00236 
00237 static mlme_scan_t scan_req = {
00238     MAC_ACTIVE_SCAN,    /*ScanType*/
00239     {
00240         CHANNEL_PAGE_0, /*channel_page (enum)*/
00241         0x07FFF800      /*channel_mask*/
00242     },
00243     5,  /*ScanDuration*/
00244     0,  /*ChannelPage*/
00245     {
00246         0,  /*SecurityLevel*/
00247         0,  /*KeyIdMode*/
00248         0,  /*KeyIndex*/
00249         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}    /*Keysource*/
00250     }
00251 };
00252 
00253 static mcps_data_req_t data_req = {
00254     3,      /*SrcAddrMode*/
00255     3,      /*DstAddrMode*/
00256     0x1234, /*DstPANId*/
00257     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},       /*DstAddr*/
00258     0,      /*msduLength*/
00259     NULL,   /*msdu*/
00260     0,      /*msduHandle*/
00261     true,   /*TxAckReq*/
00262     false,  /*IndirectTx*/
00263     false,  /*PendingBit*/
00264     false,  /*SeqNumSuppressed*/
00265     false,  /*PanIdSuppressed*/
00266     {
00267         0,  /*SecurityLevel*/
00268         0,  /*KeyIdMode*/
00269         0,  /*KeyIndex*/
00270         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}    /*Keysource*/
00271     }
00272 };
00273 
00274 static mlme_poll_t poll_req = {
00275     3,      /*CoordAddrMode*/
00276     0x1234, /*CoordPANId*/
00277     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},       /*CoordAddress*/
00278     {
00279         0,  /*SecurityLevel*/
00280         0,  /*KeyIdMode*/
00281         0,  /*KeyIndex*/
00282         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}    /*Keysource*/
00283     }
00284 };
00285 
00286 static mcps_purge_t purge_req = {
00287     0   /*msduHandle*/
00288 };
00289 
00290 static mlme_set_t set_req = {
00291     (mlme_attr_t)0x39,  /*attr*/
00292     0,                  /*attr_index*/
00293     NULL,               /*value_pointer*/
00294     0                   /*value_size*/
00295 };
00296 
00297 static mlme_get_t get_req = {
00298     (mlme_attr_t)0x39,  /*attr*/
00299     0                   /*attr_index*/
00300 };
00301 
00302 static mlme_reset_t reset_req = {
00303     true    /*SetDefaultPIB*/
00304 };
00305 
00306 static mlme_key_id_lookup_descriptor_t lookup_descriptors[LOOKUP_DESCRIPTOR_TABLE_SIZE];
00307 static mlme_key_device_descriptor_t device_descriptors[DEVICE_DESCRIPTOR_TABLE_SIZE];
00308 static mlme_key_usage_descriptor_t usage_descriptors[USAGE_DESCRIPTOR_TABLE_SIZE];
00309 static mlme_key_descriptor_entry_t key_descriptor = {
00310     lookup_descriptors,             /*KeyIdLookupList*/
00311     LOOKUP_DESCRIPTOR_TABLE_SIZE,   /*KeyIdLookupListEntries*/
00312     device_descriptors,             /*KeyDeviceList*/
00313     DEVICE_DESCRIPTOR_TABLE_SIZE,   /*KeyDeviceListEntries*/
00314     usage_descriptors,              /*KeyUsageList*/
00315     USAGE_DESCRIPTOR_TABLE_SIZE,    /*KeyUsageListEntries*/
00316     {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF} /*Key*/
00317 };
00318 
00319 struct status_list_t {
00320     uint8_t data_conf;
00321     uint8_t get_conf;
00322     uint8_t scan_conf;
00323     uint8_t poll_conf;
00324     uint8_t purge_conf;
00325     uint8_t comm_status_ind;
00326     uint8_t data_ind_len;
00327     uint8_t *data_ind;
00328 };
00329 
00330 static struct status_list_t expected_statuses = {
00331     MLME_SUCCESS,
00332     MLME_SUCCESS,
00333     MLME_SUCCESS,
00334     MLME_SUCCESS,
00335     MLME_SUCCESS,
00336     MLME_SUCCESS,
00337     0,
00338     NULL
00339 };
00340 
00341 struct beacon_list_t {
00342     size_t count;
00343     char *beacons[MLME_MAC_RES_SIZE_MAX];
00344     uint8_t beacon_lengths[MLME_MAC_RES_SIZE_MAX];
00345 };
00346 
00347 static struct beacon_list_t received_beacons = {};
00348 
00349 struct ed_scan_result_list_t {
00350     uint8_t count;
00351     uint8_t channel[MLME_MAC_RES_SIZE_MAX];
00352     uint8_t ED_values[MLME_MAC_RES_SIZE_MAX];
00353 };
00354 
00355 static struct ed_scan_result_list_t last_ed_results;
00356 
00357 static void print_security(const mlme_security_t *key)
00358 {
00359     if (key->SecurityLevel > 0) {
00360         cmd_printf("Key.SecurityLevel:  %u\n", key->SecurityLevel);
00361         cmd_printf("Key.KeyIdMode:      %u\n", key->KeyIdMode);
00362         cmd_printf("Key.KeyIndex:       %hhu\n", key->KeyIndex);
00363         cmd_printf("Key.Keysource       %s\n", trace_array(key->Keysource, 8));
00364     }
00365 }
00366 
00367 static void print_PAN_descriptor(const mlme_pan_descriptor_t *desc)
00368 {
00369     cmd_printf("PANDescriptor.CoordAddrMode:    %u\n", desc->CoordAddrMode);
00370     cmd_printf("PANDescriptor.CoordPANId:       0x%04X\n", desc->CoordPANId);
00371     cmd_printf("PANDescriptor.CoordAddress:     %s\n", trace_array(desc->CoordAddress, 8));
00372     cmd_printf("PANDescriptor.LogicalChannel:   %hhu\n", desc->LogicalChannel);
00373     cmd_printf("PANDescriptor.ChannelPage:      %hhu\n", desc->ChannelPage);
00374     cmd_printf("PANDescriptor.SuperframeSpec:   %02x:%02x\n", desc->SuperframeSpec[0], desc->SuperframeSpec[1]);
00375     cmd_printf("PANDescriptor.GTSPermit:        %s\n", desc->GTSPermit ? "true" : "false");
00376     cmd_printf("PANDescriptor.LinkQuality:      %hhu\n", desc->LinkQuality);
00377     cmd_printf("PANDescriptor.Timestamp:        %lu\n", desc->Timestamp);
00378     cmd_printf("PANDescriptor.SecurityFailure:  %hhu\n", desc->SecurityFailure);
00379     print_security(&desc->Key);
00380 }
00381 
00382 static int handle_security_args(int argc, char *argv[], mlme_security_t *key)
00383 {
00384     char *str;
00385     int32_t val;
00386 
00387     if (cmd_parameter_int(argc, argv, "--security_level", &val)) {
00388         if (val >= 0 && val <= 7) {
00389             key->SecurityLevel = val;
00390         } else {
00391             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00392         }
00393     }
00394     if (cmd_parameter_int(argc, argv, "--key_id_mode", &val)) {
00395         if (val >= 0 && val <= 3) {
00396             key->KeyIdMode = val;
00397         } else {
00398             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00399         }
00400     }
00401     if (cmd_parameter_int(argc, argv, "--key_index", &val)) {
00402         if (val >= 0 && val <= 255) {
00403             key->KeyIndex = val;
00404         } else {
00405             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00406         }
00407     }
00408     if (cmd_parameter_val(argc, argv, "--key_source", &str)) {
00409         if (strlen(str) == 2*8+7) {
00410             if (string_to_bytes(str, key->Keysource, 8) != 0) {
00411                 return CMDLINE_RETCODE_INVALID_PARAMETERS;
00412             }
00413         } else {
00414             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00415         }
00416     }
00417     return CMDLINE_RETCODE_SUCCESS;
00418 }
00419 
00420 static void add_beacon(const uint8_t *beacon, uint8_t len)
00421 {
00422     if (received_beacons.count >= MLME_MAC_RES_SIZE_MAX) {
00423         tr_warn("List of received beacons is full. Discarding %s <%.*s>", trace_array(beacon, len), len, beacon);
00424         return;
00425     }
00426     unsigned int cur_beacon = received_beacons.count;
00427     received_beacons.beacon_lengths[cur_beacon] = len;
00428     received_beacons.beacons[cur_beacon] = (char*)ns_dyn_mem_temporary_alloc(len <= 75 ? 75:len);
00429     if (len != 0) {
00430         std::memcpy(received_beacons.beacons[cur_beacon], beacon, len);
00431     }
00432     ++received_beacons.count;
00433 }
00434 
00435 static void clear_beacons(void)
00436 {
00437     for (unsigned int i = 0; i < received_beacons.count; ++i) {
00438         ns_dyn_mem_free(received_beacons.beacons[i]);
00439         received_beacons.beacons[i] = NULL;
00440         received_beacons.beacon_lengths[i] = 0;
00441     }
00442     received_beacons.count = 0;
00443 }
00444 
00445 void mac_commands_init(void)
00446 {
00447     cmd_add("start", mac_start_command, "Start a PAN", MAN_MAC_START);
00448     cmd_add("scan", mac_scan_command, "Perform a scan", MAN_MAC_SCAN);
00449     cmd_add("data", mac_data_command, "Send data", MAN_MAC_DATA);
00450     cmd_add("poll", mac_poll_command, "Poll for data", MAN_MAC_POLL);
00451     cmd_add("purge", mac_purge_command, "Purge data from the transmission queue", MAN_MAC_PURGE);
00452     cmd_add("mlme-set", mac_set_command, "Writes a given value to the PIB attribute", MAN_MAC_SET);
00453     cmd_add("mlme-get", mac_get_command, "Gets the value of a given PIB attribute", MAN_MAC_GET);
00454     cmd_add("mlme-reset", mac_reset_command, "Resets the MAC sublayer to default values", MAN_MAC_RESET);
00455     cmd_add("addr", mac_address_command, "Configure MAC addresses", MAN_MAC_ADDR);
00456     cmd_add("key", mac_key_command, "Configure or add security keys", MAN_MAC_KEY);
00457     cmd_add("add-neigh", mac_add_neighbour_command, "Add a device to the neighbour table", MAN_MAC_ADD_NEIGHBOUR);
00458     cmd_add("filter", mac_filter_command, "Add or remove filters based on MAC addresses", MAN_MAC_FILTER);
00459     cmd_add("config-status", mac_config_status_command, "Set expected return statuses for confirmations and indications", MAN_MAC_CONFIG_STATUS);
00460     cmd_add("find-beacon", mac_find_beacon_command, "Find a PAN by beacon data", MAN_MAC_FIND_BEACON);
00461     cmd_add("wait", mac_wait_command, "Wait for data", MAN_MAC_WAIT);
00462     cmd_add("analyze-ed", mac_analyze_ed_command, "Analyze the results of the last ED scan", MAN_MAC_ED_ANALYZE);
00463     cmd_add("reset", reset_command, "Reset MCPS/MLME structures to default values", MAN_RESET);
00464     cmd_add("silent-mode", silent_mode_command, "Stop printing fields of MCPS/MLME structures", MAN_SILENT);
00465 }
00466 
00467 void mac_data_confirm_handler(const mac_api_t *api, const mcps_data_conf_t *data)
00468 {
00469     cmd_printf("MCPS-DATA.confirm\n");
00470     if (!silent_mode) {
00471         cmd_printf("msduHandle: %hhu\n", data->msduHandle);
00472         cmd_printf("status:     %hhu (%s)\n", data->status, mlme_status_string(data->status));
00473         cmd_printf("timestamp:  %lu\n", data->timestamp);
00474         cmd_printf("cca_retries:%hhu\n", data->cca_retries);
00475         cmd_printf("tx_retries: %hhu\n", data->tx_retries);
00476     }
00477     if (data->status == expected_statuses.data_conf) {
00478         cmd_ready(CMDLINE_RETCODE_SUCCESS);
00479     } else {
00480         cmd_ready(CMDLINE_RETCODE_FAIL);
00481     }
00482 }
00483 
00484 void mac_data_indication_handler(const mac_api_t *api, const mcps_data_ind_t *data)
00485 {
00486     cmd_printf("MCPS-DATA.indication\n");
00487     if (!silent_mode) {
00488         cmd_printf("SrcAddrMode:    %u\n", data->SrcAddrMode);
00489         cmd_printf("SrcPANId:       0x%04X\n", data->SrcPANId);
00490         cmd_printf("SrcAddr:        %s\n", trace_array(data->SrcAddr, 8));
00491         cmd_printf("DstAddrMode:    %u\n", data->DstAddrMode);
00492         cmd_printf("DstPANId:       0x%04X\n", data->DstPANId);
00493         cmd_printf("DstAddr:        %s\n", trace_array(data->DstAddr, 8));
00494         cmd_printf("mpduLinkQuality:%hhu\n", data->mpduLinkQuality);
00495         cmd_printf("signal_dbm:     %hhi\n", data->signal_dbm);
00496         cmd_printf("timestamp:      %lu\n", data->timestamp);
00497         cmd_printf("DSN:            %hhi\n", data->DSN);
00498         print_security(&data->Key);
00499         cmd_printf("msduLength      %hu\n", data->msduLength);
00500         cmd_printf("msdu_ptr:       %s <%.*s>\n", trace_array(data->msdu_ptr, data->msduLength), data->msduLength, data->msdu_ptr);
00501     }
00502     if (data->msdu_ptr && expected_statuses.data_ind) {
00503         if (data->msduLength != expected_statuses.data_ind_len) {
00504             return;
00505         }
00506         if (strncmp((const char*)data->msdu_ptr, (const char*)expected_statuses.data_ind, expected_statuses.data_ind_len) == 0) {
00507             ++data_count;
00508         } else {
00509             tr_warn("Received unexpected data!");
00510         }
00511     }
00512 }
00513 
00514 void mac_purge_confirm_handler(const mac_api_t *api, mcps_purge_conf_t *data)
00515 {
00516     cmd_printf("MCPS-PURGE.confirm\n");
00517     if (!silent_mode) {
00518         cmd_printf("msduHandle: %hhu\n", data->msduHandle);
00519         cmd_printf("status:     %hhu (%s)\n", data->status, mlme_status_string(data->status));
00520     }
00521     if (data->status == expected_statuses.purge_conf) {
00522         cmd_ready(CMDLINE_RETCODE_SUCCESS);
00523     } else {
00524         cmd_ready(CMDLINE_RETCODE_FAIL);
00525     }
00526 }
00527 
00528 void mac_mlme_confirm_handler(const mac_api_t *api, mlme_primitive id, const void *data)
00529 {
00530     switch (id) {
00531         case MLME_ASSOCIATE: {
00532             break;
00533         }
00534         case MLME_DISASSOCIATE: {
00535             break;
00536         }
00537         case MLME_GET: {
00538             mlme_get_conf_t *get_data = (mlme_get_conf_t*)data;
00539             cmd_printf("MLME-GET.confirm\n");
00540             if (!silent_mode) {
00541                 cmd_printf("status:         %hhu (%s)\n", get_data->status, mlme_status_string(get_data->status));
00542                 cmd_printf("attr:           %hhu\n", get_data->attr);
00543                 cmd_printf("attr_index:     %hhu\n", get_data->attr_index);
00544                 cmd_printf("value_pointer:  %s\n", trace_array((uint8_t*)get_data->value_pointer, get_data->value_size));
00545                 cmd_printf("value_size:     %hhu\n", get_data->value_size);
00546             }
00547             if (get_data->status == expected_statuses.get_conf) {
00548                 cmd_ready(CMDLINE_RETCODE_SUCCESS);
00549             } else {
00550                 cmd_ready(CMDLINE_RETCODE_FAIL);
00551             }
00552             break;
00553         }
00554         case MLME_GTS: {
00555             break;
00556         }
00557         case MLME_RESET: {
00558             break;
00559         }
00560         case MLME_RX_ENABLE: {
00561             break;
00562         }
00563         case MLME_SCAN: {
00564             mlme_scan_conf_t *scan_data = (mlme_scan_conf_t*)data;
00565             cmd_printf("MLME-SCAN.confirm\n");
00566             if (!silent_mode) {
00567                 cmd_printf("status:             %hhu (%s)\n", scan_data->status, mlme_status_string(scan_data->status));
00568                 cmd_printf("ScanType:           %u\n", scan_data->ScanType);
00569                 cmd_printf("ChannelPage:        %hhu\n", scan_data->ChannelPage);
00570                 cmd_printf("UnscannedChannels:  0x%08lX\n", scan_data->UnscannedChannels.channel_mask[0]);
00571                 cmd_printf("ResultListSize:     %hhu\n", scan_data->ResultListSize);
00572             }
00573             for (unsigned int i = 0; i < scan_data->ResultListSize; ++i) {
00574                 if (scan_data->ScanType == MAC_ED_SCAN_TYPE) {
00575                     cmd_printf("Channel %d ED value:  %hhu\n", channel_from_mask(scan_req.ScanChannels.channel_mask[0], i), scan_data->ED_values[i]);
00576                     memcpy(last_ed_results.ED_values, scan_data->ED_values, scan_data->ResultListSize);
00577                     last_ed_results.count = scan_data->ResultListSize;
00578                     for (int i = 0; i < scan_data->ResultListSize; ++i) {
00579                         last_ed_results.channel[i] = channel_from_mask(scan_req.ScanChannels.channel_mask[0], i);
00580                     }
00581                 } else if (scan_data->ScanType == MAC_PASSIVE_SCAN) {
00582                     print_PAN_descriptor(scan_data->PAN_values[i]);
00583                 }
00584             }
00585             if (scan_data->status == expected_statuses.scan_conf || scan_data->status == MLME_LIMIT_REACHED) {
00586                 cmd_ready(CMDLINE_RETCODE_SUCCESS);
00587             } else {
00588                 cmd_ready(CMDLINE_RETCODE_FAIL);
00589             }
00590             break;
00591         }
00592         case MLME_SET: {
00593             break;
00594         }
00595         case MLME_START: {
00596             break;
00597         }
00598         case MLME_POLL: {
00599             mlme_poll_conf_t *poll_data = (mlme_poll_conf_t*)data;
00600             cmd_printf("MLME-POLL.confirm\n");
00601             if (!silent_mode) {
00602                 cmd_printf("status:     %hhu (%s)\n", poll_data->status, mlme_status_string(poll_data->status));
00603                 cmd_printf("data_count  %u\n", data_count);
00604             }
00605             if (expected_statuses.poll_conf == MLME_SUCCESS) {
00606                 if (data_count == 1 && poll_data->status == MLME_SUCCESS) {
00607                     cmd_ready(CMDLINE_RETCODE_SUCCESS);
00608                 } else {
00609                     cmd_ready(CMDLINE_RETCODE_FAIL);
00610                 }
00611             } else if (expected_statuses.poll_conf == poll_data->status) {
00612                 cmd_ready(CMDLINE_RETCODE_SUCCESS);
00613             } else {
00614                 cmd_ready(CMDLINE_RETCODE_FAIL);
00615             }
00616             break;
00617         }
00618         default: {
00619             cmd_ready(CMDLINE_RETCODE_COMMAND_NOT_IMPLEMENTED);
00620             break;
00621         }
00622     }
00623 }
00624 
00625 void mac_mlme_indication_handler(const mac_api_t *api, mlme_primitive id, const void *data)
00626 {
00627     switch (id) {
00628         case MLME_ASSOCIATE: {
00629             break;
00630         }
00631         case MLME_DISASSOCIATE: {
00632             break;
00633         }
00634         case MLME_BEACON_NOTIFY: {
00635             const mlme_beacon_ind_t *beacon_ind = (mlme_beacon_ind_t*)data;
00636             cmd_printf("MLME-BEACON-NOTIFY.indication\n");
00637             if (!silent_mode) {
00638                 cmd_printf("BSN:                                %hhu\n", beacon_ind->BSN);
00639                 print_PAN_descriptor(&beacon_ind->PANDescriptor);
00640                 cmd_printf("PendAddrSpec.short_address_count    %u\n", beacon_ind->PendAddrSpec.short_address_count);
00641                 cmd_printf("PendAddrSpec.extended_address_count %u\n", beacon_ind->PendAddrSpec.extended_address_count);
00642                 cmd_printf("AddrList                            %s\n", trace_array(beacon_ind->AddrList, beacon_ind->PendAddrSpec.short_address_count * 2 +
00643                                                                                                               beacon_ind->PendAddrSpec.extended_address_count * 8));
00644                 cmd_printf("beacon_data_length                  %hu\n", beacon_ind->beacon_data_length);
00645                 cmd_printf("beacon_data                         %s\n", trace_array(beacon_ind->beacon_data, beacon_ind->beacon_data_length));
00646             }
00647             add_beacon(beacon_ind->beacon_data, beacon_ind->beacon_data_length);
00648             break;
00649         }
00650         case MLME_GTS: {
00651             break;
00652         }
00653         case MLME_ORPHAN: {
00654             break;
00655         }
00656         case MLME_COMM_STATUS: {
00657             cmd_printf("MLME-COMM-STATUS.indication\n");
00658             const mlme_comm_status_t *comm_status_ind_data = (mlme_comm_status_t*)data;
00659             if (!silent_mode) {
00660                 cmd_printf("PANId:          0x%04X\n", comm_status_ind_data->PANId);
00661                 cmd_printf("SrcAddrMode:    %u\n", comm_status_ind_data->SrcAddrMode);
00662                 cmd_printf("SrcAddr:        %s\n", trace_array(comm_status_ind_data->SrcAddr, 8));
00663                 cmd_printf("DstAddrMode:    %u\n", comm_status_ind_data->DstAddrMode);
00664                 cmd_printf("DstAddr:        %s\n", trace_array(comm_status_ind_data->DstAddr, 8));
00665                 cmd_printf("status:         %hhu (%s)\n", comm_status_ind_data->status, mlme_status_string(comm_status_ind_data->status));
00666                 print_security(&comm_status_ind_data->Key);
00667             }
00668             break;
00669         }
00670         case MLME_SYNC_LOSS: {
00671             break;
00672         }
00673         default:
00674             break;
00675     }
00676 }
00677 
00678 int mac_start_command(int argc, char *argv[])
00679 {
00680     char *str;
00681     int32_t val;
00682     bool boolean;
00683 
00684     cmd_printf("MLME-START.request\n");
00685     if (cmd_parameter_val(argc, argv, "--pan_id", &str)) {
00686         uint32_t pan_id = strtoul(str, NULL, 16);
00687         if (pan_id <= 0xFFFF) {
00688             start_req.PANId = pan_id;
00689         } else {
00690             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00691         }
00692     }
00693     if (cmd_parameter_int(argc, argv, "--logical_channel", &val)) {
00694         if (val >= 0 && val <= 26) {
00695             start_req.LogicalChannel = val;
00696         } else {
00697             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00698         }
00699     }
00700     if (cmd_parameter_int(argc, argv, "--channel_page", &val)) {
00701         if (val >= 0 && val <= 2) {
00702             start_req.ChannelPage = val;
00703         } else {
00704             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00705         }
00706     }
00707     if (cmd_parameter_int(argc, argv, "--start_time", &val)) {
00708         start_req.StartTime = val;
00709     }
00710     if (cmd_parameter_int(argc, argv, "--beacon_order", &val)) {
00711         if (val >= 0 && val <= 15) {
00712             start_req.BeaconOrder = val;
00713         } else {
00714             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00715         }
00716     }
00717     if (cmd_parameter_int(argc, argv, "--super_frame_order", &val)) {
00718         if (val >= 0 && val <= 15) {
00719             start_req.SuperframeOrder = val;
00720         } else {
00721             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00722         }
00723     }
00724     if (cmd_parameter_bool(argc, argv, "--pan_coordinator", &boolean)) {
00725         start_req.PANCoordinator = boolean;
00726     }
00727     if (cmd_parameter_bool(argc, argv, "--battery_life_extension", &boolean)) {
00728         start_req.BatteryLifeExtension = boolean;
00729     }
00730     if (cmd_parameter_bool(argc, argv, "--coord_realignment", &boolean)) {
00731         start_req.CoordRealignment = boolean;
00732     }
00733     mac_interface->mlme_req(mac_interface, MLME_START, &start_req);
00734     return CMDLINE_RETCODE_SUCCESS;
00735 }
00736 
00737 int mac_scan_command(int argc, char *argv[])
00738 {
00739     char *str;
00740     int32_t val;
00741 
00742     cmd_printf("MLME-SCAN.request\n");
00743     if (cmd_parameter_int(argc, argv, "--scan_type", &val)) {
00744         if (val >= 0 && val <= 3) {
00745             scan_req.ScanType = (mac_scan_type_t)val;
00746         } else {
00747             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00748         }
00749     }
00750     if (cmd_parameter_int(argc, argv, "--channel_page_enum", &val)) {
00751         if (val >= 0 && val <= 10) {
00752             scan_req.ScanChannels.channel_page = (channel_page_e)val;
00753         } else {
00754             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00755         }
00756     }
00757     if (cmd_parameter_val(argc, argv, "--channel_mask", &str)) {
00758         scan_req.ScanChannels.channel_mask[0] = strtoul(str, NULL, 16);
00759     }
00760     if (cmd_parameter_int(argc, argv, "--scan_duration", &val)) {
00761         if (val >= 0 && val <= 14) {
00762             scan_req.ScanDuration = val;
00763         } else {
00764             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00765         }
00766     }
00767     if (cmd_parameter_int(argc, argv, "--channel_page", &val)) {
00768         if (val >= 0 && val <= 2) {
00769             scan_req.ChannelPage = val;
00770         } else {
00771             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00772         }
00773     }
00774     if (handle_security_args(argc, argv, &scan_req.Key) != CMDLINE_RETCODE_SUCCESS) {
00775         return CMDLINE_RETCODE_INVALID_PARAMETERS;
00776     }
00777     clear_beacons();
00778     mac_interface->mlme_req(mac_interface, MLME_SCAN, &scan_req);
00779     return CMDLINE_RETCODE_EXCUTING_CONTINUE;
00780 }
00781 
00782 int mac_data_command(int argc, char *argv[])
00783 {
00784     char *str;
00785     int32_t val;
00786     bool boolean;
00787 
00788     cmd_printf("MCPS-DATA.request\n");
00789     if (cmd_parameter_int(argc, argv, "--src_addr_mode", &val)) {
00790         if (val == 0 || val == 2 || val == 3) {
00791             data_req.SrcAddrMode = val;
00792         } else {
00793             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00794         }
00795     }
00796     if (cmd_parameter_int(argc, argv, "--dst_addr_mode", &val)) {
00797         if (val == 0 || val == 2 || val == 3) {
00798             data_req.DstAddrMode = val;
00799         } else {
00800             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00801         }
00802     }
00803     if (cmd_parameter_val(argc, argv, "--dst_pan_id", &str)) {
00804         uint32_t pan_id = strtoul(str, NULL, 16);
00805         if (pan_id <= 0xFFFF) {
00806             data_req.DstPANId = pan_id;
00807         } else {
00808             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00809         }
00810     }
00811     if (cmd_parameter_val(argc, argv, "--dst_addr", &str)) {
00812         int len = (data_req.DstAddrMode == 2 ? 2 : 8);
00813         if (string_to_bytes(str, data_req.DstAddr, len) != 0) {
00814             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00815         }
00816     }
00817     if (cmd_parameter_int(argc, argv, "--msdu_length", &val)) {
00818         data_req.msduLength = val;
00819     }
00820     if (cmd_parameter_val(argc, argv, "--msdu", &str)) {
00821         ns_dyn_mem_free(data_req.msdu);
00822         if (strlen(str) != data_req.msduLength) {
00823             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00824         }
00825         data_req.msdu = (uint8_t*)ns_dyn_mem_temporary_alloc(data_req.msduLength);
00826         if (data_req.msdu == NULL) {
00827             tr_error("Failed to allocate memory for the msdu");
00828             return CMDLINE_RETCODE_FAIL;
00829         }
00830         std::memcpy(data_req.msdu, str, data_req.msduLength);
00831     }
00832     if (cmd_parameter_int(argc, argv, "--msdu_handle", &val)) {
00833         if (val >= 0 && val <= 255) {
00834             data_req.msduHandle = val;
00835         }
00836     }
00837     if (cmd_parameter_bool(argc, argv, "--tx_ack_req", &boolean)) {
00838         data_req.TxAckReq = boolean;
00839     }
00840     if (cmd_parameter_bool(argc, argv, "--indirect_tx", &boolean)) {
00841         data_req.InDirectTx = boolean;
00842     }
00843     if (cmd_parameter_bool(argc, argv, "--pending_bit", &boolean)) {
00844         data_req.PendingBit = boolean;
00845     }
00846     if (cmd_parameter_bool(argc, argv, "--wait_for_confirm", &boolean)) {
00847         wait_for_confirm = boolean;
00848     }
00849     if (handle_security_args(argc, argv, &data_req.Key) != CMDLINE_RETCODE_SUCCESS) {
00850         return CMDLINE_RETCODE_INVALID_PARAMETERS;
00851     }
00852     mac_interface->mcps_data_req(mac_interface, &data_req);
00853     if (wait_for_confirm) {
00854         return CMDLINE_RETCODE_EXCUTING_CONTINUE;
00855     }
00856     return CMDLINE_RETCODE_SUCCESS;
00857 }
00858 
00859 int mac_poll_command(int argc, char *argv[])
00860 {
00861     char *str;
00862     int32_t val;
00863 
00864     cmd_printf("MLME-POLL.request\n");
00865     data_count = 0;
00866     if (cmd_parameter_int(argc, argv, "--coord_addr_mode", &val)) {
00867         if (val == 2 || val == 3) {
00868             poll_req.CoordAddrMode = val;
00869         } else {
00870             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00871         }
00872     }
00873     if (cmd_parameter_val(argc, argv, "--coord_pan_id", &str)) {
00874         unsigned long pan_id = strtoul(str, NULL, 16);
00875         if (pan_id <= 0xFFFF) {
00876             poll_req.CoordPANId = pan_id;
00877         } else {
00878             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00879         }
00880     }
00881     if (cmd_parameter_val(argc, argv, "--coord_address", &str)) {
00882         int len = (poll_req.CoordAddrMode == 2 ? 2: 8);
00883         if (string_to_bytes(str, poll_req.CoordAddress, len) != 0) {
00884             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00885         }
00886     }
00887     if (handle_security_args(argc, argv, &poll_req.Key) != CMDLINE_RETCODE_SUCCESS) {
00888         return CMDLINE_RETCODE_INVALID_PARAMETERS;
00889     }
00890     mac_interface->mlme_req(mac_interface, MLME_POLL, &poll_req);
00891     return CMDLINE_RETCODE_EXCUTING_CONTINUE;
00892 }
00893 
00894 int mac_purge_command(int argc, char *argv[])
00895 {
00896     int32_t val;
00897 
00898     cmd_printf("MCPS-PURGE.request\n");
00899     if (cmd_parameter_int(argc, argv, "--msdu_handle", &val)) {
00900         if (val >= 0 && val <= 255) {
00901             purge_req.msduHandle = val;
00902         } else {
00903             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00904         }
00905     }
00906     mac_interface->mcps_purge_req(mac_interface, &purge_req);
00907     return CMDLINE_RETCODE_EXCUTING_CONTINUE;
00908 }
00909 
00910 int mac_set_command(int argc, char *argv[])
00911 {
00912     char *str;
00913     int32_t val;
00914     uint8_t val_uint8 = 0;
00915     uint16_t val_uint16 = 0;
00916     uint32_t val_uint32 = 0;
00917     uint8_t *val_ptr_array = NULL;
00918     
00919     cmd_printf("MLME-SET.request\n");
00920     if (cmd_parameter_val(argc, argv, "--attr", &str)) {
00921         uint32_t attribute = strtoul(str, NULL, 16);
00922         if (attribute <= 255) {
00923             set_req.attr = (mlme_attr_t)attribute;
00924         } else {
00925             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00926         }
00927     }
00928     if (cmd_parameter_int(argc, argv, "--attr_index", &val)) {
00929         if (val >= 0 && val <= 255) {
00930             set_req.attr_index = val;
00931         } else {
00932             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00933         }
00934     }
00935     if (cmd_parameter_val(argc, argv, "--value_ascii", &str)) {
00936         val_ptr_array = (uint8_t*)ns_dyn_mem_temporary_alloc(strlen(str));
00937         if (val_ptr_array == NULL) {
00938             tr_error("Failed to allocate memory for MLME-SET.request");
00939             return CMDLINE_RETCODE_FAIL;
00940         }
00941         std::memcpy(val_ptr_array, str, strlen(str));
00942         set_req.value_pointer = val_ptr_array;
00943     } else if (cmd_parameter_val(argc, argv, "--value_bytes", &str)) {
00944         size_t bytes = (strlen(str) + 1) / 3;
00945         val_ptr_array = (uint8_t*)ns_dyn_mem_temporary_alloc(bytes);
00946         if (val_ptr_array == NULL) {
00947             tr_error("Failed to allocate memory for MLME-SET.request");
00948             return CMDLINE_RETCODE_FAIL;
00949         }
00950         if (string_to_bytes(str, val_ptr_array, bytes) != 0) {
00951             ns_dyn_mem_free(val_ptr_array);
00952             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00953         }
00954         set_req.value_pointer = val_ptr_array;
00955     } else if (cmd_parameter_int(argc, argv, "--value_uint8", &val)) {
00956         if (val >= 0 && val <= 0xFF) {
00957             val_uint8 = val;
00958             set_req.value_pointer = &val_uint8;
00959         } else {
00960             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00961         }
00962     } else if (cmd_parameter_int(argc, argv, "--value_uint16", &val)) {
00963         if (val >= 0 && val <= 0xFFFF) {
00964             val_uint16 = val;
00965             set_req.value_pointer = &val_uint16;
00966         } else {
00967             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00968         }
00969     } else if (cmd_parameter_int(argc, argv, "--value_uint32", &val)) {
00970         if (val >= 0 && val <= 0x7FFFFFFF) {
00971             val_uint32 = val;
00972             set_req.value_pointer = &val_uint32;
00973         } else {
00974             return CMDLINE_RETCODE_INVALID_PARAMETERS;
00975         }
00976     }
00977     if (cmd_parameter_int(argc, argv, "--value_size", &val)) {
00978         if (val >= 0 && val <= 255) {
00979             set_req.value_size = val;
00980         }
00981     }
00982 
00983     mac_interface->mlme_req(mac_interface, MLME_SET, &set_req);
00984     ns_dyn_mem_free(val_ptr_array);
00985     set_req.value_pointer = NULL;
00986     return CMDLINE_RETCODE_SUCCESS;
00987 }
00988 
00989 int mac_get_command(int argc, char *argv[])
00990 {
00991     char *str;
00992     int32_t val;
00993 
00994     cmd_printf("MLME-GET.request\n");
00995     if (cmd_parameter_val(argc, argv, "--attr", &str)) {
00996         uint32_t attribute = strtoul(str, NULL, 16);
00997         if (attribute <= 255) {
00998             get_req.attr = (mlme_attr_t)attribute;
00999         } else {
01000             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01001         }
01002     }
01003     if (cmd_parameter_int(argc, argv, "--attr_index", &val)) {
01004         if (val >= 0 && val <= 255) {
01005             get_req.attr_index = val;
01006         } else {
01007             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01008         }
01009     }
01010     mac_interface->mlme_req(mac_interface, MLME_GET, &get_req);
01011     return CMDLINE_RETCODE_SUCCESS;
01012 }
01013 
01014 int mac_reset_command(int argc, char *argv[])
01015 {
01016     bool boolean;
01017 
01018     cmd_printf("MLME-RESET.request\n");
01019     if (cmd_parameter_bool(argc, argv, "--set_default_pib", &boolean)) {
01020         reset_req.SetDefaultPIB = boolean;
01021     }
01022     mac_interface->mlme_req(mac_interface, MLME_RESET, &reset_req);
01023     return CMDLINE_RETCODE_SUCCESS;
01024 }
01025 
01026 int mac_address_command(int argc, char *argv[])
01027 {
01028     char *str;
01029     uint8_t ext_addr[8];
01030 
01031     if (cmd_parameter_val(argc, argv, "--64-bit", &str)) {
01032         if (string_to_bytes(str, ext_addr, 8) != 0) {
01033             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01034         }
01035         mac_interface->mac64_set(mac_interface, ext_addr);
01036         cmd_printf("64-bit MAC address set to: %s\n", trace_array(ext_addr, 8));
01037     } else if (cmd_parameter_val(argc, argv, "--16-bit", &str)) {
01038         uint32_t short_addr_32 = strtoul(str, NULL,  16);
01039         if (short_addr_32 <= 0xFFFF) {
01040             uint16_t short_addr = short_addr_32;
01041             mlme_set_t set_req;
01042             set_req.attr = macShortAddress;
01043             set_req.value_pointer = &short_addr;
01044             set_req.value_size = 2;
01045             mac_interface->mlme_req(mac_interface, MLME_SET, &set_req);
01046             cmd_printf("16-bit MAC address set to: 0x%04X\n", short_addr);
01047         } else {
01048             tr_warn("Invalid 16-bit MAC address given: %lu", short_addr_32);
01049         }
01050     } else if (argc == 1) {
01051         if (mac_interface->mac64_get(mac_interface, MAC_EXTENDED_READ_ONLY, ext_addr) == 0) {
01052             cmd_printf("EUI64: %s\n", trace_array(ext_addr, 8));
01053         } else {
01054             tr_warn("Failed to read EUI64");
01055             return CMDLINE_RETCODE_FAIL;
01056         }
01057         if (mac_interface->mac64_get(mac_interface, MAC_EXTENDED_DYNAMIC, ext_addr) == 0) {
01058             cmd_printf("MAC64: %s\n", trace_array(ext_addr, 8));
01059         } else {
01060             tr_warn("Failed to read MAC64");
01061             return CMDLINE_RETCODE_FAIL;
01062         }
01063     } else {
01064         return CMDLINE_RETCODE_INVALID_PARAMETERS;
01065     }
01066     return CMDLINE_RETCODE_SUCCESS;
01067 }
01068 
01069 static int key_config_command(int argc, char *argv[])
01070 {
01071     char *str;
01072     int32_t val;
01073     bool boolean;
01074     int lookup_index = 0, device_index = 0, usage_index = 0;
01075 
01076     if (cmd_parameter_val(argc, argv, "--key", &str)) {
01077         if (strlen(str) == 2*16+15) {
01078             if (string_to_bytes(str, key_descriptor.Key, 16) != 0) {
01079                 return CMDLINE_RETCODE_INVALID_PARAMETERS;
01080             }
01081         } else {
01082             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01083         }
01084     }
01085     if (cmd_parameter_int(argc, argv, "--key_id_lookup_list_entries", &val)) {
01086         if (val >= 0 && val < LOOKUP_DESCRIPTOR_TABLE_SIZE) {
01087             key_descriptor.KeyIdLookupListEntries = val;
01088         } else {
01089             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01090         }
01091     }
01092     if (cmd_parameter_int(argc, argv, "--key_device_list_entries", &val)) {
01093         if (val >= 0 && val < DEVICE_DESCRIPTOR_TABLE_SIZE) {
01094             key_descriptor.KeyDeviceListEntries = val;
01095         } else {
01096             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01097         }
01098     }
01099     if (cmd_parameter_int(argc, argv, "--key_usage_list_entries", &val)) {
01100         if (val >= 0 && val < USAGE_DESCRIPTOR_TABLE_SIZE) {
01101             key_descriptor.KeyUsageListEntries = val;
01102         } else {
01103             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01104         }
01105     }
01106     if (cmd_parameter_int(argc, argv, "--lookup_index", &val)) {
01107         if (val >= 0 && val < LOOKUP_DESCRIPTOR_TABLE_SIZE) {
01108             lookup_index = val;
01109         } else {
01110             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01111         }
01112     }
01113     if (cmd_parameter_val(argc, argv, "--lookup_data", &str)) {
01114         if (strlen(str) == 2*9+8) {
01115             if (string_to_bytes(str, key_descriptor.KeyIdLookupList[lookup_index].LookupData, 9) != 0) {
01116                 return CMDLINE_RETCODE_INVALID_PARAMETERS;
01117             }
01118         } else {
01119             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01120         }
01121     }
01122     if (cmd_parameter_int(argc, argv, "--lookup_data_size", &val)) {
01123         if (val == 0 || val == 1) {
01124             key_descriptor.KeyIdLookupList[lookup_index].LookupDataSize = val;
01125         } else {
01126             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01127         }
01128     }
01129     if (cmd_parameter_int(argc, argv, "--device_list_index", &val)) {
01130         if (val >= 0 && val < DEVICE_DESCRIPTOR_TABLE_SIZE) {
01131             device_index = val;
01132         } else {
01133             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01134         }
01135     }
01136     if (cmd_parameter_int(argc, argv, "--device_descriptor_handle", &val)) {
01137         if (val >= 0 && val <= 255) {
01138             key_descriptor.KeyDeviceList[device_index].DeviceDescriptorHandle = val;
01139         } else {
01140             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01141         }
01142     }
01143     if (cmd_parameter_bool(argc, argv, "--unique_device", &boolean)) {
01144         key_descriptor.KeyDeviceList[device_index].UniqueDevice = boolean;
01145     }
01146     if (cmd_parameter_bool(argc, argv, "--blacklisted", &boolean)) {
01147         key_descriptor.KeyDeviceList[device_index].Blacklisted = boolean;
01148     }
01149     if (cmd_parameter_int(argc, argv, "--usage_index", &val)) {
01150         if (val >= 0 && val <= USAGE_DESCRIPTOR_TABLE_SIZE) {
01151             usage_index = val;
01152         } else {
01153             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01154         }
01155     }
01156     if (cmd_parameter_int(argc, argv, "--frame_type", &val)) {
01157         if (val >= 0 && val <= 3) {
01158             key_descriptor.KeyUsageList[usage_index].FrameType = val;
01159         } else {
01160             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01161         }
01162     }
01163     if (key_descriptor.KeyUsageList[usage_index].FrameType == 3) {
01164         if (cmd_parameter_int(argc, argv, "--command_frame_identifier", &val)) {
01165             if (val >= 1 && val <= 9) {
01166                 key_descriptor.KeyUsageList[usage_index].CommandFrameIdentifier = val;
01167             } else {
01168                 return CMDLINE_RETCODE_INVALID_PARAMETERS;
01169             }
01170         }
01171     }
01172     return CMDLINE_RETCODE_SUCCESS;
01173 }
01174 
01175 static int key_add_command(int argc, char *argv[])
01176 {
01177     mlme_set_t set_req;
01178     int32_t val;
01179     int key_index = 0;
01180 
01181     if (cmd_parameter_int(argc, argv, "--index", &val)) {
01182         if (val >= 0 && val <= 255) {
01183             key_index = val;
01184         } else {
01185             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01186         }
01187     }
01188 
01189     set_req.attr = macKeyTable;
01190     set_req.attr_index = key_index;
01191     set_req.value_pointer = &key_descriptor;
01192     set_req.value_size = sizeof(mlme_key_descriptor_entry_t);
01193     mac_interface->mlme_req(mac_interface, MLME_SET, &set_req);
01194     return CMDLINE_RETCODE_SUCCESS;
01195 }
01196 
01197 int mac_key_command(int argc, char *argv[])
01198 {
01199     char *cmd = argv[1];
01200 
01201     if (strcmp(cmd, "config") == 0) {
01202         return key_config_command(argc, argv);
01203     } else if (strcmp(cmd, "add") == 0) {
01204         return key_add_command(argc, argv);
01205     }
01206     return CMDLINE_RETCODE_INVALID_PARAMETERS;
01207 }
01208 
01209 int mac_add_neighbour_command(int argc, char *argv[])
01210 {
01211     char *str;
01212     int32_t val;
01213     mlme_device_descriptor_t neighbour;
01214     mlme_set_t set_req;
01215 
01216     neighbour.Exempt = false;
01217     if (cmd_parameter_int(argc, argv, "--frame_ctr", &val)) {
01218         neighbour.FrameCounter = val;
01219     }
01220     if (cmd_parameter_val(argc, argv, "--mac16", &str)) {
01221         uint32_t short_addr = strtoul(str, NULL, 16);
01222         if (short_addr <= 0xFFFF) {
01223             neighbour.ShortAddress = short_addr;
01224         } else {
01225             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01226         }
01227     }
01228     if (cmd_parameter_val(argc, argv, "--mac64", &str)) {
01229         if (strlen(str) == 2*8+7) {
01230             if (string_to_bytes(str, neighbour.ExtAddress, 8) != 0) {
01231                 return CMDLINE_RETCODE_INVALID_PARAMETERS;
01232             }
01233         } else {
01234             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01235         }
01236     }
01237     if (cmd_parameter_val(argc, argv, "--pan_id", &str)) {
01238         uint32_t pan_id = strtoul(str, NULL, 16);
01239         if (pan_id <= 0xFFFF) {
01240             neighbour.PANId = val;
01241         } else {
01242             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01243         }
01244     }
01245     if (cmd_parameter_int(argc, argv, "--index", &val)) {
01246         if (val >= 0 && val <= 255) {
01247             set_req.attr_index = val;
01248         } else {
01249             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01250         }
01251     }
01252 
01253     set_req.attr = macDeviceTable;
01254     set_req.value_pointer = &neighbour;
01255     set_req.value_size = sizeof(mlme_device_descriptor_t);
01256     mac_interface->mlme_req(mac_interface, MLME_SET, &set_req);
01257     return CMDLINE_RETCODE_SUCCESS;
01258 }
01259 
01260 #ifndef DISABLE_FILTERING
01261 static int filter_start(int argc, char *argv[])
01262 {
01263     char *str;
01264 
01265     if (cmd_parameter_val(argc, argv, "--mode", &str)) {
01266         if (strcmp(str, "allow") == 0) {
01267             return mac_filter_start(mac_interface->parent_id, MAC_FILTER_ALLOWED) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS;
01268         } else if (strcmp(str, "block") == 0) {
01269             return mac_filter_start(mac_interface->parent_id, MAC_FILTER_BLOCKED) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS;;
01270         } else if (strcmp(str, "fixed") == 0) {
01271             int32_t lqi, dbm;
01272             if (cmd_parameter_int(argc, argv, "--lqi_m", &lqi) &&
01273                 cmd_parameter_int(argc, argv, "--dbm_m", &dbm)) {
01274                 return mac_filter_start(mac_interface->parent_id, MAC_FILTER_FIXED(lqi, dbm)) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS;
01275             }
01276         }
01277     }
01278     return CMDLINE_RETCODE_INVALID_PARAMETERS;
01279 }
01280 
01281 static int filter_add(int argc, char *argv[])
01282 {
01283     char *str;
01284     uint32_t short_addr;
01285     uint8_t long_addr[8];
01286     int32_t lqi_m, lqi_add, dbm_m, dbm_add;
01287 
01288     if (cmd_parameter_int(argc, argv, "--lqi_m", &lqi_m) &&
01289         cmd_parameter_int(argc, argv, "--lqi_add", &lqi_add) &&
01290         cmd_parameter_int(argc, argv, "--dbm_m", &dbm_m) &&
01291         cmd_parameter_int(argc, argv, "--dbm_add", &dbm_add)) {
01292     } else if (cmd_parameter_val(argc, argv, "--mode", &str)) {
01293         if (strcmp(str, "allow")) {
01294             lqi_m = dbm_m = 256;
01295             lqi_add = dbm_add = 0;
01296         } else if (strcmp(str, "block")) {
01297             lqi_m = lqi_add = dbm_m = dbm_add = 0;
01298         } else if (strcmp(str, "fixed")) {
01299             lqi_add = dbm_add = 0;
01300             if (cmd_parameter_int(argc, argv, "--lqi_m", &lqi_m) &&
01301                 cmd_parameter_int(argc, argv, "--dbm_m", &dbm_m)) {
01302             } else {
01303                 return CMDLINE_RETCODE_INVALID_PARAMETERS;
01304             }
01305         } else {
01306             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01307         }
01308     } else {
01309         return CMDLINE_RETCODE_INVALID_PARAMETERS;
01310     }
01311 
01312     if (cmd_parameter_val(argc, argv, "--short", &str)) {
01313         short_addr = strtoul(str, NULL, 16);
01314         if (short_addr <= 0xFFFF) {
01315             return mac_filter_add_short(mac_interface->parent_id, short_addr, lqi_m, lqi_add, dbm_m, dbm_add) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS;
01316         } else {
01317             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01318         }
01319     } else if (cmd_parameter_val(argc, argv, "--long", &str)) {
01320         if (string_to_bytes(str, long_addr, 8) != 0) {
01321             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01322         }
01323         return mac_filter_add_long(mac_interface->parent_id, long_addr, lqi_m, lqi_add, dbm_m, dbm_add) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS;
01324     } else {
01325         return CMDLINE_RETCODE_INVALID_PARAMETERS;
01326     }
01327 }
01328 
01329 static int filter_remove(int argc, char *argv[])
01330 {
01331     char *str;
01332     uint32_t short_addr;
01333     uint8_t long_addr[8];
01334 
01335     if (cmd_parameter_val(argc, argv, "--short", &str)) {
01336         short_addr = strtoul(str, NULL, 16);
01337         if (short_addr <= 0xFFFF) {
01338             return mac_filter_delete_short(mac_interface->parent_id, short_addr) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS;
01339         } else {
01340             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01341         }
01342     } else if (cmd_parameter_val(argc, argv, "--long", &str)) {
01343         if (string_to_bytes(str, long_addr, 8) != 0) {
01344             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01345         }
01346         return mac_filter_delete_long(mac_interface->parent_id, long_addr) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS;
01347     } else {
01348         return CMDLINE_RETCODE_INVALID_PARAMETERS;
01349     }
01350 }
01351 
01352 static int filter_clear(int argc, char *argv[])
01353 {
01354     return mac_filter_clear(mac_interface->parent_id) < 0 ? CMDLINE_RETCODE_FAIL : CMDLINE_RETCODE_SUCCESS;
01355 }
01356 
01357 static int filter_stop(int argc, char *argv[])
01358 {
01359     mac_filter_stop(mac_interface->parent_id);
01360     return CMDLINE_RETCODE_SUCCESS;
01361 }
01362 #else
01363 static int filter_start(int argc, char *argv[])
01364 {
01365     (void)argc;
01366     (void)argv;
01367     return 0;
01368 }
01369 
01370 static int filter_add(int argc, char *argv[])
01371 {
01372     (void)argc;
01373     (void)argv;
01374     return 0;
01375 }
01376 static int filter_remove(int argc, char *argv[])
01377 {
01378     (void)argc;
01379     (void)argv;
01380     return 0;
01381 }
01382 static int filter_clear(int argc, char *argv[])
01383 {
01384     (void)argc;
01385     (void)argv;
01386     return 0;
01387 }
01388 static int filter_stop(int argc, char *argv[])
01389 {
01390     (void)argc;
01391     (void)argv;
01392     return 0;
01393 }
01394 #endif
01395 int mac_filter_command(int argc, char *argv[])
01396 {
01397     char *cmd = argv[1];
01398 
01399     if (strcmp(cmd, "start") == 0) {
01400         return filter_start(argc, argv);
01401     } else if (strcmp(cmd, "add") == 0) {
01402         return filter_add(argc, argv);
01403     } else if (strcmp(cmd, "remove") == 0) {
01404         return filter_remove(argc, argv);
01405     } else if (strcmp(cmd, "clear") == 0) {
01406         return filter_clear(argc, argv);
01407     } else if (strcmp(cmd, "stop") == 0) {
01408         return filter_stop(argc, argv);
01409     }
01410     return CMDLINE_RETCODE_INVALID_PARAMETERS;
01411 }
01412 
01413 int mac_config_status_command(int argc, char *argv[])
01414 {
01415     int32_t val;
01416     char *str;
01417 
01418     if (cmd_parameter_int(argc, argv, "--data_conf", &val)) {
01419         if (val >= 0 && val <= 255) {
01420             expected_statuses.data_conf = val;
01421         } else {
01422             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01423         }
01424     } else if (cmd_parameter_val(argc, argv, "--data_ind", &str)) {
01425         size_t len = strlen(str);
01426         ns_dyn_mem_free(expected_statuses.data_ind);
01427         expected_statuses.data_ind = (uint8_t*)ns_dyn_mem_temporary_alloc(len);
01428         expected_statuses.data_ind_len = len;
01429         std::memcpy(expected_statuses.data_ind, str, len);
01430     } else if (cmd_parameter_int(argc, argv, "--get", &val)) {
01431         if (val >= 0 && val <= 255) {
01432             expected_statuses.get_conf = val;
01433         } else {
01434             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01435         }
01436     } else if (cmd_parameter_int(argc, argv, "--scan", &val)) {
01437         if (val >= 0 && val <= 255) {
01438             expected_statuses.scan_conf = val;
01439         } else {
01440             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01441         }
01442     } else if (cmd_parameter_int(argc, argv, "--poll", &val)) {
01443         if (val >= 0 && val <= 255) {
01444             expected_statuses.poll_conf = val;
01445         } else {
01446             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01447         }
01448     } else if (cmd_parameter_int(argc, argv, "--purge", &val)) {
01449         if (val >= 0 && val <= 255) {
01450             expected_statuses.purge_conf = val;
01451         } else {
01452             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01453         }
01454     } else if (cmd_parameter_int(argc, argv, "--comm_status", &val)) {
01455         if (val >= 0 && val <= 255) {
01456             expected_statuses.comm_status_ind = val;
01457         } else {
01458             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01459         }
01460     } else if (cmd_parameter_index(argc, argv, "--list") != -1) {
01461         for (unsigned int i = 0; i < 256; ++i) {
01462             const char *status = mlme_status_string(i);
01463             if (status) {
01464                 cmd_printf("%hhu\t%s\n", i, status);
01465             }
01466         }
01467     } else if (cmd_parameter_index(argc, argv, "--reset") != -1) {
01468         expected_statuses.data_conf = MLME_SUCCESS;
01469         expected_statuses.get_conf = MLME_SUCCESS;
01470         expected_statuses.scan_conf = MLME_SUCCESS;
01471         expected_statuses.poll_conf = MLME_SUCCESS;
01472         expected_statuses.purge_conf = MLME_SUCCESS;
01473         expected_statuses.comm_status_ind = MLME_SUCCESS;
01474         expected_statuses.data_ind_len = 0;
01475         expected_statuses.data_ind = NULL;
01476     } else if (argc == 1) {
01477         cmd_printf("MCPS-DATA.confirm:              %d (%s)\n", expected_statuses.data_conf, mlme_status_string(expected_statuses.data_conf));
01478         cmd_printf("MLME-GET.confirm:               %d (%s)\n", expected_statuses.get_conf, mlme_status_string(expected_statuses.get_conf));
01479         cmd_printf("MLME-SCAN.confirm:              %d (%s)\n", expected_statuses.scan_conf, mlme_status_string(expected_statuses.scan_conf));
01480         cmd_printf("MLME-POLL.confirm:              %d (%s)\n", expected_statuses.poll_conf, mlme_status_string(expected_statuses.poll_conf));
01481         cmd_printf("MCPS.PURGE.confirm.             %d (%s)\n", expected_statuses.purge_conf, mlme_status_string(expected_statuses.purge_conf));
01482         cmd_printf("MLME-COMM-STATUS.indication:    %d (%s)\n", expected_statuses.comm_status_ind, mlme_status_string(expected_statuses.comm_status_ind));
01483         cmd_printf("MCPS-DATA.indication:           %s <%.*s>\n", trace_array(expected_statuses.data_ind, expected_statuses.data_ind_len), expected_statuses.data_ind_len, expected_statuses.data_ind);
01484     } else {
01485         return CMDLINE_RETCODE_INVALID_PARAMETERS;
01486     }
01487     return CMDLINE_RETCODE_SUCCESS;
01488 }
01489 
01490 int mac_find_beacon_command(int argc, char *argv[])
01491 {
01492     char *str;
01493 
01494     if (cmd_parameter_val(argc, argv, "--data", &str)) {
01495         for (int i = 0; i < MLME_MAC_RES_SIZE_MAX; ++i) {
01496             if (received_beacons.beacons[i] == NULL) {
01497                 continue;
01498             }
01499             if (strncmp(received_beacons.beacons[i], str, received_beacons.beacon_lengths[i]) == 0) {
01500                 return CMDLINE_RETCODE_SUCCESS;
01501             }
01502         }
01503         return CMDLINE_RETCODE_FAIL;
01504     } else {
01505         return CMDLINE_RETCODE_INVALID_PARAMETERS;
01506     }
01507 }
01508 
01509 int mac_wait_command(int argc, char *argv[])
01510 {
01511     int32_t val;
01512     static uint32_t timeout_ms = 1000;
01513     int remaining_ms = timeout_ms;
01514     if (cmd_parameter_int(argc, argv, "--timeout", &val)) {
01515         if (val >= 0) {
01516             timeout_ms = val;
01517         } else {
01518             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01519         }
01520     }
01521     while (data_count < 1) {
01522         ThisThread::sleep_for(10);
01523         remaining_ms -= 10;
01524         if (remaining_ms <= 0) {
01525             return CMDLINE_RETCODE_FAIL;
01526         }
01527     }
01528     data_count = 0;
01529     return CMDLINE_RETCODE_SUCCESS;
01530 }
01531 
01532 int mac_analyze_ed_command(int argc, char *argv[])
01533 {
01534     int32_t val;
01535     int channel;
01536 
01537     if (cmd_parameter_int(argc, argv, "--channel", &val)) {
01538         if (val >= 0 && val <= 26) {
01539             channel = val;
01540         } else {
01541             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01542         }
01543     } else {
01544             return CMDLINE_RETCODE_INVALID_PARAMETERS;
01545     }
01546 
01547     if (cmd_parameter_int(argc, argv, "--above", &val)) {
01548         for (int i = 0; i < last_ed_results.count; ++i) {
01549             if (last_ed_results.channel[i] == channel) {
01550                 return last_ed_results.ED_values[i] >= val ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL;
01551             }
01552         }
01553     } else if (cmd_parameter_int(argc, argv, "--below", &val)) {
01554         for (int i = 0; i < last_ed_results.count; ++i) {
01555             if (last_ed_results.channel[i] == channel) {
01556                 return last_ed_results.ED_values[i] <= val ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL;
01557             }
01558         }
01559     } else {
01560         return CMDLINE_RETCODE_INVALID_PARAMETERS;
01561     }
01562     return CMDLINE_RETCODE_FAIL;
01563 }
01564 
01565 static void reset_security(mlme_security_t *sec)
01566 {
01567     sec->SecurityLevel = 0;
01568     sec->KeyIdMode = 0;
01569     sec->KeyIndex = 0;
01570     memset(sec->Keysource, 0, 8);
01571 }
01572 
01573 int reset_command(int argc, char *argv[])
01574 {
01575     wait_for_confirm = true;
01576     silent_mode = false;
01577     data_count = 0;
01578 
01579     start_req.PANId = 0x1234;
01580     start_req.LogicalChannel = 11;
01581     start_req.ChannelPage = 0;
01582     start_req.StartTime = 0;
01583     start_req.BeaconOrder = 15;
01584     start_req.SuperframeOrder = 15;
01585     start_req.PANCoordinator = true;
01586     start_req.BatteryLifeExtension = false;
01587     start_req.CoordRealignment = false;
01588     reset_security(&start_req.CoordRealignKey);
01589     reset_security(&start_req.BeaconRealignKey);
01590 
01591     scan_req.ScanType = MAC_ACTIVE_SCAN;
01592     scan_req.ScanChannels.channel_page = CHANNEL_PAGE_0;
01593     scan_req.ScanChannels.channel_mask[0] = 0x07FFF800;
01594     reset_security(&scan_req.Key);
01595 
01596     data_req.SrcAddrMode = 3;
01597     data_req.DstAddrMode = 3;
01598     data_req.DstPANId = 0x1234;
01599     memset(data_req.DstAddr, 0, 8);
01600     data_req.msduLength = 0;
01601     data_req.msdu = NULL;
01602     data_req.msduHandle = 0;
01603     data_req.TxAckReq = true;
01604     data_req.InDirectTx = false;
01605     data_req.PendingBit = false;
01606     reset_security(&data_req.Key);
01607 
01608     poll_req.CoordAddrMode = 3;
01609     poll_req.CoordPANId = 0x1234;
01610     memset(poll_req.CoordAddress, 0, 8);
01611     reset_security(&poll_req.Key);
01612 
01613     purge_req.msduHandle = 0;
01614 
01615     set_req.attr = (mlme_attr_t)0x39;
01616     set_req.attr_index = 0;
01617     set_req.value_pointer = NULL;
01618     set_req.value_size = 0;
01619 
01620     get_req.attr = (mlme_attr_t)0x39;
01621     get_req.attr_index = 0;
01622 
01623     reset_req.SetDefaultPIB = true;
01624 
01625     return CMDLINE_RETCODE_SUCCESS;
01626 }
01627 
01628 int silent_mode_command(int argc, char *argv[])
01629 {
01630     char *cmd;
01631     if (argc < 2) {
01632         return CMDLINE_RETCODE_FAIL;
01633     }
01634     cmd = argv[1];
01635     if (strcmp(cmd, "on") == 0) {
01636         silent_mode = true;
01637         return CMDLINE_RETCODE_SUCCESS;
01638     } else if (strcmp(cmd, "off") == 0) {
01639         silent_mode = false;
01640         return CMDLINE_RETCODE_SUCCESS;
01641     } else {
01642         return CMDLINE_RETCODE_INVALID_PARAMETERS;
01643     }
01644 }