mirror of
https://git.proxmox.com/git/fwupd
synced 2025-06-06 02:19:36 +00:00
plugins/nordic-hid: added initial version
The plugin is using Nordic Semiconductor HID config channel to perform devices update directly atteched via USB and BLE. Current implementation supports FW images compatible with the nRF Secure Immutable Bootloader. This version has been tested with nRF52840-DK board. Signed-off-by: Denis Pynkin <denis.pynkin@collabora.com> Signed-off-by: Ricardo Cañuelo <ricardo.canuelo@collabora.com> Signed-off-by: Richard Hughes <richard@hughsie.com>
This commit is contained in:
parent
c47446c411
commit
4fbe1c58c7
@ -448,6 +448,7 @@ done
|
|||||||
%endif
|
%endif
|
||||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_mtd.so
|
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_mtd.so
|
||||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_nitrokey.so
|
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_nitrokey.so
|
||||||
|
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_nordic_hid.so
|
||||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_nvme.so
|
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_nvme.so
|
||||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_optionrom.so
|
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_optionrom.so
|
||||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_parade_lspcon.so
|
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_parade_lspcon.so
|
||||||
|
@ -41,6 +41,7 @@ subdir('modem-manager')
|
|||||||
subdir('msr')
|
subdir('msr')
|
||||||
subdir('mtd')
|
subdir('mtd')
|
||||||
subdir('nitrokey')
|
subdir('nitrokey')
|
||||||
|
subdir('nordic-hid')
|
||||||
subdir('nvme')
|
subdir('nvme')
|
||||||
subdir('optionrom')
|
subdir('optionrom')
|
||||||
subdir('parade-lspcon')
|
subdir('parade-lspcon')
|
||||||
|
45
plugins/nordic-hid/README.md
Normal file
45
plugins/nordic-hid/README.md
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Nordic Semiconductor HID
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This plugin is able flash the firmware on:
|
||||||
|
|
||||||
|
* nRF52-Desktop: nrf52840dk development kit
|
||||||
|
|
||||||
|
The plugin is using Nordic Semiconductor
|
||||||
|
[HID config channel](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/applications/nrf_desktop/doc/config_channel.html)
|
||||||
|
to perform devices update.
|
||||||
|
|
||||||
|
## Firmware Format
|
||||||
|
|
||||||
|
The cabinet file contains ZIP archive prepared by Nordic Semiconductor.
|
||||||
|
This ZIP archive includes 2 signed image blobs for the target
|
||||||
|
device, one firmware blob per application slot, and the `manifest.json` file with the metadata description.
|
||||||
|
At the moment only [nRF Secure Immutable Bootloader](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/bootloader/README.html#bootloader)
|
||||||
|
aka "B0" is supported and tested.
|
||||||
|
|
||||||
|
This plugin supports the following protocol ID:
|
||||||
|
|
||||||
|
* "Nordic HID Config Channel"
|
||||||
|
|
||||||
|
## GUID Generation
|
||||||
|
|
||||||
|
For GUID generation the standard HIDRAW DeviceInstanceId values are used
|
||||||
|
with the addition of the target board and bootloader name:
|
||||||
|
|
||||||
|
* `HIDRAW\VEN_1915&DEV_52DE&BOARD_nrf52840dk&BL_B0` -> 22952036-c346-5755-9646-7bf766b28922
|
||||||
|
* `HIDRAW\VEN_1915&DEV_52DE&BOARD_nrf52840dk&BL_MCUBOOT` -> 43b38427-fdf5-5400-a23c-f3eb7ea00e7c
|
||||||
|
|
||||||
|
## Update Behavior
|
||||||
|
|
||||||
|
The firmware is deployed when the device is in normal runtime mode, and the
|
||||||
|
device will reset when the new firmware has been written.
|
||||||
|
|
||||||
|
## Vendor ID Security
|
||||||
|
|
||||||
|
The vendor ID is set from the HID vendor ID, in this instance set
|
||||||
|
to `HIDRAW:0x1915`.
|
||||||
|
|
||||||
|
## External Interface Access
|
||||||
|
|
||||||
|
This plugin requires ioctl `HIDIOCSFEATURE` and `HIDIOCGFEATURE` access.
|
186
plugins/nordic-hid/fu-nordic-hid-archive.c
Normal file
186
plugins/nordic-hid/fu-nordic-hid-archive.c
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Richard Hughes <richard@hughsie.com>
|
||||||
|
* Copyright (C) 2021 Denis Pynkin <denis.pynkin@collabora.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "fu-nordic-hid-archive.h"
|
||||||
|
#include "fu-nordic-hid-firmware-b0.h"
|
||||||
|
|
||||||
|
/* current version format is 0 */
|
||||||
|
#define MAX_VERSION_FORMAT 0
|
||||||
|
|
||||||
|
struct _FuNordicHidArchive {
|
||||||
|
FuFirmwareClass parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(FuNordicHidArchive, fu_nordic_hid_archive, FU_TYPE_FIRMWARE)
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_nordic_hid_archive_parse(FuFirmware *firmware,
|
||||||
|
GBytes *fw,
|
||||||
|
guint64 addr_start,
|
||||||
|
guint64 addr_end,
|
||||||
|
FwupdInstallFlags flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
JsonNode *json_root_node;
|
||||||
|
JsonObject *json_obj;
|
||||||
|
JsonArray *json_files;
|
||||||
|
guint manifest_ver;
|
||||||
|
guint files_cnt = 0;
|
||||||
|
GBytes *manifest = NULL;
|
||||||
|
g_autoptr(FuArchive) archive = NULL;
|
||||||
|
g_autoptr(JsonParser) parser = json_parser_new();
|
||||||
|
|
||||||
|
/* load archive */
|
||||||
|
archive = fu_archive_new(fw, FU_ARCHIVE_FLAG_IGNORE_PATH, error);
|
||||||
|
if (archive == NULL)
|
||||||
|
return FALSE;
|
||||||
|
manifest = fu_archive_lookup_by_fn(archive, "manifest.json", error);
|
||||||
|
if (manifest == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* parse JSON */
|
||||||
|
if (!json_parser_load_from_data(parser,
|
||||||
|
(const gchar *)g_bytes_get_data(manifest, NULL),
|
||||||
|
(gssize)g_bytes_get_size(manifest),
|
||||||
|
error)) {
|
||||||
|
g_prefix_error(error, "manifest not in JSON format: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
json_root_node = json_parser_get_root(parser);
|
||||||
|
if (json_root_node == NULL || !JSON_NODE_HOLDS_OBJECT(json_root_node)) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"manifest invalid as has no root");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_obj = json_node_get_object(json_root_node);
|
||||||
|
if (!json_object_has_member(json_obj, "format-version")) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"manifest has invalid format");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
manifest_ver = json_object_get_int_member(json_obj, "format-version");
|
||||||
|
if (manifest_ver > MAX_VERSION_FORMAT) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"unsupported manifest version");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_files = json_object_get_array_member(json_obj, "files");
|
||||||
|
if (json_files == NULL) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"manifest invalid as has no 'files' array");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
files_cnt = json_array_get_length(json_files);
|
||||||
|
if (files_cnt == 0) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"manifest invalid as contains no update images");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (guint i = 0; i < files_cnt; i++) {
|
||||||
|
const gchar *filename = NULL;
|
||||||
|
const gchar *bootloader_name = NULL;
|
||||||
|
guint image_addr = 0;
|
||||||
|
JsonObject *obj = json_array_get_object_element(json_files, i);
|
||||||
|
GBytes *blob = NULL;
|
||||||
|
FuFirmware *image = NULL;
|
||||||
|
g_autofree gchar *image_id = NULL;
|
||||||
|
g_auto(GStrv) board_split = NULL;
|
||||||
|
|
||||||
|
if (!json_object_has_member(obj, "file")) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"manifest invalid as has no file name for the image");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
filename = json_object_get_string_member(obj, "file");
|
||||||
|
blob = fu_archive_lookup_by_fn(archive, filename, error);
|
||||||
|
if (blob == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (json_object_has_member(obj, "version_B0")) {
|
||||||
|
bootloader_name = "B0";
|
||||||
|
image = g_object_new(FU_TYPE_NORDIC_HID_FIRMWARE_B0, NULL);
|
||||||
|
} else if (json_object_has_member(obj, "version_MCUBOOT")) {
|
||||||
|
/* TODO: add MCUboot format */
|
||||||
|
bootloader_name = "MCUBOOT";
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"MCUboot bootloader is not supported");
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"only B0 and MCUboot bootloaders are supported");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the "board" field contains board name before "_" symbol */
|
||||||
|
if (!json_object_has_member(obj, "board")) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"manifest invalid as has no target board information");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
board_split = g_strsplit(json_object_get_string_member(obj, "board"), "_", -1);
|
||||||
|
if (board_split[0] == NULL) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"manifest invalid as has no target board information");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
/* images are listed in strict order: this is guaranteed by producer
|
||||||
|
* set the id format as <board>_<bl>_<bank>N, i.e "nrf52840dk_B0_bank0" */
|
||||||
|
image_id = g_strdup_printf("%s_%s_bank%01u", board_split[0], bootloader_name, i);
|
||||||
|
if (!fu_firmware_parse(image, blob, flags, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
fu_firmware_set_id(image, image_id);
|
||||||
|
fu_firmware_set_idx(image, i);
|
||||||
|
if (json_object_has_member(obj, "load_address")) {
|
||||||
|
image_addr = json_object_get_int_member(obj, "load_address");
|
||||||
|
fu_firmware_set_addr(image, image_addr);
|
||||||
|
}
|
||||||
|
fu_firmware_add_image(firmware, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_nordic_hid_archive_init(FuNordicHidArchive *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_nordic_hid_archive_class_init(FuNordicHidArchiveClass *klass)
|
||||||
|
{
|
||||||
|
FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS(klass);
|
||||||
|
klass_firmware->parse = fu_nordic_hid_archive_parse;
|
||||||
|
}
|
16
plugins/nordic-hid/fu-nordic-hid-archive.h
Normal file
16
plugins/nordic-hid/fu-nordic-hid-archive.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fwupdplugin.h>
|
||||||
|
|
||||||
|
#define FU_TYPE_NORDIC_HID_ARCHIVE (fu_nordic_hid_archive_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE(FuNordicHidArchive,
|
||||||
|
fu_nordic_hid_archive,
|
||||||
|
FU,
|
||||||
|
NORDIC_HID_ARCHIVE,
|
||||||
|
FuArchiveFirmware)
|
1078
plugins/nordic-hid/fu-nordic-hid-cfg-channel.c
Normal file
1078
plugins/nordic-hid/fu-nordic-hid-cfg-channel.c
Normal file
File diff suppressed because it is too large
Load Diff
16
plugins/nordic-hid/fu-nordic-hid-cfg-channel.h
Normal file
16
plugins/nordic-hid/fu-nordic-hid-cfg-channel.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Ricardo Cañuelo <ricardo.canuelo@collabora.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fwupdplugin.h>
|
||||||
|
|
||||||
|
#define FU_TYPE_NORDIC_HID_CFG_CHANNEL (fu_nordic_hid_cfg_channel_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE(FuNordicDeviceCfgChannel,
|
||||||
|
fu_nordic_hid_cfg_channel,
|
||||||
|
FU,
|
||||||
|
NORDIC_HID_CFG_CHANNEL,
|
||||||
|
FuUdevDevice)
|
178
plugins/nordic-hid/fu-nordic-hid-firmware-b0.c
Normal file
178
plugins/nordic-hid/fu-nordic-hid-firmware-b0.c
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Denis Pynkin <denis.pynkin@collabora.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <fwupdplugin.h>
|
||||||
|
|
||||||
|
#include "fu-nordic-hid-firmware-b0.h"
|
||||||
|
|
||||||
|
#define UPDATE_IMAGE_MAGIC_COMMON 0x281ee6de
|
||||||
|
#define UPDATE_IMAGE_MAGIC_FWINFO 0x8fcebb4c
|
||||||
|
#define UPDATE_IMAGE_MAGIC_NRF52 0x00003402
|
||||||
|
#define UPDATE_IMAGE_MAGIC_NRF53 0x00003502
|
||||||
|
|
||||||
|
struct _FuNordicHidFirmwareB0 {
|
||||||
|
FuIhexFirmwareClass parent_instance;
|
||||||
|
guint32 crc32;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(FuNordicHidFirmwareB0, fu_nordic_hid_firmware_b0, FU_TYPE_FIRMWARE)
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_nordic_hid_firmware_b0_export(FuFirmware *firmware,
|
||||||
|
FuFirmwareExportFlags flags,
|
||||||
|
XbBuilderNode *bn)
|
||||||
|
{
|
||||||
|
FuNordicHidFirmwareB0 *self = FU_NORDIC_HID_FIRMWARE_B0(firmware);
|
||||||
|
fu_xmlb_builder_insert_kx(bn, "crc32", self->crc32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GBytes *
|
||||||
|
fu_nordic_hid_firmware_b0_write(FuFirmware *firmware, GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GByteArray) buf = g_byte_array_new();
|
||||||
|
g_autoptr(GBytes) blob = NULL;
|
||||||
|
fu_byte_array_append_uint32(buf, UPDATE_IMAGE_MAGIC_COMMON, G_LITTLE_ENDIAN);
|
||||||
|
fu_byte_array_append_uint32(buf, UPDATE_IMAGE_MAGIC_FWINFO, G_LITTLE_ENDIAN);
|
||||||
|
fu_byte_array_append_uint32(buf, UPDATE_IMAGE_MAGIC_NRF52, G_LITTLE_ENDIAN);
|
||||||
|
blob = fu_firmware_get_bytes(firmware, error);
|
||||||
|
if (blob == NULL)
|
||||||
|
return NULL;
|
||||||
|
fu_byte_array_append_bytes(buf, blob);
|
||||||
|
return g_byte_array_free_to_bytes(g_steal_pointer(&buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_nordic_hid_firmware_b0_read_fwinfo(guint8 const *buf, gsize bufsz, GError **error)
|
||||||
|
{
|
||||||
|
guint32 magic_common;
|
||||||
|
guint32 magic_fwinfo;
|
||||||
|
guint32 magic_compat;
|
||||||
|
guint32 offset;
|
||||||
|
guint32 hdr_offset[5] = {0x0000, 0x0200, 0x400, 0x800, 0x1000};
|
||||||
|
|
||||||
|
/* find correct offset to fwinfo */
|
||||||
|
for (guint32 i = 0; i < G_N_ELEMENTS(hdr_offset); i++) {
|
||||||
|
offset = hdr_offset[i];
|
||||||
|
if (!fu_common_read_uint32_safe(buf,
|
||||||
|
bufsz,
|
||||||
|
offset,
|
||||||
|
&magic_common,
|
||||||
|
G_LITTLE_ENDIAN,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_common_read_uint32_safe(buf,
|
||||||
|
bufsz,
|
||||||
|
offset + 0x04,
|
||||||
|
&magic_fwinfo,
|
||||||
|
G_LITTLE_ENDIAN,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_common_read_uint32_safe(buf,
|
||||||
|
bufsz,
|
||||||
|
offset + 0x08,
|
||||||
|
&magic_compat,
|
||||||
|
G_LITTLE_ENDIAN,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
if (magic_common != UPDATE_IMAGE_MAGIC_COMMON ||
|
||||||
|
magic_fwinfo != UPDATE_IMAGE_MAGIC_FWINFO)
|
||||||
|
continue;
|
||||||
|
switch (magic_compat) {
|
||||||
|
case UPDATE_IMAGE_MAGIC_NRF52:
|
||||||
|
case UPDATE_IMAGE_MAGIC_NRF53:
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"unable to validate the update binary");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint32
|
||||||
|
fu_nordic_hid_firmware_b0_crc32(const guint8 *buf, gsize bufsz)
|
||||||
|
{
|
||||||
|
guint crc32 = 0x01;
|
||||||
|
/* maybe skipped "^" step in fu_common_crc32_full()?
|
||||||
|
* according https://github.com/madler/zlib/blob/master/crc32.c#L225 */
|
||||||
|
crc32 ^= 0xFFFFFFFFUL;
|
||||||
|
return fu_common_crc32_full(buf, bufsz, crc32, 0xEDB88320);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
fu_nordic_hid_firmware_b0_get_checksum(FuFirmware *firmware,
|
||||||
|
GChecksumType csum_kind,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
FuNordicHidFirmwareB0 *self = FU_NORDIC_HID_FIRMWARE_B0(firmware);
|
||||||
|
if (!fu_firmware_has_flag(firmware, FU_FIRMWARE_FLAG_HAS_CHECKSUM)) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_NOT_SUPPORTED,
|
||||||
|
"unable to calculate the checksum of the update binary");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return g_strdup_printf("%x", self->crc32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_nordic_hid_firmware_b0_parse(FuFirmware *firmware,
|
||||||
|
GBytes *fw,
|
||||||
|
guint64 addr_start,
|
||||||
|
guint64 addr_end,
|
||||||
|
FwupdInstallFlags flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
FuNordicHidFirmwareB0 *self = FU_NORDIC_HID_FIRMWARE_B0(firmware);
|
||||||
|
const guint8 *buf;
|
||||||
|
gsize bufsz = 0;
|
||||||
|
|
||||||
|
buf = g_bytes_get_data(fw, &bufsz);
|
||||||
|
if (buf == NULL) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"unable to get the image binary");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!fu_nordic_hid_firmware_b0_read_fwinfo(buf, bufsz, error))
|
||||||
|
return FALSE;
|
||||||
|
self->crc32 = fu_nordic_hid_firmware_b0_crc32(buf, bufsz);
|
||||||
|
fu_firmware_add_flag(FU_FIRMWARE(self), FU_FIRMWARE_FLAG_HAS_CHECKSUM);
|
||||||
|
|
||||||
|
/* do not strip the header */
|
||||||
|
fu_firmware_set_bytes(firmware, fw);
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_nordic_hid_firmware_b0_init(FuNordicHidFirmwareB0 *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_nordic_hid_firmware_b0_class_init(FuNordicHidFirmwareB0Class *klass)
|
||||||
|
{
|
||||||
|
FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS(klass);
|
||||||
|
klass_firmware->get_checksum = fu_nordic_hid_firmware_b0_get_checksum;
|
||||||
|
klass_firmware->export = fu_nordic_hid_firmware_b0_export;
|
||||||
|
klass_firmware->parse = fu_nordic_hid_firmware_b0_parse;
|
||||||
|
klass_firmware->write = fu_nordic_hid_firmware_b0_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
FuFirmware *
|
||||||
|
fu_nordic_hid_firmware_b0_new(void)
|
||||||
|
{
|
||||||
|
return FU_FIRMWARE(g_object_new(FU_TYPE_NORDIC_HID_FIRMWARE_B0, NULL));
|
||||||
|
}
|
19
plugins/nordic-hid/fu-nordic-hid-firmware-b0.h
Normal file
19
plugins/nordic-hid/fu-nordic-hid-firmware-b0.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Denis Pynkin <denis.pynkin@collabora.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fwupdplugin.h>
|
||||||
|
|
||||||
|
#define FU_TYPE_NORDIC_HID_FIRMWARE_B0 (fu_nordic_hid_firmware_b0_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE(FuNordicHidFirmwareB0,
|
||||||
|
fu_nordic_hid_firmware_b0,
|
||||||
|
FU,
|
||||||
|
NORDIC_HID_FIRMWARE_B0,
|
||||||
|
FuFirmware)
|
||||||
|
|
||||||
|
FuFirmware *
|
||||||
|
fu_nordic_hid_firmware_b0_new(void);
|
29
plugins/nordic-hid/fu-plugin-nordic-hid.c
Normal file
29
plugins/nordic-hid/fu-plugin-nordic-hid.c
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Ricardo Cañuelo <ricardo.canuelo@collabora.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <fwupdplugin.h>
|
||||||
|
|
||||||
|
#include "fu-nordic-hid-archive.h"
|
||||||
|
#include "fu-nordic-hid-cfg-channel.h"
|
||||||
|
#include "fu-nordic-hid-firmware-b0.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_plugin_nordic_hid_init(FuPlugin *plugin)
|
||||||
|
{
|
||||||
|
fu_plugin_add_udev_subsystem(plugin, "hidraw");
|
||||||
|
fu_plugin_add_device_gtype(plugin, FU_TYPE_NORDIC_HID_CFG_CHANNEL);
|
||||||
|
fu_plugin_add_firmware_gtype(plugin, NULL, FU_TYPE_NORDIC_HID_ARCHIVE);
|
||||||
|
fu_plugin_add_firmware_gtype(plugin, NULL, FU_TYPE_NORDIC_HID_FIRMWARE_B0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fu_plugin_init_vfuncs(FuPluginVfuncs *vfuncs)
|
||||||
|
{
|
||||||
|
vfuncs->build_hash = FU_BUILD_HASH;
|
||||||
|
vfuncs->init = fu_plugin_nordic_hid_init;
|
||||||
|
}
|
34
plugins/nordic-hid/meson.build
Normal file
34
plugins/nordic-hid/meson.build
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
if get_option('gudev') and get_option('gusb')
|
||||||
|
cargs = ['-DG_LOG_DOMAIN="FuPluginNordicHid"']
|
||||||
|
|
||||||
|
install_data([
|
||||||
|
'nordic-hid.quirk',
|
||||||
|
],
|
||||||
|
install_dir: join_paths(datadir, 'fwupd', 'quirks.d')
|
||||||
|
)
|
||||||
|
|
||||||
|
shared_module('fu_plugin_nordic_hid',
|
||||||
|
fu_hash,
|
||||||
|
sources : [
|
||||||
|
'fu-plugin-nordic-hid.c',
|
||||||
|
'fu-nordic-hid-cfg-channel.c',
|
||||||
|
'fu-nordic-hid-firmware-b0.c',
|
||||||
|
'fu-nordic-hid-archive.c',
|
||||||
|
],
|
||||||
|
include_directories : [
|
||||||
|
root_incdir,
|
||||||
|
fwupd_incdir,
|
||||||
|
fwupdplugin_incdir,
|
||||||
|
],
|
||||||
|
install : true,
|
||||||
|
install_dir: plugin_dir,
|
||||||
|
link_with : [
|
||||||
|
fwupd,
|
||||||
|
fwupdplugin,
|
||||||
|
],
|
||||||
|
c_args : cargs,
|
||||||
|
dependencies : [
|
||||||
|
plugin_deps,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
endif
|
9
plugins/nordic-hid/nordic-hid.quirk
Normal file
9
plugins/nordic-hid/nordic-hid.quirk
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Mouse nRF52 Desktop
|
||||||
|
[HIDRAW\VEN_1915&DEV_52DE]
|
||||||
|
Plugin = nordic_hid
|
||||||
|
GType = FuNordicHidCfgChannel
|
||||||
|
|
||||||
|
# Nordic Semiconductor ASA Dongle nRF52 Desktop
|
||||||
|
[HIDRAW\VEN_1915&DEV_52DC]
|
||||||
|
Plugin = nordic_hid
|
||||||
|
GType = FuNordicHidCfgChannel
|
BIN
plugins/nordic-hid/tests/nordic-hid.bin
Normal file
BIN
plugins/nordic-hid/tests/nordic-hid.bin
Normal file
Binary file not shown.
3
plugins/nordic-hid/tests/nordic-hid.builder.xml
Normal file
3
plugins/nordic-hid/tests/nordic-hid.builder.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<firmware gtype="FuNordicHidFirmwareB0">
|
||||||
|
<data>aGVsbG8gd29ybGQ=</data> <!-- base64 -->
|
||||||
|
</firmware>
|
Loading…
Reference in New Issue
Block a user