mirror of
https://github.com/Scandal-UK/Incognito_RCM.git
synced 2025-02-15 13:05:42 +00:00
Implement Hekate BDK structure
This commit is contained in:
parent
850e7d93af
commit
5dde50e8c4
314 changed files with 60802 additions and 939 deletions
25
Makefile
25
Makefile
|
@ -19,15 +19,26 @@ TARGET := Incognito_RCM
|
|||
BUILDDIR := build
|
||||
OUTPUTDIR := output
|
||||
SOURCEDIR = source
|
||||
BDKDIR := bdk
|
||||
BDKINC := -I./$(BDKDIR)
|
||||
VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
|
||||
VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
|
||||
|
||||
OBJS = $(patsubst $(SOURCEDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \
|
||||
$(patsubst $(SOURCEDIR)/%.c, $(BUILDDIR)/$(TARGET)/%.o, \
|
||||
$(call rwildcard, $(SOURCEDIR), *.S *.c)))
|
||||
OBJS += $(patsubst $(BDKDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \
|
||||
$(patsubst $(BDKDIR)/%.c, $(BUILDDIR)/$(TARGET)/%.o, \
|
||||
$(call rwildcard, $(BDKDIR), *.S *.c)))
|
||||
|
||||
GFX_INC := '"../$(SOURCEDIR)/gfx/gfx.h"'
|
||||
FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"'
|
||||
|
||||
################################################################################
|
||||
|
||||
CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
|
||||
CUSTOMDEFINES += -DLP_VER_MJ=$(LPVERSION_MAJOR) -DLP_VER_MN=$(LPVERSION_MINOR) -DLP_VER_BF=$(LPVERSION_BUGFX)
|
||||
CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
|
||||
|
||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||
CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fno-inline -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall $(CUSTOMDEFINES)
|
||||
|
@ -47,16 +58,26 @@ $(OUTPUTDIR)/$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
|||
@mkdir -p "$(@D)"
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
@echo -n "Payload size is "
|
||||
@wc -c < $@
|
||||
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
|
||||
@echo $(BIN_SIZE)
|
||||
@echo "Max size is 126296 Bytes."
|
||||
@if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
|
||||
|
||||
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
|
||||
|
||||
$(BUILDDIR)/$(TARGET)/%.o: $(SOURCEDIR)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
|
||||
|
||||
$(BUILDDIR)/$(TARGET)/%.o: $(SOURCEDIR)/%.S
|
||||
@mkdir -p "$(@D)"
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
|
||||
|
||||
$(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.S
|
||||
@mkdir -p "$(@D)"
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
|
233
bdk/exception_handlers.S
Normal file
233
bdk/exception_handlers.S
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Armv7tdmi Status register.
|
||||
*
|
||||
* bit0: Mode 0.
|
||||
* bit1: Mode 1.
|
||||
* bit2: Mode 2.
|
||||
* bit3: Mode 3.
|
||||
* bit4: Mode 4.
|
||||
* bit5: Thumb state.
|
||||
* bit6: FIQ disable.
|
||||
* bit7: IRQ disable.
|
||||
* bit8-27: Reserved.
|
||||
* bit28: Overflow condition.
|
||||
* bit29: Carry/Borrow/Extend condition.
|
||||
* bit30: Zero condition.
|
||||
* bit31: Negative/Less than condition.
|
||||
*
|
||||
* M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers
|
||||
* 10000 | USER | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||
* 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq
|
||||
* 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq
|
||||
* 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc
|
||||
* 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt
|
||||
* 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und
|
||||
* 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||
*/
|
||||
|
||||
#define EXCP_EN_ADDR 0x4003FFFC
|
||||
#define EXCP_TYPE_ADDR 0x4003FFF8
|
||||
#define EXCP_LR_ADDR 0x4003FFF4
|
||||
|
||||
#define EXCP_VEC_BASE 0x6000F000
|
||||
#define EVP_COP_RESET_VECTOR 0x200
|
||||
#define EVP_COP_UNDEF_VECTOR 0x204
|
||||
#define EVP_COP_SWI_VECTOR 0x208
|
||||
#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C
|
||||
#define EVP_COP_DATA_ABORT_VECTOR 0x210
|
||||
#define EVP_COP_RSVD_VECTOR 0x214
|
||||
#define EVP_COP_IRQ_VECTOR 0x218
|
||||
#define EVP_COP_FIQ_VECTOR 0x21C
|
||||
|
||||
#define MODE_USR 0x10
|
||||
#define MODE_FIQ 0x11
|
||||
#define MODE_IRQ 0x12
|
||||
#define MODE_SVC 0x13
|
||||
#define MODE_ABT 0x17
|
||||
#define MODE_UDF 0x1B
|
||||
#define MODE_SYS 0x1F
|
||||
#define MODE_MASK 0x1F
|
||||
|
||||
#define FIQ 0x40
|
||||
#define IRQ 0x80
|
||||
|
||||
.section .text._irq_setup
|
||||
.arm
|
||||
|
||||
.extern ipl_main
|
||||
.type ipl_main, %function
|
||||
|
||||
.extern svc_handler
|
||||
.type svc_handler, %function
|
||||
|
||||
.extern irq_handler
|
||||
.type irq_handler, %function
|
||||
|
||||
.extern fiq_setup
|
||||
.type fiq_setup, %function
|
||||
|
||||
.extern fiq_handler
|
||||
.type fiq_handler, %function
|
||||
|
||||
.globl _irq_setup
|
||||
.type _irq_setup, %function
|
||||
_irq_setup:
|
||||
MRS R0, CPSR
|
||||
BIC R0, R0, #MODE_MASK /* Clear mode bits */
|
||||
ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */
|
||||
MSR CPSR, R0
|
||||
|
||||
/* Setup IRQ stack pointer */
|
||||
MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||||
LDR SP, =0x40040000
|
||||
|
||||
/* Setup SYS stack pointer */
|
||||
MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||||
LDR SP, =0x4003FF00 /* Will be changed later to DRAM */
|
||||
|
||||
MOV LR, PC
|
||||
BL setup_vectors
|
||||
/*BL fiq_setup*/
|
||||
|
||||
/* Enable interrupts */
|
||||
BL irq_enable_cpu_irq_exceptions
|
||||
|
||||
B ipl_main
|
||||
B .
|
||||
|
||||
_reset:
|
||||
LDR R0, =EXCP_EN_ADDR
|
||||
LDR R1, =0x30505645 /* EVP0 */
|
||||
STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */
|
||||
LDR R0, =EXCP_LR_ADDR
|
||||
MOV R1, LR
|
||||
STR R1, [R0] /* Save LR in EXCP_LR_ADDR */
|
||||
LDR R0, =__bss_start
|
||||
EOR R1, R1, R1
|
||||
LDR R2, =__bss_end
|
||||
SUB R2, R2, R0
|
||||
BL memset
|
||||
B _irq_setup
|
||||
|
||||
_reset_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x545352 /* RST */
|
||||
STR R1, [R0] /* RST in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
_undefined_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x464455 /* UDF */
|
||||
STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
_prefetch_abort_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x54424150 /* PABT */
|
||||
STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
_data_abort_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x54424144 /* DABT */
|
||||
STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
.globl irq_enable_cpu_irq_exceptions
|
||||
.type irq_enable_cpu_irq_exceptions, %function
|
||||
irq_enable_cpu_irq_exceptions:
|
||||
MRS R12, CPSR
|
||||
BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */
|
||||
MSR CPSR, R12
|
||||
BX LR
|
||||
|
||||
.globl irq_disable_cpu_irq_exceptions
|
||||
.type irq_disable_cpu_irq_exceptions, %function
|
||||
irq_disable_cpu_irq_exceptions:
|
||||
MRS R12, CPSR
|
||||
ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */
|
||||
MSR CPSR, R12
|
||||
BX LR
|
||||
|
||||
_irq_handler:
|
||||
MOV R13, R0 /* Save R0 in R13_IRQ */
|
||||
SUB R0, LR, #4 /* Put return address in R0_SYS */
|
||||
MOV LR, R1 /* Save R1 in R14_IRQ (LR) */
|
||||
MRS R1, SPSR /* Put the SPSR in R1_SYS */
|
||||
|
||||
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||||
STMFD SP!, {R0, R1} /* SPSR and PC */
|
||||
STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */
|
||||
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||||
SUB SP, SP, #8 /* Make room for stacking R0 and R1 */
|
||||
|
||||
MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */
|
||||
STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */
|
||||
|
||||
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||||
LDR R12, =irq_handler
|
||||
MOV LR, PC /* Copy the return address to link register */
|
||||
BX R12 /* Call the C IRQ handler (ARM/THUMB) */
|
||||
|
||||
MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||||
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||||
ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */
|
||||
|
||||
MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||||
MOV SP, R0 /* Copy SP_SYS to SP_IRQ */
|
||||
LDR R0, [SP, #28] /* Load the saved SPSR from the stack */
|
||||
MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */
|
||||
|
||||
LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */
|
||||
NOP /* Cant access barked registers immediately */
|
||||
LDR LR, [SP, #24] /* Load return address from the SYS stack */
|
||||
MOVS PC, LR /* Return restoring CPSR from SPSR */
|
||||
|
||||
_fiq_handler:
|
||||
BL fiq_handler
|
||||
|
||||
setup_vectors:
|
||||
/* Setup vectors */
|
||||
LDR R0, =EXCP_VEC_BASE
|
||||
|
||||
LDR R1, =_reset_handler
|
||||
STR R1, [R0, #EVP_COP_RESET_VECTOR]
|
||||
|
||||
LDR R1, =_undefined_handler
|
||||
STR R1, [R0, #EVP_COP_UNDEF_VECTOR]
|
||||
|
||||
LDR R1, =_reset_handler
|
||||
STR R1, [R0, #EVP_COP_SWI_VECTOR]
|
||||
|
||||
LDR R1, =_prefetch_abort_handler
|
||||
STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR]
|
||||
|
||||
LDR R1, =_data_abort_handler
|
||||
STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR]
|
||||
|
||||
LDR R1, =_reset_handler
|
||||
STR R1, [R0, #EVP_COP_RSVD_VECTOR]
|
||||
|
||||
LDR R1, =_irq_handler
|
||||
STR R1, [R0, #EVP_COP_IRQ_VECTOR]
|
||||
|
||||
LDR R1, =_fiq_handler
|
||||
STR R1, [R0, #EVP_COP_FIQ_VECTOR]
|
||||
|
||||
BX LR
|
24
bdk/fatfs_cfg.h
Normal file
24
bdk/fatfs_cfg.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _FATFS_CFG_H_
|
||||
#define _FATFS_CFG_H_
|
||||
|
||||
#ifdef FFCFG_INC
|
||||
#include FFCFG_INC
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -18,16 +18,15 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "di.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../power/max77620.h"
|
||||
#include "../power/max7762x.h"
|
||||
#include "../soc/clock.h"
|
||||
#include "../soc/gpio.h"
|
||||
#include "../soc/i2c.h"
|
||||
#include "../soc/pinmux.h"
|
||||
#include "../soc/pmc.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../utils/util.h"
|
||||
#include <power/max77620.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <soc/pmc.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#include "di.inl"
|
||||
|
||||
|
@ -145,13 +144,13 @@ void display_init()
|
|||
// Decode Display ID.
|
||||
_display_id = ((_display_id >> 8) & 0xFF00) | (_display_id & 0xFF);
|
||||
|
||||
if ((_display_id & 0xFF) == PANEL_JDI_LPM062M)
|
||||
_display_id = PANEL_JDI_LPM062M;
|
||||
if ((_display_id & 0xFF) == PANEL_JDI_XXX062M)
|
||||
_display_id = PANEL_JDI_XXX062M;
|
||||
|
||||
// Initialize display panel.
|
||||
switch (_display_id)
|
||||
{
|
||||
case PANEL_JDI_LPM062M:
|
||||
case PANEL_JDI_XXX062M:
|
||||
exec_cfg((u32 *)DSI_BASE, _display_init_config_jdi, 43);
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
|
||||
break;
|
||||
|
@ -264,7 +263,7 @@ void display_end()
|
|||
// De-initialize display panel.
|
||||
switch (_display_id)
|
||||
{
|
||||
case PANEL_JDI_LPM062M:
|
||||
case PANEL_JDI_XXX062M:
|
||||
exec_cfg((u32 *)DSI_BASE, _display_deinit_config_jdi, 22);
|
||||
break;
|
||||
case PANEL_AUO_A062TAN01:
|
||||
|
@ -337,15 +336,111 @@ void display_color_screen(u32 color)
|
|||
display_backlight(true);
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer()
|
||||
u32 *display_init_framebuffer_pitch()
|
||||
{
|
||||
// Sanitize framebuffer area.
|
||||
memset((u32 *)IPL_FB_ADDRESS, 0, 0x3C0000);
|
||||
|
||||
// This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer, 32);
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch, 32);
|
||||
usleep(35000);
|
||||
|
||||
return (u32 *)IPL_FB_ADDRESS;
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer_pitch_inv()
|
||||
{
|
||||
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch_inv, 34);
|
||||
|
||||
usleep(35000);
|
||||
|
||||
return (u32 *)NYX_FB_ADDRESS;
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer_block()
|
||||
{
|
||||
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_block, 34);
|
||||
|
||||
usleep(35000);
|
||||
|
||||
return (u32 *)NYX_FB_ADDRESS;
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer_log()
|
||||
{
|
||||
// This configures the framebuffer @ LOG_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_log, 20);
|
||||
|
||||
return (u32 *)LOG_FB_ADDRESS;
|
||||
}
|
||||
|
||||
void display_activate_console()
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window C.
|
||||
DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = WIN_ENABLE; // Enable window DD.
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0xFF80;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
|
||||
for (u32 i = 0xFF80; i < 0x10000; i++)
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
}
|
||||
|
||||
void display_deactivate_console()
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window C.
|
||||
|
||||
for (u32 i = 0xFFFF; i > 0xFF7F; i--)
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
usleep(500);
|
||||
}
|
||||
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0; // Disable window DD.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
}
|
||||
|
||||
void display_init_cursor(void *crs_fb, u32 size)
|
||||
{
|
||||
// Setup cursor.
|
||||
DISPLAY_A(_DIREG(DC_DISP_CURSOR_START_ADDR)) = CURSOR_CLIPPING(CURSOR_CLIP_WIN_A) | size | ((u32)crs_fb >> 10);
|
||||
DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) =
|
||||
CURSOR_BLEND_R8G8B8A8 | CURSOR_BLEND_DST_FACTOR(CURSOR_BLEND_K1) | CURSOR_BLEND_SRC_FACTOR(CURSOR_BLEND_K1) | 0xFF;
|
||||
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) |= CURSOR_ENABLE;
|
||||
|
||||
// Arm and activate changes.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
|
||||
}
|
||||
|
||||
void display_set_pos_cursor(u32 x, u32 y)
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_DISP_CURSOR_POSITION)) = x | (y << 16);
|
||||
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
|
||||
}
|
||||
|
||||
void display_deinit_cursor()
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) &= ~CURSOR_ENABLE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
|
||||
}
|
|
@ -18,8 +18,8 @@
|
|||
#ifndef _DI_H_
|
||||
#define _DI_H_
|
||||
|
||||
#include "../../common/memory_map.h"
|
||||
#include "../utils/types.h"
|
||||
#include <memory_map.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
/*! Display registers. */
|
||||
#define _DIREG(reg) ((reg) * 4)
|
||||
|
@ -506,7 +506,9 @@
|
|||
|
||||
enum
|
||||
{
|
||||
PANEL_JDI_LPM062M = 0x10,
|
||||
PANEL_JDI_XXX062M = 0x10,
|
||||
PANEL_JDI_LAM062M109A = 0x0910,
|
||||
PANEL_JDI_LPM062M326A = 0x2610,
|
||||
PANEL_INL_P062CCA_AZ1 = 0x0F20,
|
||||
PANEL_AUO_A062TAN01 = 0x0F30,
|
||||
PANEL_INL_P062CCA_AZ2 = 0x1020,
|
||||
|
@ -525,7 +527,12 @@ void display_backlight(bool enable);
|
|||
void display_backlight_brightness(u32 brightness, u32 step_delay);
|
||||
|
||||
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
|
||||
u32 *display_init_framebuffer();
|
||||
u32 *display_init_framebuffer_pitch();
|
||||
u32 *display_init_framebuffer_pitch_inv();
|
||||
u32 *display_init_framebuffer_block();
|
||||
u32 *display_init_framebuffer_log();
|
||||
void display_activate_console();
|
||||
void display_deactivate_console();
|
||||
void display_init_cursor(void *crs_fb, u32 size);
|
||||
void display_set_pos_cursor(u32 x, u32 y);
|
||||
void display_deinit_cursor();
|
|
@ -559,8 +559,8 @@ static const cfg_op_t cfg_display_one_color[8] = {
|
|||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} // Continuous display.
|
||||
};
|
||||
|
||||
//Display A config.
|
||||
static const cfg_op_t cfg_display_framebuffer[32] = {
|
||||
//Display A config linear pitch.
|
||||
static const cfg_op_t cfg_display_framebuffer_pitch[32] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
|
||||
|
@ -568,14 +568,14 @@ static const cfg_op_t cfg_display_framebuffer[32] = {
|
|||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_POSITION, 0}, //(0,0)
|
||||
{DC_WIN_H_INITIAL_DDA, 0},
|
||||
{DC_WIN_V_INITIAL_DDA, 0},
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)},
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
|
||||
|
@ -594,3 +594,103 @@ static const cfg_op_t cfg_display_framebuffer[32] = {
|
|||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
|
||||
};
|
||||
|
||||
//Display A config linear pitch inverse + Win D support.
|
||||
static const cfg_op_t cfg_display_framebuffer_pitch_inv[34] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_POSITION, 0}, //(0,0)
|
||||
{DC_WIN_H_INITIAL_DDA, 0},
|
||||
{DC_WIN_V_INITIAL_DDA, 0},
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
|
||||
{DC_WINBUF_SURFACE_KIND, PITCH},
|
||||
{DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
|
||||
{DC_WINBUF_ADDR_H_OFFSET, 0}, // Linear: 0x383FFC, Block: 0x3813FC.
|
||||
{DC_WINBUF_ADDR_V_OFFSET, 1279}, // Linear: 1279, Block: 0.
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, // Enable window AD.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
|
||||
};
|
||||
|
||||
//Display A config block linear.
|
||||
static const cfg_op_t cfg_display_framebuffer_block[34] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_POSITION, 0}, //(0,0)
|
||||
{DC_WIN_H_INITIAL_DDA, 0},
|
||||
{DC_WIN_V_INITIAL_DDA, 0},
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
|
||||
{DC_WINBUF_SURFACE_KIND, BLOCK_HEIGHT(4) | BLOCK},
|
||||
{DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
|
||||
{DC_WINBUF_ADDR_H_OFFSET, 0x3813FC}, // Linear: 0x383FFC, Block: 0x3813FC.
|
||||
{DC_WINBUF_ADDR_V_OFFSET, 0}, // Linear: 1279, Block: 0.
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | SCAN_COLUMN | H_DIRECTION}, // Enable window AD. | SCAN_COLUMN | H_DIRECTION.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
|
||||
};
|
||||
|
||||
//Display D config.
|
||||
static const cfg_op_t cfg_display_framebuffer_log[20] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8},
|
||||
{DC_WIN_POSITION, 0}, //(0,0)
|
||||
{DC_WIN_H_INITIAL_DDA, 0},
|
||||
{DC_WIN_V_INITIAL_DDA, 0},
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(656 * 4)},
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(656)},
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(656 * 2) | LINE_STRIDE(656 * 4)}, //656*2x656*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
|
||||
{DC_WINBUF_SURFACE_KIND, PITCH},
|
||||
{DC_WINBUF_START_ADDR, LOG_FB_ADDRESS}, // Framebuffer address.
|
||||
{DC_WINBUF_ADDR_H_OFFSET, 0},
|
||||
{DC_WINBUF_ADDR_V_OFFSET, 0},
|
||||
{DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_ENABLE | WIN_K1(200)},
|
||||
{DC_WINBUF_BLEND_MATCH_SELECT, WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 | WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1},
|
||||
{DC_WIN_WIN_OPTIONS, 0}, // Enable window DD.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_D_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_D_ACT_REQ}
|
||||
};
|
24
bdk/gfx_utils.h
Normal file
24
bdk/gfx_utils.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GFX_UTILS_H_
|
||||
#define _GFX_UTILS_H_
|
||||
|
||||
#ifdef GFX_INC
|
||||
#include GFX_INC
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -22,10 +22,10 @@
|
|||
#include "elfarch.h"
|
||||
#include "elf.h"
|
||||
|
||||
#include "../../utils/types.h"
|
||||
#include <utils/types.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "../../gfx/gfx.h"
|
||||
#include <gfx_utils.h>
|
||||
#define EL_DEBUG(format, ...) \
|
||||
gfx_printf(format __VA_OPT__(, ) __VA_ARGS__)
|
||||
#else
|
|
@ -18,12 +18,13 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "ianos.h"
|
||||
#include "../../common/common_module.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../libs/elfload/elfload.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../utils/types.h"
|
||||
#include "elfload/elfload.h"
|
||||
#include <module.h>
|
||||
#include <mem/heap.h>
|
||||
#include <storage/nx_sd.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
#include <gfx_utils.h>
|
||||
|
||||
#define IRAM_LIB_ADDR 0x4002B000
|
||||
#define DRAM_LIB_ADDR 0xE0000000
|
||||
|
@ -36,8 +37,8 @@ void *fileBuf = NULL;
|
|||
static void _ianos_call_ep(moduleEntrypoint_t entrypoint, void *moduleConfig)
|
||||
{
|
||||
bdkParams_t bdkParameters = (bdkParams_t)malloc(sizeof(struct _bdkParams_t));
|
||||
bdkParameters->gfxCon = &gfx_con;
|
||||
bdkParameters->gfxCtx = &gfx_ctxt;
|
||||
bdkParameters->gfxCon = (void *)&gfx_con;
|
||||
bdkParameters->gfxCtx = (void *)&gfx_ctxt;
|
||||
bdkParameters->memcpy = (memcpy_t)&memcpy;
|
||||
bdkParameters->memset = (memset_t)&memset;
|
||||
bdkParameters->sharedHeap = &_heap;
|
||||
|
@ -63,26 +64,20 @@ static bool _ianos_read_cb(el_ctx *ctx, void *dest, size_t numberBytes, size_t o
|
|||
}
|
||||
|
||||
//TODO: Support shared libraries.
|
||||
uintptr_t ianos_loader(bool sdmount, char *path, elfType_t type, void *moduleConfig)
|
||||
uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig)
|
||||
{
|
||||
el_ctx ctx;
|
||||
uintptr_t epaddr = 0;
|
||||
|
||||
if (sdmount)
|
||||
{
|
||||
if (!sd_mount())
|
||||
goto elfLoadFinalOut;
|
||||
}
|
||||
if (!sd_mount())
|
||||
goto elfLoadFinalOut;
|
||||
|
||||
// Read library.
|
||||
fileBuf = sd_file_read(path, NULL);
|
||||
|
||||
if (sdmount)
|
||||
sd_unmount();
|
||||
|
||||
if (!fileBuf)
|
||||
goto elfLoadFinalOut;
|
||||
|
||||
|
||||
el_ctx ctx;
|
||||
ctx.pread = _ianos_read_cb;
|
||||
|
||||
if (el_init(&ctx))
|
||||
|
@ -94,7 +89,6 @@ uintptr_t ianos_loader(bool sdmount, char *path, elfType_t type, void *moduleCon
|
|||
case EXEC_ELF:
|
||||
case AR64_ELF:
|
||||
elfBuf = (void *)DRAM_LIB_ADDR;
|
||||
sd_unmount();
|
||||
break;
|
||||
default:
|
||||
elfBuf = malloc(ctx.memsz); // Aligned to 0x10 by default.
|
||||
|
@ -123,6 +117,5 @@ elfFreeOut:
|
|||
fileBuf = NULL;
|
||||
|
||||
elfLoadFinalOut:
|
||||
|
||||
return epaddr;
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef IANOS_H
|
||||
#define IANOS_H
|
||||
|
||||
#include "../utils/types.h"
|
||||
#include <utils/types.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -29,6 +29,6 @@ typedef enum
|
|||
KEEP_IN_RAM = (1 << 31) // Shared library mask.
|
||||
} elfType_t;
|
||||
|
||||
uintptr_t ianos_loader(bool sdmount, char *path, elfType_t type, void* config);
|
||||
uintptr_t ianos_loader(char *path, elfType_t type, void* config);
|
||||
|
||||
#endif
|
118
bdk/input/als.c
Normal file
118
bdk/input/als.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Ambient light sensor driver for Nintendo Switch's Rohm BH1730
|
||||
*
|
||||
* Copyright (c) 2018 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "als.h"
|
||||
#include <power/max77620.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#define HOS_GAIN BH1730_GAIN_64X
|
||||
#define HOS_ITIME 38
|
||||
|
||||
void set_als_cfg(als_table_t *als_val, u8 gain, u8 itime)
|
||||
{
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain);
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - itime));
|
||||
|
||||
als_val->gain = gain;
|
||||
als_val->itime = itime;
|
||||
}
|
||||
|
||||
void get_als_lux(als_table_t *als_val)
|
||||
{
|
||||
u32 data[2];
|
||||
float pre_gain_lux;
|
||||
float visible_light;
|
||||
float ir_light;
|
||||
float light_ratio;
|
||||
|
||||
u8 adc_ready = 0;
|
||||
u8 retries = 100;
|
||||
|
||||
const float als_gain_idx_tbl[4] = { 1.0, 2.0, 64.0, 128.0 };
|
||||
const float als_norm_res = 100.0;
|
||||
const float als_multiplier = 3.6;
|
||||
const float als_tint = 2.7;
|
||||
|
||||
// Wait for ADC to prepare new data.
|
||||
while (!(adc_ready & BH1730_CTL_ADC_VALID) && retries)
|
||||
{
|
||||
retries--;
|
||||
adc_ready = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_CONTROL_REG));
|
||||
}
|
||||
|
||||
// Get visible and ir light raw data.
|
||||
data[0] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0LOW_REG)) +
|
||||
(i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0HIGH_REG)) << 8);
|
||||
data[1] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1LOW_REG)) +
|
||||
(i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1HIGH_REG)) << 8);
|
||||
|
||||
als_val->over_limit = data[0] > 65534 || data[1] > 65534;
|
||||
als_val->vi_light = data[0];
|
||||
als_val->ir_light = data[1];
|
||||
|
||||
if (!data[0] || !retries)
|
||||
{
|
||||
als_val->lux = 0.0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
visible_light = (float)data[0];
|
||||
ir_light = (float)data[1];
|
||||
light_ratio = (float)data[1] / (float)data[0];
|
||||
|
||||
// The following are specific to the light filter Switch uses.
|
||||
if (light_ratio < 0.5)
|
||||
pre_gain_lux = visible_light * 5.002 - ir_light * 7.502;
|
||||
else if (light_ratio < 0.754)
|
||||
pre_gain_lux = visible_light * 2.250 - ir_light * 2.000;
|
||||
else if (light_ratio < 1.029)
|
||||
pre_gain_lux = visible_light * 1.999 - ir_light * 1.667;
|
||||
else if (light_ratio < 1.373)
|
||||
pre_gain_lux = visible_light * 0.884 - ir_light * 0.583;
|
||||
else if (light_ratio < 1.879)
|
||||
pre_gain_lux = visible_light * 0.309 - ir_light * 0.165;
|
||||
else pre_gain_lux = 0.0;
|
||||
|
||||
als_val->lux = (pre_gain_lux / als_gain_idx_tbl[als_val->gain]) * (als_norm_res / ((float)als_val->itime * als_tint)) * als_multiplier;
|
||||
}
|
||||
|
||||
u8 als_init(als_table_t *als_val)
|
||||
{
|
||||
pinmux_config_i2c(I2C_2);
|
||||
clock_enable_i2c(I2C_2);
|
||||
i2c_init(I2C_2);
|
||||
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, 0xD8 | MAX77620_LDO_CFG2_ADE_MASK);
|
||||
|
||||
u8 id = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(0x12));
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_SPEC(BH1730_SPECCMD_RESET), 0);
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), HOS_GAIN);
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - HOS_ITIME));
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_CONTROL_REG), BH1730_CTL_POWER_ON | BH1730_CTL_ADC_EN);
|
||||
|
||||
als_val->gain = HOS_GAIN;
|
||||
als_val->itime = HOS_ITIME;
|
||||
|
||||
return id;
|
||||
}
|
65
bdk/input/als.h
Normal file
65
bdk/input/als.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Ambient light sensor driver for Nintendo Switch's Rohm BH1730
|
||||
*
|
||||
* Copyright (c) 2018 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ALS_H_
|
||||
#define __ALS_H_
|
||||
|
||||
#include <utils/types.h>
|
||||
|
||||
#define BH1730_I2C_ADDR 0x29
|
||||
|
||||
#define BH1730_CMD_MAGIC 0x80
|
||||
#define BH1730_CMD_SETADDR 0x00
|
||||
#define BH1730_CMD_SPECCMD 0x60
|
||||
#define BH1730_SPECCMD_RESET 0x4
|
||||
|
||||
#define BH1730_CONTROL_REG 0x00
|
||||
#define BH1730_CTL_ADC_VALID 0x10
|
||||
#define BH1730_CTL_ONE_TIME 0x08
|
||||
#define BH1730_CTL_DAT0_ONLY 0x04
|
||||
#define BH1730_CTL_ADC_EN 0x02
|
||||
#define BH1730_CTL_POWER_ON 0x01
|
||||
#define BH1730_TIMING_REG 0x01
|
||||
#define BH1730_GAIN_REG 0x07
|
||||
#define BH1730_GAIN_1X 0x00
|
||||
#define BH1730_GAIN_2X 0x01
|
||||
#define BH1730_GAIN_64X 0x02
|
||||
#define BH1730_GAIN_128X 0x03
|
||||
#define BH1730_DATA0LOW_REG 0x14
|
||||
#define BH1730_DATA0HIGH_REG 0x15
|
||||
#define BH1730_DATA1LOW_REG 0x16
|
||||
#define BH1730_DATA1HIGH_REG 0x17
|
||||
|
||||
#define BH1730_ADDR(reg) (BH1730_CMD_MAGIC | BH1730_CMD_SETADDR | reg)
|
||||
#define BH1730_SPEC(cmd) (BH1730_CMD_MAGIC | BH1730_CMD_SPECCMD | cmd)
|
||||
|
||||
typedef struct _als_table_t
|
||||
{
|
||||
float lux;
|
||||
bool over_limit;
|
||||
u32 vi_light;
|
||||
u32 ir_light;
|
||||
u8 gain;
|
||||
u8 itime;
|
||||
} als_table_t;
|
||||
|
||||
void set_als_cfg(als_table_t *als_val, u8 gain, u8 itime);
|
||||
void get_als_lux(als_table_t *als_val);
|
||||
u8 als_init(als_table_t *als_val);
|
||||
|
||||
#endif /* __ALS_H_ */
|
872
bdk/input/joycon.c
Normal file
872
bdk/input/joycon.c
Normal file
|
@ -0,0 +1,872 @@
|
|||
/*
|
||||
* Joy-Con UART driver for Nintendo Switch
|
||||
*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "joycon.h"
|
||||
#include <gfx_utils.h>
|
||||
#include <power/max17050.h>
|
||||
#include <power/regulator_5v.h>
|
||||
#include <soc/bpmp.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <soc/uart.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
// For disabling driver when logging is enabled.
|
||||
#include <libs/lv_conf.h>
|
||||
|
||||
#define JC_WIRED_CMD 0x91
|
||||
#define JC_WIRED_HID 0x92
|
||||
#define JC_WIRED_INIT_REPLY 0x94
|
||||
#define JC_INIT_HANDSHAKE 0xA5
|
||||
|
||||
#define JC_WIRED_CMD_MAC 0x01
|
||||
#define JC_WIRED_CMD_10 0x10
|
||||
|
||||
#define JC_HID_OUTPUT_RPT 0x01
|
||||
#define JC_HID_RUMBLE_RPT 0x10
|
||||
|
||||
#define JC_HID_INPUT_RPT 0x30
|
||||
#define JC_HID_SUBMCD_RPT 0x21
|
||||
|
||||
#define JC_HID_SUBCMD_HCI_STATE 0x06
|
||||
#define HCI_STATE_SLEEP 0x00
|
||||
#define HCI_STATE_RECONNECT 0x01
|
||||
#define HCI_STATE_PAIR 0x02
|
||||
#define HCI_STATE_HOME 0x04
|
||||
#define JC_HID_SUBCMD_SPI_READ 0x10
|
||||
#define SPI_READ_OFFSET 0x20
|
||||
#define JC_HID_SUBCMD_RUMBLE_CTL 0x48
|
||||
#define JC_HID_SUBCMD_SND_RUMBLE 0xFF
|
||||
|
||||
#define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status.
|
||||
#define JC_BTN_MASK_R 0x76FF
|
||||
|
||||
#define JC_ID_L 1
|
||||
#define JC_ID_R 2
|
||||
|
||||
enum
|
||||
{
|
||||
JC_BATT_EMTPY = 0,
|
||||
JC_BATT_CRIT = 2,
|
||||
JC_BATT_LOW = 4,
|
||||
JC_BATT_MID = 6,
|
||||
JC_BATT_FULL = 8
|
||||
};
|
||||
|
||||
static const u8 init_jc[] = {
|
||||
0xA1, 0xA2, 0xA3, 0xA4
|
||||
};
|
||||
|
||||
static const u8 init_handshake[] = {
|
||||
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
|
||||
JC_INIT_HANDSHAKE, 0x02, // Wired cmd and wired subcmd.
|
||||
0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data.
|
||||
};
|
||||
|
||||
static const u8 init_get_info[] = {
|
||||
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
|
||||
JC_WIRED_CMD, JC_WIRED_CMD_MAC, // Wired cmd and subcmd.
|
||||
0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data.
|
||||
};
|
||||
|
||||
static const u8 init_finilize[] = {
|
||||
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
|
||||
JC_WIRED_CMD, JC_WIRED_CMD_10, // Wired cmd and subcmd.
|
||||
0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data.
|
||||
};
|
||||
|
||||
static const u8 nx_pad_status[] = {
|
||||
0x19, 0x01, 0x03, 0x08, 0x00, // Uart header.
|
||||
JC_WIRED_HID, 0x00, // Wired cmd and hid cmd.
|
||||
0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data.
|
||||
};
|
||||
|
||||
typedef struct _jc_uart_hdr_t
|
||||
{
|
||||
u8 magic[3];
|
||||
u8 total_size_lsb;
|
||||
u8 total_size_msb;
|
||||
} jc_uart_hdr_t;
|
||||
|
||||
typedef struct _jc_wired_hdr_t
|
||||
{
|
||||
jc_uart_hdr_t uart_hdr;
|
||||
u8 cmd;
|
||||
u8 data[5];
|
||||
u8 crc;
|
||||
u8 payload[];
|
||||
} jc_wired_hdr_t;
|
||||
|
||||
typedef struct _jc_hid_out_rpt_t
|
||||
{
|
||||
u8 cmd;
|
||||
u8 pkt_id;
|
||||
u8 rumble[8];
|
||||
u8 subcmd;
|
||||
u8 subcmd_data[];
|
||||
} jc_hid_out_rpt_t;
|
||||
|
||||
typedef struct _jc_hid_out_spi_read_t
|
||||
{
|
||||
u32 addr;
|
||||
u8 size;
|
||||
} jc_hid_out_spi_read_t;
|
||||
|
||||
typedef struct _jc_hid_in_rpt_t
|
||||
{
|
||||
u8 cmd;
|
||||
u8 pkt_id;
|
||||
u8 conn_info:4;
|
||||
u8 batt_info:4;
|
||||
u8 btn_right;
|
||||
u8 btn_shared;
|
||||
u8 btn_left;
|
||||
u8 stick_h_left;
|
||||
u8 stick_m_left;
|
||||
u8 stick_v_left;
|
||||
u8 stick_h_right;
|
||||
u8 stick_m_right;
|
||||
u8 stick_v_right;
|
||||
u8 vib_decider;
|
||||
u8 submcd_ack;
|
||||
u8 subcmd;
|
||||
u8 subcmd_data[];
|
||||
} jc_hid_in_rpt_t;
|
||||
|
||||
typedef struct _jc_hid_in_spi_read_t
|
||||
{
|
||||
u32 addr;
|
||||
u8 size;
|
||||
u8 data[];
|
||||
} jc_hid_in_spi_read_t;
|
||||
|
||||
typedef struct _jc_hid_in_pair_data_t
|
||||
{
|
||||
u8 magic;
|
||||
u8 size;
|
||||
u16 checksum;
|
||||
u8 mac[6];
|
||||
u8 ltk[16];
|
||||
u8 pad0[10];
|
||||
u8 bt_caps; // bit3: Secure conn supported host, bit5: Paired to TBFC supported host, bit6: iTBFC page supported
|
||||
u8 pad1;
|
||||
} jc_hid_in_pair_data_t;
|
||||
|
||||
typedef struct _joycon_ctxt_t
|
||||
{
|
||||
u8 buf[0x100]; //FIXME: If heap is used, dumping breaks.
|
||||
u8 uart;
|
||||
u8 type;
|
||||
u8 mac[6];
|
||||
u32 hw_init_done;
|
||||
u32 last_received_time;
|
||||
u32 last_status_req_time;
|
||||
u8 rumble_sent;
|
||||
u8 connected;
|
||||
} joycon_ctxt_t;
|
||||
|
||||
static joycon_ctxt_t jc_l;
|
||||
static joycon_ctxt_t jc_r;
|
||||
|
||||
static bool jc_init_done = false;
|
||||
static u32 hid_pkt_inc = 0;
|
||||
|
||||
static jc_gamepad_rpt_t jc_gamepad;
|
||||
|
||||
void jc_power_supply(u8 uart, bool enable);
|
||||
|
||||
void joycon_send_raw(u8 uart_port, const u8 *buf, u16 size)
|
||||
{
|
||||
uart_send(uart_port, buf, size);
|
||||
uart_wait_idle(uart_port, UART_TX_IDLE);
|
||||
}
|
||||
|
||||
static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size)
|
||||
{
|
||||
out->uart_hdr.magic[0] = 0x19;
|
||||
out->uart_hdr.magic[1] = 0x01;
|
||||
out->uart_hdr.magic[2] = 0x3;
|
||||
|
||||
out->uart_hdr.total_size_lsb = 7;
|
||||
out->uart_hdr.total_size_msb = 0;
|
||||
out->cmd = wired_cmd;
|
||||
|
||||
if (data)
|
||||
memcpy(out->data, data, size);
|
||||
|
||||
out->crc = 0; // wired crc8ccit can be skipped.
|
||||
|
||||
return sizeof(jc_wired_hdr_t);
|
||||
}
|
||||
|
||||
static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size)
|
||||
{
|
||||
u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0);
|
||||
pkt_size += size;
|
||||
|
||||
rpt->uart_hdr.total_size_lsb += size;
|
||||
rpt->data[0] = size >> 8;
|
||||
rpt->data[1] = size & 0xFF;
|
||||
|
||||
if (payload)
|
||||
memcpy(rpt->payload, payload, size);
|
||||
|
||||
return pkt_size;
|
||||
}
|
||||
|
||||
void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size)
|
||||
{
|
||||
u8 rpt[0x50];
|
||||
memset(rpt, 0, sizeof(rpt));
|
||||
|
||||
u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size);
|
||||
|
||||
joycon_send_raw(uart, rpt, rpt_size);
|
||||
}
|
||||
|
||||
static u8 jc_hid_pkt_id_incr()
|
||||
{
|
||||
u8 curr_id = hid_pkt_inc;
|
||||
hid_pkt_inc++;
|
||||
|
||||
return (curr_id & 0xF);
|
||||
}
|
||||
|
||||
void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
|
||||
{
|
||||
u8 temp[0x30];
|
||||
u8 rumble_neutral[8] = {0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40};
|
||||
u8 rumble_init[8] = {0xc2, 0xc8, 0x03, 0x72, 0xc2, 0xc8, 0x03, 0x72};
|
||||
|
||||
memset(temp, 0, sizeof(temp));
|
||||
|
||||
jc_hid_out_rpt_t *hid_pkt = (jc_hid_out_rpt_t *)temp;
|
||||
|
||||
memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral));
|
||||
|
||||
if (subcmd == JC_HID_SUBCMD_SND_RUMBLE)
|
||||
{
|
||||
bool send_r_rumble = jc_r.connected && !jc_r.rumble_sent;
|
||||
bool send_l_rumble = jc_l.connected && !jc_l.rumble_sent;
|
||||
|
||||
// Enable rumble.
|
||||
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
|
||||
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
|
||||
hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
|
||||
hid_pkt->subcmd_data[0] = 1;
|
||||
if (send_r_rumble)
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10);
|
||||
if (send_l_rumble)
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10);
|
||||
|
||||
// Send rumble.
|
||||
hid_pkt->cmd = JC_HID_RUMBLE_RPT;
|
||||
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
|
||||
memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init));
|
||||
if (send_r_rumble)
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10);
|
||||
if (send_l_rumble)
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10);
|
||||
|
||||
msleep(15);
|
||||
|
||||
// Disable rumble.
|
||||
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
|
||||
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
|
||||
hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
|
||||
hid_pkt->subcmd_data[0] = 0;
|
||||
memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral));
|
||||
if (send_r_rumble)
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10);
|
||||
if (send_l_rumble)
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10);
|
||||
}
|
||||
else
|
||||
{
|
||||
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
|
||||
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
|
||||
hid_pkt->subcmd = subcmd;
|
||||
if (data)
|
||||
memcpy(hid_pkt->subcmd_data, data, size);
|
||||
|
||||
u8 pkt_size = sizeof(jc_hid_out_rpt_t) + size;
|
||||
|
||||
jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, pkt_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void jc_charging_decider(u8 batt, u8 uart)
|
||||
{
|
||||
u32 system_batt_enough = max17050_get_cached_batt_volt() > 4000;
|
||||
|
||||
// Power supply control based on battery levels and charging.
|
||||
if ((batt >> 1 << 1) < JC_BATT_LOW) // Level without checking charging.
|
||||
jc_power_supply(uart, true);
|
||||
else if (batt > (system_batt_enough ? JC_BATT_FULL : JC_BATT_MID)) // Addresses the charging bit.
|
||||
jc_power_supply(uart, false);
|
||||
}
|
||||
|
||||
static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size)
|
||||
{
|
||||
u32 btn_tmp;
|
||||
jc_hid_in_rpt_t *hid_pkt = (jc_hid_in_rpt_t *)packet;
|
||||
|
||||
switch (hid_pkt->cmd)
|
||||
{
|
||||
case JC_HID_INPUT_RPT:
|
||||
btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16;
|
||||
|
||||
if (jc->type & JC_ID_L)
|
||||
{
|
||||
jc_gamepad.buttons &= ~JC_BTN_MASK_L;
|
||||
jc_gamepad.buttons |= (btn_tmp & JC_BTN_MASK_L);
|
||||
|
||||
jc_gamepad.lstick_x = hid_pkt->stick_h_left | ((hid_pkt->stick_m_left & 0xF) << 8);
|
||||
jc_gamepad.lstick_y = (hid_pkt->stick_m_left >> 4) | (hid_pkt->stick_v_left << 4);
|
||||
|
||||
jc_gamepad.batt_info_l = hid_pkt->batt_info;
|
||||
}
|
||||
else if (jc->type & JC_ID_R)
|
||||
{
|
||||
jc_gamepad.buttons &= ~JC_BTN_MASK_R;
|
||||
jc_gamepad.buttons |= (btn_tmp & JC_BTN_MASK_R);
|
||||
|
||||
jc_gamepad.rstick_x = hid_pkt->stick_h_right | ((hid_pkt->stick_m_right & 0xF) << 8);
|
||||
jc_gamepad.rstick_y = (hid_pkt->stick_m_right >> 4) | (hid_pkt->stick_v_right << 4);
|
||||
|
||||
jc_gamepad.batt_info_r = hid_pkt->batt_info;
|
||||
|