// File: /workspace/github_cpp_makefile_star2_O3/DavieV[P]virtual-usb-printer/usb_printer.cc
// Function: UsbPrinter::HandleGetConfigurationDescriptor(int, _USBIP_CMD_SUBMIT const&, _StandardDeviceRequest const&) const
void UsbPrinter::HandleGetConfigurationDescriptor(
    int sockfd, const USBIP_CMD_SUBMIT& usb_request,
    const StandardDeviceRequest& control_request) const {
  printf("HandleGetConfigurationDescriptor %u[%u]\n", control_request.wValue1,
         control_request.wValue0);

  if (control_request.wLength == configuration_descriptor_.bLength) {
    // Only the configuration descriptor itself has been requested.
    printf("Only configuration descriptor requested\n");
    SendUsbRequest(sockfd, usb_request, (char*)&configuration_descriptor_,
                   control_request.wLength, 0);
    return;
  }

  // NOTE: This currently assumes that if the requested length was not just the
  // configuration descriptor then all of the descriptors have been requested.
  // TODO(daviev): If there are any instances where the client requests a size
  // other than the configuration descriptors bLength or wTotalLength then
  // change this function to address it.

  auto buf = std::make_unique<char[]>(control_request.wLength);
  int total = 0;

  // Place the configuration descriptor into the buffer.
  FillBuffer((char*)&configuration_descriptor_,
             configuration_descriptor_.bLength, buf.get() + total);
  total += configuration_descriptor_.bLength;

  // Place each of the corresponding interfaces into the buffer.
  for (int i = 0; i < configuration_descriptor_.bNumInterfaces; ++i) {
    auto interface = interfaces_[i];
    FillBuffer((char*)&interface, interface.bLength, buf.get() + total);
    total += interface.bLength;
    // TODO(daviev): For now this assumes that each interface has 2
    // corresponding endpoints. Update this in the future to support interfaces
    // that have only 1 endpoint.
    for (int j = i * 2; j < (i * 2) + 2; ++j) {
      auto endpoint = endpoints_[j];
      FillBuffer((char*)&endpoint, endpoint.bLength, buf.get() + total);
      total += endpoint.bLength;
    }
  }

  // After filling the buffer with all of the necessary descriptors we can send
  // a response.
  SendUsbRequest(sockfd, usb_request, buf.get(), control_request.wLength, 0);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rcx, %r15
movq %rdx, %rbx
movl %esi, %ebp
movq %rdi, %r12
movzbl 0x3(%rcx), %esi
movzbl 0x2(%rcx), %edx
leaq 0x204f(%rip), %rdi      # 0x4247
xorl %eax, %eax
callq 0x1050
movzwl 0x6(%r15), %r14d
leaq 0x12(%r12), %r13
movzbl 0x12(%r12), %eax
cmpw %ax, %r14w
jne 0x2244
leaq 0x2137(%rip), %rdi      # 0x4353
callq 0x11f0
movzwl 0x6(%r15), %ecx
movl %ebp, %edi
movq %rbx, %rsi
movq %r13, %rdx
xorl %r8d, %r8d
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1c0a
movl %ebp, 0x4(%rsp)
movq %rbx, 0x28(%rsp)
movzwl %ax, %ebx
movq %r14, %rdi
callq 0x1030
movq %rax, %r15
movq %rax, %rdi
xorl %esi, %esi
movq %r14, 0x20(%rsp)
movq %r14, %rdx
callq 0x1110
testl %ebx, %ebx
je 0x227e
movl %ebx, %edx
movq %r15, %rdi
movq %r13, %rsi
callq 0x1130
movzbl 0x16(%r12), %eax
movq %rax, 0x38(%rsp)
testq %rax, %rax
je 0x2336
movq 0x50(%r12), %rax
movq %rax, 0x30(%rsp)
movq 0x68(%r12), %r13
xorl %eax, %eax
leaq 0x8(%rsp), %r12
movq %rax, 0x40(%rsp)
leaq (%rax,%rax,8), %rax
movq 0x30(%rsp), %rdx
movb 0x8(%rdx,%rax), %cl
movb %cl, 0x18(%rsp)
movq (%rdx,%rax), %r14
movq %r14, 0x10(%rsp)
andl $0xff, %r14d
je 0x22e3
movslq %ebx, %rdi
addq %r15, %rdi
movl %r14d, %edx
leaq 0x10(%rsp), %rsi
callq 0x1130
addl %r14d, %ebx
movq $-0xe, %r14
movl 0xe(%r13,%r14), %ebp
movl 0x11(%r13,%r14), %eax
movl %eax, 0xb(%rsp)
movl %ebp, 0x8(%rsp)
andl $0xff, %ebp
je 0x2317
movslq %ebx, %rdi
addq %r15, %rdi
movl %ebp, %edx
movq %r12, %rsi
callq 0x1130
addl %ebp, %ebx
addq $0x7, %r14
jne 0x22ed
movq 0x40(%rsp), %rax
incq %rax
addq $0xe, %r13
cmpq 0x38(%rsp), %rax
jne 0x22a8
movl 0x4(%rsp), %edi
movq 0x28(%rsp), %rsi
movq %r15, %rdx
movq 0x20(%rsp), %rcx
xorl %r8d, %r8d
callq 0x1c0a
movq %r15, %rdi
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x11b0
movq %rax, %rbx
movq %r15, %rdi
callq 0x11b0
movq %rbx, %rdi
callq 0x1220