1f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum/*
2f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * Copyright 2017, The Android Open Source Project
3f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum *
4f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * Licensed under the Apache License, Version 2.0 (the "License");
5f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * you may not use this file except in compliance with the License.
6f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * You may obtain a copy of the License at
7f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum *
8f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum *     http://www.apache.org/licenses/LICENSE-2.0
9f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum *
10f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * Unless required by applicable law or agreed to in writing, software
11f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * distributed under the License is distributed on an "AS IS" BASIS,
12f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * See the License for the specific language governing permissions and
14f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * limitations under the License.
15f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum */
16f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
17f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumpackage com.android.commands.lowpan;
18f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
1967a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaumimport android.net.LinkAddress;
20f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.ILowpanInterface;
21f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanBeaconInfo;
22f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanCredential;
23f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanEnergyScanResult;
24f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanException;
25f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanIdentity;
26f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanInterface;
27f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanManager;
28f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanProvision;
29f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanScanner;
30f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.os.RemoteException;
31f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.os.ServiceSpecificException;
32f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.util.AndroidRuntimeException;
33f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport com.android.internal.os.BaseCommand;
34f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport com.android.internal.util.HexDump;
35f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport java.io.PrintStream;
36f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport java.util.HashMap;
37f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport java.util.Map;
38f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport java.util.concurrent.Semaphore;
39f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport java.util.concurrent.TimeUnit;
40f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
41f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumpublic class LowpanCtl extends BaseCommand {
42f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private LowpanManager mLowpanManager;
43f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private LowpanInterface mLowpanInterface;
44f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private ILowpanInterface mILowpanInterface;
45f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private String mLowpanInterfaceName;
46f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
47f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    /**
48f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum     * Command-line entry point.
49f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum     *
50f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum     * @param args The command-line arguments
51f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum     */
52f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    public static void main(String[] args) {
53f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        new LowpanCtl().run(args);
54f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
55f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
56f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    @Override
57f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    public void onShowUsage(PrintStream out) {
58f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        out.println(
59f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                "usage: lowpanctl [options] [subcommand] [subcommand-options]\n"
6041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "options:\n"
6141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       -I / --interface <iface-name> ..... Interface Name\n"
6241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "subcommands:\n"
63f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        + "       lowpanctl status\n"
64f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        + "       lowpanctl form\n"
65f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        + "       lowpanctl join\n"
6641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       lowpanctl attach\n"
67f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        + "       lowpanctl leave\n"
6841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       lowpanctl enable\n"
6941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       lowpanctl disable\n"
7041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       lowpanctl show-credential\n"
71f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        + "       lowpanctl scan\n"
72f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        + "       lowpanctl reset\n"
73f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        + "       lowpanctl list\n"
7441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "\n"
7541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "usage: lowpanctl [options] join/form/attach [network-name]\n"
7641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "subcommand-options:\n"
7741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       --name <network-name> ............. Network Name\n"
7841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       -p / --panid <panid> .............. PANID\n"
7941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       -c / --channel <channel> .......... Channel Index\n"
8041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       -x / --xpanid <xpanid> ............ XPANID\n"
8141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       -k / --master-key <master-key> .... Master Key\n"
8241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       --master-key-index <key-index> .... Key Index\n"
8341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "\n"
8441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "usage: lowpanctl [options] show-credential\n"
8541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "subcommand-options:\n"
8641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                        + "       -r / --raw ........................ Print only key contents\n"
87f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        + "\n");
88f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
89f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
90f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private class CommandErrorException extends AndroidRuntimeException {
91f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        public CommandErrorException(String desc) {
92f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            super(desc);
93f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
94f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
95f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
9667a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum    private class ArgumentErrorException extends IllegalArgumentException {
9767a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum        public ArgumentErrorException(String desc) {
9867a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            super(desc);
9967a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum        }
10067a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum    }
10167a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum
102f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private void throwCommandError(String desc) {
103f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        throw new CommandErrorException(desc);
104f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
105f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
10667a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum    private void throwArgumentError(String desc) {
10767a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum        throw new ArgumentErrorException(desc);
10867a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum    }
10967a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum
11067a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum    private LowpanManager getLowpanManager() {
11167a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum        if (mLowpanManager == null) {
11267a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            mLowpanManager = LowpanManager.getManager();
11367a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum
11467a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            if (mLowpanManager == null) {
11567a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                System.err.println(NO_SYSTEM_ERROR_CODE);
11667a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                throwCommandError("Can't connect to LoWPAN service; is the service running?");
11767a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            }
11867a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum        }
11967a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum        return mLowpanManager;
12067a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum    }
12167a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum
122f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private LowpanInterface getLowpanInterface() {
123f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        if (mLowpanInterface == null) {
124f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            if (mLowpanInterfaceName == null) {
12567a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                String interfaceArray[] = getLowpanManager().getInterfaceList();
126f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                if (interfaceArray.length != 0) {
127f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    mLowpanInterfaceName = interfaceArray[0];
128f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else {
129f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    throwCommandError("No LoWPAN interfaces are present");
130f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                }
131f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            }
13267a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            mLowpanInterface = getLowpanManager().getInterface(mLowpanInterfaceName);
133f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
134f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            if (mLowpanInterface == null) {
135f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                throwCommandError("Unknown LoWPAN interface \"" + mLowpanInterfaceName + "\"");
136f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            }
137f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
138f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        return mLowpanInterface;
139f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
140f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
141f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private ILowpanInterface getILowpanInterface() {
142f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        if (mILowpanInterface == null) {
143f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            mILowpanInterface = getLowpanInterface().getService();
144f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
145f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        return mILowpanInterface;
146f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
147f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
148f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    @Override
149f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    public void onRun() throws Exception {
150f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        try {
151f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            String op;
152f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            while ((op = nextArgRequired()) != null) {
153f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                if (op.equals("-I") || op.equals("--interface")) {
154f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    mLowpanInterfaceName = nextArgRequired();
15567a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                } else if (op.equals("-h") || op.equals("--help") || op.equals("help")) {
15667a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                    onShowUsage(System.out);
15767a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                    break;
158f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else if (op.startsWith("-")) {
15967a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                    throwArgumentError("Unrecognized argument \"" + op + "\"");
160f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else if (op.equals("status") || op.equals("stat")) {
161f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    runStatus();
162f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
163f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else if (op.equals("scan") || op.equals("netscan") || op.equals("ns")) {
164f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    runNetScan();
165f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
16641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                } else if (op.equals("attach")) {
167f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    runAttach();
168f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
16941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                } else if (op.equals("enable")) {
17041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                    runEnable();
17141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                    break;
17241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                } else if (op.equals("disable")) {
17341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                    runDisable();
17441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                    break;
17541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                } else if (op.equals("show-credential")) {
17641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                    runShowCredential();
177f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
178f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else if (op.equals("join")) {
179f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    runJoin();
180f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
181f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else if (op.equals("form")) {
182f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    runForm();
183f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
184f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else if (op.equals("leave")) {
185f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    runLeave();
186f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
187f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else if (op.equals("energyscan") || op.equals("energy") || op.equals("es")) {
188f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    runEnergyScan();
189f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
190f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else if (op.equals("list") || op.equals("ls")) {
191f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    runListInterfaces();
192f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
193f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else if (op.equals("reset")) {
194f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    runReset();
195f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
196f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                } else {
19767a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                    throwArgumentError("Unrecognized argument \"" + op + "\"");
198f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    break;
199f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                }
200f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            }
201f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        } catch (ServiceSpecificException x) {
202f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            System.out.println(
203f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    "ServiceSpecificException: " + x.errorCode + ": " + x.getLocalizedMessage());
20467a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            throw x;
20567a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum
20667a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum        } catch (ArgumentErrorException x) {
20767a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            // Rethrow so we get syntax help.
20867a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            throw x;
20967a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum
21067a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum        } catch (IllegalArgumentException x) {
21167a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            // This was an argument exception that wasn't an
21267a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            // argument error. We dump our stack trace immediately
21367a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            // because this might not be from a command line argument.
21467a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            x.printStackTrace(System.err);
21567a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            System.exit(1);
21667a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum
217f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        } catch (CommandErrorException x) {
21867a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            // Command errors are normal errors that just
21967a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            // get printed out without any fanfare.
220f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            System.out.println("error: " + x.getLocalizedMessage());
22167a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            System.exit(1);
222f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
223f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
224f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
225f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private void runReset() throws LowpanException {
226f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        getLowpanInterface().reset();
227f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
228f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
22941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum    private void runEnable() throws LowpanException {
23041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        getLowpanInterface().setEnabled(true);
23141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum    }
23241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum
23341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum    private void runDisable() throws LowpanException {
23441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        getLowpanInterface().setEnabled(false);
23541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum    }
23641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum
237f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private LowpanProvision getProvisionFromArgs(boolean credentialRequired) {
238f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        LowpanProvision.Builder builder = new LowpanProvision.Builder();
239f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        Map<String, Object> properties = new HashMap();
240f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        LowpanIdentity.Builder identityBuilder = new LowpanIdentity.Builder();
241f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        LowpanCredential credential = null;
242f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        String arg;
243f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        byte[] masterKey = null;
244f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        int masterKeyIndex = 0;
245f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        boolean hasName = false;
246f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
247f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        while ((arg = nextArg()) != null) {
248f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            if (arg.equals("--name")) {
249f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                identityBuilder.setName(nextArgRequired());
250f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                hasName = true;
251f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            } else if (arg.equals("-p") || arg.equals("--panid")) {
252f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                identityBuilder.setPanid(Integer.decode(nextArgRequired()));
253f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            } else if (arg.equals("-c") || arg.equals("--channel")) {
254f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                identityBuilder.setChannel(Integer.decode(nextArgRequired()));
255f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            } else if (arg.equals("-x") || arg.equals("--xpanid")) {
256f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                identityBuilder.setXpanid(HexDump.hexStringToByteArray(nextArgRequired()));
257f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            } else if (arg.equals("-k") || arg.equals("--master-key")) {
258f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                masterKey = HexDump.hexStringToByteArray(nextArgRequired());
259f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            } else if (arg.equals("--master-key-index")) {
260f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                masterKeyIndex = Integer.decode(nextArgRequired());
261f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            } else if (arg.startsWith("-") || hasName) {
26267a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                throwArgumentError("Unrecognized argument \"" + arg + "\"");
263f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            } else {
264f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                // This is the network name
265f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                identityBuilder.setName(arg);
266f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                hasName = true;
267f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            }
268f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
269f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
270f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        if (credential == null && masterKey != null) {
271f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            if (masterKeyIndex == 0) {
272f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                credential = LowpanCredential.createMasterKey(masterKey);
273f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            } else {
274f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                credential = LowpanCredential.createMasterKey(masterKey, masterKeyIndex);
275f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            }
276f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
277f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
278f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        if (credential != null) {
279f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            builder.setLowpanCredential(credential);
280f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        } else if (credentialRequired) {
28167a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            throwArgumentError("No credential (like a master key) was specified!");
282f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
283f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
284f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        return builder.setLowpanIdentity(identityBuilder.build()).build();
285f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
286f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
287f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private void runAttach() throws LowpanException {
288f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        LowpanProvision provision = getProvisionFromArgs(true);
289f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
290f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        System.out.println(
291f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                "Attaching to " + provision.getLowpanIdentity() + " with provided credential");
292f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
293f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        getLowpanInterface().attach(provision);
294f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
295f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        System.out.println("Attached.");
296f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
297f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
298f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private void runLeave() throws LowpanException {
299f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        getLowpanInterface().leave();
300f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
301f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
302f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private void runJoin() throws LowpanException {
303f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        LowpanProvision provision = getProvisionFromArgs(true);
304f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
305f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        System.out.println(
306f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                "Joining " + provision.getLowpanIdentity() + " with provided credential");
307f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
308f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        getLowpanInterface().join(provision);
309f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
310f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        System.out.println("Joined.");
311f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
312f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
313f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private void runForm() throws LowpanException {
314f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        LowpanProvision provision = getProvisionFromArgs(false);
315f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
316f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        if (provision.getLowpanCredential() != null) {
317f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            System.out.println(
31867a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                    "Forming " + provision.getLowpanIdentity() + " with provided credential");
319f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        } else {
32041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum            System.out.println("Forming " + provision.getLowpanIdentity());
321f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
322f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
323f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        getLowpanInterface().form(provision);
324f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
325f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        System.out.println("Formed.");
326f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
327f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
32841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum    private void runStatus() throws LowpanException, RemoteException {
32941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        LowpanInterface iface = getLowpanInterface();
33041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        StringBuffer sb = new StringBuffer();
33141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum
33241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        sb.append(iface.getName())
33341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                .append("\t")
334ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                .append(iface.getState());
33541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum
336ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum        if (!iface.isEnabled()) {
337ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum            sb.append(" DISABLED");
338f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
339ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum        } else if (iface.getState() != LowpanInterface.STATE_FAULT) {
340ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum            sb.append(" (" + iface.getRole() + ")");
341f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
342ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum            if (iface.isUp()) {
343ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                sb.append(" UP");
344ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum            }
345ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum
346ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum            if (iface.isConnected()) {
347ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                sb.append(" CONNECTED");
348ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum            }
34941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum
350ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum            if (iface.isCommissioned()) {
351ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                sb.append(" COMMISSIONED");
35241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum
353ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                LowpanIdentity identity = getLowpanInterface().getLowpanIdentity();
354ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum
355ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                if (identity != null) {
356ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                    sb.append("\n\t").append(identity);
357ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                }
358ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum            }
359ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum
360ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum            if (iface.isUp()) {
361ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                for (LinkAddress addr : iface.getLinkAddresses()) {
362ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                    sb.append("\n\t").append(addr);
363ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum                }
364ece938e2a9aff18b430634dea15240f410001b53Robert Quattlebaum            }
36541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        }
36641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum
36741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        sb.append("\n");
36841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        System.out.println(sb.toString());
369f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
370f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
37141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum    private void runShowCredential() throws LowpanException, RemoteException {
37241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        LowpanInterface iface = getLowpanInterface();
37341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        boolean raw = false;
37441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        String arg;
37541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        while ((arg = nextArg()) != null) {
37641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum            if (arg.equals("--raw") || arg.equals("-r")) {
37741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum                raw = true;
37841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum            } else {
37967a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                throwArgumentError("Unrecognized argument \"" + arg + "\"");
380f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            }
381f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
38241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum
38341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        LowpanCredential credential = iface.getLowpanCredential();
38441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        if (raw) {
38541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum            System.out.println(HexDump.toHexString(credential.getMasterKey()));
38641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        } else {
38767a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum            System.out.println(iface.getName() + "\t" + credential.toSensitiveString());
38841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum        }
389f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
390f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
391f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private void runListInterfaces() {
39267a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum        for (String name : getLowpanManager().getInterfaceList()) {
393f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            System.out.println(name);
394f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
395f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
396f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
397f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private void runNetScan() throws LowpanException, InterruptedException {
398f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        LowpanScanner scanner = getLowpanInterface().createScanner();
399f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        String arg;
400f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
401f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        while ((arg = nextArg()) != null) {
402f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            if (arg.equals("-c") || arg.equals("--channel")) {
403f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                scanner.addChannel(Integer.decode(nextArgRequired()));
404f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            } else {
40567a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                throwArgumentError("Unrecognized argument \"" + arg + "\"");
406f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            }
407f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
408f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
409f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        Semaphore semaphore = new Semaphore(1);
410f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
411f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        scanner.setCallback(
412f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                new LowpanScanner.Callback() {
413f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    @Override
414f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    public void onNetScanBeacon(LowpanBeaconInfo beacon) {
415f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        System.out.println(beacon.toString());
416f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    }
417f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
418f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    @Override
419f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    public void onScanFinished() {
420f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        semaphore.release();
421f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    }
422f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                });
423f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
424f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        semaphore.acquire();
425f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        scanner.startNetScan();
426f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
427f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        // Wait for our scan to complete.
428f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        if (semaphore.tryAcquire(1, 60L, TimeUnit.SECONDS)) {
429f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            semaphore.release();
430f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        } else {
431f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            throwCommandError("Timeout while waiting for scan to complete.");
432f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
433f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
434f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
435f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    private void runEnergyScan() throws LowpanException, InterruptedException {
436f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        LowpanScanner scanner = getLowpanInterface().createScanner();
437f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        String arg;
438f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
439f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        while ((arg = nextArg()) != null) {
440f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            if (arg.equals("-c") || arg.equals("--channel")) {
441f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                scanner.addChannel(Integer.decode(nextArgRequired()));
442f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            } else {
44367a620c6f11669ba8509eccec6ebff301f1fc985Robert Quattlebaum                throwArgumentError("Unrecognized argument \"" + arg + "\"");
444f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            }
445f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
446f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
447f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        Semaphore semaphore = new Semaphore(1);
448f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
449f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        scanner.setCallback(
450f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                new LowpanScanner.Callback() {
451f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    @Override
452f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    public void onEnergyScanResult(LowpanEnergyScanResult result) {
453f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        System.out.println(result.toString());
454f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    }
455f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
456f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    @Override
457f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    public void onScanFinished() {
458f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                        semaphore.release();
459f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                    }
460f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum                });
461f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
462f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        semaphore.acquire();
463f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        scanner.startEnergyScan();
464f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum
465f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        // Wait for our scan to complete.
466f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        if (semaphore.tryAcquire(1, 60L, TimeUnit.SECONDS)) {
467f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            semaphore.release();
468f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        } else {
469f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum            throwCommandError("Timeout while waiting for scan to complete.");
470f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum        }
471f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum    }
472f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum}
473