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

#include "config.h"

#include <fcntl.h>
#include <poll.h>
#include <string.h>
#include <termios.h>

#include "fu-io-channel.h"
#include "fu-altos-device.h"
#include "fu-altos-firmware.h"

struct _FuAltosDevice {
	FuUsbDevice		 parent_instance;
	gchar			*tty;
	guint64			 addr_base;
	guint64			 addr_bound;
	struct termios		 tty_termios;
	FuIOChannel		*io_channel;
};

G_DEFINE_TYPE (FuAltosDevice, fu_altos_device, FU_TYPE_USB_DEVICE)

static void
fu_altos_device_to_string (FuDevice *device, guint idt, GString *str)
{
	FuAltosDevice *self = FU_ALTOS_DEVICE (device);
	fu_common_string_append_kv (str, idt, "TTY", self->tty);
	if (self->addr_base != 0x0)
		fu_common_string_append_kx (str, idt, "AddrBase", self->addr_base);
	if (self->addr_bound != 0x0)
		fu_common_string_append_kx (str, idt, "AddrBound", self->addr_bound);
}

static void
fu_altos_device_finalize (GObject *object)
{
	FuAltosDevice *self = FU_ALTOS_DEVICE (object);

	g_free (self->tty);

	G_OBJECT_CLASS (fu_altos_device_parent_class)->finalize (object);
}

static gboolean
fu_altos_device_find_tty (FuAltosDevice *self, GError **error)
{
	GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
	g_autoptr(GList) devices = NULL;
	g_autoptr(GUdevClient) gudev_client = g_udev_client_new (NULL);

	/* find all tty devices */
	devices = g_udev_client_query_by_subsystem (gudev_client, "tty");
	for (GList *l = devices; l != NULL; l = l->next) {
		GUdevDevice *dev = G_UDEV_DEVICE (l->data);

		/* get the tty device */
		const gchar *dev_file = g_udev_device_get_device_file (dev);
		if (dev_file == NULL)
			continue;

		/* get grandparent */
		dev = g_udev_device_get_parent (dev);
		if (dev == NULL)
			continue;
		dev = g_udev_device_get_parent (dev);
		if (dev == NULL)
			continue;

		/* check correct device */
		if (g_udev_device_get_sysfs_attr_as_int (dev, "busnum") !=
		    g_usb_device_get_bus (usb_device))
			continue;
		if (g_udev_device_get_sysfs_attr_as_int (dev, "devnum") !=
		    g_usb_device_get_address (usb_device))
			continue;

		/* success */
		self->tty = g_strdup (dev_file);
		return TRUE;
	}

	/* failure */
	g_set_error (error,
		     FWUPD_ERROR,
		     FWUPD_ERROR_NOT_SUPPORTED,
		     "failed to find tty for %u:%u",
		     g_usb_device_get_bus (usb_device),
		     g_usb_device_get_address (usb_device));
	return FALSE;
}

static gboolean
fu_altos_device_tty_write (FuAltosDevice *self,
			   const gchar *data,
			   gssize data_len,
			   GError **error)
{
	/* lets assume this is text */
	if (data_len < 0)
		data_len = strlen (data);
	return fu_io_channel_write_raw (self->io_channel,
					(const guint8 *) data,
					(gsize) data_len,
					500, /* ms */
					FU_IO_CHANNEL_FLAG_NONE,
					error);
}

static GString *
fu_altos_device_tty_read (FuAltosDevice *self,
			  guint timeout_ms,
			  gssize max_size,
			  GError **error)
{
	g_autoptr(GBytes) buf = NULL;
	buf = fu_io_channel_read_bytes (self->io_channel, max_size,
					timeout_ms, FU_IO_CHANNEL_FLAG_NONE, error);
	if (buf == NULL)
		return NULL;
	return g_string_new_len (g_bytes_get_data (buf, NULL), g_bytes_get_size (buf));
}

