<!-- Source: https://medius.k4tech.net/library/guides/connection -->
# Choosing a port

_When more than one box is plugged in_

[`find`](/library/connection.md#open) grabs the first match. With more than one box, `find_medius` lists every match as a [`PortInfo`](/library/types/structs.md#port-info) (`path`, `vid`, `pid`) without opening, then [`open`](/library/connection.md#open) the chosen one.

#### EXAMPLE

```rust
use medius::{Device, find_medius};

let ports = find_medius();
for port in &ports {
    println!("{} (vid={:#06x} pid={:#06x})", port.path, port.vid, port.pid);
}

// open a chosen one (here, the first):
let port = ports.first().ok_or(medius::Error::NotFound)?;
let dev = Device::open(&port.path)?;
```

## Threading and Clone

_Share one connection across threads_

[`Device`](/library/connection.md) is `Send + Sync` and clones cheaply (an [`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) inside), so one connection serves any number of threads; a clone bumps the reference count and doesn't reopen the port.

#### EXAMPLE

```rust
use std::thread;

let worker = device.clone();
let handle = thread::spawn(move || {
    worker.move_rel(10, 0)
});
handle.join().unwrap()?;
```

## Running queries concurrently

_join and cloning across tasks_

[`AsyncDevice`](/library/features/async.md) clones the same way, so hand a clone to another task and await both queries together with [`futures::future::join`](https://docs.rs/futures/latest/futures/future/fn.join.html).

#### EXAMPLE

```rust
let (v, h) = futures::future::join(
    device.query_version(),
    device.query_health(),
).await;
let v = v?;
let h = h?;
println!("{v}, link_up={}", h.link_up);
```

> **Note**
>
> Only the queries need `.await`; mutators stay synchronous on either handle.

## Keepalive and holds

_Holding injected input past the silence window_

The box clears every injected input and pending move once no frame arrives for its [silence window](/native/injection.md#safety). A live `Device` holds your overrides past that on its own: a background thread (`medius-keepalive`) sends a [`QUERY(HEALTH)`](/native/commands/requests.md#health) every `DEFAULT_KEEPALIVE_CADENCE` (500 ms) while anything is held, so a press survives. There's no `keepalive()` to call.

| State | Behavior |
| --- | --- |
| Override held | Keepalive thread runs; the health reply is dropped. |
| Idle | No override held, so the thread sends nothing. |

#### EXAMPLE

```rust
device.press(Button::Left)?;

// No further calls. The keepalive thread sends QUERY(HEALTH) on its own,
// so the hold survives well past the 1000 ms silence window.
std::thread::sleep(std::time::Duration::from_secs(5));

device.reset()?;
```

An _override_ is the box holding an input down or up itself, set by [`press`](/library/inject.md#inject) or [`force_release`](/library/inject.md#inject); the library keeps a copy. After a dropped link, [`reapply`](/library/lifecycle.md#reapply) and [`reconnect`](/library/lifecycle.md#reconnect) restore it.

## Releasing the device

_Drop it; no close() call_

There's no `close`: dropping the last [`Arc`\-backed handle](/library/guides/connection.md#threading) tears the connection down. Its [`Drop`](https://doc.rust-lang.org/std/ops/trait.Drop.html) stops the threads and closes the port.

| Step | What drop does |
| --- | --- |
| Signal | Sets the stop flag the reader and keepalive threads watch. |
| Join | Waits for both threads to exit, so none are left running. |
| Close | Releases the serial port as the transport drops. |

For immediate hand-off call [`reset`](/library/admin.md#reset) before drop.

#### EXAMPLE

```rust
// hand the mouse back right now, not a second from now:
device.reset()?;   // box returns to passthrough immediately
drop(device);      // tears down threads and closes the port
```
