Created
February 29, 2024 12:42
-
-
Save dixyes/b631e350deb54c8fa30b386179095c5d to your computer and use it in GitHub Desktop.
fuck uvc auto exposure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// aarch64-linux-gnu-gcc fuckexposure.c -nostdinc -nostdlib -nostartfiles -e _start -g -o fuckexposure -Wall -static -ffreestanding -fno-stack-protector | |
#define NULL ((void *)0) | |
#define O_RDONLY 0 | |
#define O_WRONLY 1 | |
#define O_RDWR 2 | |
#define AT_FDCWD -100 | |
#define PROT_READ 0x1 | |
#define PROT_WRITE 0x2 | |
#define PROT_EXEC 0x4 | |
#define MAP_PRIVATE 0x02 | |
#define MAP_ANONYMOUS 0x20 | |
#define MAP_STACK 0x20000 | |
#define MAP_UNINITIALIZED 0x4000000 | |
#define MAP_FAILED ((void *)-1) | |
#if defined(__x86_64__) || defined(__aarch64__) | |
typedef int int32_t; | |
typedef unsigned int uint32_t; | |
typedef long long int64_t; | |
typedef unsigned long long uint64_t; | |
typedef int64_t ssize_t; | |
typedef uint64_t size_t; | |
typedef ssize_t off_t; | |
typedef uint64_t uintptr_t; | |
typedef int64_t intptr_t; | |
#else | |
# error "Unsupported architecture" | |
#endif | |
int errno = 0; | |
#ifdef __x86_64__ | |
# define syscall_decl(name, num, ...) \ | |
intptr_t __attribute__((sysv_abi, naked)) name(__VA_ARGS__) \ | |
{ \ | |
asm volatile( \ | |
"/* syscall " #name " */\n\t" \ | |
"mov $" #num ", %rax\n\t" \ | |
"syscall\n\t" \ | |
"test %rax, %rax\n\t" \ | |
"js .L" #name "_error\n\t" \ | |
"ret\n\t" \ | |
".L" #name "_error:\n\t" \ | |
"neg %rax\n\t" \ | |
"mov %rax, errno\n\t" \ | |
"mov $-1, %rax\n\t" \ | |
"ret" \ | |
); \ | |
} | |
# define syscall_decl4(name, num, ...) \ | |
intptr_t __attribute__((sysv_abi, naked)) name(__VA_ARGS__) \ | |
{ \ | |
asm volatile( \ | |
"/* syscall " #name " */\n\t" \ | |
"mov %rcx, %r10\n\t" \ | |
"mov $" #num ", %rax\n\t" \ | |
"syscall\n\t" \ | |
"test %rax, %rax\n\t" \ | |
"js .L" #name "_error\n\t" \ | |
"ret\n\t" \ | |
".L" #name "_error:\n\t" \ | |
"neg %rax\n\t" \ | |
"mov %rax, errno\n\t" \ | |
"mov $-1, %rax\n\t" \ | |
"ret" \ | |
); \ | |
} | |
#elif defined(__aarch64__) | |
# define syscall_decl(name, num, ...) \ | |
intptr_t name(__VA_ARGS__); \ | |
asm ( \ | |
".text\n" \ | |
".global " #name "\n" \ | |
#name ":\n\t" \ | |
"mov x8, #" #num "\n\t" \ | |
"svc 0\n\t" \ | |
"cmn x0, #4096 /* MAX_ERRNO + 1 */\n\t" \ | |
"cneg x0, x0, hi\n\t" \ | |
"b.hi .L" #name "_error\n\t" \ | |
"ret\n\t" \ | |
".L" #name "_error:\n\t" \ | |
"ldr x8, =errno\n\t" \ | |
"str x0, [x8]\n\t" \ | |
"mov x0, #-1\n\t" \ | |
"ret" \ | |
); | |
# define syscall_decl4 syscall_decl | |
#else | |
# error "Unsupported architecture" | |
#endif | |
#ifdef __x86_64__ | |
syscall_decl(write, 1, int fd, const void *buf, size_t count) | |
syscall_decl(openat, 257, int dirfd, const char *pathname, int flags, int mode) | |
syscall_decl(syscall_exit, 60, int status) | |
syscall_decl4(mmap, 9, void *addr, size_t length, int prot, int flags, int fd, off_t offset) | |
syscall_decl4(mremap, 25, void *old_address, size_t old_size, size_t new_size, int flags, void *new_address) | |
syscall_decl4(ioctl, 16, int fd, unsigned long request, void *argp) | |
int __attribute__((sysv_abi, naked, noreturn)) _start() | |
{ | |
asm volatile( | |
// clean rbp according to the convention | |
"xor %rbp, %rbp\n\t" | |
// argc | |
"mov (%rsp), %rdi\n\t" | |
// argv | |
"lea 8(%rsp), %rsi\n\t" | |
// envp | |
"lea 16(%rsp, %rdi, 8), %rdx\n\t" | |
// call main | |
"call main\n\t" | |
// call _exit | |
"mov %rax, %rdi\n\t" | |
"call _exit" | |
); | |
} | |
#elif defined(__aarch64__) | |
syscall_decl(write, 64, int fd, const void *buf, size_t count) | |
syscall_decl(openat, 56, int dirfd, const char *pathname, int flags, int mode) | |
syscall_decl(syscall_exit, 93, int status) | |
syscall_decl4(mmap, 222, void *addr, size_t length, int prot, int flags, int fd, off_t offset) | |
syscall_decl4(mremap, 235, void *old_address, size_t old_size, size_t new_size, int flags, void *new_address) | |
syscall_decl4(ioctl, 29, int fd, unsigned long request, void *argp) | |
int _start() | |
{ | |
asm volatile( | |
// argc | |
"ldr w0, [sp]\n\t" | |
// argv | |
"add x1, sp, #8\n\t" | |
// envp | |
"lsl x2, x0, #3\n\t" | |
"add x2, x2, x1\n\t" | |
"add x2, x2, #8\n\t" | |
// call main | |
"mov x29, sp\n\t" | |
"bl main\n\t" | |
// call _exit | |
"bl _exit" | |
); | |
__builtin_unreachable(); | |
} | |
#else | |
# error "Unsupported architecture" | |
#endif | |
void __attribute__((noreturn)) _exit(int status) | |
{ | |
(void) syscall_exit(status); | |
__builtin_unreachable(); | |
} | |
#define writes(msg) write(1, msg "\n", sizeof(msg)) | |
#define writeerr(msg) \ | |
do { \ | |
int err = errno; \ | |
write(2, msg, sizeof(msg) - 1); \ | |
write(2, ": ", 2); \ | |
char errStr[32]; \ | |
size_t size = itoa(err, errStr); \ | |
write(2, errStr, size); \ | |
write(2, "\n", 1); \ | |
} while (0) | |
void *mempool = NULL; | |
void *mempoolCursor = NULL; | |
intptr_t mempoolSize = 0; | |
#define MEMPOOL_PAGE_SIZE 16384 | |
#define MEMPOOL_ALIGN 8 | |
// shabby malloc | |
void *malloc(size_t size) | |
{ | |
if (mempool == NULL) { | |
mempool = (void*) mmap(NULL, MEMPOOL_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_UNINITIALIZED, -1, 0); | |
if (mempool == MAP_FAILED) { | |
mempool = NULL; | |
return NULL; | |
} | |
mempoolCursor = mempool; | |
mempoolSize = MEMPOOL_PAGE_SIZE; | |
} | |
if ((mempoolCursor - mempool) + size > mempoolSize) { | |
intptr_t mempoolSizeNew = (mempoolSize + size + MEMPOOL_PAGE_SIZE - 1) / MEMPOOL_PAGE_SIZE * MEMPOOL_PAGE_SIZE; | |
int ret = mremap(mempool, mempoolSize, mempoolSizeNew, 0, NULL); | |
if (ret == -1) { | |
return NULL; | |
} | |
mempoolSize = mempoolSizeNew; | |
} | |
void *retAddr = mempoolCursor; | |
mempoolCursor += (size + MEMPOOL_ALIGN - 1) / MEMPOOL_ALIGN * MEMPOOL_ALIGN; | |
return retAddr; | |
} | |
// shabby int to dec | |
size_t itoa(int64_t value, char *str) | |
{ | |
char *start = str; | |
if (value < 0) { | |
*str++ = '-'; | |
value = -value; | |
} | |
char *end = str; | |
do { | |
*end++ = '0' + value % 10; | |
value /= 10; | |
} while (value > 0); | |
char *p = end - 1; | |
while (str < p) { | |
char tmp = *str; | |
*str++ = *p; | |
*p-- = tmp; | |
} | |
return end - start; | |
} | |
struct v4l2_ext_control { | |
uint32_t id; | |
uint32_t size; | |
uint32_t reserved2[1]; | |
union { | |
void *ptr; | |
int32_t value; | |
int64_t value64; | |
char *string; | |
unsigned char *p_u8; | |
unsigned short *p_u16; | |
unsigned int *p_u32; | |
}; | |
} __attribute__ ((packed)); | |
struct v4l2_ext_controls { | |
union { | |
uint32_t ctrl_class; | |
uint32_t which; | |
}; | |
uint32_t count; | |
uint32_t error_idx; | |
uint32_t reserved[2]; | |
struct v4l2_ext_control *controls; | |
}; | |
#define V4L2_CTRL_CLASS_CAMERA 0x009a0000 | |
int main(int argc, const char **argv, const char **envp) | |
{ | |
if (argc < 2) { | |
writes("Usage: <this> <device>"); | |
return 1; | |
} | |
const char *devName = argv[1]; | |
int devFd = openat(AT_FDCWD, devName, O_RDWR, 0666); | |
if (devFd < 0) { | |
writeerr("Failed to open device"); | |
return 1; | |
} | |
struct v4l2_ext_control ctrl = { | |
.id = 0x009a0901 /* V4L2_CID_EXPOSURE_AUTO */, | |
.size = 0, | |
.value64 = 1 | |
}; | |
struct v4l2_ext_controls ctrls = { | |
.ctrl_class = 0x009a0000 /* V4L2_CTRL_CLASS_CAMERA */, | |
.count = 1, | |
.controls = &ctrl | |
}; | |
int ret = ioctl(devFd, 0xc0205648 /* VIDIOC_S_EXT_CTRLS */, &ctrls); | |
if (ret < 0) { | |
writeerr("Failed to set exposure"); | |
return 1; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment