Files
MAG160C/.superpowers/sdd/task-4-brief.md
T

5.5 KiB

Task 4 Brief: USB discovery and endpoint model

Context

Tasks 1-3 are complete. CMake remains unavailable on PATH; keep CMakeLists.txt correct but use direct MinGW g++ verification if CMake cannot run.

Global constraints

  • Use only original source code; do not link proprietary SDK binaries.
  • Current workspace is not a git repository; replace commit steps with verification plus updates to progress.md.
  • Keep public C ABI free of C++ types.
  • Use C++17.
  • libusb-1.0 is the only native runtime dependency for the core library.
  • Firmware update commands are not exposed as an easy accidental CLI action.
  • IR protocol gaps return MAG160C_ERR_PROTOCOL_UNKNOWN or MAG160C_ERR_UNSUPPORTED.

Files

  • Create: src/core/device.hpp
  • Create: src/core/device.cpp
  • Create: tests/cpp/test_device_model.cpp
  • Modify: CMakeLists.txt
  • Modify: include/mag160c/mag160c.h
  • Modify: src/c_api.cpp
  • Update: progress.md with the checkpoint.

Interfaces to produce

  • mag160c::core::EndpointType
  • mag160c::core::EndpointDescriptor
  • mag160c::core::EndpointPair
  • mag160c::core::DeviceInfo
  • mag160c::core::is_in_endpoint
  • mag160c::core::find_bulk_pair
  • mag160c::core::list_devices
  • mag160c_list_devices C ABI
  • mag160c_free_device_list C ABI

Required constants and structs

constexpr uint16_t MAG_IR_VENDOR_ID = 0x833c;
constexpr uint16_t MAG_IR_PRODUCT_ID = 0x0001;

enum class EndpointType {
    Other,
    Bulk,
    Interrupt,
    Isochronous
};

struct EndpointDescriptor {
    uint8_t address = 0;
    EndpointType type = EndpointType::Other;
};

struct EndpointPair {
    uint8_t bulk_in = 0;
    uint8_t bulk_out = 0;
};

struct DeviceInfo {
    mag160c_device_info_t c_info{};
};

Required public C struct and declarations

Add to include/mag160c/mag160c.h:

typedef struct mag160c_device_info_t {
    uint16_t vendor_id;
    uint16_t product_id;
    uint8_t bus;
    uint8_t address;
    uint8_t interface_number;
    uint8_t bulk_in_endpoint;
    uint8_t bulk_out_endpoint;
    char product[128];
    char manufacturer[128];
    char serial[128];
} mag160c_device_info_t;

MAG160C_API mag160c_error_t mag160c_list_devices(
    mag160c_context_t* ctx,
    mag160c_device_info_t** out_devices,
    size_t* out_count
);

MAG160C_API void mag160c_free_device_list(mag160c_device_info_t* devices);

Required endpoint behavior

  • is_in_endpoint returns true when endpoint address has bit 0x80 set.
  • find_bulk_pair scans endpoints and returns the first bulk IN and first bulk OUT.
  • find_bulk_pair returns false if either direction is absent.
  • find_bulk_pair returns false for null out pointer.

Required list_devices behavior

  • If out is null, return MAG160C_ERR_INVALID_ARGUMENT.
  • If MAG160C_HAS_LIBUSB is 0, return MAG160C_ERR_UNSUPPORTED and set last_error explaining libusb was not available at build time.
  • If MAG160C_HAS_LIBUSB is 1 and no matching device is present, return MAG160C_OK and an empty vector.
  • Only match VID 0x833C and PID 0x0001 initially.
  • If libusb is enabled, inspect config descriptors and report the first interface/altsetting with both bulk IN and bulk OUT.
  • Avoid including libusb.h unless MAG160C_HAS_LIBUSB is true so direct no-libusb builds compile.

Required C ABI behavior

  • mag160c_list_devices requires ctx, out_devices, and out_count.
  • On invalid arguments, return MAG160C_ERR_INVALID_ARGUMENT.
  • Initialize *out_devices to null and *out_count to 0 before enumeration.
  • On empty device list, return MAG160C_OK with null devices and count 0.
  • On non-empty list, allocate an array with new[] and copy mag160c_device_info_t values.
  • mag160c_free_device_list deletes the array and accepts null.

Required tests

Create tests/cpp/test_device_model.cpp:

  • endpoints {0x01 interrupt, 0x82 bulk, 0x03 bulk} returns bulk_in 0x82 and bulk_out 0x03.
  • endpoints {0x82 bulk} returns false because bulk OUT is absent.
  • optional: null out pointer returns false.

Extend tests/cpp/test_c_api.cpp if convenient:

  • mag160c_list_devices(nullptr, nullptr, nullptr) returns MAG160C_ERR_INVALID_ARGUMENT.
  • with a valid context and MAG160C_HAS_LIBUSB=0, mag160c_list_devices returns MAG160C_ERR_UNSUPPORTED, devices remains null, count remains 0.

CMake update

  • Add src/core/device.cpp to mag160c_core sources.
  • Add test_device_model executable linked to mag160c_core.
  • Give test_device_model access to src private headers.
  • Register test_device_model with CTest.

Verification

First try:

cmake --build build
ctest --test-dir build --output-on-failure

If CMake is unavailable, run:

g++ -std=c++17 -DMAG160C_STATIC -DMAG160C_HAS_LIBUSB=0 -Iinclude -Isrc src\core\error.cpp src\core\context.cpp src\core\tcm_frame.cpp src\core\tcm_device.cpp src\core\device.cpp src\c_api.cpp tests\cpp\test_c_api.cpp -o build_task4_c_api_test.exe
.\build_task4_c_api_test.exe
g++ -std=c++17 -DMAG160C_STATIC -DMAG160C_HAS_LIBUSB=0 -Iinclude -Isrc src\core\error.cpp src\core\context.cpp src\core\tcm_frame.cpp src\core\tcm_device.cpp src\core\device.cpp src\c_api.cpp tests\cpp\test_device_model.cpp -o build_task4_device_model_test.exe
.\build_task4_device_model_test.exe

Expected: both executables exit 0.

Progress checkpoint

Append this line to progress.md after verification:

- Implemented Task 4 USB device model, endpoint-pair selection, and C ABI device listing/freeing.

Report contract

Write a report to .superpowers/sdd/task-4-report.md with:

  • status: DONE, DONE_WITH_CONCERNS, NEEDS_CONTEXT, or BLOCKED
  • files created/modified
  • exact commands run
  • test results
  • concerns, if any
  • self-review notes