mirror of
https://git.proxmox.com/git/fwupd
synced 2025-07-29 19:05:25 +00:00
elantp: Support more hardware types
Read the pattern from the hardware rather than hardcoding and support bigger page sizes for later hardware versions.
This commit is contained in:
parent
ae7563d7d7
commit
581aa3c0be
@ -6,19 +6,66 @@ GType = FuElantpHidDevice
|
|||||||
Plugin = elantp
|
Plugin = elantp
|
||||||
GType = FuElantpHidDevice
|
GType = FuElantpHidDevice
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_00]
|
||||||
|
ElantpIcPageCount = 0x200
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_03]
|
||||||
|
ElantpIcPageCount = 0x300
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_06]
|
||||||
|
ElantpIcPageCount = 0x200
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_07]
|
||||||
|
ElantpIcPageCount = 0x300
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_08]
|
||||||
|
ElantpIcPageCount = 0x200
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
[DeviceInstanceId=ELANTP\ICTYPE_0A]
|
[DeviceInstanceId=ELANTP\ICTYPE_0A]
|
||||||
ElantpIcPageCount = 768
|
ElantpIcPageCount = 0x300
|
||||||
ElantpIapPassword = 0xE15A
|
ElantpIapPassword = 0xE15A
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_0B]
|
||||||
|
ElantpIcPageCount = 0x300
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_0C]
|
||||||
|
ElantpIcPageCount = 0x300
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_0E]
|
||||||
|
ElantpIcPageCount = 0x280
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
[DeviceInstanceId=ELANTP\ICTYPE_09]
|
[DeviceInstanceId=ELANTP\ICTYPE_09]
|
||||||
ElantpIcPageCount = 768
|
ElantpIcPageCount = 0x300
|
||||||
ElantpIapPassword = 0x1EA5
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
[DeviceInstanceId=ELANTP\ICTYPE_0D]
|
[DeviceInstanceId=ELANTP\ICTYPE_0D]
|
||||||
ElantpIcPageCount = 896
|
ElantpIcPageCount = 0x380
|
||||||
ElantpIapPassword = 0x1EA5
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
[DeviceInstanceId=ELANTP\ICTYPE_10]
|
[DeviceInstanceId=ELANTP\ICTYPE_10]
|
||||||
ElantpIcPageCount = 1024
|
ElantpIcPageCount = 0x400
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_11]
|
||||||
|
ElantpIcPageCount = 0x500
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_13]
|
||||||
|
ElantpIcPageCount = 0x800
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_14]
|
||||||
|
ElantpIcPageCount = 0x400
|
||||||
|
ElantpIapPassword = 0x1EA5
|
||||||
|
|
||||||
|
[DeviceInstanceId=ELANTP\ICTYPE_15]
|
||||||
|
ElantpIcPageCount = 0x400
|
||||||
ElantpIapPassword = 0x1EA5
|
ElantpIapPassword = 0x1EA5
|
||||||
Flags = iap-version-2
|
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#define FW_PAGE_SIZE 64
|
|
||||||
|
|
||||||
#define ETP_CMD_GET_HARDWARE_ID 0x0100
|
#define ETP_CMD_GET_HARDWARE_ID 0x0100
|
||||||
#define ETP_CMD_GET_MODULE_ID 0x0101
|
#define ETP_CMD_GET_MODULE_ID 0x0101
|
||||||
#define ETP_CMD_I2C_FW_CHECKSUM 0x030F
|
#define ETP_CMD_I2C_FW_CHECKSUM 0x030F
|
||||||
@ -22,6 +20,10 @@
|
|||||||
#define ETP_CMD_I2C_IAP_VERSION 0x0111
|
#define ETP_CMD_I2C_IAP_VERSION 0x0111
|
||||||
#define ETP_CMD_I2C_IAP_VERSION_2 0x0110
|
#define ETP_CMD_I2C_IAP_VERSION_2 0x0110
|
||||||
#define ETP_CMD_I2C_OSM_VERSION 0x0103
|
#define ETP_CMD_I2C_OSM_VERSION 0x0103
|
||||||
|
#define ETP_CMD_I2C_GET_HID_ID 0x0100
|
||||||
|
#define ETP_CMD_I2C_IAP_TYPE 0x0304
|
||||||
|
|
||||||
|
#define ETP_I2C_IAP_TYPE_REG 0x0040
|
||||||
|
|
||||||
#define ETP_I2C_ENABLE_REPORT 0x0800
|
#define ETP_I2C_ENABLE_REPORT 0x0800
|
||||||
|
|
||||||
|
@ -18,15 +18,19 @@
|
|||||||
struct _FuElantpHidDevice {
|
struct _FuElantpHidDevice {
|
||||||
FuUdevDevice parent_instance;
|
FuUdevDevice parent_instance;
|
||||||
guint16 ic_page_count;
|
guint16 ic_page_count;
|
||||||
|
guint16 iap_type;
|
||||||
guint16 iap_ctrl;
|
guint16 iap_ctrl;
|
||||||
guint16 iap_password;
|
guint16 iap_password;
|
||||||
guint16 module_id;
|
guint16 module_id;
|
||||||
|
guint16 fw_page_size;
|
||||||
|
guint8 pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ELANTP_DELAY_COMPLETE 1200 /* ms */
|
#define ELANTP_DELAY_COMPLETE 1200 /* ms */
|
||||||
#define ELANTP_DELAY_RESET 30 /* ms */
|
#define ELANTP_DELAY_RESET 30 /* ms */
|
||||||
#define ELANTP_DELAY_UNLOCK 100 /* ms */
|
#define ELANTP_DELAY_UNLOCK 100 /* ms */
|
||||||
#define ELANTP_DELAY_WRITE_BLOCK 35 /* ms */
|
#define ELANTP_DELAY_WRITE_BLOCK 35 /* ms */
|
||||||
|
#define ELANTP_DELAY_WRITE_BLOCK_512 50 /* ms */
|
||||||
|
|
||||||
G_DEFINE_TYPE (FuElantpHidDevice, fu_elantp_hid_device, FU_TYPE_UDEV_DEVICE)
|
G_DEFINE_TYPE (FuElantpHidDevice, fu_elantp_hid_device, FU_TYPE_UDEV_DEVICE)
|
||||||
|
|
||||||
@ -35,8 +39,11 @@ fu_elantp_hid_device_to_string (FuDevice *device, guint idt, GString *str)
|
|||||||
{
|
{
|
||||||
FuElantpHidDevice *self = FU_ELANTP_HID_DEVICE (device);
|
FuElantpHidDevice *self = FU_ELANTP_HID_DEVICE (device);
|
||||||
fu_common_string_append_kx (str, idt, "ModuleId", self->module_id);
|
fu_common_string_append_kx (str, idt, "ModuleId", self->module_id);
|
||||||
|
fu_common_string_append_kx (str, idt, "Pattern", self->pattern);
|
||||||
|
fu_common_string_append_kx (str, idt, "FwPageSize", self->fw_page_size);
|
||||||
fu_common_string_append_kx (str, idt, "IcPageCount", self->ic_page_count);
|
fu_common_string_append_kx (str, idt, "IcPageCount", self->ic_page_count);
|
||||||
fu_common_string_append_kx (str, idt, "EapCtrl", self->iap_ctrl);
|
fu_common_string_append_kx (str, idt, "IapType", self->iap_type);
|
||||||
|
fu_common_string_append_kx (str, idt, "IapCtrl", self->iap_ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -63,7 +70,10 @@ fu_elantp_hid_device_send_cmd (FuElantpHidDevice *self,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_autofree guint8 *buf = NULL;
|
g_autofree guint8 *buf = NULL;
|
||||||
|
gsize bufsz = rxsz + 3;
|
||||||
|
|
||||||
|
if (g_getenv ("FWUPD_ELANTP_VERBOSE") != NULL)
|
||||||
|
fu_common_dump_raw (G_LOG_DOMAIN, "SetReport", tx, txsz);
|
||||||
if (!fu_udev_device_ioctl (FU_UDEV_DEVICE (self),
|
if (!fu_udev_device_ioctl (FU_UDEV_DEVICE (self),
|
||||||
HIDIOCSFEATURE(txsz), tx,
|
HIDIOCSFEATURE(txsz), tx,
|
||||||
NULL, error))
|
NULL, error))
|
||||||
@ -72,12 +82,14 @@ fu_elantp_hid_device_send_cmd (FuElantpHidDevice *self,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* GetFeature */
|
/* GetFeature */
|
||||||
buf = g_malloc0 (rxsz + 1);
|
buf = g_malloc0 (bufsz);
|
||||||
buf[0] = tx[0]; /* report number */
|
buf[0] = tx[0]; /* report number */
|
||||||
if (!fu_udev_device_ioctl (FU_UDEV_DEVICE (self),
|
if (!fu_udev_device_ioctl (FU_UDEV_DEVICE (self),
|
||||||
HIDIOCGFEATURE(rxsz + 3), buf,
|
HIDIOCGFEATURE(bufsz), buf,
|
||||||
NULL, error))
|
NULL, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
if (g_getenv ("FWUPD_ELANTP_VERBOSE") != NULL)
|
||||||
|
fu_common_dump_raw (G_LOG_DOMAIN, "GetReport", buf, bufsz);
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
memcpy (rx, buf + 0x3, rxsz);
|
memcpy (rx, buf + 0x3, rxsz);
|
||||||
@ -90,8 +102,6 @@ fu_elantp_hid_device_read_cmd (FuElantpHidDevice *self, guint16 reg,
|
|||||||
{
|
{
|
||||||
guint8 buf[5] = { 0x0d, 0x05, 0x03 };
|
guint8 buf[5] = { 0x0d, 0x05, 0x03 };
|
||||||
fu_common_write_uint16 (buf + 0x3, reg, G_LITTLE_ENDIAN);
|
fu_common_write_uint16 (buf + 0x3, reg, G_LITTLE_ENDIAN);
|
||||||
if (g_getenv ("FWUPD_ELANTP_VERBOSE") != NULL)
|
|
||||||
fu_common_dump_raw (G_LOG_DOMAIN, "ReadCmd", buf, sizeof(buf));
|
|
||||||
return fu_elantp_hid_device_send_cmd (self, buf, sizeof(buf), rx, rxsz, error);
|
return fu_elantp_hid_device_send_cmd (self, buf, sizeof(buf), rx, rxsz, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,9 +113,6 @@ fu_elantp_hid_device_write_cmd (FuElantpHidDevice *self,
|
|||||||
guint8 buf[5] = { 0x0d };
|
guint8 buf[5] = { 0x0d };
|
||||||
fu_common_write_uint16 (buf + 0x1, reg, G_LITTLE_ENDIAN);
|
fu_common_write_uint16 (buf + 0x1, reg, G_LITTLE_ENDIAN);
|
||||||
fu_common_write_uint16 (buf + 0x3, cmd, G_LITTLE_ENDIAN);
|
fu_common_write_uint16 (buf + 0x3, cmd, G_LITTLE_ENDIAN);
|
||||||
if (g_getenv ("FWUPD_ELANTP_VERBOSE") != NULL)
|
|
||||||
fu_common_dump_raw (G_LOG_DOMAIN, "WriteCmd", buf, sizeof(buf));
|
|
||||||
|
|
||||||
return fu_elantp_hid_device_send_cmd (self, buf, sizeof(buf), NULL, 0, error);
|
return fu_elantp_hid_device_send_cmd (self, buf, sizeof(buf), NULL, 0, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,8 +140,8 @@ fu_elantp_hid_device_setup (FuDevice *device, GError **error)
|
|||||||
{
|
{
|
||||||
FuElantpHidDevice *self = FU_ELANTP_HID_DEVICE (device);
|
FuElantpHidDevice *self = FU_ELANTP_HID_DEVICE (device);
|
||||||
FuUdevDevice *udev_device = FU_UDEV_DEVICE (device);
|
FuUdevDevice *udev_device = FU_UDEV_DEVICE (device);
|
||||||
gboolean is_new_pattern;
|
|
||||||
guint16 fwver;
|
guint16 fwver;
|
||||||
|
guint16 iap_ver;
|
||||||
guint16 tmp;
|
guint16 tmp;
|
||||||
guint8 buf[2] = { 0x0 };
|
guint8 buf[2] = { 0x0 };
|
||||||
guint8 ic_type;
|
guint8 ic_type;
|
||||||
@ -143,6 +150,16 @@ fu_elantp_hid_device_setup (FuDevice *device, GError **error)
|
|||||||
g_autofree gchar *version_bl = NULL;
|
g_autofree gchar *version_bl = NULL;
|
||||||
g_autofree gchar *version = NULL;
|
g_autofree gchar *version = NULL;
|
||||||
|
|
||||||
|
/* get pattern */
|
||||||
|
if (!fu_elantp_hid_device_read_cmd (self,
|
||||||
|
ETP_CMD_I2C_GET_HID_ID,
|
||||||
|
buf, sizeof(buf), error)) {
|
||||||
|
g_prefix_error (error, "failed to read HID ID: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
tmp = fu_common_read_uint16 (buf, G_LITTLE_ENDIAN);
|
||||||
|
self->pattern = tmp != 0xffff ? (tmp & 0xff00) >> 8 : 0;
|
||||||
|
|
||||||
/* get current firmware version */
|
/* get current firmware version */
|
||||||
if (!fu_elantp_hid_device_read_cmd (self,
|
if (!fu_elantp_hid_device_read_cmd (self,
|
||||||
ETP_CMD_I2C_FW_VERSION,
|
ETP_CMD_I2C_FW_VERSION,
|
||||||
@ -154,16 +171,19 @@ fu_elantp_hid_device_setup (FuDevice *device, GError **error)
|
|||||||
version = fu_common_version_from_uint16 (fwver, FWUPD_VERSION_FORMAT_HEX);
|
version = fu_common_version_from_uint16 (fwver, FWUPD_VERSION_FORMAT_HEX);
|
||||||
fu_device_set_version (device, version);
|
fu_device_set_version (device, version);
|
||||||
|
|
||||||
/* get EAP firmware version */
|
/* get IAP firmware version */
|
||||||
is_new_pattern = fu_device_has_custom_flag (FU_DEVICE (self), "iap-version-2");
|
|
||||||
if (!fu_elantp_hid_device_read_cmd (self,
|
if (!fu_elantp_hid_device_read_cmd (self,
|
||||||
is_new_pattern ? ETP_CMD_I2C_IAP_VERSION_2 : ETP_CMD_I2C_IAP_VERSION,
|
self->pattern == 0 ? ETP_CMD_I2C_IAP_VERSION : ETP_CMD_I2C_IAP_VERSION_2,
|
||||||
buf, sizeof(buf), error)) {
|
buf, sizeof(buf), error)) {
|
||||||
g_prefix_error (error, "failed to read bootloader version: ");
|
g_prefix_error (error, "failed to read bootloader version: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
fwver = fu_common_read_uint16 (buf, G_LITTLE_ENDIAN);
|
if (self->pattern >= 1) {
|
||||||
version_bl = fu_common_version_from_uint16 (fwver, FWUPD_VERSION_FORMAT_HEX);
|
iap_ver = buf[1];
|
||||||
|
} else {
|
||||||
|
iap_ver = fu_common_read_uint16 (buf, G_LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
|
version_bl = fu_common_version_from_uint16 (iap_ver, FWUPD_VERSION_FORMAT_HEX);
|
||||||
fu_device_set_version_bootloader (device, version_bl);
|
fu_device_set_version_bootloader (device, version_bl);
|
||||||
|
|
||||||
/* get module ID */
|
/* get module ID */
|
||||||
@ -200,6 +220,37 @@ fu_elantp_hid_device_setup (FuDevice *device, GError **error)
|
|||||||
instance_id_ic_type = g_strdup_printf ("ELANTP\\ICTYPE_%02X", ic_type);
|
instance_id_ic_type = g_strdup_printf ("ELANTP\\ICTYPE_%02X", ic_type);
|
||||||
fu_device_add_instance_id (device, instance_id_ic_type);
|
fu_device_add_instance_id (device, instance_id_ic_type);
|
||||||
|
|
||||||
|
/* set the page size */
|
||||||
|
self->fw_page_size = 64;
|
||||||
|
if (ic_type >= 0x10) {
|
||||||
|
if (iap_ver >= 1) {
|
||||||
|
/* set the IAP type, presumably some kind of ABI */
|
||||||
|
if (!fu_elantp_hid_device_write_cmd (self,
|
||||||
|
ETP_CMD_I2C_IAP_TYPE,
|
||||||
|
ETP_I2C_IAP_TYPE_REG,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_elantp_hid_device_read_cmd (self, ETP_CMD_I2C_IAP_TYPE,
|
||||||
|
buf, sizeof(buf), error)) {
|
||||||
|
g_prefix_error (error, "failed to read IAP type: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
self->iap_type = fu_common_read_uint16 (buf, G_LITTLE_ENDIAN);
|
||||||
|
if (self->iap_type != ETP_I2C_IAP_TYPE_REG) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOT_SUPPORTED,
|
||||||
|
"failed to set IAP type");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (iap_ver >= 2 && (ic_type == 0x14 || ic_type==0x15)) {
|
||||||
|
self->fw_page_size = 512;
|
||||||
|
} else {
|
||||||
|
self->fw_page_size = 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* no quirk entry */
|
/* no quirk entry */
|
||||||
if (self->ic_page_count == 0x0) {
|
if (self->ic_page_count == 0x0) {
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
@ -209,7 +260,7 @@ fu_elantp_hid_device_setup (FuDevice *device, GError **error)
|
|||||||
ic_type);
|
ic_type);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
fu_device_set_firmware_size (device, self->ic_page_count * FW_PAGE_SIZE);
|
fu_device_set_firmware_size (device, (guint64) self->ic_page_count * (guint64) self->fw_page_size);
|
||||||
|
|
||||||
/* is in bootloader mode */
|
/* is in bootloader mode */
|
||||||
if (!fu_elantp_hid_device_ensure_iap_ctrl (self, error))
|
if (!fu_elantp_hid_device_ensure_iap_ctrl (self, error))
|
||||||
@ -293,20 +344,24 @@ fu_elantp_hid_device_write_firmware (FuDevice *device,
|
|||||||
fu_device_set_status (device, FWUPD_STATUS_DEVICE_WRITE);
|
fu_device_set_status (device, FWUPD_STATUS_DEVICE_WRITE);
|
||||||
buf = g_bytes_get_data (fw, &bufsz);
|
buf = g_bytes_get_data (fw, &bufsz);
|
||||||
iap_addr = fu_elantp_firmware_get_iap_addr (firmware_elantp);
|
iap_addr = fu_elantp_firmware_get_iap_addr (firmware_elantp);
|
||||||
chunks = fu_chunk_array_new (buf + iap_addr, bufsz - iap_addr, 0x0, 0x0, FW_PAGE_SIZE);
|
chunks = fu_chunk_array_new (buf + iap_addr, bufsz - iap_addr, 0x0, 0x0, self->fw_page_size);
|
||||||
for (guint i = 0; i < chunks->len; i++) {
|
for (guint i = 0; i < chunks->len; i++) {
|
||||||
FuChunk *chk = g_ptr_array_index (chunks, i);
|
FuChunk *chk = g_ptr_array_index (chunks, i);
|
||||||
guint16 csum_tmp = fu_elantp_calc_checksum (chk->data, chk->data_sz);
|
guint16 csum_tmp = fu_elantp_calc_checksum (chk->data, chk->data_sz);
|
||||||
guint8 blk[FW_PAGE_SIZE + 3];
|
gsize blksz = self->fw_page_size + 3;
|
||||||
|
g_autofree guint8 *blk = g_malloc0 (blksz);
|
||||||
|
|
||||||
/* write block */
|
/* write block */
|
||||||
blk[0] = 0x0B; /* report ID */
|
blk[0] = 0x0B; /* report ID */
|
||||||
memcpy (blk + 1, chk->data, chk->data_sz);
|
memcpy (blk + 1, chk->data, chk->data_sz);
|
||||||
fu_common_write_uint16 (blk + chk->data_sz + 1, csum_tmp, G_LITTLE_ENDIAN);
|
fu_common_write_uint16 (blk + chk->data_sz + 1, csum_tmp, G_LITTLE_ENDIAN);
|
||||||
|
|
||||||
if (!fu_elantp_hid_device_send_cmd (self, blk, sizeof (blk), NULL, 0, error))
|
if (!fu_elantp_hid_device_send_cmd (self, blk, blksz, NULL, 0, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
g_usleep (ELANTP_DELAY_WRITE_BLOCK * 1000);
|
g_usleep (self->fw_page_size == 512 ?
|
||||||
|
ELANTP_DELAY_WRITE_BLOCK_512 * 1000 :
|
||||||
|
ELANTP_DELAY_WRITE_BLOCK * 1000);
|
||||||
|
|
||||||
if (!fu_elantp_hid_device_ensure_iap_ctrl (self, error))
|
if (!fu_elantp_hid_device_ensure_iap_ctrl (self, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (self->iap_ctrl & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) {
|
if (self->iap_ctrl & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user