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    #[command(name = "set-power-state")]
236    /// sets the on/off state of the phy
237    SetPowerState {
238        /// id of the phy to get its power state
239        phy_id: u16,
240        /// desired state of the phy
241        state: OnOffArg,
242    },
243    #[command(name = "get-powersave-mode")]
244    /// gets the power save mode of the phy
245    GetPowerSaveMode {
246        /// id of the phy to get its power save mode
247        phy_id: u16,
248    },
249    #[command(name = "set-powersave-mode")]
250    /// sets the power save mode of the phy
251    SetPowerSaveMode {
252        /// id of the phy to set its power save mode
253        phy_id: u16,
254        #[arg(value_enum, ignore_case = true)]
255        /// desired power save mode of the phy
256        mode: PsModeArg,
257    },
258    #[command(name = "set-tx-power-scenario")]
259    /// sets the tx power scenario of the phy
260    SetTxPowerScenario {
261        /// id of the phy
262        phy_id: u16,
263        #[arg(value_enum, ignore_case = true)]
264        /// desired tx power scenario of the phy
265        mode: TxPowerScenarioArg,
266    },
267    #[command(name = "get-tx-power-scenario")]
268    /// gets the tx power scenario of the phy
269    GetTxPowerScenario {
270        /// id of the phy to query
271        phy_id: u16,
272    },
273
274    #[command(name = "reset-tx-power-scenario")]
275    ResetTxPowerScenario {
276        // id of phy to reset tx power scenario
277        phy_id: u16,
278    },
279}
280
281#[derive(Parser, Clone, Debug, PartialEq)]
282pub enum IfaceCmd {
283    #[command(name = "new")]
284    /// creates a new iface device
285    New {
286        #[arg(short = 'p', long = "phy")]
287        /// id of the phy that will host the iface
288        phy_id: u16,
289
290        #[arg(
291            short = 'r',
292            long = "role",
293            value_enum,
294            default_value = "Client",
295            ignore_case = true
296        )]
297        /// role of the new iface
298        role: RoleArg,
299
300        #[arg(short = 'm', long = "sta_addr", help = "Optional sta addr when we create an iface")]
301        /// initial sta address for this iface
302        sta_addr: Option<String>,
303    },
304
305    #[command(name = "del")]
306    /// destroys an iface device
307    Delete {
308        /// iface id to destroy
309        iface_id: u16,
310    },
311
312    #[command(name = "list")]
313    List,
314    #[command(name = "query")]
315    Query { iface_id: u16 },
316    #[command(subcommand, name = "minstrel")]
317    Minstrel(MinstrelCmd),
318    #[command(name = "status")]
319    Status(IfaceStatusCmd),
320}
321
322#[derive(Parser, Clone, Debug, PartialEq)]
323pub enum MinstrelCmd {
324    #[command(name = "list")]
325    List { iface_id: Option<u16> },
326    #[command(name = "show")]
327    Show { iface_id: Option<u16>, peer_addr: Option<String> },
328}
329
330#[derive(Parser, Clone, Debug, PartialEq)]
331pub struct ClientConnectCmd {
332    #[arg(short = 'i', long = "iface", default_value = "0")]
333    pub iface_id: u16,
334    #[arg(short = 'p', long = "password", help = "Password")]
335    pub password: Option<String>,
336    #[arg(long = "hash", help = "WPA2 PSK as hex string")]
337    pub psk: Option<String>,
338    #[arg(
339        short = 's',
340        long = "scan-type",
341        default_value = "passive",
342        value_enum,
343        ignore_case = true,
344        help = "Determines the type of scan performed on non-DFS channels when connecting."
345    )]
346    pub scan_type: ScanTypeArg,
347    #[arg(short = 'b', long = "bssid", help = "Specific BSSID to connect to")]
348    pub bssid: Option<String>,
349    #[arg(
350        help = "SSID of the target network. Connecting via only an SSID is deprecated and will be \
351                removed; use the `donut` tool instead."
352    )]
353    pub ssid: String,
354}
355
356#[derive(Parser, Clone, Debug, PartialEq)]
357pub struct ClientDisconnectCmd {
358    #[arg(short = 'i', long = "iface", default_value = "0")]
359    pub iface_id: u16,
360}
361
362#[derive(Parser, Clone, Debug, PartialEq)]
363pub struct ClientScanCmd {
364    #[arg(short = 'i', long = "iface", default_value = "0")]
365    pub iface_id: u16,
366    #[arg(
367        short = 's',
368        long = "scan-type",
369        default_value = "passive",
370        value_enum,
371        ignore_case = true,
372        help = "Experimental. Default scan type on each channel. \
373                Behavior may differ on DFS channel"
374    )]
375    pub scan_type: ScanTypeArg,
376}
377
378#[derive(Parser, Clone, Debug, PartialEq)]
379pub struct ClientWmmStatusCmd {
380    #[arg(short = 'i', long = "iface", default_value = "0")]
381    pub iface_id: u16,
382}
383
384#[derive(Parser, Clone, Debug, PartialEq)]
385pub struct IfaceStatusCmd {
386    #[arg(short = 'i', long = "iface")]
387    pub iface_id: Option<u16>,
388}
389
390#[derive(Parser, Clone, Debug, PartialEq)]
391pub enum ClientCmd {
392    #[command(name = "scan")]
393    Scan(ClientScanCmd),
394    #[command(name = "connect")]
395    Connect(ClientConnectCmd),
396    #[command(name = "disconnect")]
397    Disconnect(ClientDisconnectCmd),
398    #[command(name = "wmm_status")]
399    WmmStatus(ClientWmmStatusCmd),
400}
401
402#[derive(Parser, Clone, Debug, PartialEq)]
403pub enum ApCmd {
404    #[command(name = "start")]
405    Start {
406        #[arg(short = 'i', long = "iface", default_value = "0")]
407        iface_id: u16,
408        #[arg(short = 's', long = "ssid")]
409        ssid: String,
410        #[arg(short = 'p', long = "password")]
411        password: Option<String>,
412        #[arg(short = 'c', long = "channel")]
413        // TODO(porce): Expand to support PHY and CBW
414        channel: u8,
415        #[arg(short = 'b', long = "band", value_enum, ignore_case = true)]
416        band: BandArg,
417    },
418    #[command(name = "stop")]
419    Stop {
420        #[arg(short = 'i', long = "iface", default_value = "0")]
421        iface_id: u16,
422    },
423}
424
425#[derive(Parser, Clone, Debug, PartialEq)]
426pub enum RsnCmd {
427    #[command(name = "generate-psk")]
428    GeneratePsk {
429        #[arg(short = 'p', long = "passphrase")]
430        passphrase: String,
431        #[arg(short = 's', long = "ssid")]
432        ssid: String,
433    },
434}