int main()

in Tools/AccessorySetupGenerator/Main.c [12:286]


int main(int argc, char* argv[]) {
    HAPError err;

    if (argc <= 1) {

#ifndef _WIN32
#define B(stringLiteral) "\x1B[1m" stringLiteral "\x1B[0m"
#define U(stringLiteral) "\x1B[4m" stringLiteral "\x1B[0m"
#else
#define B(stringLiteral) stringLiteral
#define U(stringLiteral) stringLiteral
#endif

        const char* categoryDescriptions =
                "           1  Other.\n"
                "           2  Bridges.\n"
                "           3  Fans.\n"
                "           4  Garage Door Openers.\n"
                "           5  Lighting.\n"
                "           6  Locks.\n"
                "           7  Outlets.\n"
                "           8  Switches.\n"
                "           9  Thermostats.\n"
                "          10  Sensors.\n"
                "          11  Security Systems.\n"
                "          12  Doors.\n"
                "          13  Windows.\n"
                "          14  Window Coverings.\n"
                "          15  Programmable Switches.\n"
                "          16  Range Extenders.\n"
                "          19  Air Purifiers.\n"
                "          20  Heaters.\n"
                "          21  Air Conditioners.\n"
                "          22  Humidifiers.\n"
                "          23  Dehumidifiers.\n"
                "          28  Sprinklers.\n"
                "          29  Faucets.\n"
                "          30  Shower Systems.\n";

        const char* exampleOutput =
                "     1\n"
                "     518-08-582\n"
                "     263FEA64889756A8E25FD53DD5FA1022\n"
                "     D0BE3DFCC3B28A4D612943215AD71005CA4E240A5672EFF427F30EEAC173756167AC4D73779\n"
                "        3AF18937B1770E173ED346AB790E428B2771ACA62FE11C1A0FC8E01169824632BB914863\n"
                "        760918841CB3F263D5D71C431A2141C51797A91022C5BCD30D7BC9259A2037C4BDEE8F74\n"
                "        8D65B15AEA33DF2F00193FBAAC603C921820D2E4FE5747F965F31F3DD16D8A7228FE8FC8\n"
                "        5AD70138C797CB91B47488283C568D1CDAFCF6E950A1D117BD4E42FB0B90FF97992BCCE0\n"
                "        C86F62F866489BC2F556D342F4C20AC26B12A48299C642BE86270F0D3F1E6E86E84115A7\n"
                "        12931F7FE1D53E6230FB14C29AD2E23B16E0B8F6AFD4D709B562DC4921F550450AC8FD09\n"
                "        73DD80DAE629CB399DD6E3E96695E2E8060196D5FFFD292A1246AD76219E998FDD0E690B\n"
                "        405A0D2AD9C9CADF905520C4E6B66952E0DA27E523060DE310A539F6BF30E48B69A5F26D\n"
                "        5E283DE6EE8F51AFB920E00D1B1AE3BA423041A63BA788B6F6BCBA2AD7C89946EEE79D72\n"
                "        6649BCEAB43BB920F11260F8017C9921A60C169B28569\n"
                "     7OSX\n"
                "     X-HM://007JNU5AE7OSX\n";
        printf(
            B("HomeKit Accessory Setup Generator")" - Version %s (%s)\n"
            "\n"
            B("USAGE")"\n"
            "     "B("AccessorySetupGenerator")" [OPTION]...\n"
            "\n"
            B("DESCRIPTION")"\n"
            "     This tool generates information for provisioning of a HomeKit accessory,\n"
            "     namely a setup code, a corresponding SRP salt and verifier, and a setup ID.\n"
            "     The setup code is used by the controller to set up an encrypted link with\n"
            "     the accessory during HomeKit pairing. The setup ID is used to identify\n"
            "     the accessory to which a scanned label belongs.\n"
            "     \n"
            "     "B("Each accessory needs to be provisioned with unique accessory setup")"\n"
            "     "B("information before it may be used.")"\n"
            "\n"
            B("OPTIONS")"\n"
            "     The following options are available:\n"
            "     \n"
            "     "B("--ip")"\n"
            "        Accessory supports HAP over IP transport; \n"
            "     \n"
            "     "B("--ble")"\n"
            "        Accessory supports HAP over BLE transport.\n"
            "     \n"
            "     "B("--category")" "U("Category")"\n"
            "        The accessory category.\n"
            "        \n"
            "        An accessory with support for multiple categories should advertise the\n"
            "        primary category. An accessory for which a primary category cannot be\n"
            "        determined or the primary category isn't among the well defined\n"
            "        categories falls in the `Other` category.\n"
            "        \n"
            "        Well defined categories:\n"
            "%s\n"
            "     "B("--setup-code")" "U("Setup code")"\n"
            "        Generates accessory setup information that allows pairing using the\n"
            "        specified setup code (e.g. for development).\n"
            "        Format is `XXX-XX-XXX` with X being a digit from 0-9.\n"
            "        - Setup codes that only consist of a repeating digit are not allowed.\n"
            "        - `123-45-678` and `876-54-321` are not allowed.\n"
            "        If this option is not present, a random setup code is generated.\n"
            "     \n"
            "     "B("--setup-id")" "U("Setup ID")"\n"
            "        Provisions accessory setup information using a specific setup ID.\n"
            "        Format is `XXXX` with X being a digit from 0-9 or a character from A-Z.\n"
            "        - Lowercase characters are not allowed.\n"
            "        If this option is not present, a random setup ID is generated.\n"
            "\n"
            B("OUTPUT")"\n"
            "     Output consists of a series of lines in a machine-readable format.\n"
            "     Lines are terminated with a \\n character.\n"
            "     \n"
            "     1. "B("Output format version")" which is `1` for this version.\n"
            "     \n"
            "     2. "B("Setup code")" in format `XXX-XX-XXX` with X being a digit from 0-9.\n"
            "        - Must be deployed to the accessory if it has a programmable NFC tag but\n"
            "          is not connected to a display.\n"
            "        - Must be printed on labels affixed to the accessory and its packaging\n"
            "          if the accessory is not connected to a display.\n"
            "     \n"
            "     3. "B("SRP salt")" as a hexadecimal string.\n"
            "        - Must be deployed to the accessory if it is not connected to a display.\n"
            "     \n"
            "     4. "B("SRP verifier")" as a hexadecimal string.\n"
            "        - Must be deployed to the accessory if it is not connected to a display.\n"
            "     \n"
            "     5. "B("Setup ID")" in format `XXX` with X being a digit from 0-9 or a\n"
            "        character from A-Z.\n"
            "        - Must be deployed to the accessory.\n"
            "     \n"
            "     6. "B("Setup payload")" as a string.\n"
            "        - Must be printed on labels affixed to the accessory and its packaging\n"
            "          if the accessory is not connected to a display.\n"
            "\n"
            B("EXAMPLE")"\n"
            "     Example output for an "B("Outlet")" (category identifier "B("7")") accessory supporting\n"
            "     "B("HAP over IP")" and "B("Wi-Fi Accessory Configuration")" with setup code `"B("518-08-582")"`\n"
            "     and setup ID `"B("7OSX")"`.\n"
            "     \n"
            "%s",
            HAPGetVersion(), HAPGetBuild(), categoryDescriptions, exampleOutput);
#undef B
#undef U
        exit(EXIT_SUCCESS);
    }

    // Parse arguments.
    const char* fixedSetupCode = NULL;
    const char* fixedSetupID = NULL;
    HAPAccessorySetupSetupPayloadFlags flags = { .isPaired = false, .ipSupported = false, .bleSupported = false };
    HAPAccessoryCategory category = (HAPAccessoryCategory) 0;
    for (int i = 1; i < argc; i++) {
        if (HAPStringAreEqual(argv[i], "--ip")) {
            if (flags.ipSupported) {
                fprintf(stderr, "--ip specified multiple times.");
                exit(EXIT_FAILURE);
            }
            flags.ipSupported = true;
        } else if (HAPStringAreEqual(argv[i], "--ble")) {
            if (flags.bleSupported) {
                fprintf(stderr, "--ble specified multiple times.");
                exit(EXIT_FAILURE);
            }
            flags.bleSupported = true;
        } else if (HAPStringAreEqual(argv[i], "--category")) {
            if (i == argc) {
                fprintf(stderr, "--category specified without accessory category identifier.");
                exit(EXIT_FAILURE);
            }
            i++;
            uint64_t categoryID;
            err = HAPUInt64FromString(argv[i], &categoryID);
            if (err) {
                HAPAssert(err == kHAPError_InvalidData);
                fprintf(stderr, "--category specified with malformed accessory category identifier.");
                exit(EXIT_FAILURE);
            }
            if (!categoryID || categoryID > UINT8_MAX) {
                fprintf(stderr, "--category specified with out-of-range accessory category identifier.");
                exit(EXIT_FAILURE);
            }
            if (category) {
                fprintf(stderr, "--category specified multiple times.");
                exit(EXIT_FAILURE);
            }
            category = (HAPAccessoryCategory) categoryID;
        } else if (HAPStringAreEqual(argv[i], "--setup-code")) {
            if (i == argc) {
                fprintf(stderr, "--setup-code specified without setup code.");
                exit(EXIT_FAILURE);
            }
            i++;
            if (!HAPAccessorySetupIsValidSetupCode(argv[i])) {
                fprintf(stderr, "--setup-code specified with invalid setup code.");
                exit(EXIT_FAILURE);
            }
            if (fixedSetupCode) {
                fprintf(stderr, "--setup-code specified multiple times.");
                exit(EXIT_FAILURE);
            }
            fixedSetupCode = argv[i];
        } else if (HAPStringAreEqual(argv[i], "--setup-id")) {
            if (i == argc) {
                fprintf(stderr, "--setup-id specified without setup ID.");
                exit(EXIT_FAILURE);
            }
            i++;
            if (!HAPAccessorySetupIsValidSetupID(argv[i])) {
                fprintf(stderr, "--setup-id specified with invalid setup ID.");
                exit(EXIT_FAILURE);
            }
            if (fixedSetupID) {
                fprintf(stderr, "--setup-id specified multiple times.");
                exit(EXIT_FAILURE);
            }
            fixedSetupID = argv[i];
        } else {
            fprintf(stderr, "Too many arguments specified.");
            exit(EXIT_FAILURE);
        }
    }
    if (!category) {
        fprintf(stderr, "No accessory category identifier specified.");
        exit(EXIT_FAILURE);
    }
    if (!flags.ipSupported && !flags.bleSupported) {
        fprintf(stderr, "No transport specified.");
        exit(EXIT_FAILURE);
    }

    // Setup code.
    HAPSetupCode setupCode;
    if (fixedSetupCode) {
        HAPRawBufferCopyBytes(setupCode.stringValue, fixedSetupCode, sizeof setupCode.stringValue);
    } else {
        HAPAccessorySetupGenerateRandomSetupCode(&setupCode);
    }

    // Setup info.
    HAPSetupInfo setupInfo;
    HAPPlatformRandomNumberFill(setupInfo.salt, sizeof setupInfo.salt);
    const uint8_t srpUserName[] = "Pair-Setup";
    HAP_srp_verifier(
            setupInfo.verifier,
            setupInfo.salt,
            srpUserName,
            sizeof srpUserName - 1,
            (const uint8_t*) setupCode.stringValue,
            sizeof setupCode.stringValue - 1);

    // Setup ID.
    HAPSetupID setupID;
    if (fixedSetupID) {
        HAPRawBufferCopyBytes(setupID.stringValue, fixedSetupID, sizeof setupID.stringValue);
    } else {
        HAPAccessorySetupGenerateRandomSetupID(&setupID);
    }

    // Setup payload.
    HAPSetupPayload setupPayload;
    HAPAccessorySetupGetSetupPayload(&setupPayload, &setupCode, &setupID, flags, category);

    // Output.
    printf("1\n");
    printf("%s\n", setupCode.stringValue);
    for (size_t i = 0; i < sizeof setupInfo.salt; i++) {
        printf("%02X", setupInfo.salt[i]);
    }
    printf("\n");
    for (size_t i = 0; i < sizeof setupInfo.verifier; i++) {
        printf("%02X", setupInfo.verifier[i]);
    }
    printf("\n");
    printf("%s\n", setupID.stringValue);
    printf("%s\n", setupPayload.stringValue);

    return 0;
}