Serenity Operating System
1/*
2 * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/Singleton.h>
8#include <Kernel/Bus/PCI/API.h>
9#include <Kernel/Bus/USB/UHCI/UHCIController.h>
10#include <Kernel/Bus/USB/USBManagement.h>
11#include <Kernel/CommandLine.h>
12#include <Kernel/FileSystem/SysFS/Subsystems/Bus/USB/BusDirectory.h>
13#include <Kernel/Sections.h>
14
15namespace Kernel::USB {
16
17static Singleton<USBManagement> s_the;
18READONLY_AFTER_INIT bool s_initialized_sys_fs_directory = false;
19
20UNMAP_AFTER_INIT USBManagement::USBManagement()
21{
22 enumerate_controllers();
23}
24
25UNMAP_AFTER_INIT void USBManagement::enumerate_controllers()
26{
27 if (kernel_command_line().disable_usb())
28 return;
29
30 MUST(PCI::enumerate([this](PCI::DeviceIdentifier const& device_identifier) {
31 if (!(device_identifier.class_code().value() == 0xc && device_identifier.subclass_code().value() == 0x3))
32 return;
33 if (device_identifier.prog_if().value() == 0x0) {
34 if (kernel_command_line().disable_uhci_controller())
35 return;
36
37 if (auto uhci_controller_or_error = UHCIController::try_to_initialize(device_identifier); !uhci_controller_or_error.is_error())
38 m_controllers.append(uhci_controller_or_error.release_value());
39
40 return;
41 }
42
43 if (device_identifier.prog_if().value() == 0x10) {
44 dmesgln("USBManagement: OHCI controller found at {} is not currently supported.", device_identifier.address());
45 return;
46 }
47
48 if (device_identifier.prog_if().value() == 0x20) {
49 dmesgln("USBManagement: EHCI controller found at {} is not currently supported.", device_identifier.address());
50 return;
51 }
52
53 if (device_identifier.prog_if().value() == 0x30) {
54 dmesgln("USBManagement: xHCI controller found at {} is not currently supported.", device_identifier.address());
55 return;
56 }
57
58 dmesgln("USBManagement: Unknown/unsupported controller at {} with programming interface 0x{:02x}", device_identifier.address(), device_identifier.prog_if().value());
59 }));
60}
61
62bool USBManagement::initialized()
63{
64 return s_the.is_initialized();
65}
66
67UNMAP_AFTER_INIT void USBManagement::initialize()
68{
69 if (!s_initialized_sys_fs_directory) {
70 SysFSUSBBusDirectory::initialize();
71 s_initialized_sys_fs_directory = true;
72 }
73
74 s_the.ensure_instance();
75}
76
77USBManagement& USBManagement::the()
78{
79 return *s_the;
80}
81
82}