<commit_before>/*
 * Copyright (C) 2019 <NAME> <<EMAIL>>
 *
 * SPDX-License-Identifier: LGPL-2.1+
 */

#include "config.h"

#include <fwupdplugin.h>

#include <scsi/sg.h>

#include "fu-ata-device.h"

#define FU_ATA_IDENTIFY_SIZE 512 /* bytes */
#define FU_ATA_BLOCK_SIZE    512 /* bytes */

struct ata_tf {
	guint8 dev;
	guint8 command;
	guint8 error;
	guint8 status;
	guint8 feat;
	guint8 nsect;
	guint8 lbal;
	guint8 lbam;
	guint8 lbah;
};

#define ATA_USING_LBA (1 << 6)
#define ATA_STAT_DRQ  (1 << 3)
#define ATA_STAT_ERR  (1 << 0)

#define ATA_OP_IDENTIFY		  0xec
#define ATA_OP_FLUSH_CACHE	  0xe7
#define ATA_OP_DOWNLOAD_MICROCODE 0x92
#define ATA_OP_STANDBY_IMMEDIATE  0xe0

#define ATA_SUBCMD_MICROCODE_OBSOLETE		      0x01
#define ATA_SUBCMD_MICROCODE_DOWNLOAD_CHUNKS_ACTIVATE 0x03
#define ATA_SUBCMD_MICROCODE_DOWNLOAD_CHUNK	      0x07
#define ATA_SUBCMD_MICROCODE_DOWNLOAD_CHUNKS	      0x0e
#define ATA_SUBCMD_MICROCODE_ACTIVATE		      0x0f

#define SG_CHECK_CONDITION 0x02
#define SG_DRIVER_SENSE	   0x08

#define SG_ATA_12     0xa1
#define SG_ATA_12_LEN 12

#define SG_ATA_PROTO_NON_DATA (3 << 1)
#define SG_ATA_PROTO_PIO_IN   (4 << 1)
#define SG_ATA_PROTO_PIO_OUT  (5 << 1)

enum {
	SG_CDB2_TLEN_NODATA = 0 << 0,
	SG_CDB2_TLEN_FEAT = 1 << 0,
	SG_CDB2_TLEN_NSECT = 2 << 0,

	SG_CDB2_TLEN_BYTES = 0 << 2,
	SG_CDB2_TLEN_SECTORS = 1 << 2,

	SG_CDB2_TDIR_TO_DEV = 0 << 3,
	SG_CDB2_TDIR_FROM_DEV = 1 << 3,

	SG_CDB2_CHECK_COND = 1 << 5,
};

struct _FuAtaDevice {
	FuUdevDevice parent_instance;
	guint pci_depth;
	guint usb_depth;
	guint16 transfer_blocks;
	guint8 transfer_mode;
	guint32 oui;
};

G_DEFINE_TYPE(FuAtaDevice, fu_ata_device, FU_TYPE_UDEV_DEVICE)

guint8
fu_ata_device_get_transfer_mode(FuAtaDevice *self)
{
	return self->transfer_mode;
}

guint16
fu_ata_device_get_transfer_blocks(FuAtaDevice *self)
{
	return self->transfer_blocks;
}

static gchar *
fu_ata_device_get_string(const guint16 *buf, guint start, guint end)
{
	g_autoptr(GString) str = g_string_new(NULL);
	for (guint i = start; i <= end; i++) {
		g_string_append_c(str, (gchar)(buf[i] >> 8));
		g_string_append_c(str, (gchar)(buf[i] & 0xff));
	}

	/* remove whitespace before returning */
	if (str->len > 0) {
		g_strstrip(str->str);
		if (str->str[0] == '\0')
			return NULL;
	}
	return g_string_free(g_steal_pointer(&str), FALSE);
}

static void
fu_ata_device_to_string(FuDevice *device, guint idt, GString *str)
{
	FuAtaDevice *self = FU_ATA_DEVICE(device);
	fu_common_string_append_kx(str, idt, "TransferMode", self->transfer_mode);
	fu_common_string_append_kx(str, idt, "TransferBlocks", self->transfer_blocks);
	if (self->oui != 0x0)
		fu_common_string_append_kx(str, idt, "OUI", self->oui);
	fu_common_string_append_ku(str, idt, "PciDepth", self->pci_depth);
	fu_common_string_append_ku(str, idt, "UsbDepth", self->usb_depth);
}

