// File: /workspace/github_c_makefile_star2_O2/DrYerzinia[P]C_DigiMode/src/io/uart/UART.c
// Function: UART_open
int UART_open(UART *self, char *device_name, unsigned int baud_rate){

	self->fd = open(device_name, O_RDWR | O_NOCTTY);
	if(self->fd < 0){
		perror("Unable to open UART");
		return -1;
	}

	tcgetattr(self->fd, &(self->tio));

	self->tio.c_cflag = CS8 | CLOCAL | CREAD;
	self->tio.c_iflag = IGNPAR;
	self->tio.c_oflag = 0;
	self->tio.c_lflag = 0;

	/* Set baud rate
	 */
	speed_t standard_baud_rate = B0;
	switch(baud_rate){
		case 50:
			standard_baud_rate = B50;
			break;
		case 75:
			standard_baud_rate = B75;
			break;
		case 110:
			standard_baud_rate = B110;
			break;
		case 134:
			standard_baud_rate = B134;
			break;
		case 150:
			standard_baud_rate = B150;
			break;
		case 200:
			standard_baud_rate = B200;
			break;
		case 300:
			standard_baud_rate = B300;
			break;
		case 600:
			standard_baud_rate = B600;
			break;
		case 1200:
			standard_baud_rate = B1200;
			break;
		case 1800:
			standard_baud_rate = B1800;
			break;
		case 2400:
			standard_baud_rate = B2400;
			break;
		case 4800:
			standard_baud_rate = B4800;
			break;
		case 9600:
			standard_baud_rate = B9600;
			break;
		case 19200:
			standard_baud_rate = B19200;
			break;
		case 38400:
			standard_baud_rate = B38400;
			break;
		case 57600:
			standard_baud_rate = B57600;
			break;
		case 115200:
			standard_baud_rate = B115200;
			break;
		case 230400:
			standard_baud_rate = B230400;
			break;
	}

	if(standard_baud_rate == B38400){

		// Ensure 38400 is actually 38400
		struct serial_struct ss;
		ioctl(self->fd, TIOCGSERIAL, &ss);
		ss.flags &= ~ASYNC_SPD_MASK;
		ioctl(self->fd, TIOCSSERIAL, &ss);

	} else if(standard_baud_rate == B0){

		standard_baud_rate = B38400;

		struct serial_struct ss;

		ioctl(self->fd, TIOCGSERIAL, &ss);

		ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;

		ss.custom_divisor = ((float)(ss.baud_base + (baud_rate / 2)) / baud_rate) + 0.5;

		unsigned int actual_rate = ss.baud_base / ss.custom_divisor;

		fprintf(stderr, "Actual baud rate set to %d\n", actual_rate);
		fprintf(stderr, "Error of %f%%\n", fabs((float)(baud_rate - actual_rate) / ((float)(baud_rate + actual_rate) / 2.0F)) * 100.0F);

		ioctl(self->fd, TIOCSSERIAL, &ss);

	}

	cfsetispeed(&(self->tio), standard_baud_rate);
	cfsetispeed(&(self->tio), standard_baud_rate);

	/* Wait until there is at least 1 byte and
	 * have an indefinite timeout
	 */
	self->tio.c_cc[VMIN] = 1;
	self->tio.c_cc[VTIME] = 0;

	tcflush(self->fd, TCIFLUSH);
	tcsetattr(self->fd, TCSANOW, &(self->tio));

	return 0;

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movl %edx, %ebp
movq %rdi, %rbx
movq %rsi, %rdi
movl $0x102, %esi            # imm = 0x102
xorl %eax, %eax
callq 0x10e0
movl %eax, (%rbx)
testl %eax, %eax
js 0x1509
leaq 0x4(%rbx), %r14
movl %eax, %edi
movq %r14, %rsi
callq 0x10c0
movapd 0xcba(%rip), %xmm0      # 0x2100
movupd %xmm0, 0x4(%rbx)
cmpl $0x32, %ebp
je 0x1587
cmpl $0x38400, %ebp          # imm = 0x38400
je 0x1580
cmpl $0x6e, %ebp
je 0x1593
cmpl $0x86, %ebp
je 0x153b
cmpl $0x96, %ebp
je 0x1574
cmpl $0xc8, %ebp
je 0x158f
cmpl $0x12c, %ebp            # imm = 0x12C
je 0x1521
cmpl $0x258, %ebp            # imm = 0x258
je 0x158b
cmpl $0x4b0, %ebp            # imm = 0x4B0
je 0x153f
cmpl $0x708, %ebp            # imm = 0x708
je 0x157c
cmpl $0x960, %ebp            # imm = 0x960
je 0x151d
cmpl $0x12c0, %ebp           # imm = 0x12C0
je 0x1525
cmpl $0x2580, %ebp           # imm = 0x2580
je 0x1578
cmpl $0x4b00, %ebp           # imm = 0x4B00
je 0x1537
cmpl $0x9600, %ebp           # imm = 0x9600
je 0x1543
cmpl $0xe100, %ebp           # imm = 0xE100
je 0x1529
cmpl $0x1c200, %ebp          # imm = 0x1C200
je 0x1530
cmpl $0x4b, %ebp
jne 0x15d8
pushq $0x2
jmp 0x1595
leaq 0xc24(%rip), %rdi       # 0x2134
callq 0x1100
pushq $-0x1
popq %rbp
jmp 0x15c7
pushq $0xb
jmp 0x1595
pushq $0x7
jmp 0x1595
pushq $0xc
jmp 0x1595
movl $0x1001, %ebp           # imm = 0x1001
jmp 0x1596
movl $0x1002, %ebp           # imm = 0x1002
jmp 0x1596
pushq $0xe
jmp 0x1595
pushq $0x4
jmp 0x1595
pushq $0x9
jmp 0x1595
movl (%rbx), %edi
movq %rsp, %r15
movl $0x541e, %esi           # imm = 0x541E
movq %r15, %rdx
xorl %eax, %eax
callq 0x1050
andl $0xffffefcf, 0x10(%r15) # imm = 0xFFFFEFCF
movl (%rbx), %edi
movl $0x541f, %esi           # imm = 0x541F
movq %r15, %rdx
xorl %eax, %eax
callq 0x1050
pushq $0xf
jmp 0x1595
pushq $0x5
jmp 0x1595
pushq $0xd
jmp 0x1595
pushq $0xa
jmp 0x1595
movl $0x1003, %ebp           # imm = 0x1003
jmp 0x1596
pushq $0x1
jmp 0x1595
pushq $0x8
jmp 0x1595
pushq $0x6
jmp 0x1595
pushq $0x3
popq %rbp
movq %r14, %rdi
movl %ebp, %esi
callq 0x10f0
movq %r14, %rdi
movl %ebp, %esi
callq 0x10f0
movw $0x100, 0x1a(%rbx)      # imm = 0x100
movl (%rbx), %edi
xorl %ebp, %ebp
xorl %esi, %esi
callq 0x1040
movl (%rbx), %edi
xorl %esi, %esi
movq %r14, %rdx
callq 0x10d0
movl %ebp, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl (%rbx), %edi
movq %rsp, %r15
movl $0x541e, %esi           # imm = 0x541E
movq %r15, %rdx
xorl %eax, %eax
callq 0x1050
movl $0xffffefcf, %eax       # imm = 0xFFFFEFCF
andl 0x10(%r15), %eax
orl $0x30, %eax
movl %eax, 0x10(%r15)
movl 0x1c(%r15), %eax
movl %ebp, %ecx
shrl %ecx
addl %eax, %ecx
cvtsi2ss %rcx, %xmm0
movl %ebp, %ecx
cvtsi2ss %rcx, %xmm1
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
addsd 0xafe(%rip), %xmm0      # 0x2120
cvttsd2si %xmm0, %ecx
movl %ecx, 0x18(%r15)
cltd
idivl %ecx
movl %eax, %r12d
movq 0x29c1(%rip), %r13      # 0x3ff8
movq (%r13), %rdi
leaq 0xb06(%rip), %rsi       # 0x2148
movl %eax, %edx
xorl %eax, %eax
callq 0x10a0
movl %ebp, %eax
subl %r12d, %eax
cvtsi2ss %rax, %xmm0
addl %ebp, %r12d
cvtsi2ss %r12, %xmm1
mulss 0xacb(%rip), %xmm1      # 0x2130
divss %xmm1, %xmm0
andps 0xaa0(%rip), %xmm0      # 0x2110
movq (%r13), %rdi
cvtss2sd %xmm0, %xmm0
mulsd 0xaa8(%rip), %xmm0      # 0x2128
leaq 0xadd(%rip), %rsi       # 0x2164
movb $0x1, %al
callq 0x10a0
jmp 0x155f