wlan_dev/
opts.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use clap::{Parser, ValueEnum};
6use fidl_fuchsia_wlan_common::PowerSaveType;
7use {fidl_fuchsia_wlan_common as wlan_common, fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211};
8
9#[derive(ValueEnum, PartialEq, Copy, Clone, Debug)]
10pub enum RoleArg {
11    Client,
12    Ap,
13}
14
15#[derive(ValueEnum, PartialEq, Copy, Clone, Debug)]
16pub enum PhyArg {
17    Erp,
18    Ht,
19    Vht,
20}
21
22#[derive(ValueEnum, PartialEq, Copy, Clone, Debug)]
23pub enum CbwArg {
24    Cbw20,
25    Cbw40,
26    Cbw80,
27}
28
29#[derive(ValueEnum, PartialEq, Copy, Clone, Debug)]
30pub enum ScanTypeArg {
31    Active,
32    Passive,
33}
34
35#[derive(ValueEnum, PartialEq, Copy, Clone, Debug)]
36pub enum PsModeArg {
37    PsModeUltraLowPower,
38    PsModeLowPower,
39    PsModeBalanced,
40    PsModePerformance,
41}
42
43#[derive(ValueEnum, PartialEq, Copy, Clone, Debug)]
44pub enum OnOffArg {
45    On,
46    Off,
47}
48
49impl ::std::convert::From<RoleArg> for wlan_common::WlanMacRole {
50    fn from(arg: RoleArg) -> Self {
51        match arg {
52            RoleArg::Client => wlan_common::WlanMacRole::Client,
53            RoleArg::Ap => wlan_common::WlanMacRole::Ap,
54        }
55    }
56}
57
58impl ::std::convert::From<PhyArg> for wlan_common::WlanPhyType {
59    fn from(arg: PhyArg) -> Self {
60        match arg {
61            PhyArg::Erp => wlan_common::WlanPhyType::Erp,
62            PhyArg::Ht => wlan_common::WlanPhyType::Ht,
63            PhyArg::Vht => wlan_common::WlanPhyType::Vht,
64        }
65    }
66}
67
68impl ::std::convert::From<CbwArg> for fidl_ieee80211::ChannelBandwidth {
69    fn from(arg: CbwArg) -> Self {
70        match arg {
71            CbwArg::Cbw20 => fidl_ieee80211::ChannelBandwidth::Cbw20,
72            CbwArg::Cbw40 => fidl_ieee80211::ChannelBandwidth::Cbw40,
73            CbwArg::Cbw80 => fidl_ieee80211::ChannelBandwidth::Cbw80,
74        }
75    }
76}
77
78impl ::std::convert::From<ScanTypeArg> for wlan_common::ScanType {
79    fn from(arg: ScanTypeArg) -> Self {
80        match arg {
81            ScanTypeArg::Active => wlan_common::ScanType::Active,
82            ScanTypeArg::Passive => wlan_common::ScanType::Passive,
83        }
84    }
85}
86
87impl ::std::convert::From<PsModeArg> for PowerSaveType {
88    fn from(arg: PsModeArg) -> Self {
89        match arg {
90            PsModeArg::PsModePerformance => PowerSaveType::PsModePerformance,
91            PsModeArg::PsModeBalanced => PowerSaveType::PsModeBalanced,
92            PsModeArg::PsModeLowPower => PowerSaveType::PsModeLowPower,
93            PsModeArg::PsModeUltraLowPower => PowerSaveType::PsModeUltraLowPower,
94        }
95    }
96}
97
98impl ::std::convert::From<OnOffArg> for bool {
99    fn from(arg: OnOffArg) -> Self {
100        match arg {
101            OnOffArg::On => true,
102            OnOffArg::Off => false,
103        }
104    }
105}
106
107#[derive(Parser, Debug, PartialEq)]
108pub enum Opt {
109    #[command(subcommand, name = "phy")]
110    /// commands for wlan phy devices
111    Phy(PhyCmd),
112
113    #[command(subcommand, name = "iface")]
114    /// commands for wlan iface devices
115    Iface(IfaceCmd),
116
117    /// commands for client stations
118    #[command(subcommand, name = "client")]
119    Client(ClientCmd),
120    #[command(name = "connect")]
121    Connect(ClientConnectCmd),
122    #[command(name = "disconnect")]
123    Disconnect(ClientDisconnectCmd),
124    #[command(name = "scan")]
125    Scan(ClientScanCmd),
126    #[command(name = "status")]
127    Status(IfaceStatusCmd),
128    #[command(name = "wmm_status")]
129    WmmStatus(ClientWmmStatusCmd),
130
131    #[command(subcommand, name = "ap")]
132    /// commands for AP stations
133    Ap(ApCmd),
134
135    #[command(subcommand, name = "rsn")]
136    #[cfg(target_os = "fuchsia")]
137    /// commands for verifying RSN behavior
138    Rsn(RsnCmd),
139}
140
141#[derive(Parser, Clone, Debug, PartialEq)]
142pub enum PhyCmd {
143    #[command(name = "list")]
144    /// lists phy devices
145    List,
146    #[command(name = "query")]
147    /// queries a phy device
148    Query {
149        /// id of the phy to query
150        phy_id: u16,
151    },
152    #[command(name = "get-country")]
153    /// gets the phy's country used for WLAN regulatory purposes
154    GetCountry {
155        /// id of the phy to query
156        phy_id: u16,
157    },
158    #[command(name = "set-country")]
159    /// sets the phy's country for WLAN regulatory purpose
160    SetCountry {
161        /// id of the phy to query
162        phy_id: u16,
163        country: String,
164    },
165    #[command(name = "clear-country")]
166    /// sets the phy's country code to world-safe value
167    ClearCountry {
168        /// id of the phy to query
169        phy_id: u16,
170    },
171    #[command(name = "reset")]
172    Reset {
173        /// id of the phy to reset
174        phy_id: u16,
175    },
176    #[command(name = "get-power-state")]
177    /// gets the on/off state of the phy
178    GetPowerState {
179        /// id of the phy to get its power state
180        phy_id: u16,
181    },
182    #[command(name = "set-power-state")]
183    /// sets the on/off state of the phy
184    SetPowerState {
185        /// id of the phy to get its power state
186        phy_id: u16,
187        /// desired state of the phy
188        state: OnOffArg,
189    },
190    #[command(name = "get-powersave-mode")]
191    /// gets the power save mode of the phy
192    GetPowerSaveMode {
193        /// id of the phy to get its power save mode
194        phy_id: u16,
195    },
196    #[command(name = "set-powersave-mode")]
197    /// sets the power save mode of the phy
198    SetPowerSaveMode {
199        /// id of the phy to set its power save mode
200        phy_id: u16,
201        #[arg(value_enum, ignore_case = true)]
202        /// desired power save mode of the phy
203        mode: PsModeArg,
204    },
205}
206
207#[derive(Parser, Clone, Debug, PartialEq)]
208pub enum IfaceCmd {
209    #[command(name = "new")]
210    /// creates a new iface device
211    New {
212        #[arg(short = 'p', long = "phy")]
213        /// id of the phy that will host the iface
214        phy_id: u16,
215
216        #[arg(
217            short = 'r',
218            long = "role",
219            value_enum,
220            default_value = "Client",
221            ignore_case = true
222        )]
223        /// role of the new iface
224        role: RoleArg,
225
226        #[arg(short = 'm', long = "sta_addr", help = "Optional sta addr when we create an iface")]
227        /// initial sta address for this iface
228        sta_addr: Option<String>,
229    },
230
231    #[command(name = "del")]
232    /// destroys an iface device
233    Delete {
234        /// iface id to destroy
235        iface_id: u16,
236    },
237
238    #[command(name = "list")]
239    List,
240    #[command(name = "query")]
241    Query { iface_id: u16 },
242    #[command(subcommand, name = "minstrel")]
243    Minstrel(MinstrelCmd),
244    #[command(name = "status")]
245    Status(IfaceStatusCmd),
246}
247
248#[derive(Parser, Clone, Debug, PartialEq)]
249pub enum MinstrelCmd {
250    #[command(name = "list")]
251    List { iface_id: Option<u16> },
252    #[command(name = "show")]
253    Show { iface_id: Option<u16>, peer_addr: Option<String> },
254}
255
256#[derive(Parser, Clone, Debug, PartialEq)]
257pub struct ClientConnectCmd {
258    #[arg(short = 'i', long = "iface", default_value = "0")]
259    pub iface_id: u16,
260    #[arg(short = 'p', long = "password", help = "Password")]
261    pub password: Option<String>,
262    #[arg(short = 'h', long = "hash", help = "WPA2 PSK as hex string")]
263    pub psk: Option<String>,
264    #[arg(
265        short = 's',
266        long = "scan-type",
267        default_value = "passive",
268        value_enum,
269        ignore_case = true,
270        help = "Determines the type of scan performed on non-DFS channels when connecting."
271    )]
272    pub scan_type: ScanTypeArg,
273    #[arg(short = 'b', long = "bssid", help = "Specific BSSID to connect to")]
274    pub bssid: Option<String>,
275    #[arg(
276        help = "SSID of the target network. Connecting via only an SSID is deprecated and will be \
277                removed; use the `donut` tool instead."
278    )]
279    pub ssid: String,
280}
281
282#[derive(Parser, Clone, Debug, PartialEq)]
283pub struct ClientDisconnectCmd {
284    #[arg(short = 'i', long = "iface", default_value = "0")]
285    pub iface_id: u16,
286}
287
288#[derive(Parser, Clone, Debug, PartialEq)]
289pub struct ClientScanCmd {
290    #[arg(short = 'i', long = "iface", default_value = "0")]
291    pub iface_id: u16,
292    #[arg(
293        short = 's',
294        long = "scan-type",
295        default_value = "passive",
296        value_enum,
297        ignore_case = true,
298        help = "Experimental. Default scan type on each channel. \
299                Behavior may differ on DFS channel"
300    )]
301    pub scan_type: ScanTypeArg,
302}
303
304#[derive(Parser, Clone, Debug, PartialEq)]
305pub struct ClientWmmStatusCmd {
306    #[arg(short = 'i', long = "iface", default_value = "0")]
307    pub iface_id: u16,
308}
309
310#[derive(Parser, Clone, Debug, PartialEq)]
311pub struct IfaceStatusCmd {
312    #[arg(short = 'i', long = "iface")]
313    pub iface_id: Option<u16>,
314}
315
316#[derive(Parser, Clone, Debug, PartialEq)]
317pub enum ClientCmd {
318    #[command(name = "scan")]
319    Scan(ClientScanCmd),
320    #[command(name = "connect")]
321    Connect(ClientConnectCmd),
322    #[command(name = "disconnect")]
323    Disconnect(ClientDisconnectCmd),
324    #[command(name = "wmm_status")]
325    WmmStatus(ClientWmmStatusCmd),
326}
327
328#[derive(Parser, Clone, Debug, PartialEq)]
329pub enum ApCmd {
330    #[command(name = "start")]
331    Start {
332        #[arg(short = 'i', long = "iface", default_value = "0")]
333        iface_id: u16,
334        #[arg(short = 's', long = "ssid")]
335        ssid: String,
336        #[arg(short = 'p', long = "password")]
337        password: Option<String>,
338        #[arg(short = 'c', long = "channel")]
339        // TODO(porce): Expand to support PHY and CBW
340        channel: u8,
341    },
342    #[command(name = "stop")]
343    Stop {
344        #[arg(short = 'i', long = "iface", default_value = "0")]
345        iface_id: u16,
346    },
347}
348
349#[derive(Parser, Clone, Debug, PartialEq)]
350pub enum RsnCmd {
351    #[command(name = "generate-psk")]
352    GeneratePsk {
353        #[arg(short = 'p', long = "passphrase")]
354        passphrase: String,
355        #[arg(short = 's', long = "ssid")]
356        ssid: String,
357    },
358}