Metadata-Version: 2.4
Name: pytactl
Version: 2.0.0
Summary: Python Test Automation Controller (TAC/Alpaca) for Qualcomm debug boards
Author-email: "Qualcomm Technologies, Inc." <qc.opensource@qti.qualcomm.com>
Maintainer-email: Milosz Wasilewski <milosz.wasilewski@oss.qualcomm.com>
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/qualcomm/pytactl
Project-URL: Repository, https://github.com/qualcomm/pytactl
Project-URL: Issues, https://github.com/qualcomm/pytactl/issues
Project-URL: Documentation, https://github.com/qualcomm/pytactl/blob/main/README.md
Project-URL: Security Policy, https://github.com/qualcomm/pytactl/blob/main/SECURITY.md
Keywords: debug-board,hardware,qualcomm,tac,test-automation
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Embedded Systems
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: System :: Hardware
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Flask
Requires-Dist: Flask-RESTful
Requires-Dist: pyftdi
Requires-Dist: pyusb
Requires-Dist: pexpect
Requires-Dist: pyserial
Requires-Dist: requests
Requires-Dist: platformdirs
Requires-Dist: hid
Provides-Extra: dev
Requires-Dist: ruff==0.15.17; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

# pytactl

Python implementation of Test Automation Controller (TAC/Alpaca) for controlling Qualcomm debug boards.
It uses config files and PSOC firmware from the original TAC (Alpaca) system.

# Installation

