superio: Move all the IT85xx code to a subclassed device object

This commit is contained in:
Richard Hughes 2019-03-22 11:49:50 +00:00
parent ebd55e5d14
commit ebedf62b15
6 changed files with 132 additions and 69 deletions

View File

@ -8,7 +8,7 @@
#include "fu-plugin-vfuncs.h"
#include "fu-superio-device.h"
#include "fu-superio-it85-device.h"
#define FU_QUIRKS_SUPERIO_CHIPSETS "SuperioChipsets"
@ -41,12 +41,26 @@ fu_plugin_superio_coldplug_chipset (FuPlugin *plugin, const gchar *chipset, GErr
return FALSE;
}
/* create IT8xxx */
/* create IT89xx or IT89xx */
if (id >> 8 == 0x85) {
dev = g_object_new (FU_TYPE_SUPERIO_IT85_DEVICE,
"chipset", chipset,
"id", id,
"port", port,
NULL);
} else if (id >> 8 == 0x89) {
dev = g_object_new (FU_TYPE_SUPERIO_DEVICE,
"chipset", chipset,
"id", id,
"port", port,
NULL);
} else {
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"SuperIO chip %s has unsupported Id", chipset);
return FALSE;
}
/* unlock */
locker = fu_device_locker_new (dev, error);

View File

