Skip to content

Instantly share code, notes, and snippets.

@dixyes
Created February 29, 2024 12:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dixyes/b631e350deb54c8fa30b386179095c5d to your computer and use it in GitHub Desktop.
Save dixyes/b631e350deb54c8fa30b386179095c5d to your computer and use it in GitHub Desktop.
fuck uvc auto exposure
// 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