Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multiple command line arguments for UDC, Interface, BT alias #5

Merged
merged 11 commits into from
Dec 23, 2024
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ simplelog = { version = "0.11.2", features = ["paris", "ansi_term"] }
clap = { version = "3.0.13", features = ["derive"] }
humantime = "2.1.0"
log = "0.4.22"
simple_config_parser = "1.0.0"
netif = "0.1.6"

[build-dependencies]
protoc-bin-vendored = "3.1.0"
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,17 @@ USAGE:

OPTIONS:
-a, --advertise BLE advertising
-b, --btalias <BTALIAS> BLE device name
-c, --connect <CONNECT> Auto-connect to saved phone or specified phone MAC address if
provided
-d, --debug Enable debug info
-l, --legacy Enable legacy mode
-h, --help Print help information
-i, --iface <IFACE> WLAN / Wi-Fi Hotspot interface [default: wlan0]
-l, --legacy Enable legacy mode
-l, --logfile <LOGFILE> Log file path [default: /var/log/aa-proxy-rs.log]
-s, --stats-interval <SECONDS> Interval of showing data transfer statistics (0 = disabled)
[default: 0]
-u, --udc <UDC> UDC Controller name
-V, --version Print version information
```
Most options are self explanatory, but these needs some more attention:<br>
Expand Down
62 changes: 50 additions & 12 deletions src/bluetooth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use bluer::{
Adapter, Address, Uuid,
};
use futures::StreamExt;
use simple_config_parser::Config;
use simplelog::*;
use std::sync::Arc;
use std::time::{Duration, Instant};
Expand Down Expand Up @@ -36,10 +37,9 @@ const HSP_HS_UUID: Uuid = Uuid::from_u128(0x0000110800001000800000805f9b34fb);
const HSP_AG_UUID: Uuid = Uuid::from_u128(0x0000111200001000800000805f9b34fb);
const BT_ALIAS: &str = "WirelessAADongle";

const WLAN_IFACE: &str = "wlan0";
const WLAN_IP_ADDR: &str = "10.0.0.1";
const WLAN_SSID: &str = "AAWirelessDongle";
const WLAN_WPA_KEY: &str = "ConnectAAWirelessDongle";
const DEFAULT_WLAN_ADDR: &str = "10.0.0.1";

const HOSTAPD_FILE: &str = "/etc/hostapd.conf";

#[derive(Debug, Clone, PartialEq)]
#[repr(u16)]
Expand Down Expand Up @@ -74,12 +74,16 @@ pub async fn get_cpu_serial_number_suffix() -> Result<String> {

async fn power_up_and_wait_for_connection(
advertise: bool,
btalias: Option<String>,
connect: Option<Address>,
) -> Result<(BluetoothState, Stream)> {
// setting BT alias for further use
let alias = match get_cpu_serial_number_suffix().await {
Ok(suffix) => format!("{}-{}", BT_ALIAS, suffix),
Err(_) => String::from(BT_ALIAS),
let alias = match btalias {
None => match get_cpu_serial_number_suffix().await {
Ok(suffix) => format!("{}-{}", BT_ALIAS, suffix),
Err(_) => String::from(BT_ALIAS),
},
Some(btalias) => btalias,
};
info!("{} 🥏 Bluetooth alias: <bold><green>{}</>", NAME, alias);

Expand Down Expand Up @@ -337,6 +341,8 @@ pub async fn bluetooth_stop(state: BluetoothState) -> Result<()> {

pub async fn bluetooth_setup_connection(
advertise: bool,
btalias: Option<String>,
iface: &str,
connect: Option<Address>,
tcp_start: Arc<Notify>,
) -> Result<BluetoothState> {
Expand All @@ -345,21 +351,53 @@ pub async fn bluetooth_setup_connection(
let mut stage = 1;
let mut started;

let (state, mut stream) = power_up_and_wait_for_connection(advertise, connect).await?;
let mut wlan_ip_addr = String::from(DEFAULT_WLAN_ADDR);

let (state, mut stream) = power_up_and_wait_for_connection(advertise, btalias, connect).await?;

// Get UP interface and IP
for ifa in netif::up().unwrap() {
match ifa.name() {
val if val == iface => {
debug!("Found interface: {:?}", ifa);
// IPv4 Address contains None scope_id, while IPv6 contains Some
match ifa.scope_id() {
None => {
wlan_ip_addr = ifa.address().to_string();
break;
}
_ => (),
}
}
_ => (),
}
}

// Create a new config from hostapd.conf
let hostapd = Config::new().file(HOSTAPD_FILE).unwrap();

// read SSID and WPA_KEY
let wlan_ssid = &hostapd.get_str("ssid").unwrap();
let wlan_wpa_key = &hostapd.get_str("wpa_passphrase").unwrap();

info!("{} 📲 Sending parameters via bluetooth to phone...", NAME);
let mut start_req = WifiStartRequest::new();
start_req.set_ip_address(String::from(WLAN_IP_ADDR));
info!("{} 🛜 Sending Host IP Address: {}", NAME, wlan_ip_addr);
start_req.set_ip_address(wlan_ip_addr);
start_req.set_port(TCP_SERVER_PORT);
send_message(&mut stream, stage, MessageId::WifiStartRequest, start_req).await?;
stage += 1;
started = Instant::now();
read_message(&mut stream, stage, MessageId::WifiInfoRequest, started).await?;

let mut info = WifiInfoResponse::new();
info.set_ssid(String::from(WLAN_SSID));
info.set_key(String::from(WLAN_WPA_KEY));
let bssid = mac_address::mac_address_by_name(WLAN_IFACE)
info.set_ssid(String::from(wlan_ssid));
info.set_key(String::from(wlan_wpa_key));
info!(
"{} 🛜 Sending Host SSID and Password: {}, {}",
NAME, wlan_ssid, wlan_wpa_key
);
let bssid = mac_address::mac_address_by_name(iface)
.unwrap()
.unwrap()
.to_string();
Expand Down
30 changes: 28 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ struct Args {
/// Interval of showing data transfer statistics (0 = disabled)
#[clap(short, long, value_name = "SECONDS", default_value_t = 0)]
stats_interval: u16,

/// UDC Controller name
#[clap(short, long)]
udc: Option<String>,

/// WLAN / Wi-Fi Hotspot interface
#[clap(short, long, default_value = "wlan0")]
iface: String,

/// BLE device name
#[clap(short, long)]
btalias: Option<String>,
}

fn logging_init(debug: bool, log_path: &PathBuf) {
Expand Down Expand Up @@ -104,8 +116,11 @@ fn logging_init(debug: bool, log_path: &PathBuf) {

async fn tokio_main(
advertise: bool,
btalias: Option<String>,
legacy: bool,
iface: String,
connect: Option<Address>,
udc: Option<String>,
need_restart: Arc<Notify>,
tcp_start: Arc<Notify>,
) {
Expand All @@ -117,15 +132,23 @@ async fn tokio_main(
std::thread::spawn(|| uevent_listener(accessory_started_cloned));
}

let mut usb = UsbGadgetState::new(legacy);
let mut usb = UsbGadgetState::new(legacy, udc);
loop {
if let Err(e) = usb.init() {
error!("{} 🔌 USB init error: {}", NAME, e);
}

let bt_stop;
loop {
match bluetooth_setup_connection(advertise, connect, tcp_start.clone()).await {
match bluetooth_setup_connection(
advertise,
btalias.clone(),
&iface,
connect,
tcp_start.clone(),
)
.await
{
Ok(state) => {
// we're ready, gracefully shutdown bluetooth in task
bt_stop = tokio::spawn(async move { bluetooth_stop(state).await });
Expand Down Expand Up @@ -201,8 +224,11 @@ fn main() {
runtime.spawn(async move {
tokio_main(
args.advertise,
args.btalias,
args.legacy,
args.iface,
args.connect,
args.udc,
need_restart,
tcp_start,
)
Expand Down
29 changes: 20 additions & 9 deletions src/usb_gadget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,27 +53,38 @@ pub struct UsbGadgetState {
configfs_path: PathBuf,
udc_name: String,
legacy: bool,
udc: Option<String>,
}

impl UsbGadgetState {
pub fn new(legacy: bool) -> UsbGadgetState {
pub fn new(legacy: bool, udc: Option<String>) -> UsbGadgetState {
let mut state = UsbGadgetState {
configfs_path: PathBuf::from("/sys/kernel/config/usb_gadget"),
udc_name: String::new(),
legacy,
udc,
};

let udc_dir = PathBuf::from("/sys/class/udc");
if let Ok(entries) = fs::read_dir(&udc_dir) {
for entry in entries {
if let Ok(entry) = entry {
debug!("Using UDC: {:?}", entry.file_name());
if let Ok(fname) = entry.file_name().into_string() {
state.udc_name.push_str(fname.as_str());
break;
// If UDC argument is passed, use it, otherwise check sys
match state.udc {
None => {
let udc_dir = PathBuf::from("/sys/class/udc");
if let Ok(entries) = fs::read_dir(&udc_dir) {
for entry in entries {
if let Ok(entry) = entry {
info!("{} Using UDC: {:?}", NAME, entry.file_name());
if let Ok(fname) = entry.file_name().into_string() {
state.udc_name.push_str(fname.as_str());
break;
}
}
}
}
}
Some(ref udcname) => {
info!("Using UDC: {:?}", udcname);
state.udc_name.push_str(&udcname);
}
}

return state;
Expand Down
Loading