@ -17,10 +17,6 @@
#define FU_PLUGIN_SUPERIO_TIMEOUT 0.25 /* s */
/* unknown source, IT87 only */
#define SIO_CMD_EC_GET_NAME_STR 0x92
#define SIO_CMD_EC_GET_VERSION_STR 0x93
typedef struct
{
gint fd;
@ -206,7 +202,7 @@ fu_superio_device_ec_write1 (FuSuperioDevice *self, guint8 data, GError **error)
return fu_superio_outb (priv->fd, priv->pm1_iobad1, data, error);
}
static gboolean
gboolean
fu_superio_device_ec_flush (FuSuperioDevice *self, GError **error)
{
FuSuperioDevicePrivate *priv = GET_PRIVATE (self);
@ -231,7 +227,7 @@ fu_superio_device_ec_flush (FuSuperioDevice *self, GError **error)
return TRUE;
}
static gboolean
gboolean
fu_superio_device_ec_get_param (FuSuperioDevice *self, guint8 param, guint8 *data, GError **error)
{
if (!fu_superio_device_ec_write1 (self, SIO_CMD_EC_READ, error))
@ -253,23 +249,6 @@ fu_superio_device_ec_set_param (FuSuperioDevice *self, guint8 param, guint8 data
}
#endif
static gchar *
fu_superio_device_ec_get_str (FuSuperioDevice *self, guint8 idx, GError **error)
{
GString *str = g_string_new (NULL);
if (!fu_superio_device_ec_write1 (self, idx, error))
return NULL;
for (guint i = 0; i < 0xff; i++) {
guint8 c = 0;
if (!fu_superio_device_ec_read (self, &c, error))
return NULL;
if (c == '$')
break;
g_string_append_c (str, c);
}
return g_string_free (str, FALSE);
}
static gboolean
fu_superio_device_open (FuDevice *device, GError **error)
{
@ -306,40 +285,6 @@ fu_superio_device_probe (FuDevice *device, GError **error)
return TRUE;
}
static gboolean
fu_superio_device_setup_it85xx (FuSuperioDevice *self, GError **error)
{
guint8 size_tmp = 0;
g_autofree gchar *name = NULL;
g_autofree gchar *version = NULL;
/* get EC size */
if (!fu_superio_device_ec_flush (self, error)) {
g_prefix_error (error, "failed to flush: ");
return FALSE;
}
if (!fu_superio_device_ec_get_param (self, 0xe5, &size_tmp, error)) {
g_prefix_error (error, "failed to get EC size: ");
return FALSE;
}
fu_device_set_firmware_size (FU_DEVICE (self), ((guint32) size_tmp) << 10);
/* get EC strings */
name = fu_superio_device_ec_get_str (self, SIO_CMD_EC_GET_NAME_STR, error);
if (name == NULL) {
g_prefix_error (error, "failed to get EC name: ");
return FALSE;
}
fu_device_set_name (FU_DEVICE (self), name);
version = fu_superio_device_ec_get_str (self, SIO_CMD_EC_GET_VERSION_STR, error);
if (version == NULL) {
g_prefix_error (error, "failed to get EC version: ");
return FALSE;
}
fu_device_set_version (FU_DEVICE (self), version);
return TRUE;
}
static gboolean
fu_superio_device_it89xx_read_ec_register (FuSuperioDevice *self,
guint16 addr,
@ -450,6 +395,7 @@ fu_superio_device_setup_it89xx (FuSuperioDevice *self, GError **error)
static gboolean
fu_superio_device_setup (FuDevice *device, GError **error)
{
FuSuperioDeviceClass *klass = FU_SUPERIO_DEVICE_GET_CLASS (device);
FuSuperioDevice *self = FU_SUPERIO_DEVICE (device);
FuSuperioDevicePrivate *priv = GET_PRIVATE (self);
guint8 tmp = 0x0;
@ -506,11 +452,9 @@ fu_superio_device_setup (FuDevice *device, GError **error)
fu_common_dump_raw (G_LOG_DOMAIN, "EC Registers", buf, 0x100);
}
/* IT85xx */
if (priv->id >> 8 == 0x85) {
if (!fu_superio_device_setup_it85xx (self, error))
return FALSE;
}
/* subclassed setup */
if (klass->setup != NULL)
return klass->setup (self, error);
/* IT89xx */
if (priv->id >> 8 == 0x89) {

View File

@ -16,8 +16,12 @@ G_DECLARE_DERIVABLE_TYPE (FuSuperioDevice, fu_superio_device, FU, SUPERIO_DEVICE
struct _FuSuperioDeviceClass
{
FuDeviceClass parent_class;
gboolean (*setup) (FuSuperioDevice *self,
GError **error);
};
gboolean fu_superio_device_ec_flush (FuSuperioDevice *self,
GError **error);
gboolean fu_superio_device_ec_read (FuSuperioDevice *self,
guint8 *data,
GError **error);
@ -27,6 +31,10 @@ gboolean fu_superio_device_ec_write0 (FuSuperioDevice *self,
gboolean fu_superio_device_ec_write1 (FuSuperioDevice *self,
guint8 data,
GError **error);
gboolean fu_superio_device_ec_get_param (FuSuperioDevice *self,
guint8 param,
guint8 *data,
GError **error);
gboolean fu_superio_device_regval (FuSuperioDevice *self,
guint8 addr,
guint8 *data,

View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2018-2019 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-chunk.h"
#include "fu-superio-common.h"
#include "fu-superio-it85-device.h"
struct _FuSuperioIt85Device {
FuSuperioDevice parent_instance;
};
G_DEFINE_TYPE (FuSuperioIt85Device, fu_superio_it85_device, FU_TYPE_SUPERIO_DEVICE)
static gchar *
fu_superio_it85_device_get_str (FuSuperioDevice *self, guint8 idx, GError **error)
{
GString *str = g_string_new (NULL);
if (!fu_superio_device_ec_write1 (self, idx, error))
return NULL;
for (guint i = 0; i < 0xff; i++) {
guint8 c = 0;
if (!fu_superio_device_ec_read (self, &c, error))
return NULL;
if (c == '$')
break;
g_string_append_c (str, c);
}
return g_string_free (str, FALSE);
}
static gboolean
fu_superio_it85_device_setup (FuSuperioDevice *self, GError **error)
{
guint8 size_tmp = 0;
g_autofree gchar *name = NULL;
g_autofree gchar *version = NULL;
/* get EC size */
if (!fu_superio_device_ec_flush (self, error)) {
g_prefix_error (error, "failed to flush: ");
return FALSE;
}
if (!fu_superio_device_ec_get_param (self, 0xe5, &size_tmp, error)) {
g_prefix_error (error, "failed to get EC size: ");
return FALSE;
}
fu_device_set_firmware_size (FU_DEVICE (self), ((guint32) size_tmp) << 10);
/* get EC strings */
name = fu_superio_it85_device_get_str (self, SIO_CMD_EC_GET_NAME_STR, error);
if (name == NULL) {
g_prefix_error (error, "failed to get EC name: ");
return FALSE;
}
fu_device_set_name (FU_DEVICE (self), name);
version = fu_superio_it85_device_get_str (self, SIO_CMD_EC_GET_VERSION_STR, error);
if (version == NULL) {
g_prefix_error (error, "failed to get EC version: ");
return FALSE;
}
fu_device_set_version (FU_DEVICE (self), version);
return TRUE;
}
static void
fu_superio_it85_device_init (FuSuperioIt85Device *self)
{
}
static void
fu_superio_it85_device_class_init (FuSuperioIt85DeviceClass *klass)
{
FuSuperioDeviceClass *klass_superio_device = FU_SUPERIO_DEVICE_CLASS (klass);
klass_superio_device->setup = fu_superio_it85_device_setup;
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2018-2019 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include "fu-superio-device.h"
G_BEGIN_DECLS
#define FU_TYPE_SUPERIO_IT85_DEVICE (fu_superio_it85_device_get_type ())
G_DECLARE_FINAL_TYPE (FuSuperioIt85Device, fu_superio_it85_device, FU, SUPERIO_IT85_DEVICE, FuSuperioDevice)
G_END_DECLS

View File

@ -9,6 +9,7 @@ shared_module('fu_plugin_superio',
sources : [
'fu-plugin-superio.c',
'fu-superio-device.c',
'fu-superio-it85-device.c',
'fu-superio-common.c',
],
include_directories : [