static gboolean
fu_altos_device_tty_open (FuAltosDevice *self, GError **error)
{
	struct termios termios;
	g_autoptr(GString) str = NULL;

	/* open device */
	self->io_channel = fu_io_channel_new_file (self->tty, error);
	if (self->io_channel == NULL)
		return FALSE;

	/* get the old termios settings so we can restore later */<commit_msg>altos: Output raw buffer data when using FWUPD_ALTOS_VERBOSE<commit_after>/*
 * Copyright (C) 2016-2017 <NAME> <<EMAIL>>
 *
 * SPDX-License-Identifier: LGPL-2.1+
 */

#include "config.h"

#include <fcntl.h>
#include <poll.h>
#include <string.h>
#include <termios.h>

#include "fu-io-channel.h"
#include "fu-altos-device.h"
#include "fu-altos-firmware.h"

struct _FuAltosDevice {
	FuUsbDevice		 parent_instance;
	gchar			*tty;
	guint64			 addr_base;
	guint64			 addr_bound;
	struct termios		 tty_termios;
	FuIOChannel		*io_channel;
};

G_DEFINE_TYPE (FuAltosDevice, fu_altos_device, FU_TYPE_USB_DEVICE)

static void
fu_altos_device_to_string (FuDevice *device, guint idt, GString *str)
{
	FuAltosDevice *self = FU_ALTOS_DEVICE (device);
	fu_common_string_append_kv (str, idt, "TTY", self->tty);
	if (self->addr_base != 0x0)
		fu_common_string_append_kx (str, idt, "AddrBase", self->addr_base);
	if (self->addr_bound != 0x0)
		fu_common_string_append_kx (str, idt, "AddrBound", self->addr_bound);
}

static void
fu_altos_device_finalize (GObject *object)
{
	FuAltosDevice *self = FU_ALTOS_DEVICE (object);

	g_free (self->tty);

	G_OBJECT_CLASS (fu_altos_device_parent_class)->finalize (object);
}

static gboolean
fu_altos_device_find_tty (FuAltosDevice *self, GError **error)
{
	GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
	g_autoptr(GList) devices = NULL;
	g_autoptr(GUdevClient) gudev_client = g_udev_client_new (NULL);

	/* find all tty devices */
	devices = g_udev_client_query_by_subsystem (gudev_client, "tty");
	for (GList *l = devices; l != NULL; l = l->next) {
		GUdevDevice *dev = G_UDEV_DEVICE (l->data);

		/* get the tty device */
		const gchar *dev_file = g_udev_device_get_device_file (dev);
		if (dev_file == NULL)
			continue;

		/* get grandparent */
		dev = g_udev_device_get_parent (dev);
		if (dev == NULL)
			continue;
		dev = g_udev_device_get_parent (dev);
		if (dev == NULL)
			continue;

		/* check correct device */
		if (g_udev_device_get_sysfs_attr_as_int (dev, "busnum") !=
		    g_usb_device_get_bus (usb_device))
			continue;
		if (g_udev_device_get_sysfs_attr_as_int (dev, "devnum") !=
		    g_usb_device_get_address (usb_device))
			continue;

		/* success */
		self->tty = g_strdup (dev_file);
		return TRUE;
	}

	/* failure */
	g_set_error (error,
		     FWUPD_ERROR,
		     FWUPD_ERROR_NOT_SUPPORTED,
		     "failed to find tty for %u:%u",
		     g_usb_device_get_bus (usb_device),
		     g_usb_device_get_address (usb_device));
	return FALSE;
}

static gboolean
fu_altos_device_tty_write (FuAltosDevice *self,
			   const gchar *data,
			   gssize data_len,
			   GError **error)
{
	/* lets assume this is text */
	if (data_len < 0)
		data_len = strlen (data);
	if (g_getenv ("FWUPD_ALTOS_VERBOSE") != NULL)
		fu_common_dump_raw (G_LOG_DOMAIN, "write", (const guint8 *) data, (gsize) data_len);
	return fu_io_channel_write_raw (self->io_channel,
					(const guint8 *) data,
					(gsize) data_len,
					500, /* ms */
					FU_IO_CHANNEL_FLAG_NONE,
					error);
}

static GString *
fu_altos_device_tty_read (FuAltosDevice *self,
			  guint timeout_ms,
			  gssize max_size,
			  GError **error)
{
	g_autoptr(GBytes) buf = NULL;
	buf = fu_io_channel_read_bytes (self->io_channel, max_size,
					timeout_ms, FU_IO_CHANNEL_FLAG_NONE, error);
	if (buf == NULL)
		return NULL;
	if (g_getenv ("FWUPD_ALTOS_VERBOSE") != NULL)
		fu_common_dump_bytes (G_LOG_DOMAIN, "read", buf);
	return g_string_new_len (g_bytes_get_data (buf, NULL), g_bytes_get_size (buf));
}

static gboolean
fu_altos_device_tty_open (FuAltosDevice *self, GError **error)
{
	struct termios termios;
	g_autoptr(GString) str = NULL;

	/* open device */
	self->io_channel = fu_io_channel_new_file (self->tty, error);
	if (self->io_channel == NULL)
		return FALSE;

	/* get the old termios settings so we can restore later */
{'fraction_non_alphanumeric': 0.1194331983805668, 'fraction_numerical': 0.006342780026990553, 'mean_word_length': 4.421360643745428, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 47, 'https://': 0, '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': '4915492', 'n_tokens_mistral': 3211, 'n_tokens_neox': 2934, 'n_words': 629}