//..............................................................................
//
// USB log packet declarations and representer
//

import "log_Representation.jnc"
import "io_UsbDb.jnc"
import "UsbLogRecordCode.jnc"

//..............................................................................

char const* formatDeviceString(DeviceParams const* params) {
	char const* string = $"bus \e[34m%(1;03d):%(2;03d)\e[m ID \e[34m%(3;04x):%(4;04x)\e[m" (
		params.m_bus,
		params.m_address,
		params.m_vendorId,
		params.m_productId
	);

	io.UsbDb* db = io.getStdUsbDb();
	io.UsbVendor const* vendor = db.findVendor(params.m_vendorId);
	io.UsbProduct const* product = vendor ? vendor.findProduct(params.m_productId) : null;

	if (vendor) {
		string = $"$string $(vendor.m_name)";

		if (product)
			string = $"$string $(product.m_name)";
		else
			string = $"$string PID_$(params.m_productId; 04x)";
	}

	return string;
}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

bool representUsbLog(
	log.Representation* representation,
	uint64_t recordCode,
	void const* p,
	size_t size,
	uint_t foldFlags
) {
	switch (recordCode) {
	case UsbLogRecordCode.DeviceOpened:
		DeviceParams const* params = (DeviceParams const*) p;
		representation.m_lineAttr.m_iconIdx = log.StdLogIcon.Connect;
		representation.m_lineAttr.m_backColor = log.StdLogColor.Connect;
		representation.addHyperText($"Device opened: $(formatDeviceString (params))");
		break;

	case UsbLogRecordCode.DeviceOpenError:
		std.Error const* error = (std.Error const*) p;
		representation.m_lineAttr.m_iconIdx = log.StdLogIcon.Error;
		representation.m_lineAttr.m_backColor = log.StdLogColor.Error;
		representation.addHyperText($"Cannot open device: $(error.m_description)");
		break;

	case UsbLogRecordCode.DeviceClosed:
		representation.m_lineAttr.m_iconIdx = log.StdLogIcon.Disconnect;
		representation.m_lineAttr.m_backColor = log.StdLogColor.Disconnect;
		representation.addHyperText("Device closed");
		break;

	case UsbLogRecordCode.KernelDriverDetached:
		uint8_t ifaceId = *(uint8_t const*) p;
		representation.m_lineAttr.m_iconIdx = log.StdLogIcon.Warning;
		representation.m_lineAttr.m_backColor = log.StdLogColor.Warning;
		representation.addHyperText($"Kernel driver detached from interface ID \e[34m$ifaceId");
		break;

	case UsbLogRecordCode.InterfaceClaimed:
		InterfaceParams const* params = (InterfaceParams const*) p;
		representation.m_lineAttr.m_iconIdx = log.StdLogIcon.Info;
		representation.m_lineAttr.m_backColor = log.StdLogColor.Info;
		representation.addHyperText($"Interface claimed: ID \e[34m$(params.m_interfaceId):$(params.m_altSettingId)");
		break;

	case UsbLogRecordCode.InterfaceClaimError:
		std.Error const* error = (std.Error const*) p;
		representation.m_lineAttr.m_iconIdx = log.StdLogIcon.Error;
		representation.m_lineAttr.m_backColor = log.StdLogColor.Error;
		representation.addHyperText($"Cannot claim interface: $(error.m_description)");
		break;

	case UsbLogRecordCode.InterfaceReleased:
		representation.m_lineAttr.m_iconIdx = log.StdLogIcon.Info;
		representation.m_lineAttr.m_backColor = log.StdLogColor.Info;
		representation.addHyperText($"Interface released");
		break;

	case UsbLogRecordCode.ReadingStarted:
		uint8_t endpointId = *(uint8_t const*) p;
		representation.m_lineAttr.m_iconIdx = log.StdLogIcon.Info;
		representation.m_lineAttr.m_backColor = log.StdLogColor.Info;
		representation.addHyperText($"Reading started from endpoint ID \e[34m$(endpointId; 02x)");
		break;

	case UsbLogRecordCode.ReadingStopped:
		representation.m_lineAttr.m_iconIdx = log.StdLogIcon.Info;
		representation.m_lineAttr.m_backColor = log.StdLogColor.Info;
		representation.addHyperText($"Reading stopped");
		break;

	case UsbLogRecordCode.EndpointOpenError:
		std.Error const* error = (std.Error const*) p;
		representation.m_lineAttr.m_iconIdx = log.StdLogIcon.Error;
		representation.m_lineAttr.m_backColor = log.StdLogColor.Error;
		representation.addHyperText($"Cannot open endpoint: $(error.m_description)");
		break;

	case UsbLogRecordCode.ControlTransfer:
		ControlTransferParams const* params = (ControlTransferParams const*) p;
		representation.m_lineAttr.m_iconIdx = (params.m_type & 0x80) ? log.StdLogIcon.RxPacket : log.StdLogIcon.TxPacket;
		representation.m_lineAttr.m_backColor = ui.StdColor.PastelGray;
		representation.addHyperText(
			$"Type: $(params.m_type; 02x) "
			$"Code: $(params.m_code; 02x) "
			$"Value: $(params.m_value; 04x) "
			$"Index: $(params.m_index; 04x)"
		);
		break;

	default:
		return false;
	}

	return true;
}

//..............................................................................
