Using the Acroname Programmable USB 2x4 hub as a software accessible USB switch between two hosts

2021 March 18
Multi-host USB Switch diagram

Often a simple USB switch with a physical button is used to switch USB devices between two different host computers. In many cases it would be nice to execute the host switch without physically pushing a button on the device. The Acroname Programmable USB 2x4 hub (2x4) allows a user to switch hosts programmatically without pushing a button.

There are multiple ways to accomplish a host switch with the 2x4, however the easiest approach is to run a simple command line tool on each host to tell the 2x4 to switch upstream channels. The following code snippets, presented in both python and C++, are all that is required to execute the upstream host switch.

Once the script working, place it on each of the host computers that will be connected to the 2x4. To switch upstream ports simply execute the script on the host currently connected to the 2x4. Paired with an application such as display-switch, this example code can provide basic "KVM" functionality.

 

 

Python

To run the python version of the command line tool below, you first need to install the BrainStem library wheel that is included in the Brainstem development kit. Please see the readme included in the download for infomation about setting up your python environment to run this code.

Once you've installed the Brainstem python library, copy and paste the code into your favorite text editor and save the resulting file as 'host_switch.py'. The script can then be executed from the command line:

$ python host_switch.py
Connecting to USBHub2x4...
Connected to USBHub2x4 with serial number: 0x8374051B
Switching host control...
  to port 0
Done.
# host_switch.py
import sys

from brainstem.stem import USBHub2x4
from brainstem.link import Spec
from brainstem.result import Result

def main():

    print('\nConnecting to USBHub2x4...')
    hub = USBHub2x4()

    # To Locate and connect to the first USBHub2x4 you find on USB
    result = hub.discoverAndConnect(Spec.USB)
    # To Locate and connect to a specific module, add a second parameter with your serial number (hex).
    # result = stem.discoverAndConnect(Spec.USB, 0x66F4859B)

    if result == (Result.NO_ERROR):
        result = hub.system.getSerialNumber()
        print("Connected to USBHub2x4 with serial number: 0x%08X" % result.value)
        print("Switching host control...")
        result = hub.usb.getUpstreamState()
        if result.error == Result.NO_ERROR:
            if result.value == 0:
                print("  to port 1")
                result = hub.usb.setUpstreamMode(1)
            else:
                print("  to port 0") 
                result = hub.usb.setUpstreamMode(0)
        else:
            print("Error determining new host port.")

        if result in [Result.NO_ERROR, Result.TIMEOUT]:
            print("Done.")
        else:
            print("Error setting port.")
    else:
        print('Could not find a module.\n')

    hub.disconnect()

if __name__ == "__main__":
    sys.exit(main())

 

C++

Acroname also provides platform specific shared libraries and C++ examples. To use the following C++ code, find the USB 2x4 C++ example in the Brainstem development kit, and replace the contents of the main.cpp file with the code listed below. Follow the instructions for compiling included in the examples.

Once you've compiled the brainstem example, run the following command to switch upstream ports:

$ BrainStem2Example
Connecting to USBHub2x4...
Connected to USBHub2x4 with serial number: 8374051b
Switching host control...
  to port 
Done

 

// host_switch.cpp
#include 
#include "BrainStem2/BrainStem-all.h"

int main(int argc, const char * argv[]) {
    std::cout << "\nConnecting to USBHub2x4..." << std::endl;

    // Create an instance of the USBHub2x4
    aUSBHub2x4 hub;
    uint32_t serial = 0;
    uint8_t state = 2;
    aErr err = aErrNone;

    // Connect to the hardware.
    // err = stem.discoverAndConnect(USB, 0x40F5849A); // for a known serial number
    err = hub.discoverAndConnect(USB);
    if (err != aErrNone) {
        std::cout << "Could not find a module.\n" << std::endl;
        return 1;
    }

    err = hub.system.getSerialNumber(&serial);
    if (err != aErrNone) {
        std::cout << "Could not get serial number." << std::endl;
        hub.disconnect();
        return 1;
    }
    std::cout << "Connected to USBHub2x4 with serial number: " << std::hex << serial << std::endl;
    std::cout << "Switching host control..." << std::endl;

    err = hub.usb.getUpstreamState(&state);
    if (err != aErrNone) {
        std::cout << "  Error determining new host port." << std::endl;
        hub.disconnect();
        return 1;
    }

    if (state == 0) {
        std::cout << "  to port 1" << std::endl;
        err = hub.usb.setUpstreamMode(1);
    } else {
        std::cout << "  to port 0" << std::endl;
        err = hub.usb.setUpstreamMode(0);
    }

    if (err == aErrNone || err == aErrTimeout) {
        std::cout << "Done" << std::endl;
        hub.disconnect();
        return 0;
    } else {
        std::cout << "Error setting port." << std::endl;
        hub.disconnect();
        return 1;
    }

}

 

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.