Packages

An Elixir implementation of the Open Supervised Device Protocol (OSDP).

Current section

Files

Jump to
jeff lib jeff command.ex
Raw

lib/jeff/command.ex

defmodule Jeff.Command do
@moduledoc """
Commands are sent from an ACU to a PD
| Code | Name | Description | Data Type |
|------|--------------|---------------------------------------|-------------------------|
| 0x60 | POLL | Poll | - |
| 0x61 | ID | ID Report Request | - |
| 0x62 | CAP | PD Capabilities Request | [Capability] |
| 0x64 | LSTAT | Local Status Report Request | - |
| 0x65 | ISTAT | Input Status Report Request | - |
| 0x66 | OSTAT | Output Status Report Request | - |
| 0x67 | RSTAT | Reader Status Report Request | - |
| 0x68 | OUT | Output Control Command | OutputSettings |
| 0x69 | LED | Reader Led Control Command | LedSettings |
| 0x6A | BUZ | Reader Buzzer Control Command | BuzzerSettings |
| 0x6B | TEXT | Text Output Command | TextSettings |
| 0x6E | COMSET | PD Communication Config Command | ComSettings |
| 0x73 | BIOREAD | Scan and Send Biometric Data | Requested Return Format |
| 0x74 | BIOMATCH | Scan and Match Biometric Template | Biometric Template |
| 0x75 | KEYSET | Encryption Key Set Command | EncryptionKey |
| 0x76 | CHLNG | Challenge/Secure Session Init Request | ChallengeData |
| 0x77 | SCRYPT | Server Cryptogram | EncryptionData |
| 0x7B | ACURXSIZE | Max ACU receive size | Buffer size |
| 0x7C | FILETRANSFER | Send data file to PD | File contents |
| 0x80 | MFG | Manufacturer Specific Command | Any |
| 0xA1 | XWR | Extended write data | APDU and details |
| 0xA2 | ABORT | Abort PD operation | - |
| 0xA3 | PIVDATA | Get PIV Data | Object details |
| 0xA4 | GENAUTH | Request Authenticate | Request details |
| 0xA5 | CRAUTH | Request Crypto Response | Challenge details |
| 0xA7 | KEEPACTIVE | PD read activation | Time duration |
"""
@type t() :: %__MODULE__{
address: byte(),
code: byte(),
data: binary(),
name: atom(),
caller: reference()
}
defstruct [:address, :code, :data, :name, :caller]
alias Jeff.Command.{
BuzzerSettings,
ChallengeData,
EncryptionServer,
ComSettings,
EncryptionKey,
LedSettings,
OutputSettings,
TextSettings
}
@names %{
0x60 => POLL,
0x61 => ID,
0x62 => CAP,
0x64 => LSTAT,
0x65 => ISTAT,
0x66 => OSTAT,
0x67 => RSTAT,
0x68 => OUT,
0x69 => LED,
0x6A => BUZ,
0x6B => TEXT,
0x6E => COMSET,
0x73 => BIOREAD,
0x74 => BIOMATCH,
0x75 => KEYSET,
0x76 => CHLNG,
0x77 => SCRYPT,
0x7B => ACURXSIZE,
0x7C => FILETRANSFER,
0x80 => MFG,
0xA1 => XWR,
0xA2 => ABORT,
0xA3 => PIVDATA,
0xA4 => GENAUTH,
0xA5 => CRAUTH,
0xA7 => KEEPACTIVE
}
@codes Map.new(@names, fn {code, name} -> {name, code} end)
def new(address, name, params \\ []) do
{caller, params} = Keyword.pop(params, :caller)
code = code(name)
data = encode(name, params)
%__MODULE__{
address: address,
code: code,
data: data,
name: name,
caller: caller
}
end
defp encode(POLL, _params), do: nil
defp encode(ID, _params), do: <<0x00>>
defp encode(CAP, _params), do: <<0x00>>
defp encode(LSTAT, _params), do: nil
defp encode(ISTAT, _params), do: nil
defp encode(OSTAT, _params), do: nil
defp encode(RSTAT, _params), do: nil
defp encode(OUT, params), do: OutputSettings.encode(params)
defp encode(LED, params), do: LedSettings.encode(params)
defp encode(BUZ, params), do: BuzzerSettings.encode(params)
defp encode(TEXT, params), do: TextSettings.encode(params)
defp encode(COMSET, params), do: ComSettings.encode(params)
defp encode(KEYSET, params), do: EncryptionKey.encode(params)
defp encode(CHLNG, params), do: ChallengeData.encode(params)
defp encode(SCRYPT, params), do: EncryptionServer.encode(params)
defp encode(ACURXSIZE, size: size), do: <<size::size(16)-little>>
defp encode(ABORT, _params), do: nil
def code(name), do: @codes[name]
def name(code), do: @names[code]
end