# `EtherCAT.Bus.Transport.RawSocket`
[🔗](https://github.com/sid2baker/ethercat/blob/main/lib/ethercat/bus/transport/raw_socket.ex#L1)

Raw AF_PACKET socket transport for EtherCAT.

Sends and receives full Ethernet frames with EtherType 0x88A4.
Implements the `EtherCAT.Bus.Transport` behaviour.

Uses sysfs for MAC address lookup and `:net` for interface index.
The EtherCAT payload (from `Bus.Frame.encode/1`) is wrapped in a standard
Ethernet frame internally — callers only deal with EtherCAT payloads.

On Linux this transport enables `PACKET_IGNORE_OUTGOING` so the kernel does
not loop the process' own transmitted EtherCAT frames back to the socket.

# `t`

```elixir
@type t() :: %EtherCAT.Bus.Transport.RawSocket{
  ifindex: non_neg_integer(),
  interface: String.t(),
  raw: :socket.socket() | nil,
  src_mac: &lt;&lt;_::48&gt;&gt;
}
```

# `close`

```elixir
@spec close(t()) :: t()
```

Close the underlying socket. Returns the struct with `raw` set to `nil`.

# `drain`

```elixir
@spec drain(t()) :: :ok
```

Drain all frames in the socket buffer; cancel any lingering select.

# `interface`

```elixir
@spec interface(t()) :: String.t()
```

Returns the interface name used by the bus link monitor.

# `match`

```elixir
@spec match(t(), term()) ::
  {:ok, binary(), integer(), binary()} | {:error, term()} | :ignore
```

Match a `{:"$socket", raw, :select, _}` message from this socket.

When matched, calls `recvmsg` internally to read the frame, strips the
Ethernet headers, and returns the EtherCAT payload with an rx timestamp
and the frame's source MAC address (6 bytes).
Returns `:ignore` for all other messages or non-EtherCAT frames.

# `name`

```elixir
@spec name(t()) :: String.t()
```

Returns the network interface name for telemetry and link monitoring.

# `open`

```elixir
@spec open(keyword()) :: {:ok, t()} | {:error, term()}
```

Open a raw AF_PACKET socket bound to the given interface.

# `open?`

```elixir
@spec open?(t()) :: boolean()
```

Returns `true` when the socket handle is open.

# `rearm`

```elixir
@spec rearm(t()) :: :ok
```

Re-arm without draining — self-sends a select notification.

# `send`

```elixir
@spec send(t(), binary()) :: {:ok, integer()} | {:error, term()}
```

Send an EtherCAT payload wrapped in an Ethernet frame.

# `set_active_once`

```elixir
@spec set_active_once(t()) :: :ok
```

Arm for one async receive via `:socket` select mechanism.

# `src_mac`

```elixir
@spec src_mac(t()) :: &lt;&lt;_::48&gt;&gt;
```

Returns this NIC's source MAC address (6 bytes).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
