556 lines
17 KiB
C
Raw Normal View History

2025-02-18 15:40:42 +08:00
#include "system/app_core.h"
#include "system/includes.h"
#include "server/server_core.h"
#include "app_config.h"
#include "app_action.h"
#include "vm.h"
#include "update_loader_download.h"
#if(CONFIG_APP_GAMEBOX)
#include "gamebox.h"
#define LOG_TAG_CONST GAMEBOX
#define LOG_TAG "[GAMBOX]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
extern u8 get_jl_update_flag(void);
static void uart_recv_packet();
static void uart_write(const u8 *buffer, u32 len);
static void uart_comm_init();
#define UART_RX_EVENT 0x55410001
#define HEARTBEAT_EVENT 0x55410002
#define HOT_KEY_EVENT 0x55410003
#define TOUCH_POINT
const char hid_report_desc[HID_REPORT_SIZE] = {
0x05, 0x0D, // Usage Page (Digitizer)
0x09, 0x04, // Usage (Touch Screen)
0xA1, 0x01, // Collection (Application)
0x85, TOUCH_SCREEN_ID, // Report ID (1)
0x09, 0x22, // Usage (Finger)
0xA1, 0x02, // Collection (Logical)
0x09, 0x42, // Usage (Tip Switch)
0x09, 0x32, // Usage (In Range)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x02, // Report Count (2)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x51, // Usage (Contact Identifier)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0x09, 0x30, // Usage (X)
0x26, 0xA8, 0x0C, // Logical Maximum (3240)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x31, // Usage (Y)
0x26, 0x80, 0x16, // Logical Maximum (5760)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0xA1, 0x02, // Collection (Logical)
0x05, 0x0D, // Usage Page (Digitizer)
0x09, 0x42, // Usage (Tip Switch)
0x09, 0x32, // Usage (In Range)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x02, // Report Count (2)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x51, // Usage (Contact Identifier)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0x09, 0x30, // Usage (X)
0x26, 0xA8, 0x0C, // Logical Maximum (3240)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x31, // Usage (Y)
0x26, 0x80, 0x16, // Logical Maximum (5760)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0xC0, // End Collection
0x05, 0x0D, // Usage Page (Digitizer)
0x09, 0x02, // Usage (Pen)
0xA1, 0x01, // Collection (Application)
0x85, MOUSE_POINT_ID, // Report ID (2)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (0x01)
0x29, 0x03, // Usage Maximum (0x03)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x03, // Report Count (3)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x38, // Usage (Wheel)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x75, 0x08, // Report Size (8)
0x95, 0x03, // Report Count (3)
0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0xC0, // End Collection
// 167 bytes
};
#define TASK_NAME "gamebox"
u8 mouse_data_send ;
u8 touch_data_send;
struct mouse_point_t mouse_data;
static u8 is_mouse_point_mode = FALSE;
static u32 cur_work_mode = BT_MODE;
static u32 need_pre_reset = 0;
u32 get_run_mode()
{
/* return UT_DEBUG_MODE; */
/* return BT_MODE; */
/* return USB_MODE; */
/* return UART_MODE; */
return cur_work_mode;
}
void set_run_mode(u32 mode)
{
cur_work_mode = mode;
}
extern u32 get_jl_rcsp_update_status();
static u32 check_ota_mode()
{
if (UPDATE_MODULE_IS_SUPPORT(UPDATE_APP_EN)) {
#if RCSP_UPDATE_EN
if (get_jl_rcsp_update_status()) {
r_printf("OTA ing");
set_run_mode(OTA_MODE);
usb_sie_close_all();//关闭usb
JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10);//关闭串口
return 1;
}
#endif
}
return 0;
}
static void device_insert(const char *dev_name)
{
u32 id = dev_name[strlen(dev_name) - 1] - '0';
log_info("device_insert %s id: %x", dev_name, id);
if (strncmp(dev_name, "hid", 3) == 0) {
hid_process(id);
need_pre_reset = 0;
} else {
#if TCFG_AOA_ENABLE && TCFG_ADB_ENABLE
if (strncmp(dev_name, "adb", 3) == 0) {
if (get_run_mode() == BT_MODE) {
adb_process();
} else {
adb_switch_aoa(id);
}
} else if (strncmp(dev_name, "aoa", 3) == 0) {
u32 succ = aoa_process(1, id);
if (succ) {
set_phone_connect_status(USB_MODE);
} else {
r_printf("aoa error");
}
}
#else
if (adb_process()) {
usb_h_force_reset(id);
usb_otg_suspend(id, OTG_UNINSTALL);
usb_otg_resume(id);
}
#endif
}
}
void heartbeat(void *p)
{
int err = os_taskq_post_msg(TASK_NAME, 1, HEARTBEAT_EVENT);
}
static void gamebox_task(void *arg)
{
int ret = 0;
int msg[16];
u8 heartbeat_packet[1] = {0};
key_list_init();
set_run_mode(UT_DEBUG_MODE);
uart_comm_init();
u16 timer_id = sys_timer_add(NULL, heartbeat, 500);
while (1) {
ret = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));
if (ret != OS_TASKQ) {
continue;
}
if (msg[0] != Q_MSG) {
continue;
}
switch (msg[1]) {
case DEVICE_EVENT_IN:
if (get_run_mode() != OTA_MODE) {
device_insert((const char *)msg[2]);
}
break;
case UART_RX_EVENT:
/* uart_recv_packet(); */
break;
case HEARTBEAT_EVENT:
heartbeat_packet[0]++;
/* uart_write(heartbeat_packet,1); */
if (check_ota_mode()) {
#if TCFG_PC_ENABLE
usb_stop(0);
#endif
r_printf("%s()", __func__);
sys_timer_del(timer_id);
}
break;
case HOT_KEY_EVENT:
//switch IOS or Android
log_info("hot key %x", msg[2]);
break;
default:
break;
}
}
}
static void usb_event_handler(struct sys_event *event, void *priv)
{
const char *usb_msg;
usb_dev usb_id;
switch ((u32)event->arg) {
case DEVICE_EVENT_FROM_OTG:
usb_msg = (const char *)event->u.dev.value;
usb_id = usb_msg[2] - '0';
log_debug("usb event : %d DEVICE_EVENT_FROM_OTG %s",
event->u.dev.event, usb_msg);
if (usb_msg[0] == 'h') {
if (event->u.dev.event == DEVICE_EVENT_IN) {
log_info("usb %c online", usb_msg[2]);
if (usb_host_mount(usb_id, 3, 20, 250)) {
usb_h_force_reset(usb_id);
usb_otg_suspend(usb_id, OTG_UNINSTALL);
usb_otg_resume(usb_id);
}
} else if (event->u.dev.event == DEVICE_EVENT_OUT) {
log_info("usb %c offline", usb_msg[2]);
set_phone_connect_status(0);
usb_host_unmount(usb_id);
}
} else if (usb_msg[0] == 's') {
#if TCFG_PC_ENABLE
if (event->u.dev.event == DEVICE_EVENT_IN) {
usb_start(usb_id);
} else {
usb_stop(usb_id);
}
#endif
}
break;
case DEVICE_EVENT_FROM_USB_HOST:
log_debug("host_event %x", event->u.dev.event);
if ((event->u.dev.event == DEVICE_EVENT_IN) ||
(event->u.dev.event == DEVICE_EVENT_CHANGE)) {
int err = os_taskq_post_msg(TASK_NAME, 2, DEVICE_EVENT_IN, event->u.dev.value);
if (err) {
r_printf("err %x ", err);
}
} else if (event->u.dev.event == DEVICE_EVENT_OUT) {
log_error("device out %x", event->u.dev.value);
}
break;
}
}
static u16 sys_event_id;
void gamebox_init()
{
register_sys_event_handler(SYS_DEVICE_EVENT, 0, 2, usb_event_handler);
int err = task_create(gamebox_task, NULL, TASK_NAME);
}
struct ut_packet {
char id[4];
u16 type;//USB_CLASS_HID_KEYBOARD : Keyboard MOUSE_POINT_MODE: mouse
union {
struct mouse_data_t m;
struct keyboard_data_t k;
} d;
u16 crc;
} _GNU_PACKED_;
static u8 uart_dma_buffer[256] __attribute__((aligned(4)));
static u8 uart_rxbuf[32];
static u8 uart_txbuf[32] __attribute__((aligned(4)));
static void send2uart(u32 type, const void *p)
{
struct ut_packet *packet = (struct ut_packet *)uart_txbuf;
strcpy(packet[0].id, "HID");
packet[0].type = type;
memcpy(&(packet[0].d), p, sizeof(packet[0].d));
packet[0].crc = CRC16(&packet[0], sizeof(packet[0]) - 2);
packet[1] = packet[0];
/* printf_buf(packet,2*sizeof(*packet)); */
uart_write((u8 *)packet, 2 * sizeof(*packet));
}
static u32 mouse_filter(struct mouse_data_t *p)
{
if (check_ota_mode()) {
return 0;
}
if (p->btn & BIT(2)) { //middle button
is_mouse_point_mode = !is_mouse_point_mode;
point_list_empty();
p->x = 1;
p->y = 1;
p->btn = 0;
return 1;
} else {
return 1; // as mouse event
}
}
void mouse_route(const struct mouse_data_t *p)
{
if (get_run_mode() != UART_MODE) {
if (mouse_filter((void *)p) == 0) {
return;
}
}
/* log_info("btn: %x x-y %d %d wheel %d ac_pan %d", */
/* p->btn, p->x, p->y, p->wheel, p->ac_pan); */
switch (get_run_mode()) {
case UART_MODE ://在USB中断函数调用
send2uart(MOUSE_POINT_MODE, p);
break;
case BT_MODE ://在uart中断 或者usb中断函数调用
case USB_MODE://在串口中断调用
if (is_mouse_point_mode) {
send2phone(MOUSE_POINT_MODE, p);
} else {
mouse_mapping(p);
send2phone(TOUCH_SCREEN_MODE, p);
}
break;
case MAPPING_MODE:
send2phone(MOUSE_POINT_MODE + 1, p);
break;
default :
log_info("btn: %x x-y %d %d wheel %d ac_pan %d",
p->btn, p->x, p->y, p->wheel, p->ac_pan);
break;
}
}
u32 keyboard_filter(struct keyboard_data_t *k)
{
if (check_ota_mode()) {
return 0;
}
if ((k->fun_key & _KEY_MOD_LMETA) &&
(k->Keypad[0] == _KEY_F1)) {
os_taskq_post_msg(TASK_NAME, 2, HOT_KEY_EVENT, _KEY_F1);
return 0; //hook this msg
}
return 2;
}
void keyboard_route(const u8 *p)
{
/* log_info("keyboard:"); */
/* printf_buf(p, 8); */
if (keyboard_filter((struct keyboard_data_t *)p) == 0) {
return;
}
switch (get_run_mode()) {
case UART_MODE ://在USB中断函数调用
send2uart(KEYBOARD_MODE, p);
break;
case BT_MODE ://在uart接收事件 或者usb中断函数调用
case USB_MODE://在串口事件调用
key_mapping((const void *)p);
send2phone(TOUCH_SCREEN_MODE, p);
break;
case MAPPING_MODE:
send2phone(KEYBOARD_MODE, p);
break;
default :
printf_buf((u8 *)p, 8);
break;
}
}
static volatile u32 tx_idle;
static KFIFO uart_fifo;
SET_INTERRUPT
static void uart_isr(void)
{
u32 rx_len;
if ((JL_UART1->CON0 & BIT(2)) && (JL_UART1->CON0 & BIT(15))) {
JL_UART1->CON0 |= BIT(13);
tx_idle = 1;
}
if ((JL_UART1->CON0 & BIT(3)) && (JL_UART1->CON0 & BIT(14))) {
JL_UART1->CON0 |= BIT(12); //清RX PND
}
if ((JL_UART1->CON0 & BIT(5)) && (JL_UART1->CON0 & BIT(11))) {
//OTCNT PND
JL_UART1->CON0 |= BIT(7); //DMA模式
JL_UART1->CON0 |= BIT(10); //清OTCNT PND
JL_UART1->CON0 |= BIT(12); //清RX PND(这里的顺序不能改变,这里要清一次)
rx_len = JL_UART1->HRXCNT; //读当前串口接收数据的个数
if (rx_len) {
uart_fifo.buf_in += rx_len;
uart_recv_packet();
}
}
}
static void uart_comm_init()
{
request_irq(IRQ_UART1_IDX, 2, uart_isr, 0);//优先级不能比usb低
uart_fifo.buffer = uart_dma_buffer;
uart_fifo.buf_size = sizeof(uart_dma_buffer);
uart_fifo.buf_in = uart_fifo.buf_out = 0;
gpio_set_uart1(-1);
gpio_output_channle(IO_PORTB_08, CH1_UT1_TX);
gpio_uart_rx_input(IO_PORTB_09, 1, 1);
gpio_set_pull_up(IO_PORTB_08, 1);
JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10);
JL_UART1->RXSADR = (u32)uart_fifo.buffer;
JL_UART1->RXEADR = (u32)(uart_fifo.buffer + uart_fifo.buf_size);
JL_UART1->RXCNT = uart_fifo.buf_size / 2;
JL_UART1->OTCNT = 100 * (clk_get("lsb") / 1000000);
JL_UART1->BAUD = (clk_get("uart") / 2000000) / 4 - 1;
JL_UART1->CON0 |= BIT(6) | BIT(5) | BIT(3);
JL_UART1->CON0 |= BIT(0);
memset(uart_txbuf, cur_work_mode, 32);
}
static u32 kfifo_get(KFIFO *kfifo, u8 *buffer, u32 len)
{
unsigned int i;
len = MIN(len, kfifo->buf_in - kfifo->buf_out);
i = MIN(len, kfifo->buf_size - (kfifo->buf_out & (kfifo->buf_size - 1)));
memcpy(buffer, kfifo->buffer + (kfifo->buf_out & (kfifo->buf_size - 1)), i);
memcpy(buffer + i, kfifo->buffer, len - i);
kfifo->buf_out += len;
return len;
}
static u32 uart_read(u8 *buffer, u32 len)
{
return kfifo_get(&uart_fifo, buffer, len);
}
static void uart_write(const u8 *buffer, u32 len)
{
tx_idle = 0;
JL_UART1->CON0 |= BIT(13);
JL_UART1->CON0 |= BIT(2);
JL_UART1->TXADR = (u32)buffer;
JL_UART1->TXCNT = len;
while (!tx_idle) {
asm("idle");
}
}
static void uart_recv_packet()
{
struct ut_packet *p;
memset(uart_rxbuf, 0, sizeof(uart_rxbuf));
u8 *u = uart_rxbuf;
u8 len;
__r0:
len = uart_read(u, sizeof(uart_rxbuf));
if (len < sizeof(*p)) {
return;
}
__r1:
p = (struct ut_packet *)strstr((const char *)u, "HID");
if (p) {
if (p->crc == CRC16(p, sizeof(*p) - 2)) {
if (p->type == MOUSE_POINT_MODE) {
mouse_route(&p->d.m);
} else if (p->type == KEYBOARD_MODE) {
keyboard_route((const u8 *)&p->d.m);
}
goto __r0;
/* return; */
}
} else {
p = (struct ut_packet *)strstr((const char *)u, "UPDATE");//reset 进入uboot模式
}
if (u < &uart_rxbuf[sizeof(*p)]) {
u += sizeof(*p);
goto __r1;
}
goto __r0;
}
#endif