Skip to main content

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