/* https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-ide-devices */
static gchar *
fu_ata_device_pad_string_for_id(const gchar *name)
{
	GString *str = g_string_new(name);
	fu_common_string_replace(str, " ", "_");
	for (guint i = str->len; i < 40; i++)
		g_string_append_c(str, '_');<commit_msg>ata: Correctly chain up to FuUdevDevice when debugging<commit_after>/*
 * Copyright (C) 2019 <NAME> <<EMAIL>>
 *
 * SPDX-License-Identifier: LGPL-2.1+
 */

#include "config.h"

#include <fwupdplugin.h>

#include <scsi/sg.h>

#include "fu-ata-device.h"

#define FU_ATA_IDENTIFY_SIZE 512 /* bytes */
#define FU_ATA_BLOCK_SIZE    512 /* bytes */

struct ata_tf {
	guint8 dev;
	guint8 command;
	guint8 error;
	guint8 status;
	guint8 feat;
	guint8 nsect;
	guint8 lbal;
	guint8 lbam;
	guint8 lbah;
};

#define ATA_USING_LBA (1 << 6)
#define ATA_STAT_DRQ  (1 << 3)
#define ATA_STAT_ERR  (1 << 0)

#define ATA_OP_IDENTIFY		  0xec
#define ATA_OP_FLUSH_CACHE	  0xe7
#define ATA_OP_DOWNLOAD_MICROCODE 0x92
#define ATA_OP_STANDBY_IMMEDIATE  0xe0

#define ATA_SUBCMD_MICROCODE_OBSOLETE		      0x01
#define ATA_SUBCMD_MICROCODE_DOWNLOAD_CHUNKS_ACTIVATE 0x03
#define ATA_SUBCMD_MICROCODE_DOWNLOAD_CHUNK	      0x07
#define ATA_SUBCMD_MICROCODE_DOWNLOAD_CHUNKS	      0x0e
#define ATA_SUBCMD_MICROCODE_ACTIVATE		      0x0f

#define SG_CHECK_CONDITION 0x02
#define SG_DRIVER_SENSE	   0x08

#define SG_ATA_12     0xa1
#define SG_ATA_12_LEN 12

#define SG_ATA_PROTO_NON_DATA (3 << 1)
#define SG_ATA_PROTO_PIO_IN   (4 << 1)
#define SG_ATA_PROTO_PIO_OUT  (5 << 1)

enum {
	SG_CDB2_TLEN_NODATA = 0 << 0,
	SG_CDB2_TLEN_FEAT = 1 << 0,
	SG_CDB2_TLEN_NSECT = 2 << 0,

	SG_CDB2_TLEN_BYTES = 0 << 2,
	SG_CDB2_TLEN_SECTORS = 1 << 2,

	SG_CDB2_TDIR_TO_DEV = 0 << 3,
	SG_CDB2_TDIR_FROM_DEV = 1 << 3,

	SG_CDB2_CHECK_COND = 1 << 5,
};

struct _FuAtaDevice {
	FuUdevDevice parent_instance;
	guint pci_depth;
	guint usb_depth;
	guint16 transfer_blocks;
	guint8 transfer_mode;
	guint32 oui;
};

G_DEFINE_TYPE(FuAtaDevice, fu_ata_device, FU_TYPE_UDEV_DEVICE)

guint8
fu_ata_device_get_transfer_mode(FuAtaDevice *self)
{
	return self->transfer_mode;
}

guint16
fu_ata_device_get_transfer_blocks(FuAtaDevice *self)
{
	return self->transfer_blocks;
}

static gchar *
fu_ata_device_get_string(const guint16 *buf, guint start, guint end)
{
	g_autoptr(GString) str = g_string_new(NULL);
	for (guint i = start; i <= end; i++) {
		g_string_append_c(str, (gchar)(buf[i] >> 8));
		g_string_append_c(str, (gchar)(buf[i] & 0xff));
	}

	/* remove whitespace before returning */
	if (str->len > 0) {
		g_strstrip(str->str);
		if (str->str[0] == '\0')
			return NULL;
	}
	return g_string_free(g_steal_pointer(&str), FALSE);
}

static void
fu_ata_device_to_string(FuDevice *device, guint idt, GString *str)
{
	FuAtaDevice *self = FU_ATA_DEVICE(device);
	FU_DEVICE_CLASS(fu_ata_device_parent_class)->to_string(device, idt, str);
	fu_common_string_append_kx(str, idt, "TransferMode", self->transfer_mode);
	fu_common_string_append_kx(str, idt, "TransferBlocks", self->transfer_blocks);
	if (self->oui != 0x0)
		fu_common_string_append_kx(str, idt, "OUI", self->oui);
	fu_common_string_append_ku(str, idt, "PciDepth", self->pci_depth);
	fu_common_string_append_ku(str, idt, "UsbDepth", self->usb_depth);
}

/* https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-ide-devices */
static gchar *
fu_ata_device_pad_string_for_id(const gchar *name)
{
	GString *str = g_string_new(name);
	fu_common_string_replace(str, " ", "_");
	for (guint i = str->len; i < 40; i++)
		g_string_append_c(str, '_');
{'fraction_non_alphanumeric': 0.11942625506704085, 'fraction_numerical': 0.03461178671655753, 'mean_word_length': 5.320197044334975, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 44, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5187872', 'n_tokens_mistral': 3015, 'n_tokens_neox': 2857, 'n_words': 514}