Steward
分享是一種喜悅、更是一種幸福
掌機 - Anbernic RG351P - 修正STM32F103手柄吞鍵問題
參考資料:
https://github.com/OpenSimHardware/PedalButtonController
https://opensimhardware.wordpress.com/pedal-button-controller/
main.c
#include <linux/types.h>
#include <linux/input.h>
#include <linux/hidraw.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <SDL.h>
#include <SDL_ttf.h>
#include <SDL_image.h>
#ifndef PC
#include "hex_font.h"
#endif
#include "hex_splash.h"
TTF_Font *font = NULL;
SDL_Surface *real = NULL;
SDL_Surface *screen = NULL;
SDL_Surface *splash = NULL;
uint8_t mycfg[] = {
0x04, 0x01, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0x0f,
0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x16, 0x16, 0x16,
0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00,
0x04, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x32, 0x04, 0x05,
0x04, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x2f,
0x78, 0xf9, 0x8c, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01,
0x7f, 0x38, 0xd8, 0xf4, 0x58, 0xf9, 0x74, 0x00, 0xb2, 0x15, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x01,
0x50, 0xf9, 0x74, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x69, 0x00, 0x2d, 0x00, 0x6d, 0x00, 0x73, 0x00,
0x04, 0x04, 0x00, 0x01, 0x7f, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x73, 0x00, 0x68, 0x00, 0x01, 0x7f,
0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x2d, 0x00, 0x6f, 0x01, 0x7f, 0x00, 0x73, 0x00, 0x6f, 0x00,
0x6c, 0x00, 0x65, 0x00, 0x01, 0x7f, 0x65, 0x00, 0x2d, 0x00, 0x6c, 0x00, 0x31, 0x00, 0x2d, 0x01,
0x7f, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x00, 0x00,
0x04, 0x05, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
0xe8, 0xe8, 0xee, 0xed, 0xec, 0xeb, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
0xe8, 0xe8, 0x74, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x40, 0xcd, 0x8b, 0x77, 0xd0, 0x38, 0x8d, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0xd2, 0x8b, 0x77, 0xed, 0x3a, 0xd8, 0xf4, 0x00, 0x00, 0x8c, 0x00,
0x04, 0x06, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
0xe8, 0xe8, 0xff, 0xff, 0x30, 0xfa, 0x74, 0x00, 0x2b, 0x17, 0x8b, 0x77, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0xa9, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xfa, 0x74, 0x00,
0x04, 0x07, 0x00, 0x00, 0xd0, 0x01, 0xa0, 0x03, 0x50, 0x05, 0x20, 0x07, 0xc0, 0x08, 0xa0, 0x0a,
0x40, 0x0c, 0x40, 0x0e, 0xff, 0x0f, 0x00, 0x00, 0x80, 0x05, 0xc0, 0x09, 0x40, 0x0c, 0x10, 0x0e,
0x10, 0x0f, 0x80, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x60, 0x00, 0x30, 0x01, 0x70, 0x02, 0x40, 0x04, 0x60, 0x08, 0xff, 0x0f, 0xb0, 0x75,
0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xa0, 0x01, 0xb0, 0x04, 0x70, 0x0b, 0x40, 0x0e,
0xb0, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x40, 0x04, 0x50, 0x06, 0x80, 0x07, 0xc0, 0x07,
0xf0, 0x07, 0x60, 0x08, 0x60, 0x09, 0xd0, 0x0b, 0xff, 0x0f, 0xff, 0x0f, 0x40, 0x0e, 0x40, 0x0c,
0xa0, 0x0a, 0xc0, 0x08, 0x20, 0x07, 0x50, 0x05, 0xa0, 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00,
0x04, 0x09, 0x4c, 0x69, 0x6e, 0x65, 0x61, 0x72, 0x00, 0x00, 0x00, 0x00, 0x45, 0x78, 0x70, 0x6f,
0x6e, 0x65, 0x6e, 0x74, 0x31, 0x00, 0x45, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x32, 0x00,
0x53, 0x68, 0x61, 0x70, 0x65, 0x31, 0x00, 0x00, 0x00, 0x00, 0x53, 0x68, 0x61, 0x70, 0x65, 0x32,
0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00,
};
int upgrade(void)
{
char buf[255] = { 0 };
struct hidraw_devinfo info = { 0 };
struct hidraw_report_descriptor rpt_desc = { 0 };
int fd = -1, x = 0, r = 0, desc_size = 0, err_cnt = 0;
fd = open("/dev/hidraw0", O_RDWR | O_NONBLOCK);
if (fd < 0) {
printf("failed to open device\n");
return -1;
}
ioctl(fd, HIDIOCGRDESCSIZE, &desc_size);
rpt_desc.size = desc_size;
ioctl(fd, HIDIOCGRDESC, &rpt_desc);
ioctl(fd, HIDIOCGRAWNAME(sizeof(buf)), buf);
if (strcmp(buf, "OpenSimHardware OSH PB Controller") != 0) {
printf("failed to open rg351p device\n");
close(fd);
return -1;
}
ioctl(fd, HIDIOCGRAWPHYS(sizeof(buf)), buf);
ioctl(fd, HIDIOCGRAWINFO, &info);
buf[0] = 0x9;
buf[1] = 0xff;
buf[2] = 0xff;
buf[3] = 0xff;
ioctl(fd, HIDIOCSFEATURE(4), buf);
buf[0] = 0x9;
ioctl(fd, HIDIOCGFEATURE(sizeof(buf)), buf);
err_cnt = 0;
for (x = 0; x < 9; x++) {
mycfg[64 * x] = 2;
r = write(fd, &mycfg[64 * x], 64);
if (r < 0) {
err_cnt += 1;
}
printf("wrote: %d\n", r);
usleep(100000);
}
close(fd);
return err_cnt;
}
void flip_screen(void)
{
int x = 0, y = 0;
uint16_t *s = screen->pixels;
uint16_t *d = real->pixels;
for (y = 0; y < 320; y++) {
for (x = 0; x < 480; x++) {
d[y + ((480 - x) * 320)] = s[x + (y * 480)];
}
}
SDL_Flip(real);
}
void text(char *msg, uint8_t r, uint8_t g, uint8_t b)
{
int w, h;
SDL_Rect rt = { 0 };
SDL_Surface *t = NULL;
SDL_Color col = { r, g, b };
t = TTF_RenderUTF8_Blended(font, msg, col);
if (t) {
TTF_SizeUTF8(font, msg, &w, &h);
rt.x = (480 - w) / 2;
rt.y = 260;
SDL_BlitSurface(splash, NULL, screen, NULL);
SDL_BlitSurface(t, NULL, screen, &rt);
SDL_FreeSurface(t);
}
flip_screen();
}
int main(int argc, char **argv)
{
int ok = 0;
SDL_Surface *t = NULL;
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
printf("failed to init sdl\n");
return -1;
}
real = SDL_SetVideoMode(320, 480, 16, SDL_HWSURFACE);
if (real == NULL) {
printf("failed to set video mode\n");
return -1;
}
SDL_ShowCursor(SDL_FALSE);
if (TTF_Init() == -1) {
printf("failed to init ttf\n");
return -1;
}
#ifndef PC
font = TTF_OpenFontRW(SDL_RWFromMem(hex_font, sizeof(hex_font)), 1, 38);
#else
font = TTF_OpenFont("font.ttf", 38);
#endif
screen = SDL_CreateRGBSurface(SDL_SWSURFACE, 480, 320, 16, 0, 0, 0, 0);
SDL_FillRect(real, &real->clip_rect, SDL_MapRGB(real->format, 0, 0, 0));
SDL_RWops *rw = NULL;
rw = SDL_RWFromMem(hex_splash, sizeof(hex_splash)); t = IMG_Load_RW(rw, 1);
splash = SDL_ConvertSurface(t, real->format, 0); SDL_FreeSurface(t);
text("手柄固件更新中...", 0x00, 0x00, 0xa0);
ok = upgrade();
SDL_Delay(1000);
if (ok < 0) {
text("更新失败, 系统关机中...", 0xa0, 0x00, 0x00);
}
else {
text("更新完成, 系统关机中...", 0x00, 0xa0, 0x00);
}
SDL_Delay(1500);
TTF_Quit();
SDL_FreeSurface(splash);
SDL_Quit();
#ifndef PC
system("poweroff");
#endif
return 0;
}