USBDevice.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/OwnPtr.h>
  7. #include <AK/String.h>
  8. #include <AK/Types.h>
  9. #include <AK/Vector.h>
  10. #include <Kernel/Bus/USB/USBController.h>
  11. #include <Kernel/Bus/USB/USBDescriptors.h>
  12. #include <Kernel/Bus/USB/USBDevice.h>
  13. #include <Kernel/Bus/USB/USBRequest.h>
  14. #include <Kernel/StdLib.h>
  15. namespace Kernel::USB {
  16. KResultOr<NonnullRefPtr<Device>> Device::try_create(USBController const& controller, u8 port, DeviceSpeed speed)
  17. {
  18. auto pipe_or_error = Pipe::try_create_pipe(controller, Pipe::Type::Control, Pipe::Direction::Bidirectional, 0, 8, 0);
  19. if (pipe_or_error.is_error())
  20. return pipe_or_error.error();
  21. auto device = try_make_ref_counted<Device>(controller, port, speed, pipe_or_error.release_value());
  22. if (!device)
  23. return ENOMEM;
  24. auto enumerate_result = device->enumerate_device();
  25. if (enumerate_result.is_error())
  26. return enumerate_result;
  27. return device.release_nonnull();
  28. }
  29. Device::Device(USBController const& controller, u8 port, DeviceSpeed speed, NonnullOwnPtr<Pipe> default_pipe)
  30. : m_device_port(port)
  31. , m_device_speed(speed)
  32. , m_address(0)
  33. , m_controller(controller)
  34. , m_default_pipe(move(default_pipe))
  35. {
  36. }
  37. Device::Device(NonnullRefPtr<USBController> controller, u8 address, u8 port, DeviceSpeed speed, NonnullOwnPtr<Pipe> default_pipe)
  38. : m_device_port(port)
  39. , m_device_speed(speed)
  40. , m_address(address)
  41. , m_controller(controller)
  42. , m_default_pipe(move(default_pipe))
  43. {
  44. }
  45. Device::Device(Device const& device, NonnullOwnPtr<Pipe> default_pipe)
  46. : m_device_port(device.port())
  47. , m_device_speed(device.speed())
  48. , m_address(device.address())
  49. , m_device_descriptor(device.device_descriptor())
  50. , m_controller(device.controller())
  51. , m_default_pipe(move(default_pipe))
  52. {
  53. }
  54. Device::~Device()
  55. {
  56. }
  57. KResult Device::enumerate_device()
  58. {
  59. USBDeviceDescriptor dev_descriptor {};
  60. // Send 8-bytes to get at least the `max_packet_size` from the device
  61. constexpr u8 short_device_descriptor_length = 8;
  62. auto transfer_length_or_error = m_default_pipe->control_transfer(USB_REQUEST_TRANSFER_DIRECTION_DEVICE_TO_HOST, USB_REQUEST_GET_DESCRIPTOR, (DESCRIPTOR_TYPE_DEVICE << 8), 0, short_device_descriptor_length, &dev_descriptor);
  63. if (transfer_length_or_error.is_error())
  64. return transfer_length_or_error.error();
  65. auto transfer_length = transfer_length_or_error.release_value();
  66. // FIXME: This be "not equal to" instead of "less than", but control transfers report a higher transfer length than expected.
  67. if (transfer_length < short_device_descriptor_length) {
  68. dbgln("USB Device: Not enough bytes for short device descriptor. Expected {}, got {}.", short_device_descriptor_length, transfer_length);
  69. return EIO;
  70. }
  71. if constexpr (USB_DEBUG) {
  72. dbgln("USB Short Device Descriptor:");
  73. dbgln("Descriptor length: {}", dev_descriptor.descriptor_header.length);
  74. dbgln("Descriptor type: {}", dev_descriptor.descriptor_header.descriptor_type);
  75. dbgln("Device Class: {:02x}", dev_descriptor.device_class);
  76. dbgln("Device Sub-Class: {:02x}", dev_descriptor.device_sub_class);
  77. dbgln("Device Protocol: {:02x}", dev_descriptor.device_protocol);
  78. dbgln("Max Packet Size: {:02x} bytes", dev_descriptor.max_packet_size);
  79. }
  80. // Ensure that this is actually a valid device descriptor...
  81. VERIFY(dev_descriptor.descriptor_header.descriptor_type == DESCRIPTOR_TYPE_DEVICE);
  82. m_default_pipe->set_max_packet_size(dev_descriptor.max_packet_size);
  83. transfer_length_or_error = m_default_pipe->control_transfer(USB_REQUEST_TRANSFER_DIRECTION_DEVICE_TO_HOST, USB_REQUEST_GET_DESCRIPTOR, (DESCRIPTOR_TYPE_DEVICE << 8), 0, sizeof(USBDeviceDescriptor), &dev_descriptor);
  84. if (transfer_length_or_error.is_error())
  85. return transfer_length_or_error.error();
  86. transfer_length = transfer_length_or_error.release_value();
  87. // FIXME: This be "not equal to" instead of "less than", but control transfers report a higher transfer length than expected.
  88. if (transfer_length < sizeof(USBDeviceDescriptor)) {
  89. dbgln("USB Device: Unexpected device descriptor length. Expected {}, got {}.", sizeof(USBDeviceDescriptor), transfer_length);
  90. return EIO;
  91. }
  92. // Ensure that this is actually a valid device descriptor...
  93. VERIFY(dev_descriptor.descriptor_header.descriptor_type == DESCRIPTOR_TYPE_DEVICE);
  94. if constexpr (USB_DEBUG) {
  95. dbgln("USB Device Descriptor for {:04x}:{:04x}", dev_descriptor.vendor_id, dev_descriptor.product_id);
  96. dbgln("Device Class: {:02x}", dev_descriptor.device_class);
  97. dbgln("Device Sub-Class: {:02x}", dev_descriptor.device_sub_class);
  98. dbgln("Device Protocol: {:02x}", dev_descriptor.device_protocol);
  99. dbgln("Max Packet Size: {:02x} bytes", dev_descriptor.max_packet_size);
  100. dbgln("Number of configurations: {:02x}", dev_descriptor.num_configurations);
  101. }
  102. auto new_address = m_controller->allocate_address();
  103. // Attempt to set devices address on the bus
  104. transfer_length_or_error = m_default_pipe->control_transfer(USB_REQUEST_TRANSFER_DIRECTION_HOST_TO_DEVICE, USB_REQUEST_SET_ADDRESS, new_address, 0, 0, nullptr);
  105. if (transfer_length_or_error.is_error())
  106. return transfer_length_or_error.error();
  107. // This has to be set after we send out the "Set Address" request because it might be sent to the root hub.
  108. // The root hub uses the address to intercept requests to itself.
  109. m_address = new_address;
  110. m_default_pipe->set_device_address(new_address);
  111. dbgln_if(USB_DEBUG, "USB Device: Set address to {}", m_address);
  112. memcpy(&m_device_descriptor, &dev_descriptor, sizeof(USBDeviceDescriptor));
  113. return KSuccess;
  114. }
  115. }