Rename device4 into device_mcu

Signed-off-by: Jacki <jacki@thejackimonster.de>
This commit is contained in:
Jacki 2024-08-02 00:52:44 +02:00
parent 776fb7204d
commit 09ad6dc04e
No known key found for this signature in database
GPG key ID: B404184796354C5E
12 changed files with 894 additions and 893 deletions

View file

@ -1,5 +1,5 @@
add_subdirectory(debug_imu)
add_subdirectory(debug_d4)
add_subdirectory(debug_mcu)
add_subdirectory(mcu_firmware)

View file

@ -26,9 +26,9 @@
#include <stdio.h>
void test3(uint64_t timestamp,
device_imu_event_type event,
const device_imu_ahrs_type* ahrs) {
void test(uint64_t timestamp,
device_imu_event_type event,
const device_imu_ahrs_type* ahrs) {
device_imu_quat_type orientation;
device_imu_euler_type euler;
@ -47,13 +47,13 @@ void test3(uint64_t timestamp,
}
int main(int argc, const char** argv) {
device_imu_type dev3;
if (DEVICE_IMU_ERROR_NO_ERROR != device_imu_open(&dev3, test3)) {
device_imu_type dev;
if (DEVICE_IMU_ERROR_NO_ERROR != device_imu_open(&dev, test)) {
return 1;
}
device_imu_clear(&dev3);
while (DEVICE_IMU_ERROR_NO_ERROR == device_imu_read(&dev3, -1));
device_imu_close(&dev3);
device_imu_clear(&dev);
while (DEVICE_IMU_ERROR_NO_ERROR == device_imu_read(&dev, -1));
device_imu_close(&dev);
return 0;
}

View file

@ -1,17 +1,17 @@
cmake_minimum_required(VERSION 3.16)
project(xrealAirDebugD4 C)
project(xrealAirDebugMCU C)
set(CMAKE_C_STANDARD 17)
add_executable(
xrealAirDebugD4
xrealAirDebugMCU
src/debug.c
)
target_include_directories(xrealAirDebugD4
target_include_directories(xrealAirDebugMCU
BEFORE PUBLIC ${XREAL_AIR_INCLUDE_DIR}
)
target_link_libraries(xrealAirDebugD4
target_link_libraries(xrealAirDebugMCU
${XREAL_AIR_LIBRARY}
)

View file

@ -1,7 +1,7 @@
//
// Created by thejackimonster on 05.04.23.
//
// Copyright (c) 2023 thejackimonster. All rights reserved.
// Copyright (c) 2023-2024 thejackimonster. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,22 +22,22 @@
// THE SOFTWARE.
//
#include "device4.h"
#include "device_mcu.h"
#include <stdio.h>
void test4(uint64_t timestamp,
device4_event_type event,
uint8_t brightness,
const char* msg) {
void test(uint64_t timestamp,
device_mcu_event_type event,
uint8_t brightness,
const char* msg) {
switch (event) {
case DEVICE4_EVENT_MESSAGE:
case DEVICE_MCU_EVENT_MESSAGE:
printf("Message: `%s`\n", msg);
break;
case DEVICE4_EVENT_BRIGHTNESS_UP:
case DEVICE_MCU_EVENT_BRIGHTNESS_UP:
printf("Increase Brightness: %u\n", brightness);
break;
case DEVICE4_EVENT_BRIGHTNESS_DOWN:
case DEVICE_MCU_EVENT_BRIGHTNESS_DOWN:
printf("Decrease Brightness: %u\n", brightness);
break;
default:
@ -46,13 +46,13 @@ void test4(uint64_t timestamp,
}
int main(int argc, const char** argv) {
device4_type dev4;
if (DEVICE4_ERROR_NO_ERROR != device4_open(&dev4, test4)) {
device_mcu_type dev;
if (DEVICE_MCU_ERROR_NO_ERROR != device_mcu_open(&dev, test)) {
return 1;
}
device4_clear(&dev4);
while (DEVICE4_ERROR_NO_ERROR == device4_read(&dev4, -1));
device4_close(&dev4);
device_mcu_clear(&dev);
while (DEVICE_MCU_ERROR_NO_ERROR == device_mcu_read(&dev, -1));
device_mcu_close(&dev);
return 0;
}

View file

@ -22,7 +22,7 @@
// THE SOFTWARE.
//
#include "device4.h"
#include "device_mcu.h"
#include <stdio.h>
#include <string.h>
@ -67,13 +67,13 @@ int main(int argc, const char** argv) {
return 0;
}
device4_type dev4;
if (DEVICE4_ERROR_NO_ERROR != device4_open(&dev4, NULL)) {
device_mcu_type dev;
if (DEVICE_MCU_ERROR_NO_ERROR != device_mcu_open(&dev, NULL)) {
return 1;
}
device4_clear(&dev4);
device4_update_mcu_firmware(&dev4, path);
device4_close(&dev4);
device_mcu_clear(&dev);
device_mcu_update_firmware(&dev, path);
device_mcu_close(&dev);
return 0;
}

View file

@ -13,7 +13,7 @@ add_library(
src/crc32.c
src/device.c
src/device_imu.c
src/device4.c
src/device_mcu.c
src/hid_ids.c
)

View file

@ -1,192 +0,0 @@
#pragma once
//
// Created by thejackimonster on 29.03.23.
//
// Copyright (c) 2023 thejackimonster. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#ifndef __cplusplus
#include <stdbool.h>
#endif
#ifndef __cplusplus
#include <stdint.h>
#else
#include <cstdint>
#endif
#define DEVICE4_MSG_R_BRIGHTNESS 0x03
#define DEVICE4_MSG_W_BRIGHTNESS 0x04
#define DEVICE4_MSG_R_DISP_MODE 0x07
#define DEVICE4_MSG_W_DISP_MODE 0x08
#define DEVICE4_MSG_R_GLASSID 0x15
#define DEVICE4_MSG_R_DP7911_FW_VERSION 0x16
#define DEVICE4_MSG_R_DSP_VERSION 0x18
#define DEVICE4_MSG_W_CANCEL_ACTIVATION 0x19
#define DEVICE4_MSG_P_HEARTBEAT 0x1A
#define DEVICE4_MSG_W_SLEEP_TIME 0x1E
#define DEVICE4_MSG_R_DSP_APP_FW_VERSION 0x21
#define DEVICE4_MSG_R_MCU_APP_FW_VERSION 0x26
#define DEVICE4_MSG_R_ACTIVATION_TIME 0x29
#define DEVICE4_MSG_W_ACTIVATION_TIME 0x2A
#define DEVICE4_MSG_R_DP7911_FW_IS_UPDATE 0x3C
#define DEVICE4_MSG_W_UPDATE_DP 0x3D
#define DEVICE4_MSG_W_UPDATE_MCU_APP_FW_PREPARE 0x3E
#define DEVICE4_MSG_W_UPDATE_MCU_APP_FW_START 0x3F
#define DEVICE4_MSG_W_UPDATE_MCU_APP_FW_TRANSMIT 0x40
#define DEVICE4_MSG_W_UPDATE_MCU_APP_FW_FINISH 0x41
#define DEVICE4_MSG_W_BOOT_JUMP_TO_APP 0x42
#define DEVICE4_MSG_W_MCU_APP_JUMP_TO_BOOT 0x44
#define DEVICE4_MSG_W_UPDATE_DSP_APP_FW_PREPARE 0x45
#define DEVICE4_MSG_W_UPDATE_DSP_APP_FW_START 0x46
#define DEVICE4_MSG_W_UPDATE_DSP_APP_FW_TRANSMIT 0x47
#define DEVICE4_MSG_W_UPDATE_DSP_APP_FW_FINISH 0x48
#define DEVICE4_MSG_R_IS_NEED_UPGRADE_DSP_FW 0x49
#define DEVICE4_MSG_W_FORCE_UPGRADE_DSP_FW 0x69
#define DEVICE4_MSG_W_BOOT_UPDATE_MODE 0x1100
#define DEVICE4_MSG_W_BOOT_UPDATE_CONFIRM 0x1101
#define DEVICE4_MSG_W_BOOT_UPDATE_PREPARE 0x1102
#define DEVICE4_MSG_W_BOOT_UPDATE_START 0x1103
#define DEVICE4_MSG_W_BOOT_UPDATE_TRANSMIT 0x1104
#define DEVICE4_MSG_W_BOOT_UPDATE_FINISH 0x1105
#define DEVICE4_MSG_P_START_HEARTBEAT 0x6c02
#define DEVICE4_MSG_P_BUTTON_PRESSED 0x6C05
#define DEVICE4_MSG_P_END_HEARTBEAT 0x6c12
#define DEVICE4_MSG_P_ASYNC_TEXT_LOG 0x6c09
#define DEVICE4_MSG_E_DSP_ONE_PACKGE_WRITE_FINISH 0x6C0E
#define DEVICE4_MSG_E_DSP_UPDATE_PROGRES 0x6C10
#define DEVICE4_MSG_E_DSP_UPDATE_ENDING 0x6C11
#define DEVICE4_BUTTON_PHYS_DISPLAY_TOGGLE 0x1
#define DEVICE4_BUTTON_PHYS_BRIGHTNESS_UP 0x2
#define DEVICE4_BUTTON_PHYS_BRIGHTNESS_DOWN 0x3
#define DEVICE4_DISPLAY_MODE_1920x1080_60 0x1
#define DEVICE4_DISPLAY_MODE_3840x1080_60_SBS 0x3
#define DEVICE4_DISPLAY_MODE_3840x1080_72_SBS 0x4
#define DEVICE4_DISPLAY_MODE_1920x1080_72 0x5
#define DEVICE4_DISPLAY_MODE_1920x1080_60_SBS 0x8
#define DEVICE4_DISPLAY_MODE_3840x1080_90_SBS 0x9
#define DEVICE4_DISPLAY_MODE_1920x1080_90 0xA
#define DEVICE4_DISPLAY_MODE_1920x1080_120 0xB
#define DEVICE4_BUTTON_VIRT_DISPLAY_TOGGLE 0x1
#define DEVICE4_BUTTON_VIRT_BRIGHTNESS_UP 0x6
#define DEVICE4_BUTTON_VIRT_BRIGHTNESS_DOWN 0x7
#define DEVICE4_BUTTON_VIRT_UP 0x8
#define DEVICE4_BUTTON_VIRT_DOWN 0x9
#ifdef __cplusplus
extern "C" {
#endif
enum device4_error_t {
DEVICE4_ERROR_NO_ERROR = 0,
DEVICE4_ERROR_NO_DEVICE = 1,
DEVICE4_ERROR_NO_HANDLE = 2,
DEVICE4_ERROR_NO_ACTIVATION = 3,
DEVICE4_ERROR_WRONG_SIZE = 4,
DEVICE4_ERROR_UNPLUGGED = 5,
DEVICE4_ERROR_UNEXPECTED = 6,
DEVICE4_ERROR_WRONG_HEAD = 7,
DEVICE4_ERROR_INVALID_LENGTH = 8,
DEVICE4_ERROR_NOT_INITIALIZED = 9,
DEVICE4_ERROR_PAYLOAD_FAILED = 10,
DEVICE4_ERROR_UNKNOWN = 11,
};
struct __attribute__((__packed__)) device4_packet_t {
uint8_t head;
uint32_t checksum;
uint16_t length;
uint64_t timestamp;
uint16_t msgid;
uint8_t reserved [5];
union {
char text [42];
uint8_t data [42];
};
};
enum device4_event_t {
DEVICE4_EVENT_UNKNOWN = 0,
DEVICE4_EVENT_SCREEN_ON = 1,
DEVICE4_EVENT_SCREEN_OFF = 2,
DEVICE4_EVENT_BRIGHTNESS_UP = 3,
DEVICE4_EVENT_BRIGHTNESS_DOWN = 4,
DEVICE4_EVENT_MESSAGE = 5,
};
typedef enum device4_error_t device4_error_type;
typedef struct device4_packet_t device4_packet_type;
typedef enum device4_event_t device4_event_type;
typedef void (*device4_event_callback)(
uint64_t timestamp,
device4_event_type event,
uint8_t brightness,
const char* msg
);
struct device4_t {
uint16_t vendor_id;
uint16_t product_id;
void* handle;
bool activated;
char mcu_app_fw_version [42];
char dp_fw_version [42];
char dsp_fw_version [42];
bool active;
uint8_t brightness;
uint8_t disp_mode;
device4_event_callback callback;
};
typedef struct device4_t device4_type;
device4_error_type device4_open(device4_type* device, device4_event_callback callback);
device4_error_type device4_clear(device4_type* device);
device4_error_type device4_read(device4_type* device, int timeout);
device4_error_type device4_poll_display_mode(device4_type* device);
device4_error_type device4_update_display_mode(device4_type* device);
device4_error_type device4_update_mcu_firmware(device4_type* device, const char* path);
device4_error_type device4_close(device4_type* device);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -0,0 +1,192 @@
#pragma once
//
// Created by thejackimonster on 29.03.23.
//
// Copyright (c) 2023-2024 thejackimonster. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#ifndef __cplusplus
#include <stdbool.h>
#endif
#ifndef __cplusplus
#include <stdint.h>
#else
#include <cstdint>
#endif
#define DEVICE_MCU_MSG_R_BRIGHTNESS 0x03
#define DEVICE_MCU_MSG_W_BRIGHTNESS 0x04
#define DEVICE_MCU_MSG_R_DISP_MODE 0x07
#define DEVICE_MCU_MSG_W_DISP_MODE 0x08
#define DEVICE_MCU_MSG_R_GLASSID 0x15
#define DEVICE_MCU_MSG_R_DP7911_FW_VERSION 0x16
#define DEVICE_MCU_MSG_R_DSP_VERSION 0x18
#define DEVICE_MCU_MSG_W_CANCEL_ACTIVATION 0x19
#define DEVICE_MCU_MSG_P_HEARTBEAT 0x1A
#define DEVICE_MCU_MSG_W_SLEEP_TIME 0x1E
#define DEVICE_MCU_MSG_R_DSP_APP_FW_VERSION 0x21
#define DEVICE_MCU_MSG_R_MCU_APP_FW_VERSION 0x26
#define DEVICE_MCU_MSG_R_ACTIVATION_TIME 0x29
#define DEVICE_MCU_MSG_W_ACTIVATION_TIME 0x2A
#define DEVICE_MCU_MSG_R_DP7911_FW_IS_UPDATE 0x3C
#define DEVICE_MCU_MSG_W_UPDATE_DP 0x3D
#define DEVICE_MCU_MSG_W_UPDATE_MCU_APP_FW_PREPARE 0x3E
#define DEVICE_MCU_MSG_W_UPDATE_MCU_APP_FW_START 0x3F
#define DEVICE_MCU_MSG_W_UPDATE_MCU_APP_FW_TRANSMIT 0x40
#define DEVICE_MCU_MSG_W_UPDATE_MCU_APP_FW_FINISH 0x41
#define DEVICE_MCU_MSG_W_BOOT_JUMP_TO_APP 0x42
#define DEVICE_MCU_MSG_W_MCU_APP_JUMP_TO_BOOT 0x44
#define DEVICE_MCU_MSG_W_UPDATE_DSP_APP_FW_PREPARE 0x45
#define DEVICE_MCU_MSG_W_UPDATE_DSP_APP_FW_START 0x46
#define DEVICE_MCU_MSG_W_UPDATE_DSP_APP_FW_TRANSMIT 0x47
#define DEVICE_MCU_MSG_W_UPDATE_DSP_APP_FW_FINISH 0x48
#define DEVICE_MCU_MSG_R_IS_NEED_UPGRADE_DSP_FW 0x49
#define DEVICE_MCU_MSG_W_FORCE_UPGRADE_DSP_FW 0x69
#define DEVICE_MCU_MSG_W_BOOT_UPDATE_MODE 0x1100
#define DEVICE_MCU_MSG_W_BOOT_UPDATE_CONFIRM 0x1101
#define DEVICE_MCU_MSG_W_BOOT_UPDATE_PREPARE 0x1102
#define DEVICE_MCU_MSG_W_BOOT_UPDATE_START 0x1103
#define DEVICE_MCU_MSG_W_BOOT_UPDATE_TRANSMIT 0x1104
#define DEVICE_MCU_MSG_W_BOOT_UPDATE_FINISH 0x1105
#define DEVICE_MCU_MSG_P_START_HEARTBEAT 0x6c02
#define DEVICE_MCU_MSG_P_BUTTON_PRESSED 0x6C05
#define DEVICE_MCU_MSG_P_END_HEARTBEAT 0x6c12
#define DEVICE_MCU_MSG_P_ASYNC_TEXT_LOG 0x6c09
#define DEVICE_MCU_MSG_E_DSP_ONE_PACKGE_WRITE_FINISH 0x6C0E
#define DEVICE_MCU_MSG_E_DSP_UPDATE_PROGRES 0x6C10
#define DEVICE_MCU_MSG_E_DSP_UPDATE_ENDING 0x6C11
#define DEVICE_MCU_BUTTON_PHYS_DISPLAY_TOGGLE 0x1
#define DEVICE_MCU_BUTTON_PHYS_BRIGHTNESS_UP 0x2
#define DEVICE_MCU_BUTTON_PHYS_BRIGHTNESS_DOWN 0x3
#define DEVICE_MCU_DISPLAY_MODE_1920x1080_60 0x1
#define DEVICE_MCU_DISPLAY_MODE_3840x1080_60_SBS 0x3
#define DEVICE_MCU_DISPLAY_MODE_3840x1080_72_SBS 0x4
#define DEVICE_MCU_DISPLAY_MODE_1920x1080_72 0x5
#define DEVICE_MCU_DISPLAY_MODE_1920x1080_60_SBS 0x8
#define DEVICE_MCU_DISPLAY_MODE_3840x1080_90_SBS 0x9
#define DEVICE_MCU_DISPLAY_MODE_1920x1080_90 0xA
#define DEVICE_MCU_DISPLAY_MODE_1920x1080_120 0xB
#define DEVICE_MCU_BUTTON_VIRT_DISPLAY_TOGGLE 0x1
#define DEVICE_MCU_BUTTON_VIRT_BRIGHTNESS_UP 0x6
#define DEVICE_MCU_BUTTON_VIRT_BRIGHTNESS_DOWN 0x7
#define DEVICE_MCU_BUTTON_VIRT_UP 0x8
#define DEVICE_MCU_BUTTON_VIRT_DOWN 0x9
#ifdef __cplusplus
extern "C" {
#endif
enum device_mcu_error_t {
DEVICE_MCU_ERROR_NO_ERROR = 0,
DEVICE_MCU_ERROR_NO_DEVICE = 1,
DEVICE_MCU_ERROR_NO_HANDLE = 2,
DEVICE_MCU_ERROR_NO_ACTIVATION = 3,
DEVICE_MCU_ERROR_WRONG_SIZE = 4,
DEVICE_MCU_ERROR_UNPLUGGED = 5,
DEVICE_MCU_ERROR_UNEXPECTED = 6,
DEVICE_MCU_ERROR_WRONG_HEAD = 7,
DEVICE_MCU_ERROR_INVALID_LENGTH = 8,
DEVICE_MCU_ERROR_NOT_INITIALIZED = 9,
DEVICE_MCU_ERROR_PAYLOAD_FAILED = 10,
DEVICE_MCU_ERROR_UNKNOWN = 11,
};
struct __attribute__((__packed__)) device_mcu_packet_t {
uint8_t head;
uint32_t checksum;
uint16_t length;
uint64_t timestamp;
uint16_t msgid;
uint8_t reserved [5];
union {
char text [42];
uint8_t data [42];
};
};
enum device_mcu_event_t {
DEVICE_MCU_EVENT_UNKNOWN = 0,
DEVICE_MCU_EVENT_SCREEN_ON = 1,
DEVICE_MCU_EVENT_SCREEN_OFF = 2,
DEVICE_MCU_EVENT_BRIGHTNESS_UP = 3,
DEVICE_MCU_EVENT_BRIGHTNESS_DOWN = 4,
DEVICE_MCU_EVENT_MESSAGE = 5,
};
typedef enum device_mcu_error_t device_mcu_error_type;
typedef struct device_mcu_packet_t device_mcu_packet_type;
typedef enum device_mcu_event_t device_mcu_event_type;
typedef void (*device_mcu_event_callback)(
uint64_t timestamp,
device_mcu_event_type event,
uint8_t brightness,
const char* msg
);
struct device_mcu_t {
uint16_t vendor_id;
uint16_t product_id;
void* handle;
bool activated;
char mcu_app_fw_version [42];
char dp_fw_version [42];
char dsp_fw_version [42];
bool active;
uint8_t brightness;
uint8_t disp_mode;
device_mcu_event_callback callback;
};
typedef struct device_mcu_t device_mcu_type;
device_mcu_error_type device_mcu_open(device_mcu_type* device, device_mcu_event_callback callback);
device_mcu_error_type device_mcu_clear(device_mcu_type* device);
device_mcu_error_type device_mcu_read(device_mcu_type* device, int timeout);
device_mcu_error_type device_mcu_poll_display_mode(device_mcu_type* device);
device_mcu_error_type device_mcu_update_display_mode(device_mcu_type* device);
device_mcu_error_type device_mcu_update_firmware(device_mcu_type* device, const char* path);
device_mcu_error_type device_mcu_close(device_mcu_type* device);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -12,4 +12,5 @@
extern const uint16_t xreal_vendor_id;
extern const uint16_t xreal_product_ids[NUM_SUPPORTED_PRODUCTS];
bool is_xreal_product_id(uint16_t product_id);

View file

@ -1,645 +0,0 @@
//
// Created by thejackimonster on 29.03.23.
//
// Copyright (c) 2023-2024 thejackimonster. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include "device4.h"
#include "device.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <hidapi/hidapi.h>
#include "crc32.h"
#include "hid_ids.h"
#ifndef NDEBUG
#define device4_error(msg) fprintf(stderr, "ERROR: %s\n", msg)
#else
#define device4_error(msg) (0)
#endif
#define MAX_PACKET_SIZE 64
#define PACKET_HEAD 0xFD
static bool send_payload(device4_type* device, uint8_t size, const uint8_t* payload) {
int payload_size = size;
if (payload_size > MAX_PACKET_SIZE) {
payload_size = MAX_PACKET_SIZE;
}
int transferred = hid_write(device->handle, payload, payload_size);
if (transferred != payload_size) {
device4_error("Sending payload failed");
return false;
}
return (transferred == size);
}
static bool recv_payload(device4_type* device, uint8_t size, uint8_t* payload) {
int payload_size = size;
if (payload_size > MAX_PACKET_SIZE) {
payload_size = MAX_PACKET_SIZE;
}
int transferred = hid_read(device->handle, payload, payload_size);
if (transferred >= payload_size) {
transferred = payload_size;
}
if (transferred == 0) {
return false;
}
if (transferred != payload_size) {
device4_error("Receiving payload failed");
return false;
}
return (transferred == size);
}
static bool send_payload_action(device4_type* device, uint16_t msgid, uint8_t len, const uint8_t* data) {
static device4_packet_type packet;
const uint16_t packet_len = 17 + len;
const uint16_t payload_len = 5 + packet_len;
packet.head = PACKET_HEAD;
packet.length = htole16(packet_len);
packet.timestamp = htole64(0);
packet.msgid = htole16(msgid);
memset(packet.reserved, 0, 5);
memcpy(packet.data, data, len);
packet.checksum = htole32(
crc32_checksum(
(const uint8_t*) (&packet.length),
packet.length
)
);
return send_payload(device, payload_len, (uint8_t*) (&packet));
}
static bool recv_payload_msg(device4_type* device, uint16_t msgid, uint8_t len, uint8_t* data) {
static device4_packet_type packet;
packet.head = 0;
packet.length = 0;
packet.msgid = 0;
const uint16_t packet_len = 18 + len;
const uint16_t payload_len = 5 + packet_len;
if (!recv_payload(device, payload_len, (uint8_t*) (&packet))) {
return false;
}
if (packet.head != PACKET_HEAD) {
device4_error("Invalid payload received");
return false;
}
if (le16toh(packet.msgid) != msgid) {
device4_error("Unexpected payload received");
return false;
}
const uint8_t status = packet.data[0];
if (status != 0) {
device4_error("Payload status failed");
return false;
}
const uint16_t data_len = le16toh(packet.length) - 18;
if (len <= data_len) {
memcpy(data, packet.data + 1, len);
} else {
memcpy(data, packet.data + 1, data_len);
memset(data + data_len, 0, len - data_len);
}
return true;
}
static bool do_payload_action(device4_type* device, uint16_t msgid, uint8_t len, const uint8_t* data) {
if (!send_payload_action(device, msgid, len, data)) {
return false;
}
const uint16_t attempts_per_second = (device->active? 60 : 1);
uint16_t attempts = attempts_per_second * 5;
while (attempts > 0) {
if (recv_payload_msg(device, msgid, 0, NULL)) {
return true;
}
attempts--;
}
return false;
}
device4_error_type device4_open(device4_type* device, device4_event_callback callback) {
if (!device) {
device4_error("No device");
return DEVICE4_ERROR_NO_DEVICE;
}
memset(device, 0, sizeof(device4_type));
device->vendor_id = xreal_vendor_id;
device->product_id = 0;
device->callback = callback;
if (!device_init()) {
device4_error("Not initialized");
return DEVICE4_ERROR_NOT_INITIALIZED;
}
struct hid_device_info* info = hid_enumerate(
device->vendor_id,
device->product_id
);
struct hid_device_info* it = info;
while (it) {
if (is_xreal_product_id(it->product_id) && it->interface_number == 4) {
#ifndef NDEBUG
printf("Found device with product_id: 0x%x\n", it->product_id);
#endif
device->product_id = it->product_id;
device->handle = hid_open_path(it->path);
break;
}
it = it->next;
}
hid_free_enumeration(info);
if (!device->handle) {
device4_error("No handle");
return DEVICE4_ERROR_NO_HANDLE;
}
device4_clear(device);
if (!send_payload_action(device, DEVICE4_MSG_R_ACTIVATION_TIME, 0, NULL)) {
device4_error("Requesting activation time failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
uint8_t activated;
if (!recv_payload_msg(device, DEVICE4_MSG_R_ACTIVATION_TIME, 1, &activated)) {
device4_error("Receiving activation time failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
device->activated = (activated != 0);
if (!device->activated) {
device4_error("Device is not activated");
return DEVICE4_ERROR_NO_ACTIVATION;
}
if (!send_payload_action(device, DEVICE4_MSG_R_MCU_APP_FW_VERSION, 0, NULL)) {
device4_error("Requesting current MCU app firmware version");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE4_MSG_R_MCU_APP_FW_VERSION, 41, (uint8_t*) device->mcu_app_fw_version)) {
device4_error("Receiving current MCU app firmware version failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
if (!send_payload_action(device, DEVICE4_MSG_R_DP7911_FW_VERSION, 0, NULL)) {
device4_error("Requesting current DP firmware version");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE4_MSG_R_DP7911_FW_VERSION, 41, (uint8_t*) device->dp_fw_version)) {
device4_error("Receiving current DP firmware version failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
if (!send_payload_action(device, DEVICE4_MSG_R_DSP_APP_FW_VERSION, 0, NULL)) {
device4_error("Requesting current DSP app firmware version");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE4_MSG_R_DSP_APP_FW_VERSION, 41, (uint8_t*) device->dsp_fw_version)) {
device4_error("Receiving current DSP app firmware version failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
#ifndef NDEBUG
printf("MCU: %s\n", device->mcu_app_fw_version);
printf("DP: %s\n", device->dp_fw_version);
printf("DSP: %s\n", device->dsp_fw_version);
#endif
if (!send_payload_action(device, DEVICE4_MSG_R_BRIGHTNESS, 0, NULL)) {
device4_error("Requesting initial brightness failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE4_MSG_R_BRIGHTNESS, 1, &device->brightness)) {
device4_error("Receiving initial brightness failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
if (!send_payload_action(device, DEVICE4_MSG_R_DISP_MODE, 0, NULL)) {
device4_error("Requesting display mode failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE4_MSG_R_DISP_MODE, 1, &device->disp_mode)) {
device4_error("Receiving display mode failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
#ifndef NDEBUG
printf("Brightness: %d\n", device->brightness);
printf("Disp-Mode: %d\n", device->disp_mode);
#endif
return DEVICE4_ERROR_NO_ERROR;
}
static void device4_callback(device4_type* device,
uint64_t timestamp,
device4_event_type event,
uint8_t brightness,
const char* msg) {
if (!device->callback) {
return;
}
device->callback(timestamp, event, brightness, msg);
}
device4_error_type device4_clear(device4_type* device) {
return device4_read(device, 10);
}
device4_error_type device4_read(device4_type* device, int timeout) {
if (!device) {
device4_error("No device");
return DEVICE4_ERROR_NO_DEVICE;
}
if (!device->handle) {
device4_error("No handle");
return DEVICE4_ERROR_NO_HANDLE;
}
if (MAX_PACKET_SIZE != sizeof(device4_packet_type)) {
device4_error("Not proper size");
return DEVICE4_ERROR_WRONG_SIZE;
}
device4_packet_type packet;
memset(&packet, 0, sizeof(device4_packet_type));
int transferred = hid_read_timeout(
device->handle,
(uint8_t*) &packet,
MAX_PACKET_SIZE,
timeout
);
if (transferred == -1) {
device4_error("Device may be unplugged");
return DEVICE4_ERROR_UNPLUGGED;
}
if (transferred == 0) {
return DEVICE4_ERROR_NO_ERROR;
}
if (MAX_PACKET_SIZE != transferred) {
device4_error("Unexpected packet size");
return DEVICE4_ERROR_UNEXPECTED;
}
if (packet.head != PACKET_HEAD) {
device4_error("Wrong packet head");
return DEVICE4_ERROR_WRONG_HEAD;
}
const uint32_t timestamp = le32toh(packet.timestamp);
const uint16_t msgid = le16toh(packet.msgid);
const uint16_t length = le16toh(packet.length);
const size_t data_len = (size_t) &(packet.data) - (size_t) &(packet.length);
#ifndef NDEBUG
printf("MSG: %d = %04x (%d)\n", msgid, msgid, length);
if (length > 11) {
for (int i = 0; i < length - 11; i++) {
printf("%02x ", packet.data[i]);
}
printf("\n");
}
#endif
switch (msgid) {
case DEVICE4_MSG_P_START_HEARTBEAT: {
break;
}
case DEVICE4_MSG_P_BUTTON_PRESSED: {
const uint8_t phys_button = packet.data[0];
const uint8_t virt_button = packet.data[4];
const uint8_t value = packet.data[8];
switch (virt_button) {
case DEVICE4_BUTTON_VIRT_DISPLAY_TOGGLE:
device->active = value;
if (device->active) {
device4_callback(
device,
timestamp,
DEVICE4_EVENT_SCREEN_ON,
device->brightness,
NULL
);
} else {
device4_callback(
device,
timestamp,
DEVICE4_EVENT_SCREEN_OFF,
device->brightness,
NULL
);
}
break;
case DEVICE4_BUTTON_VIRT_BRIGHTNESS_UP:
device->brightness = value;
device4_callback(
device,
timestamp,
DEVICE4_EVENT_BRIGHTNESS_UP,
device->brightness,
NULL
);
break;
case DEVICE4_BUTTON_VIRT_BRIGHTNESS_DOWN:
device->brightness = value;
device4_callback(
device,
timestamp,
DEVICE4_EVENT_BRIGHTNESS_DOWN,
device->brightness,
NULL
);
break;
default:
break;
}
break;
}
case DEVICE4_MSG_P_ASYNC_TEXT_LOG: {
const char* text = packet.text;
const size_t text_len = strlen(text);
device->active = true;
if (data_len + text_len != length) {
device4_error("Not matching length");
return DEVICE4_ERROR_INVALID_LENGTH;
}
device4_callback(
device,
timestamp,
DEVICE4_EVENT_MESSAGE,
device->brightness,
text
);
break;
}
case DEVICE4_MSG_P_END_HEARTBEAT: {
break;
}
default:
device4_callback(
device,
timestamp,
DEVICE4_EVENT_UNKNOWN,
device->brightness,
NULL
);
break;
}
return DEVICE4_ERROR_NO_ERROR;
}
device4_error_type device4_poll_display_mode(device4_type* device) {
if (!device) {
device4_error("No device");
return DEVICE4_ERROR_NO_DEVICE;
}
if (!device->handle) {
device4_error("No handle");
return DEVICE4_ERROR_NO_HANDLE;
}
if (!send_payload_action(device, DEVICE4_MSG_R_DISP_MODE, 0, NULL)) {
device4_error("Requesting display mode failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE4_MSG_R_DISP_MODE, 1, &device->disp_mode)) {
device4_error("Receiving display mode failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
return DEVICE4_ERROR_NO_ERROR;
}
device4_error_type device4_update_display_mode(device4_type* device) {
if (!device) {
device4_error("No device");
return DEVICE4_ERROR_NO_DEVICE;
}
if (!device->handle) {
device4_error("No handle");
return DEVICE4_ERROR_NO_HANDLE;
}
if (!do_payload_action(device, DEVICE4_MSG_W_DISP_MODE, 1, &device->disp_mode)) {
device4_error("Sending display mode failed");
return DEVICE4_ERROR_PAYLOAD_FAILED;
}
return DEVICE4_ERROR_NO_ERROR;
}
device4_error_type device4_update_mcu_firmware(device4_type* device, const char* path) {
if (!device) {
device4_error("No device");
return DEVICE4_ERROR_NO_DEVICE;
}
if (!device->handle) {
device4_error("No handle");
return DEVICE4_ERROR_NO_HANDLE;
}
if (!device->activated) {
device4_error("Device is not activated");
return DEVICE4_ERROR_NO_ACTIVATION;
}
size_t firmware_len = 0;
uint8_t* firmware = NULL;
FILE* file = fopen(path, "rb");
bool result = DEVICE4_ERROR_UNKNOWN;
if (file) {
fseek(file, 0, SEEK_END);
firmware_len = ftell(file);
if (firmware_len > 0) {
firmware = (uint8_t*) malloc(firmware_len);
fread(firmware, sizeof(uint8_t), firmware_len, file);
}
fclose(file);
}
device4_clear(device);
printf("Prepare upload: %lu\n", firmware_len);
if (!do_payload_action(device, DEVICE4_MSG_W_UPDATE_MCU_APP_FW_PREPARE, 0, NULL)) {
device4_error("Failed preparing the device for MCU firmware update!\n");
goto cleanup;
}
if (!do_payload_action(device, DEVICE4_MSG_W_MCU_APP_JUMP_TO_BOOT, 0, NULL)) {
device4_error("Failed mcu app jumping to boot");
goto cleanup;
}
if (!send_payload_action(device, DEVICE4_MSG_R_ACTIVATION_TIME, 0, NULL)) {
device4_error("Requesting activation time failed");
goto cleanup;
}
uint8_t activated;
if (!recv_payload_msg(device, DEVICE4_MSG_R_ACTIVATION_TIME, 1, &activated)) {
device4_error("Receiving activation time failed");
goto cleanup;
}
if (!activated) {
device4_error("Device is not activated");
goto jump_to_app;
}
size_t offset = 0;
while (offset < firmware_len) {
const size_t remaining = firmware_len - offset;
printf("Upload: %lu / %lu\n", offset, firmware_len);
uint8_t len;
uint16_t msgid;
if (offset == 0) {
len = remaining > 24? 24 : remaining;
msgid = DEVICE4_MSG_W_UPDATE_MCU_APP_FW_START;
} else {
len = remaining > 42? 42 : remaining;
msgid = DEVICE4_MSG_W_UPDATE_MCU_APP_FW_TRANSMIT;
}
if (!do_payload_action(device, msgid, len, firmware + offset)) {
device4_error("Failed sending firmware upload");
goto jump_to_app;
}
offset += len;
}
printf("Finish upload");
if (!do_payload_action(device, DEVICE4_MSG_W_UPDATE_MCU_APP_FW_FINISH, 0, NULL)) {
device4_error("Failed finishing firmware upload");
goto jump_to_app;
}
result = DEVICE4_ERROR_NO_ERROR;
jump_to_app:
if (!do_payload_action(device, DEVICE4_MSG_W_BOOT_JUMP_TO_APP, 0, NULL)) {
device4_error("Failed boot jumping back to app");
goto cleanup;
}
cleanup:
if (firmware) {
free(firmware);
}
return result;
}
device4_error_type device4_close(device4_type* device) {
if (!device) {
device4_error("No device");
return DEVICE4_ERROR_NO_DEVICE;
}
if (device->handle) {
hid_close(device->handle);
}
memset(device, 0, sizeof(device4_type));
device_exit();
return DEVICE4_ERROR_NO_ERROR;
}

View file

@ -0,0 +1,645 @@
//
// Created by thejackimonster on 29.03.23.
//
// Copyright (c) 2023-2024 thejackimonster. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include "device_mcu.h"
#include "device.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <hidapi/hidapi.h>
#include "crc32.h"
#include "hid_ids.h"
#ifndef NDEBUG
#define device_mcu_error(msg) fprintf(stderr, "ERROR: %s\n", msg)
#else
#define device_mcu_error(msg) (0)
#endif
#define MAX_PACKET_SIZE 64
#define PACKET_HEAD 0xFD
static bool send_payload(device_mcu_type* device, uint8_t size, const uint8_t* payload) {
int payload_size = size;
if (payload_size > MAX_PACKET_SIZE) {
payload_size = MAX_PACKET_SIZE;
}
int transferred = hid_write(device->handle, payload, payload_size);
if (transferred != payload_size) {
device_mcu_error("Sending payload failed");
return false;
}
return (transferred == size);
}
static bool recv_payload(device_mcu_type* device, uint8_t size, uint8_t* payload) {
int payload_size = size;
if (payload_size > MAX_PACKET_SIZE) {
payload_size = MAX_PACKET_SIZE;
}
int transferred = hid_read(device->handle, payload, payload_size);
if (transferred >= payload_size) {
transferred = payload_size;
}
if (transferred == 0) {
return false;
}
if (transferred != payload_size) {
device_mcu_error("Receiving payload failed");
return false;
}
return (transferred == size);
}
static bool send_payload_action(device_mcu_type* device, uint16_t msgid, uint8_t len, const uint8_t* data) {
static device_mcu_packet_type packet;
const uint16_t packet_len = 17 + len;
const uint16_t payload_len = 5 + packet_len;
packet.head = PACKET_HEAD;
packet.length = htole16(packet_len);
packet.timestamp = htole64(0);
packet.msgid = htole16(msgid);
memset(packet.reserved, 0, 5);
memcpy(packet.data, data, len);
packet.checksum = htole32(
crc32_checksum(
(const uint8_t*) (&packet.length),
packet.length
)
);
return send_payload(device, payload_len, (uint8_t*) (&packet));
}
static bool recv_payload_msg(device_mcu_type* device, uint16_t msgid, uint8_t len, uint8_t* data) {
static device_mcu_packet_type packet;
packet.head = 0;
packet.length = 0;
packet.msgid = 0;
const uint16_t packet_len = 18 + len;
const uint16_t payload_len = 5 + packet_len;
if (!recv_payload(device, payload_len, (uint8_t*) (&packet))) {
return false;
}
if (packet.head != PACKET_HEAD) {
device_mcu_error("Invalid payload received");
return false;
}
if (le16toh(packet.msgid) != msgid) {
device_mcu_error("Unexpected payload received");
return false;
}
const uint8_t status = packet.data[0];
if (status != 0) {
device_mcu_error("Payload status failed");
return false;
}
const uint16_t data_len = le16toh(packet.length) - 18;
if (len <= data_len) {
memcpy(data, packet.data + 1, len);
} else {
memcpy(data, packet.data + 1, data_len);
memset(data + data_len, 0, len - data_len);
}
return true;
}
static bool do_payload_action(device_mcu_type* device, uint16_t msgid, uint8_t len, const uint8_t* data) {
if (!send_payload_action(device, msgid, len, data)) {
return false;
}
const uint16_t attempts_per_second = (device->active? 60 : 1);
uint16_t attempts = attempts_per_second * 5;
while (attempts > 0) {
if (recv_payload_msg(device, msgid, 0, NULL)) {
return true;
}
attempts--;
}
return false;
}
device_mcu_error_type device_mcu_open(device_mcu_type* device, device_mcu_event_callback callback) {
if (!device) {
device_mcu_error("No device");
return DEVICE_MCU_ERROR_NO_DEVICE;
}
memset(device, 0, sizeof(device_mcu_type));
device->vendor_id = xreal_vendor_id;
device->product_id = 0;
device->callback = callback;
if (!device_init()) {
device_mcu_error("Not initialized");
return DEVICE_MCU_ERROR_NOT_INITIALIZED;
}
struct hid_device_info* info = hid_enumerate(
device->vendor_id,
device->product_id
);
struct hid_device_info* it = info;
while (it) {
if (is_xreal_product_id(it->product_id) && it->interface_number == 4) {
#ifndef NDEBUG
printf("Found device with product_id: 0x%x\n", it->product_id);
#endif
device->product_id = it->product_id;
device->handle = hid_open_path(it->path);
break;
}
it = it->next;
}
hid_free_enumeration(info);
if (!device->handle) {
device_mcu_error("No handle");
return DEVICE_MCU_ERROR_NO_HANDLE;
}
device_mcu_clear(device);
if (!send_payload_action(device, DEVICE_MCU_MSG_R_ACTIVATION_TIME, 0, NULL)) {
device_mcu_error("Requesting activation time failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
uint8_t activated;
if (!recv_payload_msg(device, DEVICE_MCU_MSG_R_ACTIVATION_TIME, 1, &activated)) {
device_mcu_error("Receiving activation time failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
device->activated = (activated != 0);
if (!device->activated) {
device_mcu_error("Device is not activated");
return DEVICE_MCU_ERROR_NO_ACTIVATION;
}
if (!send_payload_action(device, DEVICE_MCU_MSG_R_MCU_APP_FW_VERSION, 0, NULL)) {
device_mcu_error("Requesting current MCU app firmware version");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE_MCU_MSG_R_MCU_APP_FW_VERSION, 41, (uint8_t*) device->mcu_app_fw_version)) {
device_mcu_error("Receiving current MCU app firmware version failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
if (!send_payload_action(device, DEVICE_MCU_MSG_R_DP7911_FW_VERSION, 0, NULL)) {
device_mcu_error("Requesting current DP firmware version");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE_MCU_MSG_R_DP7911_FW_VERSION, 41, (uint8_t*) device->dp_fw_version)) {
device_mcu_error("Receiving current DP firmware version failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
if (!send_payload_action(device, DEVICE_MCU_MSG_R_DSP_APP_FW_VERSION, 0, NULL)) {
device_mcu_error("Requesting current DSP app firmware version");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE_MCU_MSG_R_DSP_APP_FW_VERSION, 41, (uint8_t*) device->dsp_fw_version)) {
device_mcu_error("Receiving current DSP app firmware version failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
#ifndef NDEBUG
printf("MCU: %s\n", device->mcu_app_fw_version);
printf("DP: %s\n", device->dp_fw_version);
printf("DSP: %s\n", device->dsp_fw_version);
#endif
if (!send_payload_action(device, DEVICE_MCU_MSG_R_BRIGHTNESS, 0, NULL)) {
device_mcu_error("Requesting initial brightness failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE_MCU_MSG_R_BRIGHTNESS, 1, &device->brightness)) {
device_mcu_error("Receiving initial brightness failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
if (!send_payload_action(device, DEVICE_MCU_MSG_R_DISP_MODE, 0, NULL)) {
device_mcu_error("Requesting display mode failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE_MCU_MSG_R_DISP_MODE, 1, &device->disp_mode)) {
device_mcu_error("Receiving display mode failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
#ifndef NDEBUG
printf("Brightness: %d\n", device->brightness);
printf("Disp-Mode: %d\n", device->disp_mode);
#endif
return DEVICE_MCU_ERROR_NO_ERROR;
}
static void device_mcu_callback(device_mcu_type* device,
uint64_t timestamp,
device_mcu_event_type event,
uint8_t brightness,
const char* msg) {
if (!device->callback) {
return;
}
device->callback(timestamp, event, brightness, msg);
}
device_mcu_error_type device_mcu_clear(device_mcu_type* device) {
return device_mcu_read(device, 10);
}
device_mcu_error_type device_mcu_read(device_mcu_type* device, int timeout) {
if (!device) {
device_mcu_error("No device");
return DEVICE_MCU_ERROR_NO_DEVICE;
}
if (!device->handle) {
device_mcu_error("No handle");
return DEVICE_MCU_ERROR_NO_HANDLE;
}
if (MAX_PACKET_SIZE != sizeof(device_mcu_packet_type)) {
device_mcu_error("Not proper size");
return DEVICE_MCU_ERROR_WRONG_SIZE;
}
device_mcu_packet_type packet;
memset(&packet, 0, sizeof(device_mcu_packet_type));
int transferred = hid_read_timeout(
device->handle,
(uint8_t*) &packet,
MAX_PACKET_SIZE,
timeout
);
if (transferred == -1) {
device_mcu_error("Device may be unplugged");
return DEVICE_MCU_ERROR_UNPLUGGED;
}
if (transferred == 0) {
return DEVICE_MCU_ERROR_NO_ERROR;
}
if (MAX_PACKET_SIZE != transferred) {
device_mcu_error("Unexpected packet size");
return DEVICE_MCU_ERROR_UNEXPECTED;
}
if (packet.head != PACKET_HEAD) {
device_mcu_error("Wrong packet head");
return DEVICE_MCU_ERROR_WRONG_HEAD;
}
const uint32_t timestamp = le32toh(packet.timestamp);
const uint16_t msgid = le16toh(packet.msgid);
const uint16_t length = le16toh(packet.length);
const size_t data_len = (size_t) &(packet.data) - (size_t) &(packet.length);
#ifndef NDEBUG
printf("MSG: %d = %04x (%d)\n", msgid, msgid, length);
if (length > 11) {
for (int i = 0; i < length - 11; i++) {
printf("%02x ", packet.data[i]);
}
printf("\n");
}
#endif
switch (msgid) {
case DEVICE_MCU_MSG_P_START_HEARTBEAT: {
break;
}
case DEVICE_MCU_MSG_P_BUTTON_PRESSED: {
const uint8_t phys_button = packet.data[0];
const uint8_t virt_button = packet.data[4];
const uint8_t value = packet.data[8];
switch (virt_button) {
case DEVICE_MCU_BUTTON_VIRT_DISPLAY_TOGGLE:
device->active = value;
if (device->active) {
device_mcu_callback(
device,
timestamp,
DEVICE_MCU_EVENT_SCREEN_ON,
device->brightness,
NULL
);
} else {
device_mcu_callback(
device,
timestamp,
DEVICE_MCU_EVENT_SCREEN_OFF,
device->brightness,
NULL
);
}
break;
case DEVICE_MCU_BUTTON_VIRT_BRIGHTNESS_UP:
device->brightness = value;
device_mcu_callback(
device,
timestamp,
DEVICE_MCU_EVENT_BRIGHTNESS_UP,
device->brightness,
NULL
);
break;
case DEVICE_MCU_BUTTON_VIRT_BRIGHTNESS_DOWN:
device->brightness = value;
device_mcu_callback(
device,
timestamp,
DEVICE_MCU_EVENT_BRIGHTNESS_DOWN,
device->brightness,
NULL
);
break;
default:
break;
}
break;
}
case DEVICE_MCU_MSG_P_ASYNC_TEXT_LOG: {
const char* text = packet.text;
const size_t text_len = strlen(text);
device->active = true;
if (data_len + text_len != length) {
device_mcu_error("Not matching length");
return DEVICE_MCU_ERROR_INVALID_LENGTH;
}
device_mcu_callback(
device,
timestamp,
DEVICE_MCU_EVENT_MESSAGE,
device->brightness,
text
);
break;
}
case DEVICE_MCU_MSG_P_END_HEARTBEAT: {
break;
}
default:
device_mcu_callback(
device,
timestamp,
DEVICE_MCU_EVENT_UNKNOWN,
device->brightness,
NULL
);
break;
}
return DEVICE_MCU_ERROR_NO_ERROR;
}
device_mcu_error_type device_mcu_poll_display_mode(device_mcu_type* device) {
if (!device) {
device_mcu_error("No device");
return DEVICE_MCU_ERROR_NO_DEVICE;
}
if (!device->handle) {
device_mcu_error("No handle");
return DEVICE_MCU_ERROR_NO_HANDLE;
}
if (!send_payload_action(device, DEVICE_MCU_MSG_R_DISP_MODE, 0, NULL)) {
device_mcu_error("Requesting display mode failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
if (!recv_payload_msg(device, DEVICE_MCU_MSG_R_DISP_MODE, 1, &device->disp_mode)) {
device_mcu_error("Receiving display mode failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
return DEVICE_MCU_ERROR_NO_ERROR;
}
device_mcu_error_type device_mcu_update_display_mode(device_mcu_type* device) {
if (!device) {
device_mcu_error("No device");
return DEVICE_MCU_ERROR_NO_DEVICE;
}
if (!device->handle) {
device_mcu_error("No handle");
return DEVICE_MCU_ERROR_NO_HANDLE;
}
if (!do_payload_action(device, DEVICE_MCU_MSG_W_DISP_MODE, 1, &device->disp_mode)) {
device_mcu_error("Sending display mode failed");
return DEVICE_MCU_ERROR_PAYLOAD_FAILED;
}
return DEVICE_MCU_ERROR_NO_ERROR;
}
device_mcu_error_type device_mcu_update_firmware(device_mcu_type* device, const char* path) {
if (!device) {
device_mcu_error("No device");
return DEVICE_MCU_ERROR_NO_DEVICE;
}
if (!device->handle) {
device_mcu_error("No handle");
return DEVICE_MCU_ERROR_NO_HANDLE;
}
if (!device->activated) {
device_mcu_error("Device is not activated");
return DEVICE_MCU_ERROR_NO_ACTIVATION;
}
size_t firmware_len = 0;
uint8_t* firmware = NULL;
FILE* file = fopen(path, "rb");
bool result = DEVICE_MCU_ERROR_UNKNOWN;
if (file) {
fseek(file, 0, SEEK_END);
firmware_len = ftell(file);
if (firmware_len > 0) {
firmware = (uint8_t*) malloc(firmware_len);
fread(firmware, sizeof(uint8_t), firmware_len, file);
}
fclose(file);
}
device_mcu_clear(device);
printf("Prepare upload: %lu\n", firmware_len);
if (!do_payload_action(device, DEVICE_MCU_MSG_W_UPDATE_MCU_APP_FW_PREPARE, 0, NULL)) {
device_mcu_error("Failed preparing the device for MCU firmware update!\n");
goto cleanup;
}
if (!do_payload_action(device, DEVICE_MCU_MSG_W_MCU_APP_JUMP_TO_BOOT, 0, NULL)) {
device_mcu_error("Failed mcu app jumping to boot");
goto cleanup;
}
if (!send_payload_action(device, DEVICE_MCU_MSG_R_ACTIVATION_TIME, 0, NULL)) {
device_mcu_error("Requesting activation time failed");
goto cleanup;
}
uint8_t activated;
if (!recv_payload_msg(device, DEVICE_MCU_MSG_R_ACTIVATION_TIME, 1, &activated)) {
device_mcu_error("Receiving activation time failed");
goto cleanup;
}
if (!activated) {
device_mcu_error("Device is not activated");
goto jump_to_app;
}
size_t offset = 0;
while (offset < firmware_len) {
const size_t remaining = firmware_len - offset;
printf("Upload: %lu / %lu\n", offset, firmware_len);
uint8_t len;
uint16_t msgid;
if (offset == 0) {
len = remaining > 24? 24 : remaining;
msgid = DEVICE_MCU_MSG_W_UPDATE_MCU_APP_FW_START;
} else {
len = remaining > 42? 42 : remaining;
msgid = DEVICE_MCU_MSG_W_UPDATE_MCU_APP_FW_TRANSMIT;
}
if (!do_payload_action(device, msgid, len, firmware + offset)) {
device_mcu_error("Failed sending firmware upload");
goto jump_to_app;
}
offset += len;
}
printf("Finish upload");
if (!do_payload_action(device, DEVICE_MCU_MSG_W_UPDATE_MCU_APP_FW_FINISH, 0, NULL)) {
device_mcu_error("Failed finishing firmware upload");
goto jump_to_app;
}
result = DEVICE_MCU_ERROR_NO_ERROR;
jump_to_app:
if (!do_payload_action(device, DEVICE_MCU_MSG_W_BOOT_JUMP_TO_APP, 0, NULL)) {
device_mcu_error("Failed boot jumping back to app");
goto cleanup;
}
cleanup:
if (firmware) {
free(firmware);
}
return result;
}
device_mcu_error_type device_mcu_close(device_mcu_type* device) {
if (!device) {
device_mcu_error("No device");
return DEVICE_MCU_ERROR_NO_DEVICE;
}
if (device->handle) {
hid_close(device->handle);
}
memset(device, 0, sizeof(device_mcu_type));
device_exit();
return DEVICE_MCU_ERROR_NO_ERROR;
}

View file

@ -23,7 +23,7 @@
//
#include "device_imu.h"
#include "device4.h"
#include "device_mcu.h"
#include <stdio.h>
#include <sys/wait.h>
@ -31,9 +31,9 @@
#include <math.h>
void test3(uint64_t timestamp,
device_imu_event_type event,
const device_imu_ahrs_type* ahrs) {
void test_imu(uint64_t timestamp,
device_imu_event_type event,
const device_imu_ahrs_type* ahrs) {
static device_imu_quat_type old;
static float dmax = -1.0f;
@ -74,18 +74,18 @@ void test3(uint64_t timestamp,
old = q;
}
void test4(uint64_t timestamp,
device4_event_type event,
uint8_t brightness,
const char* msg) {
void test_mcu(uint64_t timestamp,
device_mcu_event_type event,
uint8_t brightness,
const char* msg) {
switch (event) {
case DEVICE4_EVENT_MESSAGE:
case DEVICE_MCU_EVENT_MESSAGE:
printf("Message: `%s`\n", msg);
break;
case DEVICE4_EVENT_BRIGHTNESS_UP:
case DEVICE_MCU_EVENT_BRIGHTNESS_UP:
printf("Increase Brightness: %u\n", brightness);
break;
case DEVICE4_EVENT_BRIGHTNESS_DOWN:
case DEVICE_MCU_EVENT_BRIGHTNESS_DOWN:
printf("Decrease Brightness: %u\n", brightness);
break;
default:
@ -102,28 +102,28 @@ int main(int argc, const char** argv) {
}
if (pid == 0) {
device_imu_type dev3;
if (DEVICE_IMU_ERROR_NO_ERROR != device_imu_open(&dev3, test3)) {
device_imu_type dev_imu;
if (DEVICE_IMU_ERROR_NO_ERROR != device_imu_open(&dev_imu, test_imu)) {
return 1;
}
device_imu_clear(&dev3);
device_imu_calibrate(&dev3, 1000, true, true, false);
while (DEVICE_IMU_ERROR_NO_ERROR == device_imu_read(&dev3, -1));
device_imu_close(&dev3);
device_imu_clear(&dev_imu);
device_imu_calibrate(&dev_imu, 1000, true, true, false);
while (DEVICE_IMU_ERROR_NO_ERROR == device_imu_read(&dev_imu, -1));
device_imu_close(&dev_imu);
return 0;
} else {
int status = 0;
device4_type dev4;
if (DEVICE4_ERROR_NO_ERROR != device4_open(&dev4, test4)) {
device_mcu_type dev_mcu;
if (DEVICE_MCU_ERROR_NO_ERROR != device_mcu_open(&dev_mcu, test_mcu)) {
status = 1;
goto exit;
}
device4_clear(&dev4);
while (DEVICE4_ERROR_NO_ERROR == device4_read(&dev4, -1));
device4_close(&dev4);
device_mcu_clear(&dev_mcu);
while (DEVICE_MCU_ERROR_NO_ERROR == device_mcu_read(&dev_mcu, -1));
device_mcu_close(&dev_mcu);
exit:
if (pid != waitpid(pid, &status, 0)) {