/* Explicit-specimen, read-only diagnostics and malformed-request bench. */ #define main nxs_hid_legacy_main #include "hid-bench.c" #undef main static nxs_message_t revised_request(nxs_operation_t operation, uint32_t generation) { nxs_message_t request = prepare(operation, generation, NULL); request.protocol_minor = NXS_PROTOCOL_MINOR; return request; } static void print_diagnostics(const nxs_runtime_diagnostics_t *diagnostics) { printf("{\"kind\":\"diagnostics\",\"ring_underruns\":%u,\"i2s_stalls\":%u,\"rejected_packets\":%u,\"dsp_failures\":%u,\"deadline_misses\":%u,\"usb_suspends\":%u,\"usb_resumes\":%u}\n", diagnostics->ring_underrun_count, diagnostics->i2s_stall_count, diagnostics->rejected_packet_count, diagnostics->dsp_failure_count, diagnostics->deadline_miss_count, diagnostics->usb_suspend_count, diagnostics->usb_resume_count); } static nxs_message_t diagnostic_sample(IOHIDDeviceRef device) { nxs_message_t request = revised_request(NXS_OPERATION_DIAGNOSTICS, 0); nxs_message_t reply = exchange(device, &request, NXS_RESULT_OK); REQUIRE(reply.protocol_minor == NXS_DIAGNOSTICS_PROTOCOL_MINOR); nxs_runtime_diagnostics_t diagnostics; REQUIRE(nxs_runtime_diagnostics_decode(reply.payload, reply.payload_length, &diagnostics) == NXS_RESULT_OK); print_diagnostics(&diagnostics); nxs_message_t replay = exchange(device, &request, NXS_RESULT_OK); REQUIRE(replay.payload_length == reply.payload_length && !memcmp(replay.payload, reply.payload, reply.payload_length)); return reply; } static void rejected_without_reply(IOHIDDeviceRef device, unsigned mutation) { nxs_message_t previous = diagnostic_sample(device); uint8_t expected[NXS_REPORT_SIZE]; REQUIRE(nxs_message_encode(&previous, expected, sizeof(expected)) == NXS_RESULT_OK); nxs_message_t request = revised_request(NXS_OPERATION_DIAGNOSTICS, 0); uint8_t report[NXS_REPORT_SIZE]; REQUIRE(nxs_message_encode(&request, report, sizeof(report)) == NXS_RESULT_OK); static const char *names[] = {"unsupported_minor", "unknown_operation", "dirty_padding", "response_direction", "bad_magic", "zero_request_id", "oversized_payload"}; REQUIRE(mutation < sizeof(names) / sizeof(names[0])); switch (mutation) { case 0: report[2] = NXS_PROTOCOL_MINOR + 1u; break; case 1: report[3] = 0xff; break; case 2: report[NXS_REPORT_SIZE - 1] = 1; break; case 3: report[8] = NXS_FLAG_RESPONSE; break; case 4: report[4] ^= 1; break; case 5: memset(report + 12, 0, 4); break; case 6: report[10] = report[11] = 0xff; break; } REQUIRE(IOHIDDeviceSetReport(device, kIOHIDReportTypeFeature, NXS_REPORT_ID, report, sizeof(report)) == kIOReturnSuccess); CFIndex length = sizeof(report); REQUIRE(IOHIDDeviceGetReport(device, kIOHIDReportTypeFeature, NXS_REPORT_ID, report, &length) == kIOReturnSuccess); REQUIRE(length == NXS_REPORT_SIZE && !memcmp(report, expected, sizeof(report))); printf("{\"kind\":\"malformed_verified\",\"case\":\"%s\",\"previous_reply_retained\":true}\n", names[mutation]); } static void invalid_payloads(IOHIDDeviceRef device, const nxs_message_t *baseline) { nxs_message_t request = revised_request(NXS_OPERATION_DIAGNOSTICS, 0); request.payload_length = 1; request.payload[0] = 0x7f; exchange(device, &request, NXS_RESULT_INVALID_PARAMETERS); puts("{\"kind\":\"malformed_verified\",\"case\":\"diagnostic_payload\",\"result\":4}"); for (unsigned mutation = 0; mutation < 2; ++mutation) { request = revised_request(NXS_OPERATION_APPLY_STATE, baseline->generation); request.payload_length = baseline->payload_length; memcpy(request.payload, baseline->payload, request.payload_length); REQUIRE(request.payload[21] == 1); if (mutation == 0) request.payload[22] = 1; else { request.payload[24] = request.payload[25] = 0; request.payload[26] = 0xc0; request.payload[27] = 0x7f; } exchange(device, &request, NXS_RESULT_INVALID_PARAMETERS); printf("{\"kind\":\"malformed_verified\",\"case\":\"%s\",\"result\":4}\n", mutation == 0 ? "snapshot_padding" : "snapshot_nan"); } } int nxs_hid_bench_main(int count, char **arguments) { bool malformed = count == 3 && !strcmp(arguments[2], "malformed"); REQUIRE(count == 2 || (count == 3 && (malformed || !strcmp(arguments[2], "inspect")))); next_request_id = arc4random_uniform(0x7fffffffu) + 1u; IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); REQUIRE(manager != NULL); CFSetRef devices; IOHIDDeviceRef device = selected_device(manager, arguments[1], &devices); nxs_message_t request = revised_request(NXS_OPERATION_CAPABILITIES, 0); nxs_message_t reply = exchange(device, &request, NXS_RESULT_OK); nxs_capabilities_t capabilities; REQUIRE(nxs_capabilities_decode(reply.payload, reply.payload_length, &capabilities) == NXS_RESULT_OK); REQUIRE(!strcmp(capabilities.device_serial, arguments[1]) && capabilities.system_clock_hz == NXS_SYSTEM_CLOCK_HZ); REQUIRE(capabilities.flash_size_bytes == 4194304u && capabilities.feature_flags == (NXS_FEATURE_PERSISTENCE | NXS_FEATURE_FLASH_VERIFIED | NXS_FEATURE_DIAGNOSTICS)); printf("{\"kind\":\"capabilities\",\"serial\":\"%s\",\"firmware\":\"%s\",\"protocol_minor\":%u,\"features\":%u,\"clock_hz\":%u}\n", capabilities.device_serial, capabilities.firmware_version, reply.protocol_minor, capabilities.feature_flags, capabilities.system_clock_hz); nxs_message_t baseline = query(device, NXS_OPERATION_READ_STATE); nxs_snapshot_t snapshot; REQUIRE(nxs_snapshot_decode(baseline.payload, baseline.payload_length, &snapshot) == NXS_RESULT_OK && snapshot.muted == 1); printf("{\"kind\":\"state\",\"generation\":%u,\"muted\":%u,\"attenuation_db\":%.9g}\n", baseline.generation, snapshot.muted, snapshot.attenuation_db); status(device); diagnostic_sample(device); if (malformed) { invalid_payloads(device, &baseline); for (unsigned mutation = 0; mutation < 7; ++mutation) rejected_without_reply(device, mutation); reply = query(device, NXS_OPERATION_READ_STATE); REQUIRE(reply.generation == baseline.generation && reply.payload_length == baseline.payload_length); REQUIRE(!memcmp(reply.payload, baseline.payload, baseline.payload_length)); puts("{\"kind\":\"malformed_suite_complete\",\"cases\":10,\"state_and_generation_unchanged\":true}"); } REQUIRE(IOHIDManagerClose(manager, kIOHIDOptionsTypeNone) == kIOReturnSuccess); CFRelease(devices); CFRelease(manager); return 0; } #ifndef NXS_BENCH_LIBRARY int main(int count, char **arguments) { return nxs_hid_bench_main(count, arguments); } #endif