// File: /workspace/github_cpp_makefile_star2_O2/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 $0x58, %rsp
movq %rcx, %r12
movq %rdx, %r14
movl %esi, %r15d
movq %rdi, %rbx
movzbl 0x3(%rcx), %esi
movzbl 0x2(%rcx), %edx
leaq 0x13f8(%rip), %rdi      # 0x3247
xorl %eax, %eax
callq 0x1050
movzwl 0x6(%r12), %ebp
leaq 0x12(%rbx), %r13
movzbl 0x12(%rbx), %eax
cmpw %ax, %bp
jne 0x1e9a
leaq 0x14e3(%rip), %rdi      # 0x3353
callq 0x11e0
movzwl 0x6(%r12), %ecx
movl %r15d, %edi
movq %r14, %rsi
movq %r13, %rdx
xorl %r8d, %r8d
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x18dc
movq %r12, 0x30(%rsp)
movl %r15d, 0xc(%rsp)
movq %r14, 0x38(%rsp)
movzwl %ax, %r12d
movq %rbp, %rdi
callq 0x1030
movq %rax, %r15
xorl %r14d, %r14d
movq %rax, %rdi
xorl %esi, %esi
movq %rbp, %rdx
callq 0x1110
movq %r15, 0x18(%rsp)
movq %r13, %rdi
movl %r12d, %esi
movq %r15, %rdx
callq 0x20a6
movzbl 0x16(%rbx), %eax
movq %rax, 0x48(%rsp)
movq 0x50(%rbx), %rax
movq %rax, 0x40(%rsp)
movq 0x68(%rbx), %r13
leaq 0x10(%rsp), %rbx
cmpq 0x48(%rsp), %r14
jae 0x1f82
movq %r14, 0x50(%rsp)
leaq (%r14,%r14,8), %rax
movq 0x40(%rsp), %rdx
movb 0x8(%rdx,%rax), %cl
movb %cl, 0x28(%rsp)
movq (%rdx,%rax), %rax
movq %rax, 0x20(%rsp)
movzbl %al, %ebp
movslq %r12d, %r12
leaq (%r15,%r12), %rdx
leaq 0x20(%rsp), %rdi
movl %ebp, %esi
callq 0x20a6
addl %ebp, %r12d
xorl %r14d, %r14d
cmpq $0xe, %r14
je 0x1f71
movl (%r13,%r14), %eax
movl 0x3(%r13,%r14), %ecx
movl %ecx, 0x13(%rsp)
movl %eax, 0x10(%rsp)
movzbl %al, %ebp
movslq %r12d, %r12
leaq (%r15,%r12), %rdx
movq %rbx, %rdi
movl %ebp, %esi
callq 0x20a6
addl %ebp, %r12d
addq $0x7, %r14
jmp 0x1f3c
movq 0x50(%rsp), %r14
incq %r14
addq $0xe, %r13
jmp 0x1ef6
movq 0x30(%rsp), %rax
movzwl 0x6(%rax), %ecx
movl 0xc(%rsp), %edi
movq 0x38(%rsp), %rsi
movq %r15, %rdx
xorl %r8d, %r8d
callq 0x18dc
leaq 0x18(%rsp), %rdi
callq 0x21d8
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x21d8
movq %rbx, %rdi
callq 0x1210
nop