Install the `pytactl` command on your system from [PyPI](https://pypi.org/project/pytactl/)
with [pipx](https://pipx.pypa.io):

    pipx install pytactl

To install from a checkout of this repository instead:

    pipx install .

This puts a single `pytactl` entry point on your `PATH`. Note that the `hid`
dependency needs `libhidapi` package to be installed (required for Bughopper V2 boards).

Alternatively, for development in a virtualenv:

    virtualenv -p python3 venv
    . ./venv/bin/activate
    pip install -e .

Run `pytactl -h` to see all available options.

## System dependencies

pytactl uses `hidapi` for HID-based debug boards, including Bughopper V2.
Install the native HIDAPI library before installing or running `pytactl`.

### Ubuntu / Debian

```bash
sudo apt update
sudo apt install -y libhidapi-hidraw0 libhidapi-libusb0
```

### Fedora

```bash
sudo dnf install -y hidapi
```

## USB permissions

By default, USB devices are not accessible without root. Create a udev rule for your board:

    echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="05c6", ATTR{idProduct}=="9302", MODE="0666", GROUP="plugdev"' \
      | sudo tee /etc/udev/rules.d/99-alpaca.rules
    sudo udevadm control --reload-rules && sudo udevadm trigger

Bughopper V2 also exposes a HID interface, so it needs a `hidraw` rule:

    echo 'SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="b001", MODE="0660", GROUP="plugdev", TAG+="uaccess"' \
      | sudo tee /etc/udev/rules.d/99-bughopper-v2.rules
    sudo udevadm control --reload-rules && sudo udevadm trigger

Then make sure your user is in the `plugdev` group (log out and back in after):

    sudo usermod -aG plugdev $USER

# Configuration

**Bughopper boards (V1 and V2) work out of the box.** They are self-describing and need no
config files.

**All other debug boards (FTDI, PSOC) require configuration files** that are NOT shipped with
pytactl. The easiest way to obtain them is the `installconfigs` subcommand, which downloads every
`.tcnf` file and `devicelist.json` from the
[qcom-test-automation-controller](https://github.com/qualcomm/qcom-test-automation-controller/tree/main/configurations)
project:

    pytactl installconfigs

With no arguments it fetches from the default config repository and installs into a per-user
data directory (resolved with [platformdirs](https://pypi.org/project/platformdirs/), e.g.
`~/.local/share/pytactl` on Linux). Once that directory is populated, the board subcommands use it
automatically as the default `--tac-config-path`. Override either with:

    pytactl installconfigs \
      --config-repository https://github.com/qualcomm/qcom-test-automation-controller/ \
      --local-path /path/to/install \
      --ref main \
      --repository-path configurations

`--ref` selects the git ref (branch, tag, or commit; default `HEAD`) and `--repository-path` the
directory within the repository to fetch from (default `configurations`).

`installconfigs` also copies the default FTDI Alpaca-Lite config (which has no upstream `.tcnf`
file) in as `default.tcnf` and rewrites empty `configPath` entries in `devicelist.json` to point
at it.

You can also copy the `configurations/` directory by hand and point pytactl at it with
`--tac-config-path <dir>`.

Note: some configs in qcom-test-automation-controller currently have syntax issues; pick the
ones that match your board.

`devicelist.json` maps board hardware IDs to their `.tcnf` config files, and must be present in
the `--tac-config-path` directory for FTDI/PSOC boards. Example entry for a PSOC board:

    {
      "catalog": [
        {
          "platform_id": 17,
          "configPath": "tac_configs/TAC_PSOC_17.tcnf"
        }
      ]
    }

## Finding your board's serial number

The `--serial` argument takes the USB serial number, not a device path. The easiest way to
discover connected boards and their serial numbers is the `list` subcommand:

    pytactl list

It prints every recognised debug board with its type, USB vendor/product ID, and serial number
(read from udev, the same `ID_SERIAL_SHORT` value you pass to `--serial`):

    Connected debug boards:
      Bughopper V1   vid:pid=0403:6015  serial=DP05DIAN
      PSOC           vid:pid=05c6:9302  serial=0123456789

Alternatively, find it manually with `udevadm`:

    udevadm info /dev/ttyACM0 | grep ID_SERIAL_SHORT

Or using `lsusb` (replace `VID:PID` with `0403:6011` for FTDI or `05c6:9302` for PSOC):

    lsusb -v -d VID:PID | grep iSerial

# Using as a shell

Start the interactive shell with the `shell` subcommand:

    pytactl shell --serial <ID_SERIAL_SHORT>

Optional arguments:

    --tac-config-path <dir>   # path to config directory (required for FTDI/PSOC boards, see Configuration)
    --log-level DEBUG         # log verbosity (default: DEBUG)

Once started, the shell prompt accepts commands generated from your board's config script. The available commands depend on the config — not all boards define every command (e.g. newer configs may omit `powerOn`/`powerOff`). Typical commands:

**Power control:**

    powerOn
    powerOff
    devicePowerOn
    devicePowerOff
    usbDevicePowerOn
    usbDevicePowerOff

**Boot modes:**

    bootToEDL
    bootToFastboot
    bootToUEFI
    reset

**GPIO pins** (use with `1` to assert, `0` to deassert):

    pkey 1      # press power key
    pkey 0      # release power key
    volup 1
    voldn 1

Type `help` in the shell to list all commands available for your specific board.

# Running a single command

Use the `oneshot` subcommand to run one command and exit, without entering the interactive
shell. This is handy for scripting:

    pytactl oneshot bootToEDL --serial <ID_SERIAL_SHORT>
    pytactl oneshot reset --serial <ID_SERIAL_SHORT>

GPIO pin commands take an integer value (`1` to assert, `0` to deassert):

    pytactl oneshot pkey 1 --serial <ID_SERIAL_SHORT>
    pytactl oneshot pkey 0 --serial <ID_SERIAL_SHORT>

The same commands available in the shell can be used here. An unknown command exits with an
error listing the commands supported by your board.

# Using as a service

    pytactl service --serial <ID_SERIAL_SHORT_1> [<ID_SERIAL_SHORT_2> ...]

The REST API runs on `http://localhost:5000`. Example usage with curl:

    # List connected boards
    curl http://localhost:5000/

    # List available quick methods (bootToEDL, powerOn, etc.)
    curl http://localhost:5000/<boardid>/quick

    # Power on/off
    curl -X PUT http://localhost:5000/<boardid>/quick/powerOn
    curl -X PUT http://localhost:5000/<boardid>/quick/powerOff

    # Boot to EDL
    curl -X PUT http://localhost:5000/<boardid>/quick/bootToEDL

    # Boot to fastboot
    curl -X PUT http://localhost:5000/<boardid>/quick/bootToFastboot

    # Set a named pin
    curl -X PUT "http://localhost:5000/<boardid>/command/reset?value=1"

    # Set a raw pin (e.g., bus A, pin 0)
    curl -X PUT "http://localhost:5000/<boardid>/pin/A0?value=1"

Note: REST API server runs in debug mode. Running with multiple concurrent threads may lead to unexpected behaviour.

# License

pytactl is licensed under the [BSD-3-clause License](https://spdx.org/licenses/BSD-3-Clause.html). See [LICENSE](LICENSE) for the full license text.
