mirror of
https://git.proxmox.com/git/fwupd
synced 2026-01-03 20:26:51 +00:00
Add support for devices supporting the Logitech bulk controller protocol
This commit is contained in:
parent
ce6da002aa
commit
b6ff1ea40e
@ -7,6 +7,13 @@ export DESTDIR=${root}/dist
|
||||
build=$root/build-win32
|
||||
rm -rf $DESTDIR $build
|
||||
|
||||
# For logitech bulk controller being disabled (-Dplugin_logitech_bulkcontroller=false):
|
||||
# See https://bugzilla.redhat.com/show_bug.cgi?id=1991749
|
||||
# When fixed need to do the following to enable:
|
||||
# 1. need to add mingw64-protobuf mingw64-protobuf-tools to CI build deps
|
||||
# 2. add protoc = /path/to/protoc-c.exe in mingw64.cross
|
||||
# 3. Only enable when not a tagged release (Unsupported by Logitech)
|
||||
|
||||
#build
|
||||
mkdir -p $build $DESTDIR && cd $build
|
||||
meson .. \
|
||||
@ -22,6 +29,7 @@ meson .. \
|
||||
-Dplugin_redfish=false \
|
||||
-Dplugin_altos=false \
|
||||
-Dplugin_dell=false \
|
||||
-Dplugin_logitech_bulkcontroller=false \
|
||||
-Dplugin_nvme=false \
|
||||
-Dplugin_parade_lspcon=false \
|
||||
-Dplugin_realtek_mst=false \
|
||||
|
||||
@ -1553,4 +1553,41 @@
|
||||
<package>ShellCheck</package>
|
||||
</distro>
|
||||
</dependency>
|
||||
<dependency type="build" id="libprotobuf-c-dev">
|
||||
<distro id="arch">
|
||||
<package>protobuf-c</package>
|
||||
</distro>
|
||||
<distro id="debian">
|
||||
<control />
|
||||
<package variant="x86_64" />
|
||||
<package variant="i386" />
|
||||
</distro>
|
||||
<distro id="ubuntu">
|
||||
<control />
|
||||
<package variant="x86_64" />
|
||||
</distro>
|
||||
<distro id="fedora">
|
||||
<package>protobuf-c-devel</package>
|
||||
</distro>
|
||||
<distro id="void">
|
||||
<package>protobuf-c-devel</package>
|
||||
</distro>
|
||||
</dependency>
|
||||
<dependency type="build" id="protobuf-c-compiler">
|
||||
<distro id="debian">
|
||||
<control />
|
||||
<package variant="x86_64" />
|
||||
<package variant="i386" />
|
||||
</distro>
|
||||
<distro id="ubuntu">
|
||||
<control />
|
||||
<package variant="x86_64" />
|
||||
</distro>
|
||||
<distro id="fedora">
|
||||
<package />
|
||||
</distro>
|
||||
<distro id="void">
|
||||
<package>protobuf</package>
|
||||
</distro>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@ -26,6 +26,7 @@ LIB_DEPENDS= libcurl.so:ftp/curl \
|
||||
libgusb.so:devel/libgusb \
|
||||
libjcat.so:textproc/libjcat \
|
||||
libjson-glib-1.0.so:devel/json-glib \
|
||||
libprotobuf-c.so:devel/protobuf-c \
|
||||
libxmlb.so:textproc/libxmlb \
|
||||
libefiboot.so:devel/gnu-efi
|
||||
|
||||
|
||||
@ -481,6 +481,7 @@ done
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_uefi_recovery.so
|
||||
%endif
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_logind.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_logitech_bulkcontroller.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_logitech_hidpp.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_upower.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_vli.so
|
||||
|
||||
@ -544,6 +544,12 @@ if get_option('libarchive')
|
||||
plugin_deps += libarchive
|
||||
endif
|
||||
|
||||
if get_option('plugin_logitech_bulkcontroller')
|
||||
protobufc = dependency('libprotobuf-c')
|
||||
protoc = find_program('protoc', 'protoc-c')
|
||||
plugin_deps += protobufc
|
||||
endif
|
||||
|
||||
root_incdir = include_directories('.')
|
||||
|
||||
if get_option('docs') == 'gtkdoc'
|
||||
|
||||
@ -17,6 +17,7 @@ option('plugin_amt', type : 'boolean', value : true, description : 'enable Intel
|
||||
option('plugin_dell', type : 'boolean', value : true, description : 'enable Dell-specific support')
|
||||
option('plugin_dummy', type : 'boolean', value : false, description : 'enable the dummy device')
|
||||
option('plugin_emmc', type : 'boolean', value : true, description : 'enable eMMC support')
|
||||
option('plugin_logitech_bulkcontroller', type : 'boolean', value : true, description : 'enable Logitech bulk controller support')
|
||||
option('plugin_parade_lspcon', type : 'boolean', value : true, description : 'enable Parade LSPCON support')
|
||||
option('plugin_realtek_mst', type : 'boolean', value : true, description : 'enable Realtek MST hub support')
|
||||
option('plugin_synaptics_mst', type: 'boolean', value: true, description : 'enable Synaptics MST hub support')
|
||||
|
||||
40
plugins/logitech-bulkcontroller/README.md
Normal file
40
plugins/logitech-bulkcontroller/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Logitech Video Collaboration
|
||||
|
||||
## Introduction
|
||||
|
||||
This plugin can upgrade the firmware on Logitech Video Collaboration products (Rally Bar and Rally Bar Mini), using USB bulk transfer.
|
||||
|
||||
## Firmware Format
|
||||
|
||||
The daemon will decompress the cabinet archive and extract a firmware blob in
|
||||
a packed binary file format.
|
||||
|
||||
This plugin supports the following protocol ID:
|
||||
|
||||
* com.logitech.vc.proto
|
||||
|
||||
## GUID Generation
|
||||
|
||||
These devices use the standard USB DeviceInstanceId values, e.g.
|
||||
|
||||
* `USB\VID_046D&PID_089B`
|
||||
* `USB\VID_046D&PID_08D3`
|
||||
|
||||
## Quirk Use
|
||||
|
||||
This plugin uses the following plugin-specific quirks:
|
||||
|
||||
## Update Behavior
|
||||
|
||||
The peripheral firmware is deployed when the device is in normal runtime mode,
|
||||
and the device will reset when the new firmware has been written.
|
||||
|
||||
## Design Notes
|
||||
|
||||
## Vendor ID Security
|
||||
|
||||
The vendor ID is set from the USB vendor, in this instance set to `USB:0x046D`
|
||||
|
||||
## External Interface Access
|
||||
|
||||
This plugin requires read/write access to `/dev/bus/usb`.
|
||||
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#include "fu-logitech-bulkcontroller-common.h"
|
||||
#include "usb_msg.pb-c.h"
|
||||
|
||||
static void
|
||||
proto_manager_set_header(Logi__Device__Proto__Header *header_msg)
|
||||
{
|
||||
gint64 timestamp_tv;
|
||||
|
||||
g_return_if_fail(header_msg != NULL);
|
||||
|
||||
timestamp_tv = g_get_real_time();
|
||||
header_msg->id = g_uuid_string_random();
|
||||
header_msg->timestamp = g_strdup_printf("%" G_GINT64_FORMAT, timestamp_tv / 1000);
|
||||
}
|
||||
|
||||
GByteArray *
|
||||
proto_manager_generate_get_device_info_request(void)
|
||||
{
|
||||
GByteArray *buf = g_byte_array_new();
|
||||
Logi__Device__Proto__Header header_msg = LOGI__DEVICE__PROTO__HEADER__INIT;
|
||||
Logi__Device__Proto__GetDeviceInfoRequest get_deviceinfo_msg =
|
||||
LOGI__DEVICE__PROTO__GET_DEVICE_INFO_REQUEST__INIT;
|
||||
Logi__Device__Proto__Request request_msg = {
|
||||
PROTOBUF_C_MESSAGE_INIT(&logi__device__proto__request__descriptor),
|
||||
LOGI__DEVICE__PROTO__REQUEST__PAYLOAD_GET_DEVICE_INFO_REQUEST,
|
||||
{&get_deviceinfo_msg}};
|
||||
Logi__Device__Proto__UsbMsg usb_msg = LOGI__DEVICE__PROTO__USB_MSG__INIT;
|
||||
|
||||
proto_manager_set_header(&header_msg);
|
||||
usb_msg.header = &header_msg;
|
||||
usb_msg.message_case = LOGI__DEVICE__PROTO__USB_MSG__MESSAGE_REQUEST;
|
||||
usb_msg.request = &request_msg;
|
||||
|
||||
fu_byte_array_set_size(buf, logi__device__proto__usb_msg__get_packed_size(&usb_msg));
|
||||
logi__device__proto__usb_msg__pack(&usb_msg, (unsigned char *)buf->data);
|
||||
return buf;
|
||||
}
|
||||
|
||||
GByteArray *
|
||||
proto_manager_generate_transition_to_device_mode_request(void)
|
||||
{
|
||||
GByteArray *buf = g_byte_array_new();
|
||||
Logi__Device__Proto__Header header_msg = LOGI__DEVICE__PROTO__HEADER__INIT;
|
||||
Logi__Device__Proto__TransitionToDeviceModeRequest transition_to_device_mode_msg =
|
||||
LOGI__DEVICE__PROTO__TRANSITION_TO_DEVICE_MODE_REQUEST__INIT;
|
||||
Logi__Device__Proto__Request request_msg = {
|
||||
PROTOBUF_C_MESSAGE_INIT(&logi__device__proto__request__descriptor),
|
||||
LOGI__DEVICE__PROTO__REQUEST__PAYLOAD_TRANSITION_TO_DEVICEMODE_REQUEST,
|
||||
{(Logi__Device__Proto__GetDeviceInfoRequest *)&transition_to_device_mode_msg}};
|
||||
Logi__Device__Proto__UsbMsg usb_msg = LOGI__DEVICE__PROTO__USB_MSG__INIT;
|
||||
|
||||
proto_manager_set_header(&header_msg);
|
||||
usb_msg.header = &header_msg;
|
||||
usb_msg.message_case = LOGI__DEVICE__PROTO__USB_MSG__MESSAGE_REQUEST;
|
||||
usb_msg.request = &request_msg;
|
||||
|
||||
fu_byte_array_set_size(buf, logi__device__proto__usb_msg__get_packed_size(&usb_msg));
|
||||
logi__device__proto__usb_msg__pack(&usb_msg, (unsigned char *)buf->data);
|
||||
return buf;
|
||||
}
|
||||
|
||||
GByteArray *
|
||||
proto_manager_decode_message(const guint8 *data,
|
||||
guint32 len,
|
||||
FuLogitechBulkcontrollerProtoId *proto_id,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GByteArray) buf_decoded = g_byte_array_new();
|
||||
|
||||
Logi__Device__Proto__UsbMsg *usb_msg =
|
||||
logi__device__proto__usb_msg__unpack(NULL, len, (const unsigned char *)data);
|
||||
if (usb_msg == NULL) {
|
||||
g_set_error_literal(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"unable to unpack data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (usb_msg->message_case) {
|
||||
case LOGI__DEVICE__PROTO__USB_MSG__MESSAGE_ACK:
|
||||
*proto_id = kProtoId_Ack;
|
||||
break;
|
||||
case LOGI__DEVICE__PROTO__USB_MSG__MESSAGE_RESPONSE:
|
||||
if (!usb_msg->response) {
|
||||
g_set_error_literal(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"no USB response");
|
||||
return NULL;
|
||||
}
|
||||
switch (usb_msg->response->payload_case) {
|
||||
case LOGI__DEVICE__PROTO__RESPONSE__PAYLOAD_GET_DEVICE_INFO_RESPONSE:
|
||||
if (usb_msg->response->get_device_info_response) {
|
||||
const gchar *tmp =
|
||||
usb_msg->response->get_device_info_response->payload;
|
||||
*proto_id = kProtoId_GetDeviceInfoResponse;
|
||||
if (tmp != NULL)
|
||||
g_byte_array_append(buf_decoded,
|
||||
(const guint8 *)tmp,
|
||||
strlen(tmp));
|
||||
}
|
||||
break;
|
||||
case LOGI__DEVICE__PROTO__RESPONSE__PAYLOAD_TRANSITION_TO_DEVICEMODE_RESPONSE:
|
||||
if (usb_msg->response->transition_to_devicemode_response) {
|
||||
*proto_id = kProtoId_TransitionToDeviceModeResponse;
|
||||
fu_byte_array_append_uint8(
|
||||
buf_decoded,
|
||||
usb_msg->response->transition_to_devicemode_response->success);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
case LOGI__DEVICE__PROTO__USB_MSG__MESSAGE_EVENT:
|
||||
if (!usb_msg->response) {
|
||||
g_set_error_literal(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"no USB event");
|
||||
return NULL;
|
||||
}
|
||||
switch (usb_msg->event->payload_case) {
|
||||
case LOGI__DEVICE__PROTO__EVENT__PAYLOAD_KONG_EVENT:
|
||||
if (usb_msg->event->kong_event) {
|
||||
const gchar *tmp = usb_msg->event->kong_event->mqtt_event;
|
||||
*proto_id = kProtoId_KongEvent;
|
||||
if (tmp != NULL)
|
||||
g_byte_array_append(buf_decoded,
|
||||
(const guint8 *)tmp,
|
||||
strlen(tmp));
|
||||
}
|
||||
break;
|
||||
case LOGI__DEVICE__PROTO__EVENT__PAYLOAD_HANDSHAKE_EVENT:
|
||||
if (usb_msg->event->handshake_event) {
|
||||
*proto_id = kProtoId_HandshakeEvent;
|
||||
}
|
||||
break;
|
||||
case LOGI__DEVICE__PROTO__EVENT__PAYLOAD_CRASH_DUMP_AVAILABLE_EVENT:
|
||||
*proto_id = kProtoId_CrashDumpAvailableEvent;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
logi__device__proto__usb_msg__free_unpacked(usb_msg, NULL);
|
||||
return g_steal_pointer(&buf_decoded);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
fu_logitech_bulkcontroller_device_status_to_string(FuLogitechBulkcontrollerDeviceStatus status)
|
||||
{
|
||||
if (status == kDeviceStateUnknown)
|
||||
return "Unknown";
|
||||
if (status == kDeviceStateOffline)
|
||||
return "Offline";
|
||||
if (status == kDeviceStateOnline)
|
||||
return "Online";
|
||||
if (status == kDeviceStateIdle)
|
||||
return "Idle";
|
||||
if (status == kDeviceStateInUse)
|
||||
return "InUse";
|
||||
if (status == kDeviceStateAudioOnly)
|
||||
return "AudioOnly";
|
||||
if (status == kDeviceStateEnumerating)
|
||||
return "Enumerating";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
fu_logitech_bulkcontroller_device_update_state_to_string(
|
||||
FuLogitechBulkcontrollerDeviceUpdateState update_state)
|
||||
{
|
||||
if (update_state == kUpdateStateUnknown)
|
||||
return "Unknown";
|
||||
if (update_state == kUpdateStateCurrent)
|
||||
return "Current";
|
||||
if (update_state == kUpdateStateAvailable)
|
||||
return "Available";
|
||||
if (update_state == kUpdateStateStarting)
|
||||
return "Starting";
|
||||
if (update_state == kUpdateStateDownloading)
|
||||
return "Downloading";
|
||||
if (update_state == kUpdateStateReady)
|
||||
return "Ready";
|
||||
if (update_state == kUpdateStateUpdating)
|
||||
return "Updating";
|
||||
if (update_state == kUpdateStateScheduled)
|
||||
return "Scheduled";
|
||||
if (update_state == kUpdateStateError)
|
||||
return "Error";
|
||||
return NULL;
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "usb_msg.pb-c.h"
|
||||
|
||||
typedef enum {
|
||||
kDeviceStateUnknown = -1,
|
||||
kDeviceStateOffline,
|
||||
kDeviceStateOnline,
|
||||
kDeviceStateIdle,
|
||||
kDeviceStateInUse,
|
||||
kDeviceStateAudioOnly,
|
||||
kDeviceStateEnumerating
|
||||
} FuLogitechBulkcontrollerDeviceStatus;
|
||||
|
||||
typedef enum {
|
||||
kUpdateStateUnknown = -1,
|
||||
kUpdateStateCurrent,
|
||||
kUpdateStateAvailable,
|
||||
kUpdateStateStarting = 3,
|
||||
kUpdateStateDownloading,
|
||||
kUpdateStateReady,
|
||||
kUpdateStateUpdating,
|
||||
kUpdateStateScheduled,
|
||||
kUpdateStateError
|
||||
} FuLogitechBulkcontrollerDeviceUpdateState;
|
||||
|
||||
typedef enum {
|
||||
kProtoId_UnknownId,
|
||||
kProtoId_GetDeviceInfoResponse,
|
||||
kProtoId_TransitionToDeviceModeResponse,
|
||||
kProtoId_Ack,
|
||||
kProtoId_KongEvent,
|
||||
kProtoId_HandshakeEvent,
|
||||
kProtoId_CrashDumpAvailableEvent
|
||||
} FuLogitechBulkcontrollerProtoId;
|
||||
|
||||
const gchar *
|
||||
fu_logitech_bulkcontroller_device_status_to_string(FuLogitechBulkcontrollerDeviceStatus status);
|
||||
const gchar *
|
||||
fu_logitech_bulkcontroller_device_update_state_to_string(
|
||||
FuLogitechBulkcontrollerDeviceUpdateState update_state);
|
||||
GByteArray *
|
||||
proto_manager_generate_get_device_info_request(void);
|
||||
GByteArray *
|
||||
proto_manager_generate_transition_to_device_mode_request(void);
|
||||
GByteArray *
|
||||
proto_manager_decode_message(const guint8 *data,
|
||||
guint32 len,
|
||||
FuLogitechBulkcontrollerProtoId *proto_id,
|
||||
GError **error);
|
||||
@ -0,0 +1,704 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* Copyright (C) 2021 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fu-logitech-bulkcontroller-common.h"
|
||||
#include "fu-logitech-bulkcontroller-device.h"
|
||||
|
||||
/* SYNC interface follows TLSV (Type, Length, SequenceID, Value) protocol */
|
||||
/* UPD interface follows TLV (Type, Length, Value) protocol */
|
||||
/* Payload size limited to 8k for both interfaces */
|
||||
#define UPD_PACKET_HEADER_SIZE (2 * sizeof(guint32))
|
||||
#define SYNC_PACKET_HEADER_SIZE (3 * sizeof(guint32))
|
||||
#define WRITE_TIME_OUT 100
|
||||
#define HASH_TIMEOUT 30000
|
||||
#define MAX_DATA_SIZE 8192 /* 8k */
|
||||
#define PAYLOAD_SIZE MAX_DATA_SIZE - UPD_PACKET_HEADER_SIZE
|
||||
#define UPD_INTERFACE_SUBPROTOCOL_ID 117
|
||||
#define SYNC_INTERFACE_SUBPROTOCOL_ID 118
|
||||
#define BULK_TRANSFER_TIMEOUT 1000
|
||||
#define HASH_VALUE_SIZE 16
|
||||
#define LENGTH_OFFSET 0x4
|
||||
#define COMMAND_OFFSET 0x0
|
||||
#define SYNC_ACK_PAYLOAD_LENGTH 5
|
||||
|
||||
enum { SHA_256, SHA_512, MD5 };
|
||||
|
||||
enum { EP_OUT, EP_IN, EP_LAST };
|
||||
|
||||
enum { BULK_INTERFACE_UPD, BULK_INTERFACE_SYNC };
|
||||
|
||||
typedef enum {
|
||||
CMD_CHECK_BUFFERSIZE = 0xCC00,
|
||||
CMD_INIT = 0xCC01,
|
||||
CMD_START_TRANSFER = 0xCC02,
|
||||
CMD_DATA_TRANSFER = 0xCC03,
|
||||
CMD_END_TRANSFER = 0xCC04,
|
||||
CMD_UNINIT = 0xCC05,
|
||||
CMD_BUFFER_READ = 0xCC06,
|
||||
CMD_BUFFER_WRITE = 0xCC07,
|
||||
CMD_UNINIT_BUFFER = 0xCC08,
|
||||
CMD_ACK = 0xFF01,
|
||||
CMD_TIMEOUT = 0xFF02,
|
||||
CMD_NACK = 0xFF03
|
||||
} UsbCommands;
|
||||
|
||||
struct _FuLogitechBulkcontrollerDevice {
|
||||
FuUsbDevice parent_instance;
|
||||
guint sync_ep[EP_LAST];
|
||||
guint update_ep[EP_LAST];
|
||||
guint sync_iface;
|
||||
guint update_iface;
|
||||
FuLogitechBulkcontrollerDeviceStatus status;
|
||||
FuLogitechBulkcontrollerDeviceUpdateState update_status;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FuLogitechBulkcontrollerDevice, fu_logitech_bulkcontroller_device, FU_TYPE_USB_DEVICE)
|
||||
|
||||
static void
|
||||
fu_logitech_bulkcontroller_device_to_string(FuDevice *device, guint idt, GString *str)
|
||||
{
|
||||
FuLogitechBulkcontrollerDevice *self = FU_LOGITECH_BULKCONTROLLER_DEVICE(device);
|
||||
fu_common_string_append_kx(str, idt, "SyncIface", self->sync_iface);
|
||||
fu_common_string_append_kx(str, idt, "UpdateIface", self->update_iface);
|
||||
fu_common_string_append_kv(
|
||||
str,
|
||||
idt,
|
||||
"Status",
|
||||
fu_logitech_bulkcontroller_device_status_to_string(self->status));
|
||||
fu_common_string_append_kv(
|
||||
str,
|
||||
idt,
|
||||
"UpdateState",
|
||||
fu_logitech_bulkcontroller_device_update_state_to_string(self->update_status));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_probe(FuDevice *device, GError **error)
|
||||
{
|
||||
FuLogitechBulkcontrollerDevice *self = FU_LOGITECH_BULKCONTROLLER_DEVICE(device);
|
||||
g_autoptr(GPtrArray) intfs = NULL;
|
||||
|
||||
intfs = g_usb_device_get_interfaces(fu_usb_device_get_dev(FU_USB_DEVICE(self)), error);
|
||||
if (intfs == NULL)
|
||||
return FALSE;
|
||||
for (guint i = 0; i < intfs->len; i++) {
|
||||
GUsbInterface *intf = g_ptr_array_index(intfs, i);
|
||||
if (g_usb_interface_get_class(intf) == G_USB_DEVICE_CLASS_VENDOR_SPECIFIC &&
|
||||
g_usb_interface_get_protocol(intf) == 0x1) {
|
||||
if (g_usb_interface_get_subclass(intf) == SYNC_INTERFACE_SUBPROTOCOL_ID) {
|
||||
g_autoptr(GPtrArray) endpoints =
|
||||
g_usb_interface_get_endpoints(intf);
|
||||
self->sync_iface = g_usb_interface_get_number(intf);
|
||||
if (endpoints == NULL)
|
||||
continue;
|
||||
for (guint j = 0; j < endpoints->len; j++) {
|
||||
GUsbEndpoint *ep = g_ptr_array_index(endpoints, j);
|
||||
if (j == EP_OUT)
|
||||
self->sync_ep[EP_OUT] =
|
||||
g_usb_endpoint_get_address(ep);
|
||||
else
|
||||
self->sync_ep[EP_IN] =
|
||||
g_usb_endpoint_get_address(ep);
|
||||
}
|
||||
} else if (g_usb_interface_get_subclass(intf) ==
|
||||
UPD_INTERFACE_SUBPROTOCOL_ID) {
|
||||
g_autoptr(GPtrArray) endpoints =
|
||||
g_usb_interface_get_endpoints(intf);
|
||||
self->sync_iface = g_usb_interface_get_number(intf);
|
||||
if (endpoints == NULL)
|
||||
continue;
|
||||
for (guint j = 0; j < endpoints->len; j++) {
|
||||
GUsbEndpoint *ep = g_ptr_array_index(endpoints, j);
|
||||
if (j == EP_OUT)
|
||||
self->update_ep[EP_OUT] =
|
||||
g_usb_endpoint_get_address(ep);
|
||||
else
|
||||
self->update_ep[EP_IN] =
|
||||
g_usb_endpoint_get_address(ep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_send(FuLogitechBulkcontrollerDevice *self,
|
||||
GByteArray *buf,
|
||||
gint interface_id,
|
||||
GError **error)
|
||||
{
|
||||
gsize transferred = 0;
|
||||
gint ep;
|
||||
GCancellable *cancellable = NULL;
|
||||
g_return_val_if_fail(buf != NULL, FALSE);
|
||||
|
||||
if (interface_id == BULK_INTERFACE_SYNC) {
|
||||
ep = self->sync_ep[EP_OUT];
|
||||
} else if (interface_id == BULK_INTERFACE_UPD) {
|
||||
ep = self->update_ep[EP_OUT];
|
||||
} else {
|
||||
g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_FAILED, "interface is invalid");
|
||||
return FALSE;
|
||||
}
|
||||
if (!g_usb_device_bulk_transfer(fu_usb_device_get_dev(FU_USB_DEVICE(self)),
|
||||
ep,
|
||||
(guint8 *)buf->data,
|
||||
buf->len,
|
||||
&transferred,
|
||||
WRITE_TIME_OUT,
|
||||
cancellable,
|
||||
error)) {
|
||||
g_prefix_error(error, "bulk transfer failed: ");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_recv(FuLogitechBulkcontrollerDevice *self,
|
||||
GByteArray *buf,
|
||||
gint interface_id,
|
||||
guint timeout,
|
||||
GError **error)
|
||||
{
|
||||
gsize received_length = 0;
|
||||
gint ep;
|
||||
|
||||
g_return_val_if_fail(buf != NULL, FALSE);
|
||||
|
||||
if (interface_id == BULK_INTERFACE_SYNC) {
|
||||
ep = self->sync_ep[EP_IN];
|
||||
} else if (interface_id == BULK_INTERFACE_UPD) {
|
||||
ep = self->update_ep[EP_IN];
|
||||
} else {
|
||||
g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_FAILED, "interface is invalid");
|
||||
return FALSE;
|
||||
}
|
||||
if (!g_usb_device_bulk_transfer(fu_usb_device_get_dev(FU_USB_DEVICE(self)),
|
||||
ep,
|
||||
buf->data,
|
||||
buf->len,
|
||||
&received_length,
|
||||
timeout,
|
||||
NULL,
|
||||
error)) {
|
||||
g_prefix_error(error, "bulk transfer failed: ");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_send_upd_cmd(FuLogitechBulkcontrollerDevice *self,
|
||||
guint32 cmd,
|
||||
GByteArray *buf,
|
||||
GError **error)
|
||||
{
|
||||
guint32 cmd_tmp = 0x0;
|
||||
guint timeout = BULK_TRANSFER_TIMEOUT;
|
||||
g_autoptr(GByteArray) buf_pkt = g_byte_array_new();
|
||||
g_autoptr(GByteArray) buf_ack = g_byte_array_new();
|
||||
|
||||
fu_byte_array_append_uint32(buf_pkt, cmd, G_LITTLE_ENDIAN); /* Type(T) : Command type */
|
||||
fu_byte_array_append_uint32(buf_pkt,
|
||||
buf != NULL ? buf->len : 0,
|
||||
G_LITTLE_ENDIAN); /*Length(L) : Length of payload */
|
||||
if (buf != NULL) {
|
||||
g_byte_array_append(buf_pkt,
|
||||
buf->data,
|
||||
buf->len); /* Value(V) : Actual payload data */
|
||||
}
|
||||
if (!fu_logitech_bulkcontroller_device_send(self, buf_pkt, BULK_INTERFACE_UPD, error))
|
||||
return FALSE;
|
||||
|
||||
/* receiving INIT ACK */
|
||||
fu_byte_array_set_size(buf_ack, MAX_DATA_SIZE);
|
||||
|
||||
/* Extending the bulk transfer timeout value, as android device takes some time to
|
||||
calculate Hash and respond */
|
||||
if (CMD_END_TRANSFER == cmd)
|
||||
timeout = HASH_TIMEOUT;
|
||||
|
||||
if (!fu_logitech_bulkcontroller_device_recv(self,
|
||||
buf_ack,
|
||||
BULK_INTERFACE_UPD,
|
||||
timeout,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (!fu_common_read_uint32_safe(buf_ack->data,
|
||||
buf_ack->len,
|
||||
COMMAND_OFFSET,
|
||||
&cmd_tmp,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
if (cmd_tmp != CMD_ACK) {
|
||||
g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, "not CMD_ACK, got %x", cmd);
|
||||
return FALSE;
|
||||
}
|
||||
if (!fu_common_read_uint32_safe(buf_ack->data,
|
||||
buf_ack->len,
|
||||
UPD_PACKET_HEADER_SIZE,
|
||||
&cmd_tmp,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
if (cmd_tmp != cmd) {
|
||||
g_set_error(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"invalid upd message received, expected %x, got %x",
|
||||
cmd,
|
||||
cmd_tmp);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_send_sync_cmd(FuLogitechBulkcontrollerDevice *self,
|
||||
guint32 cmd,
|
||||
GByteArray *buf,
|
||||
GError **error)
|
||||
{
|
||||
guint32 cmd_tmp = 0x0;
|
||||
guint64 cmd_tmp_64 = 0x0;
|
||||
guint32 verify_cmd = 0x0;
|
||||
gchar ack_payload[SYNC_ACK_PAYLOAD_LENGTH] = {0x0};
|
||||
g_autoptr(GByteArray) buf_pkt = g_byte_array_new();
|
||||
g_autoptr(GByteArray) buf_ack = g_byte_array_new();
|
||||
|
||||
fu_byte_array_append_uint32(buf_pkt, cmd, G_LITTLE_ENDIAN); /* Type(T) : Command type */
|
||||
fu_byte_array_append_uint32(buf_pkt,
|
||||
buf != NULL ? buf->len : 0,
|
||||
G_LITTLE_ENDIAN); /*Length(L) : Length of payload */
|
||||
fu_byte_array_append_uint32(buf_pkt,
|
||||
g_random_int_range(0, G_MAXUINT16),
|
||||
G_LITTLE_ENDIAN); /*Sequence(S) : Sequence ID of the data */
|
||||
if (buf != NULL) {
|
||||
g_byte_array_append(buf_pkt,
|
||||
buf->data,
|
||||
buf->len); /* Value(V) : Actual payload data */
|
||||
}
|
||||
if (!fu_logitech_bulkcontroller_device_send(self, buf_pkt, BULK_INTERFACE_SYNC, error))
|
||||
return FALSE;
|
||||
|
||||
/* receiving ACK */
|
||||
fu_byte_array_set_size(buf_ack, MAX_DATA_SIZE);
|
||||
if (!fu_logitech_bulkcontroller_device_recv(self,
|
||||
buf_ack,
|
||||
BULK_INTERFACE_SYNC,
|
||||
BULK_TRANSFER_TIMEOUT,
|
||||
error))
|
||||
return FALSE;
|
||||
if (!fu_common_read_uint32_safe(buf_ack->data,
|
||||
buf_ack->len,
|
||||
COMMAND_OFFSET,
|
||||
&cmd_tmp,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
if (cmd_tmp != CMD_ACK) {
|
||||
g_set_error(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"not sync CMD_ACK, got %x",
|
||||
cmd_tmp);
|
||||
return FALSE;
|
||||
}
|
||||
if (!fu_common_read_uint64_safe(buf_ack->data,
|
||||
buf_ack->len,
|
||||
SYNC_PACKET_HEADER_SIZE,
|
||||
&cmd_tmp_64,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
if (!fu_memcpy_safe((guint8 *)ack_payload,
|
||||
sizeof(ack_payload),
|
||||
0x0,
|
||||
(guint8 *)&cmd_tmp_64,
|
||||
sizeof(cmd_tmp_64),
|
||||
0x0,
|
||||
SYNC_ACK_PAYLOAD_LENGTH,
|
||||
error)) {
|
||||
g_prefix_error(error, "failed to retrieve payload data: ");
|
||||
return FALSE;
|
||||
}
|
||||
verify_cmd = fu_common_strtoull(ack_payload);
|
||||
if (verify_cmd != cmd) {
|
||||
g_set_error(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"invalid sync message payload received, expected %x, got %x",
|
||||
cmd,
|
||||
verify_cmd);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_recv_sync_cmd(FuLogitechBulkcontrollerDevice *self,
|
||||
guint32 cmd,
|
||||
GByteArray *buf,
|
||||
GError **error)
|
||||
{
|
||||
guint32 cmd_tmp = 0x0;
|
||||
guint32 response_length = 0;
|
||||
g_autoptr(GByteArray) buf_pkt = g_byte_array_new();
|
||||
g_autoptr(GByteArray) buf_ack = g_byte_array_new();
|
||||
|
||||
fu_byte_array_set_size(buf_pkt, MAX_DATA_SIZE);
|
||||
if (!fu_logitech_bulkcontroller_device_recv(self,
|
||||
buf_pkt,
|
||||
BULK_INTERFACE_SYNC,
|
||||
BULK_TRANSFER_TIMEOUT,
|
||||
error))
|
||||
return FALSE;
|
||||
if (!fu_common_read_uint32_safe(buf_pkt->data,
|
||||
buf_pkt->len,
|
||||
COMMAND_OFFSET,
|
||||
&cmd_tmp,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
if (cmd_tmp != cmd) {
|
||||
g_set_error(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"invalid sync message received, expected %x, got %x",
|
||||
cmd,
|
||||
cmd_tmp);
|
||||
return FALSE;
|
||||
}
|
||||
if (!fu_common_read_uint32_safe(buf_pkt->data,
|
||||
buf_pkt->len,
|
||||
LENGTH_OFFSET,
|
||||
&response_length,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
fu_byte_array_append_uint32(buf_ack, CMD_ACK, G_LITTLE_ENDIAN); /* ACK message */
|
||||
fu_byte_array_append_uint32(buf_ack, sizeof(guint32), G_LITTLE_ENDIAN); /* Length */
|
||||
fu_byte_array_append_uint32(buf_ack, 0, G_LITTLE_ENDIAN); /* Sequence ID */
|
||||
fu_byte_array_append_uint32(buf_ack, cmd, G_LITTLE_ENDIAN); /* Payload */
|
||||
if (!fu_logitech_bulkcontroller_device_send(self, buf_ack, BULK_INTERFACE_SYNC, error))
|
||||
return FALSE;
|
||||
if (buf != NULL)
|
||||
g_byte_array_append(buf, buf_pkt->data + SYNC_PACKET_HEADER_SIZE, response_length);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
fu_logitech_bulkcontroller_device_compute_hash(GBytes *data)
|
||||
{
|
||||
guint8 md5buf[HASH_VALUE_SIZE] = {0};
|
||||
gsize data_len = sizeof(md5buf);
|
||||
GChecksum *checksum = g_checksum_new(G_CHECKSUM_MD5);
|
||||
g_checksum_update(checksum, g_bytes_get_data(data, NULL), g_bytes_get_size(data));
|
||||
g_checksum_get_digest(checksum, (guint8 *)&md5buf, &data_len);
|
||||
return g_base64_encode(md5buf, sizeof(md5buf));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_write_firmware(FuDevice *device,
|
||||
FuFirmware *firmware,
|
||||
FwupdInstallFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
FuLogitechBulkcontrollerDevice *self = FU_LOGITECH_BULKCONTROLLER_DEVICE(device);
|
||||
g_autofree gchar *base64hash = NULL;
|
||||
g_autoptr(GByteArray) end_pkt = g_byte_array_new();
|
||||
g_autoptr(GByteArray) start_pkt = g_byte_array_new();
|
||||
g_autoptr(GBytes) fw = NULL;
|
||||
g_autoptr(GPtrArray) chunks = NULL;
|
||||
|
||||
/* get default image */
|
||||
fw = fu_firmware_get_bytes(firmware, error);
|
||||
if (fw == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Sending INIT */
|
||||
if (!fu_logitech_bulkcontroller_device_send_upd_cmd(self, CMD_INIT, NULL, error)) {
|
||||
g_prefix_error(error, "error in writing init transfer packet: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* transfer sent */
|
||||
fu_device_set_status(device, FWUPD_STATUS_DEVICE_WRITE);
|
||||
fu_byte_array_append_uint64(start_pkt, g_bytes_get_size(fw), G_LITTLE_ENDIAN);
|
||||
if (!fu_logitech_bulkcontroller_device_send_upd_cmd(self,
|
||||
CMD_START_TRANSFER,
|
||||
start_pkt,
|
||||
error)) {
|
||||
g_prefix_error(error, "error in writing start transfer packet: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* each block */
|
||||
chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, PAYLOAD_SIZE);
|
||||
for (guint i = 0; i < chunks->len; i++) {
|
||||
FuChunk *chk = g_ptr_array_index(chunks, i);
|
||||
g_autoptr(GByteArray) data_pkt = g_byte_array_new();
|
||||
g_byte_array_append(data_pkt, fu_chunk_get_data(chk), fu_chunk_get_data_sz(chk));
|
||||
if (!fu_logitech_bulkcontroller_device_send_upd_cmd(self,
|
||||
CMD_DATA_TRANSFER,
|
||||
data_pkt,
|
||||
error)) {
|
||||
g_prefix_error(error, "failed to send data packet 0x%x: ", i);
|
||||
return FALSE;
|
||||
}
|
||||
fu_device_set_progress_full(FU_DEVICE(self), i + 1, chunks->len);
|
||||
}
|
||||
|
||||
/* sending end transfer */
|
||||
base64hash = fu_logitech_bulkcontroller_device_compute_hash(fw);
|
||||
fu_byte_array_append_uint32(end_pkt, 1, G_LITTLE_ENDIAN); /* update */
|
||||
fu_byte_array_append_uint32(end_pkt, 0, G_LITTLE_ENDIAN); /* force */
|
||||
fu_byte_array_append_uint32(end_pkt, MD5, G_LITTLE_ENDIAN); /* checksum type */
|
||||
g_byte_array_append(end_pkt, (const guint8 *)base64hash, strlen(base64hash));
|
||||
if (!fu_logitech_bulkcontroller_device_send_upd_cmd(self,
|
||||
CMD_END_TRANSFER,
|
||||
end_pkt,
|
||||
error)) {
|
||||
g_prefix_error(error, "error in writing end transfer transfer packet: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* send uninit */
|
||||
if (!fu_logitech_bulkcontroller_device_send_upd_cmd(self, CMD_UNINIT, NULL, error)) {
|
||||
g_prefix_error(error, "error in writing finish transfer packet: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* success! */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_open(FuDevice *device, GError **error)
|
||||
{
|
||||
FuLogitechBulkcontrollerDevice *self = FU_LOGITECH_BULKCONTROLLER_DEVICE(device);
|
||||
GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(device));
|
||||
|
||||
/* FuUsbDevice->open */
|
||||
if (!FU_DEVICE_CLASS(fu_logitech_bulkcontroller_device_parent_class)->open(device, error))
|
||||
return FALSE;
|
||||
|
||||
/* claim both interfaces */
|
||||
if (!g_usb_device_claim_interface(usb_device,
|
||||
self->update_iface,
|
||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
||||
error)) {
|
||||
g_prefix_error(error, "failed to claim update interface: ");
|
||||
return FALSE;
|
||||
}
|
||||
if (!g_usb_device_claim_interface(usb_device,
|
||||
self->sync_iface,
|
||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
||||
error)) {
|
||||
g_prefix_error(error, "failed to claim sync interface: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_close(FuDevice *device, GError **error)
|
||||
{
|
||||
FuLogitechBulkcontrollerDevice *self = FU_LOGITECH_BULKCONTROLLER_DEVICE(device);
|
||||
GUsbDevice *usb_device = fu_usb_device_get_dev(FU_USB_DEVICE(device));
|
||||
|
||||
if (!g_usb_device_release_interface(usb_device,
|
||||
self->update_iface,
|
||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
||||
error)) {
|
||||
g_prefix_error(error, "failed to release update interface: ");
|
||||
return FALSE;
|
||||
}
|
||||
if (!g_usb_device_release_interface(usb_device,
|
||||
self->sync_iface,
|
||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
||||
error)) {
|
||||
g_prefix_error(error, "failed to release sync interface: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* FuUsbDevice->close */
|
||||
return FU_DEVICE_CLASS(fu_logitech_bulkcontroller_device_parent_class)
|
||||
->close(device, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_json_parser(FuDevice *device,
|
||||
GByteArray *decoded_pkt,
|
||||
GError **error)
|
||||
{
|
||||
FuLogitechBulkcontrollerDevice *self = FU_LOGITECH_BULKCONTROLLER_DEVICE(device);
|
||||
JsonArray *json_devices;
|
||||
JsonNode *json_root;
|
||||
JsonObject *json_device;
|
||||
JsonObject *json_object;
|
||||
JsonObject *json_payload;
|
||||
g_autoptr(JsonParser) json_parser = json_parser_new();
|
||||
|
||||
/* parse JSON reply */
|
||||
if (!json_parser_load_from_data(json_parser,
|
||||
(const gchar *)decoded_pkt->data,
|
||||
decoded_pkt->len,
|
||||
error)) {
|
||||
g_prefix_error(error, "error in parsing json data: ");
|
||||
return FALSE;
|
||||
}
|
||||
json_root = json_parser_get_root(json_parser);
|
||||
if (json_root == NULL) {
|
||||
g_set_error_literal(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"did not get JSON root");
|
||||
return FALSE;
|
||||
}
|
||||
json_object = json_node_get_object(json_root);
|
||||
json_payload = json_object_get_object_member(json_object, "payload");
|
||||
if (json_payload == NULL) {
|
||||
g_set_error_literal(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"did not get JSON payload");
|
||||
return FALSE;
|
||||
}
|
||||
json_devices = json_object_get_array_member(json_payload, "devices");
|
||||
if (json_devices == NULL) {
|
||||
g_set_error_literal(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"did not get JSON devices");
|
||||
return FALSE;
|
||||
}
|
||||
json_device = json_array_get_object_element(json_devices, 0);
|
||||
if (json_device == NULL) {
|
||||
g_set_error_literal(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"did not get JSON device");
|
||||
return FALSE;
|
||||
}
|
||||
if (json_object_has_member(json_device, "name"))
|
||||
fu_device_set_name(device, json_object_get_string_member(json_device, "name"));
|
||||
if (json_object_has_member(json_device, "sw"))
|
||||
fu_device_set_version(device, json_object_get_string_member(json_device, "sw"));
|
||||
if (json_object_has_member(json_device, "type"))
|
||||
fu_device_add_instance_id(device,
|
||||
json_object_get_string_member(json_device, "type"));
|
||||
if (json_object_has_member(json_device, "status"))
|
||||
self->status = json_object_get_int_member(json_device, "status");
|
||||
if (json_object_has_member(json_device, "updateStatus"))
|
||||
self->update_status = json_object_get_int_member(json_device, "updateStatus");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_logitech_bulkcontroller_device_setup(FuDevice *device, GError **error)
|
||||
{
|
||||
FuLogitechBulkcontrollerDevice *self = FU_LOGITECH_BULKCONTROLLER_DEVICE(device);
|
||||
g_autoptr(GByteArray) device_info_request = g_byte_array_new();
|
||||
g_autoptr(GByteArray) decoded_pkt = g_byte_array_new();
|
||||
g_autoptr(GByteArray) device_info_response = g_byte_array_new();
|
||||
FuLogitechBulkcontrollerProtoId proto_id = kProtoId_UnknownId;
|
||||
|
||||
/* FuUsbDevice->setup */
|
||||
if (!FU_DEVICE_CLASS(fu_logitech_bulkcontroller_device_parent_class)->setup(device, error))
|
||||
return FALSE;
|
||||
|
||||
/* sending GetDeviceInfoRequest */
|
||||
device_info_request = proto_manager_generate_get_device_info_request();
|
||||
if (!fu_logitech_bulkcontroller_device_send_sync_cmd(self,
|
||||
CMD_BUFFER_WRITE,
|
||||
device_info_request,
|
||||
error)) {
|
||||
g_prefix_error(error, "error in sending buffer write packet: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* wait for the GetDeviceInfoResponse */
|
||||
if (!fu_logitech_bulkcontroller_device_recv_sync_cmd(self,
|
||||
CMD_BUFFER_READ,
|
||||
device_info_response,
|
||||
error)) {
|
||||
g_prefix_error(error, "error in buffer read packet: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!fu_logitech_bulkcontroller_device_recv_sync_cmd(self,
|
||||
CMD_UNINIT_BUFFER,
|
||||
NULL,
|
||||
error)) {
|
||||
g_prefix_error(error, "error in buffer read packet: ");
|
||||
return FALSE;
|
||||
}
|
||||
if (!fu_logitech_bulkcontroller_device_send_sync_cmd(self,
|
||||
CMD_UNINIT_BUFFER,
|
||||
NULL,
|
||||
error)) {
|
||||
g_prefix_error(error, "error in sending buffer uninitialize packet: ");
|
||||
return FALSE;
|
||||
}
|
||||
decoded_pkt = proto_manager_decode_message(device_info_response->data,
|
||||
device_info_response->len,
|
||||
&proto_id,
|
||||
error);
|
||||
if (decoded_pkt == NULL) {
|
||||
g_prefix_error(error, "error in unpacking packet: ");
|
||||
return FALSE;
|
||||
}
|
||||
if (proto_id != kProtoId_GetDeviceInfoResponse) {
|
||||
g_set_error_literal(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"did not get kProtoId_GetDeviceInfoResponse");
|
||||
return FALSE;
|
||||
}
|
||||
if (!fu_logitech_bulkcontroller_device_json_parser(device, decoded_pkt, error))
|
||||
return FALSE;
|
||||
|
||||
/* success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fu_logitech_bulkcontroller_device_init(FuLogitechBulkcontrollerDevice *self)
|
||||
{
|
||||
fu_device_add_protocol(FU_DEVICE(self), "com.logitech.vc.proto");
|
||||
fu_device_set_version_format(FU_DEVICE(self), FWUPD_VERSION_FORMAT_TRIPLET);
|
||||
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_UPDATABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_logitech_bulkcontroller_device_class_init(FuLogitechBulkcontrollerDeviceClass *klass)
|
||||
{
|
||||
FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass);
|
||||
klass_device->to_string = fu_logitech_bulkcontroller_device_to_string;
|
||||
klass_device->write_firmware = fu_logitech_bulkcontroller_device_write_firmware;
|
||||
klass_device->probe = fu_logitech_bulkcontroller_device_probe;
|
||||
klass_device->setup = fu_logitech_bulkcontroller_device_setup;
|
||||
klass_device->open = fu_logitech_bulkcontroller_device_open;
|
||||
klass_device->close = fu_logitech_bulkcontroller_device_close;
|
||||
}
|
||||
@ -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_LOGITECH_BULKCONTROLLER_DEVICE (fu_logitech_bulkcontroller_device_get_type())
|
||||
G_DECLARE_FINAL_TYPE(FuLogitechBulkcontrollerDevice,
|
||||
fu_logitech_bulkcontroller_device,
|
||||
FU,
|
||||
LOGITECH_BULKCONTROLLER_DEVICE,
|
||||
FuUsbDevice)
|
||||
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#include "fu-logitech-bulkcontroller-device.h"
|
||||
|
||||
void
|
||||
fu_plugin_init(FuPlugin *plugin)
|
||||
{
|
||||
fu_plugin_set_build_hash(plugin, FU_BUILD_HASH);
|
||||
fu_plugin_add_device_gtype(plugin, FU_TYPE_LOGITECH_BULKCONTROLLER_DEVICE);
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
# TODO: revisit InstallDuration
|
||||
|
||||
[USB\VID_046D&PID_089B]
|
||||
Plugin = logitech_bulkcontroller
|
||||
InstallDuration = 1500
|
||||
|
||||
[USB\VID_046D&PID_08D3]
|
||||
Plugin = logitech_bulkcontroller
|
||||
InstallDuration = 1500
|
||||
Flags = is-mini
|
||||
37
plugins/logitech-bulkcontroller/meson.build
Normal file
37
plugins/logitech-bulkcontroller/meson.build
Normal file
@ -0,0 +1,37 @@
|
||||
if get_option('plugin_logitech_bulkcontroller')
|
||||
|
||||
if not get_option('gusb')
|
||||
error('gusb is required for plugin_logitech_bulkcontroller')
|
||||
endif
|
||||
|
||||
cargs = ['-DG_LOG_DOMAIN="FuPluginLogitechBulkController"']
|
||||
|
||||
install_data(['logitech-bulkcontroller.quirk'],
|
||||
install_dir: join_paths(get_option('datadir'), 'fwupd', 'quirks.d')
|
||||
)
|
||||
subdir('proto')
|
||||
shared_module('fu_plugin_logitech_bulkcontroller',
|
||||
fu_hash,
|
||||
sources : [
|
||||
generated,
|
||||
'fu-logitech-bulkcontroller-common.c',
|
||||
'fu-logitech-bulkcontroller-device.c',
|
||||
'fu-plugin-logitech-bulkcontroller.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
|
||||
41
plugins/logitech-bulkcontroller/proto/antiflicker.proto
Normal file
41
plugins/logitech-bulkcontroller/proto/antiflicker.proto
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
import "device_common.proto";
|
||||
|
||||
/**
|
||||
* This message data structure holds information about the
|
||||
* current AntiFlicker configuration.
|
||||
*
|
||||
*/
|
||||
message AntiFlickerConfiguration
|
||||
{
|
||||
enum Mode {
|
||||
NTSC_60HZ = 0;
|
||||
PAL_50HZ = 1;
|
||||
}
|
||||
|
||||
Mode mode = 1;
|
||||
}
|
||||
|
||||
message SetAntiFlickerConfigurationRequest
|
||||
{
|
||||
AntiFlickerConfiguration.Mode mode = 1;
|
||||
}
|
||||
|
||||
message SetAntiFlickerConfigurationResponse
|
||||
{
|
||||
bool success = 1;
|
||||
|
||||
repeated Error errors = 2;
|
||||
}
|
||||
28
plugins/logitech-bulkcontroller/proto/ble_cfg.proto
Normal file
28
plugins/logitech-bulkcontroller/proto/ble_cfg.proto
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
import "device_common.proto";
|
||||
|
||||
message SetBLECfgRequest
|
||||
{
|
||||
/**
|
||||
* (REQUIRED) If true, BLE is enabled and active otherwise disabled
|
||||
*/
|
||||
bool BLE_ON = 1;
|
||||
}
|
||||
|
||||
message SetBLECfgResponse
|
||||
{
|
||||
bool success = 1;
|
||||
repeated Error errors = 2;
|
||||
}
|
||||
285
plugins/logitech-bulkcontroller/proto/crash_info.proto
Normal file
285
plugins/logitech-bulkcontroller/proto/crash_info.proto
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
/**
|
||||
* Kong as an Android device can accumulate
|
||||
* crash debug information during its operation.
|
||||
* When Kong is running in device mode, those
|
||||
* crash dump files need to be copied over to
|
||||
* PC and uploaded to S3.
|
||||
* Note, if Kong is running in host mode, uploaded
|
||||
* files, and then moved to device mode, will it
|
||||
* copy the same files over?
|
||||
*
|
||||
* This message requests that crash dump files be
|
||||
* copied over to PC
|
||||
*
|
||||
* EXPECTED RESPONSE
|
||||
* SendCrashDumpResponse
|
||||
*
|
||||
*/
|
||||
message SendCrashDumpRequest
|
||||
{
|
||||
/**
|
||||
* Unused. Reserved for future use.
|
||||
*/
|
||||
bool reserved = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crash dump information. Most of these
|
||||
* are supplied by the crash analytics service, so lets
|
||||
* pass this information along.
|
||||
*/
|
||||
message CrashDumpInfo
|
||||
{
|
||||
/**
|
||||
* the filename
|
||||
*/
|
||||
string file_name = 1;
|
||||
|
||||
/**
|
||||
* the serial number
|
||||
*/
|
||||
string device_id = 2;
|
||||
|
||||
/**
|
||||
* the software version
|
||||
*/
|
||||
string software_version = 3;
|
||||
|
||||
/**
|
||||
* the file size
|
||||
*/
|
||||
uint64 file_size = 4;
|
||||
|
||||
/**
|
||||
* timestamp
|
||||
*/
|
||||
uint64 timestamp = 5;
|
||||
|
||||
/**
|
||||
* md5 for file
|
||||
*/
|
||||
string md5 = 6;
|
||||
|
||||
/**
|
||||
* the device type . Kong|Diddy
|
||||
*/
|
||||
string device_type = 7;
|
||||
|
||||
/**
|
||||
* the device mode. Hosted|Appliance
|
||||
*/
|
||||
string device_mode = 8;
|
||||
|
||||
/**
|
||||
* the report type. BugReport|EventLog,Diagnostics
|
||||
*/
|
||||
string report_type = 9;
|
||||
|
||||
/**
|
||||
* the content type. application/zip | text/plain | application/json
|
||||
*/
|
||||
string content_type = 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response which contains the crash dump file name
|
||||
* information and bool value to indicate will send
|
||||
* file
|
||||
*/
|
||||
message SendCrashDumpResponse
|
||||
{
|
||||
/**
|
||||
* (OPTIONAL)
|
||||
* If crash dump exists, this variable
|
||||
* contains the file name of crash dump
|
||||
* that will be copied over.
|
||||
*/
|
||||
string crash_dump_file = 1;
|
||||
|
||||
/**
|
||||
* (REQUIRED)
|
||||
* bool value to indicate will send file
|
||||
* true if sending file over.
|
||||
* false if no file to send.
|
||||
* If true, caller will look at CrashDumpInfo
|
||||
*/
|
||||
bool will_send_file = 2;
|
||||
|
||||
/**
|
||||
* (OPTIONAL)
|
||||
* Crash dump info
|
||||
*/
|
||||
CrashDumpInfo crash_dump_info = 3;
|
||||
}
|
||||
|
||||
message SendCrashDumpRequestv2
|
||||
{
|
||||
/**
|
||||
* The attestation challenge.
|
||||
* (REQUIRED)
|
||||
*/
|
||||
string challenge = 1;
|
||||
|
||||
/**
|
||||
* Time to live
|
||||
* (REQUIRED)
|
||||
*/
|
||||
int32 ttl = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response which contains the crash dump file name
|
||||
* information, bool value to indicate will send
|
||||
* file, body of the request and signature
|
||||
*/
|
||||
message SendCrashDumpResponsev2
|
||||
{
|
||||
/**
|
||||
* (OPTIONAL)
|
||||
* If crash dump exists, this variable
|
||||
* contains the file name of crash dump
|
||||
* that will be copied over.
|
||||
*/
|
||||
string crash_dump_file = 1;
|
||||
|
||||
/**
|
||||
* (REQUIRED)
|
||||
* bool value to indicate will send file
|
||||
* true if sending file over.
|
||||
* false if no file to send.
|
||||
* If true, caller will look at CrashDumpInfo
|
||||
*/
|
||||
bool will_send_file = 2;
|
||||
|
||||
/**
|
||||
* (OPTIONAL)
|
||||
* The get upload url body. This is a json string
|
||||
*/
|
||||
string body = 3;
|
||||
|
||||
/**
|
||||
* (OPTIONAL)
|
||||
* The get upload url body signature.
|
||||
*/
|
||||
string signature = 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is event sent from PC or Kong to indicate
|
||||
* Success
|
||||
*/
|
||||
message SendCrashDumpEvent
|
||||
{
|
||||
/**
|
||||
* (REQUIRED)
|
||||
* Contains the file name of crash dump
|
||||
* that is being sent or in process of being
|
||||
* received
|
||||
*/
|
||||
string crash_dump_file = 1;
|
||||
|
||||
/**
|
||||
* (REQUIRED)
|
||||
* Transfer state.
|
||||
* true indicates file was received without errors and bug report file was
|
||||
* uploaded false means an error occurred
|
||||
*/
|
||||
bool success = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Place holder for Android requesting that a crash dump copy
|
||||
* get initiated from PC side
|
||||
*/
|
||||
message CrashDumpAvailableEvent
|
||||
{
|
||||
/**
|
||||
* Unused. Reserved for future use.
|
||||
*/
|
||||
bool reserved = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask device to generate a bug report. This could be
|
||||
* for gathering logcat, system logs, etc.
|
||||
* Similar to SendCrashDumpRequestv2, but bug report generation is on
|
||||
* demand.
|
||||
* EXPECTED RESPONSE:
|
||||
* GenerateCrashDumpResponse
|
||||
* It should follow the same flow as described here
|
||||
* https://docs.google.com/document/d/1D5nx1nenDu9ucZbYPXlNNxFEN1tx3W7k044mvi74x28/edit#heading=h.a9wyfbpb2282
|
||||
*/
|
||||
message GenerateCrashDumpRequest
|
||||
{
|
||||
/**
|
||||
* The attestation challenge.
|
||||
* (REQUIRED)
|
||||
*/
|
||||
string challenge = 1;
|
||||
|
||||
/**
|
||||
* Time to live
|
||||
* (REQUIRED)
|
||||
*/
|
||||
int32 ttl = 2;
|
||||
|
||||
/**
|
||||
* The note to include in the bug report. This could be empty.
|
||||
* (OPTIONAL)
|
||||
*/
|
||||
string note = 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response which contains the
|
||||
* crash dump file name information,
|
||||
* bool value to indicate will send file,
|
||||
* body of the request and signature.
|
||||
* Similar to SendCrashDumpResponsev2, but bug report generation is on
|
||||
* demand.
|
||||
* It should follow the same flow as described here
|
||||
* https://docs.google.com/document/d/1D5nx1nenDu9ucZbYPXlNNxFEN1tx3W7k044mvi74x28/edit#heading=h.a9wyfbpb2282
|
||||
*/
|
||||
message GenerateCrashDumpResponse
|
||||
{
|
||||
/**
|
||||
* (OPTIONAL)
|
||||
* If crash dump exists, this variable
|
||||
* contains the file name of crash dump
|
||||
* that will be copied over.
|
||||
*/
|
||||
string crash_dump_file = 1;
|
||||
|
||||
/**
|
||||
* (REQUIRED)
|
||||
* bool value to indicate will send file
|
||||
* true if sending file over.
|
||||
* false if no file to send.
|
||||
*/
|
||||
bool will_send_file = 2;
|
||||
|
||||
/**
|
||||
* (OPTIONAL)
|
||||
* The get upload url body. This is a json string
|
||||
*/
|
||||
string body = 3;
|
||||
|
||||
/**
|
||||
* (OPTIONAL)
|
||||
* The get upload url body signature.
|
||||
*/
|
||||
string signature = 4;
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
/**
|
||||
* Request for certificate chain
|
||||
* This is to be included in UsbMsg
|
||||
|
||||
* EXPECTED RESPONSE
|
||||
* GetCertificateChainResponse
|
||||
*/
|
||||
message GetCertificateChainRequest
|
||||
{
|
||||
/**
|
||||
* attestation challenge
|
||||
*/
|
||||
string attestation = 1;
|
||||
|
||||
/**
|
||||
* time to live
|
||||
*/
|
||||
int32 ttl = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get certificate chain response
|
||||
*/
|
||||
message GetCertificateChainResponse
|
||||
{
|
||||
/**
|
||||
* array of certs
|
||||
*/
|
||||
repeated string certchain = 1;
|
||||
}
|
||||
48
plugins/logitech-bulkcontroller/proto/device_common.proto
Normal file
48
plugins/logitech-bulkcontroller/proto/device_common.proto
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
/**
|
||||
* This error messages describe a failure that was encountered
|
||||
* by the Sync service and primarily consist of an error code
|
||||
* and a short, human-readable message. Therefore, if a client
|
||||
* receives a message with a field reserved for Error messages,
|
||||
* it is prudent that the application first check if there are
|
||||
* errors before doing any further processing of the message.
|
||||
*/
|
||||
message Error
|
||||
{
|
||||
/**
|
||||
* (REQUIRED) Error code.
|
||||
*/
|
||||
uint32 error_code = 1;
|
||||
|
||||
/**
|
||||
* (OPTIONAL) Short, human-readable error message. If no
|
||||
* message is available, then this will be an empty string.
|
||||
*/
|
||||
string error_message = 2;
|
||||
|
||||
/**
|
||||
* (OPTIONAL) A URI to a log file or some other document
|
||||
* that contains more detailed information about the error.
|
||||
* If such a file is not available, this will be an empty
|
||||
* string.
|
||||
*/
|
||||
string error_log_uri = 3;
|
||||
|
||||
/**
|
||||
* (OPTIONAL) An optional JSON string with additional
|
||||
* metadata that may be useful to the client.
|
||||
*/
|
||||
string json_metadata = 4;
|
||||
}
|
||||
38
plugins/logitech-bulkcontroller/proto/device_info.proto
Normal file
38
plugins/logitech-bulkcontroller/proto/device_info.proto
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
/**
|
||||
* Request Device information
|
||||
* This is to be included in UsbMsg
|
||||
|
||||
* EXPECTED RESPONSE
|
||||
* GetDeviceInfoResponse
|
||||
*/
|
||||
message GetDeviceInfoRequest
|
||||
{
|
||||
/**
|
||||
* Unused. Reserved for future use.
|
||||
*/
|
||||
bool reserved = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device information response
|
||||
*/
|
||||
message GetDeviceInfoResponse
|
||||
{
|
||||
/**
|
||||
* payload contains actual mqtt message
|
||||
*/
|
||||
string payload = 1;
|
||||
}
|
||||
183
plugins/logitech-bulkcontroller/proto/device_mode.proto
Normal file
183
plugins/logitech-bulkcontroller/proto/device_mode.proto
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
/**
|
||||
* Behavior change as of 1/28/2021 EE
|
||||
* Kong sync-agent should not deprovision when this message is
|
||||
* received. If would just start forwarding events to PC when message is
|
||||
* received.
|
||||
*
|
||||
* (Legacy)
|
||||
* Request to transition to device mode
|
||||
* Kong could be provisioned in Host mode. This message
|
||||
* will ask Kong to deprovisioned/remove host mode provisioning
|
||||
* data.
|
||||
* This is to be included in UsbMsg
|
||||
|
||||
* EXPECTED RESPONSE
|
||||
* TransitionToDeviceModeResponse
|
||||
*/
|
||||
message TransitionToDeviceModeRequest
|
||||
{
|
||||
/**
|
||||
* Unused. Reserved for future use.
|
||||
*/
|
||||
bool reserved = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to transition to device mode response
|
||||
*/
|
||||
message TransitionToDeviceModeResponse
|
||||
{
|
||||
/**
|
||||
* boolean value to indicate Kong was able to transition to
|
||||
* device mode. If Kong is not provisioned, should just respond
|
||||
* with true value.
|
||||
* set to false if error was encountered during transition, and Kong
|
||||
* wasn't able to transition (is this possible?)
|
||||
*/
|
||||
bool success = 1;
|
||||
|
||||
/**
|
||||
* the error in integer if success was false
|
||||
*/
|
||||
int32 error = 2;
|
||||
|
||||
/**
|
||||
* the error description
|
||||
*/
|
||||
string error_description = 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added 1/28/2021 EE
|
||||
* Request to deprovision Kong
|
||||
* This request is sent by PC sync-agent when PC
|
||||
* is provisioned.
|
||||
* Kong sync-agent should deprovision (if provisioned)
|
||||
*
|
||||
* EXPECTED RESPONSE
|
||||
* SetDeprovisionResponse
|
||||
*/
|
||||
message SetDeprovisionRequest
|
||||
{
|
||||
/**
|
||||
* Unused. Reserved for future use.
|
||||
*/
|
||||
bool reserved = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response to deprovision request
|
||||
*/
|
||||
message SetDeprovisionResponse
|
||||
{
|
||||
/**
|
||||
* boolean value to indicate Kong was able to deprovision Kong.
|
||||
* If Kong is not provisioned, should just respond
|
||||
* with true value.
|
||||
* set to false if error was encountered during deprovisioning.
|
||||
*/
|
||||
bool success = 1;
|
||||
|
||||
/**
|
||||
* the error in integer if success was false
|
||||
*/
|
||||
int32 error = 2;
|
||||
|
||||
/**
|
||||
* the error description
|
||||
*/
|
||||
string error_description = 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added 3/22/2021 EE
|
||||
* For sending a certificate as data. There are currently
|
||||
* 2 known certificate that will be transferred - Root CA, and 802.1x cert.
|
||||
* Upon receipt, sync-agent should verify using the supplied hash
|
||||
* and write the data to the file system.
|
||||
*
|
||||
* EXPECTED RESPONSE
|
||||
* SendCertificateDataResponse
|
||||
*/
|
||||
message SendCertificateDataRequest
|
||||
{
|
||||
/**
|
||||
* The certificate type
|
||||
*/
|
||||
enum CertType {
|
||||
/**
|
||||
* Reserved. Do not use.
|
||||
*/
|
||||
RESERVED = 0;
|
||||
/**
|
||||
* Root CA
|
||||
*/
|
||||
ROOT_CA = 1;
|
||||
/**
|
||||
* 802.1x cert
|
||||
*/
|
||||
NET_CONFIG = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* (REQUIRED)
|
||||
* The certificate type
|
||||
*/
|
||||
CertType cert_type = 1;
|
||||
|
||||
/**
|
||||
* (REQUIRED)
|
||||
* the certificate file name
|
||||
*/
|
||||
string file_name = 2;
|
||||
|
||||
/**
|
||||
* (REQUIRED)
|
||||
* the certificate data
|
||||
*/
|
||||
bytes cert_data = 3;
|
||||
|
||||
/**
|
||||
* (REQUIRED)
|
||||
* the certificate md5 hash
|
||||
*/
|
||||
string md5 = 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response to SendCertificateData Request
|
||||
*/
|
||||
message SendCertificateDataResponse
|
||||
{
|
||||
/**
|
||||
* (REQUIRED)
|
||||
* boolean value to indicate data was received, hash verified .
|
||||
* set to false if error was encountered during transfer and verification.
|
||||
*/
|
||||
bool success = 1;
|
||||
|
||||
/**
|
||||
* (OPTIONAL)
|
||||
* the error in integer if success was false
|
||||
*/
|
||||
int32 error = 2;
|
||||
|
||||
/**
|
||||
* (OPTIONAL)
|
||||
* the error description if there are errors
|
||||
*/
|
||||
string error_description = 3;
|
||||
}
|
||||
143
plugins/logitech-bulkcontroller/proto/device_request.proto
Normal file
143
plugins/logitech-bulkcontroller/proto/device_request.proto
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
/**
|
||||
* Request to reboot device
|
||||
* This is to be included in UsbMsg
|
||||
|
||||
* EXPECTED RESPONSE
|
||||
* RebootDeviceResponse
|
||||
*/
|
||||
message RebootDeviceRequest
|
||||
{
|
||||
/**
|
||||
* Unused. Reserved for future use.
|
||||
*/
|
||||
bool reserved = 1;
|
||||
|
||||
/**
|
||||
* A timestamp indicating when the reboot request
|
||||
* was initiated.
|
||||
* The device should include this entry as part of the event information
|
||||
* it sends back to PC during a reboot request.
|
||||
*/
|
||||
uint64 iat = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reboot device response
|
||||
*/
|
||||
message RebootDeviceResponse
|
||||
{
|
||||
/**
|
||||
* bool value to indicate reboot was requested. If there are errors
|
||||
* while requesting a device to reboot, should set the value to false
|
||||
*/
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This message requests that the speaker boost audio setting be changed.
|
||||
* The device should send a device info event after this setting request are
|
||||
* handled.
|
||||
*
|
||||
* EXPECTED RESPONSE
|
||||
* SetSpeakerBoostResponse
|
||||
*
|
||||
*/
|
||||
message SetSpeakerBoostRequest
|
||||
{
|
||||
/**
|
||||
* (REQUIRED) The speaker boost setting to be set
|
||||
*
|
||||
* If value is 0, the request is to disable. If 1,
|
||||
* the request is to enable.
|
||||
*/
|
||||
int32 speaker_boost = 1;
|
||||
}
|
||||
|
||||
message SetSpeakerBoostResponse
|
||||
{
|
||||
/**
|
||||
* (REQUIRED) set to true if the audio setting request was successfully sent,
|
||||
* false otherwise
|
||||
*/
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This message requests that the noise reduction audio setting be changed.
|
||||
* The device should send a device info event after this setting request are
|
||||
* handled.
|
||||
*
|
||||
* EXPECTED RESPONSE
|
||||
* SetNoiseReductionResponse
|
||||
*
|
||||
*/
|
||||
message SetNoiseReductionRequest
|
||||
{
|
||||
/**
|
||||
* (REQUIRED) The noise reduction setting to be set
|
||||
*
|
||||
* If value is 0, the request is to disable. If 1,
|
||||
* the request is to enable.
|
||||
*/
|
||||
int32 noise_reduction = 1;
|
||||
}
|
||||
|
||||
message SetNoiseReductionResponse
|
||||
{
|
||||
/**
|
||||
* (REQUIRED) set to true if the audio setting request was successfully sent,
|
||||
* false otherwise
|
||||
*/
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This message requests that the reverb mode audio setting be changed.
|
||||
* The device should send a device info event after this setting request are
|
||||
* handled.
|
||||
*
|
||||
* EXPECTED RESPONSE
|
||||
* SetReverbModeResponse
|
||||
*
|
||||
*/
|
||||
message SetReverbModeRequest
|
||||
{
|
||||
/**
|
||||
* Reverb mode enumeration
|
||||
*/
|
||||
enum ReverbMode {
|
||||
DISABLED = 0;
|
||||
MILD = 1;
|
||||
NORMAL = 2;
|
||||
AGGRESSIVE = 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* (REQUIRED) The reverb mode setting to be set
|
||||
*
|
||||
* see Reverb mode enumeration
|
||||
*/
|
||||
ReverbMode reverb_mode = 1;
|
||||
}
|
||||
|
||||
message SetReverbModeResponse
|
||||
{
|
||||
/**
|
||||
* (REQUIRED) set to true if the setting request was successfully sent, false
|
||||
* otherwise
|
||||
*/
|
||||
bool success = 1;
|
||||
}
|
||||
32
plugins/logitech-bulkcontroller/proto/device_time.proto
Normal file
32
plugins/logitech-bulkcontroller/proto/device_time.proto
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
/**
|
||||
* Request for setting device time
|
||||
* This is to be included in UsbMsg
|
||||
*/
|
||||
message SetDeviceTimeRequest
|
||||
{
|
||||
/**
|
||||
* utc timestamp.
|
||||
*/
|
||||
uint64 ts = 1;
|
||||
/**
|
||||
* the time zone.
|
||||
*/
|
||||
string time_zone = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an ack as the response
|
||||
*/
|
||||
38
plugins/logitech-bulkcontroller/proto/firmware_update.proto
Normal file
38
plugins/logitech-bulkcontroller/proto/firmware_update.proto
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
/**
|
||||
* Request to start update
|
||||
* This is to be included in UsbMsg
|
||||
|
||||
* EXPECTED RESPONSE
|
||||
* UpdateNowResponse
|
||||
*/
|
||||
message UpdateNowRequest
|
||||
{
|
||||
/**
|
||||
* Unused. Reserved for future use.
|
||||
*/
|
||||
bool reserved = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update now response
|
||||
*/
|
||||
message UpdateNowResponse
|
||||
{
|
||||
/**
|
||||
* bool value to indicate update was started
|
||||
*/
|
||||
bool started = 1;
|
||||
}
|
||||
21
plugins/logitech-bulkcontroller/proto/meson.build
Normal file
21
plugins/logitech-bulkcontroller/proto/meson.build
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
gen = generator(protoc, \
|
||||
output : ['@BASENAME@.pb-c.c', '@BASENAME@.pb-c.h'],
|
||||
arguments : ['--proto_path=@CURRENT_SOURCE_DIR@', '--c_out=@BUILD_DIR@', '@INPUT@'])
|
||||
|
||||
src = [
|
||||
'antiflicker.proto',
|
||||
'ble_cfg.proto',
|
||||
'crash_info.proto',
|
||||
'device_attestation.proto',
|
||||
'device_common.proto',
|
||||
'device_info.proto',
|
||||
'device_mode.proto',
|
||||
'device_request.proto',
|
||||
'device_time.proto',
|
||||
'firmware_update.proto',
|
||||
'rightsight.proto',
|
||||
'ota_manifest.proto',
|
||||
'usb_msg.proto',
|
||||
]
|
||||
generated = gen.process(src)
|
||||
72
plugins/logitech-bulkcontroller/proto/ota_manifest.proto
Normal file
72
plugins/logitech-bulkcontroller/proto/ota_manifest.proto
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
/**
|
||||
* Request device to create a GetManifestv2 body. See
|
||||
* https://docs.google.com/document/d/1l31A1TWhtJC0xR8GwuNtiGN4vPLURRsj5ZcC1uEIwVQ/edit#heading=h.ctbthi1iyxw1
|
||||
*
|
||||
*
|
||||
* This is to be included in UsbMsg
|
||||
*
|
||||
* EXPECTED RESPONSE
|
||||
* GetManifestBodyResponse
|
||||
*/
|
||||
message GetManifestBodyRequest
|
||||
{
|
||||
/**
|
||||
* The attestation challenge.
|
||||
* (REQUIRED)
|
||||
*/
|
||||
string challenge = 1;
|
||||
|
||||
/**
|
||||
* The manifest version.
|
||||
* (REQUIRED)
|
||||
*/
|
||||
string version = 2;
|
||||
|
||||
/**
|
||||
* The channel. Dont use if empty or null
|
||||
* (OPTIONAL)
|
||||
*/
|
||||
string channel = 3;
|
||||
|
||||
/**
|
||||
* The meta info in json format. This
|
||||
* field usually comes from PC.
|
||||
* (OPTIONAL)
|
||||
*/
|
||||
string meta_info = 4;
|
||||
|
||||
/**
|
||||
* Time to live
|
||||
* (REQUIRED)
|
||||
*/
|
||||
int32 ttl = 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetManifestv2 body response
|
||||
*/
|
||||
message GetManifestBodyResponse
|
||||
{
|
||||
/**
|
||||
* The get manifest body. This is a json string
|
||||
*/
|
||||
string body = 1;
|
||||
|
||||
/**
|
||||
* The get manifest body signature.
|
||||
*/
|
||||
string signature = 2;
|
||||
}
|
||||
123
plugins/logitech-bulkcontroller/proto/rightsight.proto
Normal file
123
plugins/logitech-bulkcontroller/proto/rightsight.proto
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
import "device_common.proto";
|
||||
|
||||
/**
|
||||
* This message data structure holds information about the
|
||||
* current RightSight configuration.
|
||||
*
|
||||
*/
|
||||
message RightSightConfiguration
|
||||
{
|
||||
/**
|
||||
* Enumeration of modes that the RightSight service can be in.
|
||||
*/
|
||||
enum Mode {
|
||||
/**
|
||||
* This does not indicate a default value.
|
||||
*
|
||||
*/
|
||||
DO_NOT_USE = 0;
|
||||
|
||||
/**
|
||||
* The camera will continually pan, tilt, and zoom
|
||||
* to properly frame everyone during a meeting.
|
||||
*/
|
||||
DYNAMIC = 1;
|
||||
|
||||
/**
|
||||
* The camera will pan, tilt, and zoom to properly in
|
||||
* the meeting only when the call starts.
|
||||
*/
|
||||
ON_CALL_START = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* (REQUIRED) If true, RightSight is enabled and active.
|
||||
*/
|
||||
bool enabled = 1;
|
||||
|
||||
/**
|
||||
* (REQUIRED) The current mode that RightSight is in.
|
||||
*/
|
||||
Mode mode = 2;
|
||||
|
||||
/**
|
||||
* (REQUIRED) A timestamp indicating when the RightSight
|
||||
* settings were last modified. This is the number of
|
||||
* milliseconds since the epoch.
|
||||
*/
|
||||
uint64 last_modified = 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* RightSight is an auto-framing feature that is available in Kong.
|
||||
* With RightSight enabled, your device will automatically pan, tilt, and zoom
|
||||
* the camera lens in order to capture all meeting participants
|
||||
* within the image frame. This feature can be set to one of two
|
||||
* modes: dynamic and on call start. When in dynamic mode, the
|
||||
* device will actively pan, tilt, and zoom the camera lens when
|
||||
* appropriate in order to keep all participants in frame during
|
||||
* the entire course of the meeting. When in on call start mode,
|
||||
* the camera lens will pan, tilt, and zoom to capture everybody
|
||||
* in frame only when the meeting starts.
|
||||
*
|
||||
* When RightSight is enabled, it is set
|
||||
* to dynamic mode by default.
|
||||
*
|
||||
* This message requests that the RightSight configuration
|
||||
* settings be changed.
|
||||
*
|
||||
* EXPECTED RESPONSE
|
||||
* SetRightSightConfigurationResponse
|
||||
*
|
||||
*/
|
||||
message SetRightSightConfigurationRequest
|
||||
{
|
||||
/**
|
||||
* (REQUIRED) If true, requests that RightSight be
|
||||
* turned on. If false, indicates that
|
||||
* RightSight should be turned off.
|
||||
*/
|
||||
bool enabled = 1;
|
||||
|
||||
/**
|
||||
* (REQUIRED) The mode for RightSight to be in. A value is
|
||||
* required, but if none is provided, then this will
|
||||
* default to DYNAMIC mode.
|
||||
*
|
||||
* If enabled is set to false, then this will effectively
|
||||
* do nothing as RightSight is turned off.
|
||||
*/
|
||||
RightSightConfiguration.Mode mode = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response which contains the RightSight configuration that was
|
||||
* set as a result of the request.
|
||||
*/
|
||||
message SetRightSightConfigurationResponse
|
||||
{
|
||||
/**
|
||||
* (OPTIONAL) If any errors occurred while processing the
|
||||
* request, then this field should be set accordingly.
|
||||
*/
|
||||
repeated Error errors = 1;
|
||||
|
||||
/**
|
||||
* (REQUIRED) The RightSight configuration that was set on
|
||||
* the product.
|
||||
*/
|
||||
RightSightConfiguration right_sight_configuration = 2;
|
||||
}
|
||||
204
plugins/logitech-bulkcontroller/proto/usb_msg.proto
Normal file
204
plugins/logitech-bulkcontroller/proto/usb_msg.proto
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2021 Logitech, Inc.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package logi.device.proto;
|
||||
|
||||
option java_package = "com.logitech.vc.proto";
|
||||
|
||||
import "device_info.proto";
|
||||
import "firmware_update.proto";
|
||||
import "crash_info.proto";
|
||||
import "device_mode.proto";
|
||||
import "device_attestation.proto";
|
||||
import "rightsight.proto";
|
||||
import "ota_manifest.proto";
|
||||
import "device_time.proto";
|
||||
import "ble_cfg.proto";
|
||||
import "antiflicker.proto";
|
||||
import "device_request.proto";
|
||||
|
||||
/**
|
||||
*
|
||||
* Header message to be included in UsbMsg. This contains
|
||||
* message metadata that aids in processing of messages
|
||||
*/
|
||||
message Header
|
||||
{
|
||||
/**
|
||||
* A unique id of the message. If responding after receiving
|
||||
* data, the value stored in this field should be used in the ack message
|
||||
* msgId field
|
||||
*/
|
||||
string id = 1;
|
||||
/**
|
||||
* A timestamp indicating when the message was
|
||||
* sent. This is the number of milliseconds that have
|
||||
* elapsed since the epoch, in string format
|
||||
*/
|
||||
string timestamp = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Ack message.
|
||||
* This is to be included in UsbMsg
|
||||
*/
|
||||
message Acknowledge
|
||||
{
|
||||
/**
|
||||
* The message Id. This should be the same value
|
||||
* in UsbMsg.Header.id field
|
||||
*/
|
||||
string msgId = 1;
|
||||
|
||||
/**
|
||||
* The message processing result. true indicates message was
|
||||
* successfully processed, false otherwise.
|
||||
*/
|
||||
bool success = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Kong Event message.
|
||||
* Anything that is not part of
|
||||
* Request/Response messaging, but is being sent to mqtt distributor
|
||||
* should be considered as a KongEvent, and forwarded to device host.
|
||||
* This is to be included in UsbMsg
|
||||
*/
|
||||
message KongEvent
|
||||
{
|
||||
/**
|
||||
* mqtt_event contains actual mqtt message
|
||||
*/
|
||||
string mqtt_event = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sent by Kong sync-agent.
|
||||
* If Kong sync-agent starts-up and it is in Device mode, then
|
||||
* it can send this event. When PC sync-agent receives this event,
|
||||
* it should send a TransitionToDeviceModeRequest.
|
||||
* This is to be included in UsbMsg
|
||||
*/
|
||||
message HandshakeEvent
|
||||
{
|
||||
/**
|
||||
* Unused. Reserved for future use.
|
||||
*/
|
||||
bool reserved = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The enclosing message.
|
||||
* This is the root message of all messagesszx
|
||||
*/
|
||||
message UsbMsg
|
||||
{
|
||||
/**
|
||||
* Header for the message containing additional
|
||||
* message metadata.
|
||||
*/
|
||||
Header header = 1;
|
||||
|
||||
/**
|
||||
* The actual message being sent. One of these must be
|
||||
* included
|
||||
*/
|
||||
oneof message
|
||||
{
|
||||
/**
|
||||
* Ack message
|
||||
*/
|
||||
Acknowledge ack = 2;
|
||||
/**
|
||||
* Request message
|
||||
*/
|
||||
Request request = 3;
|
||||
/**
|
||||
* Response message
|
||||
*/
|
||||
Response response = 4;
|
||||
/**
|
||||
* Event
|
||||
*/
|
||||
Event event = 5;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Request message.
|
||||
* This is to be included in UsbMsg
|
||||
*/
|
||||
message Request
|
||||
{
|
||||
oneof payload
|
||||
{
|
||||
GetDeviceInfoRequest get_device_info_request = 2;
|
||||
UpdateNowRequest update_now_request = 3;
|
||||
SendCrashDumpRequest crash_dump_request = 4;
|
||||
TransitionToDeviceModeRequest transition_to_devicemode_request = 5;
|
||||
GetCertificateChainRequest get_certificate_chain_request = 6;
|
||||
SetRightSightConfigurationRequest set_right_sight_configuration_request = 7;
|
||||
GetManifestBodyRequest get_manifest_body_request = 8;
|
||||
SendCrashDumpRequestv2 crash_dump_request_v2 = 9;
|
||||
SetDeviceTimeRequest set_device_time_request = 10;
|
||||
SetAntiFlickerConfigurationRequest set_anti_flicker_configuration_request = 11;
|
||||
SetBLECfgRequest set_ble_cfg_request = 12;
|
||||
SetDeprovisionRequest set_deprovision_request = 13;
|
||||
RebootDeviceRequest reboot_device_request = 14;
|
||||
SetSpeakerBoostRequest speaker_boost_request = 15;
|
||||
SetNoiseReductionRequest noise_reduction_request = 16;
|
||||
SetReverbModeRequest reverb_mode_request = 17;
|
||||
GenerateCrashDumpRequest generate_bug_report_request = 18;
|
||||
SendCertificateDataRequest send_certificate_data_request = 19;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Response message.
|
||||
* This is to be included in UsbMsg
|
||||
*/
|
||||
message Response
|
||||
{
|
||||
oneof payload
|
||||
{
|
||||
GetDeviceInfoResponse get_device_info_response = 2;
|
||||
UpdateNowResponse update_now_response = 3;
|
||||
SendCrashDumpResponse crash_dump_response = 4;
|
||||
TransitionToDeviceModeResponse transition_to_devicemode_response = 5;
|
||||
GetCertificateChainResponse get_certificate_chain_response = 6;
|
||||
SetRightSightConfigurationResponse set_right_sight_configuration_response = 7;
|
||||
GetManifestBodyResponse get_manifest_body_response = 8;
|
||||
SendCrashDumpResponsev2 crash_dump_response_v2 = 9;
|
||||
SetAntiFlickerConfigurationResponse set_anti_flicker_configuration_response = 11;
|
||||
SetBLECfgResponse set_ble_cfg_response = 12;
|
||||
SetDeprovisionResponse set_deprovision_response = 13;
|
||||
RebootDeviceResponse reboot_device_response = 14;
|
||||
|
||||
SetSpeakerBoostResponse speaker_boost_response = 15;
|
||||
SetNoiseReductionResponse noise_reduction_response = 16;
|
||||
SetReverbModeResponse reverb_mode_response = 17;
|
||||
GenerateCrashDumpResponse generate_bug_report_response = 18;
|
||||
SendCertificateDataResponse send_certificate_data_response = 19;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Event message.
|
||||
* This is to be included in UsbMsg
|
||||
*/
|
||||
message Event
|
||||
{
|
||||
oneof payload
|
||||
{
|
||||
KongEvent kong_event = 1;
|
||||
SendCrashDumpEvent send_crash_dump_event = 2;
|
||||
CrashDumpAvailableEvent crash_dump_available_event = 3;
|
||||
HandshakeEvent handshake_event = 4;
|
||||
}
|
||||
}
|
||||
@ -35,6 +35,7 @@ subdir('linux-swap')
|
||||
subdir('linux-tainted')
|
||||
subdir('logind')
|
||||
subdir('logitech-hidpp')
|
||||
subdir('logitech-bulkcontroller')
|
||||
subdir('modem-manager')
|
||||
subdir('msr')
|
||||
subdir('nitrokey')
|
||||
|
||||
@ -211,11 +211,13 @@ parts:
|
||||
- libpango1.0-dev
|
||||
- libpci-dev
|
||||
- libpolkit-gobject-1-dev
|
||||
- libprotobuf-c-dev
|
||||
- libsmbios-dev
|
||||
- libsqlite3-dev
|
||||
- libsystemd-dev
|
||||
- locales
|
||||
- pkg-config
|
||||
- protobuf-c-compiler
|
||||
- systemd
|
||||
- uuid-dev
|
||||
stage-packages:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user