fix: move RTL-SDR to userspace
This commit is contained in:
@@ -10,7 +10,6 @@
|
||||
#include "HidMouse.hpp"
|
||||
#include "MassStorage.hpp"
|
||||
#include "Bluetooth/Bluetooth.hpp"
|
||||
#include "Radio/RtlSdr.hpp"
|
||||
#include <Terminal/Terminal.hpp>
|
||||
#include <CppLib/Stream.hpp>
|
||||
#include <Memory/HHDM.hpp>
|
||||
@@ -351,11 +350,6 @@ namespace Drivers::USB::UsbDevice {
|
||||
bool foundBulkOut = false;
|
||||
uint16_t hidReportDescLen = 0;
|
||||
|
||||
// RTL-SDR dongles are vendor-class (0xFF) devices identified by VID:PID.
|
||||
// They expose a single bulk-IN endpoint that streams raw I/Q samples;
|
||||
// treat them like the other bulk-capable class drivers below.
|
||||
bool foundRadio = Drivers::USB::Radio::IsRtlSdr(devDesc.idVendor, devDesc.idProduct);
|
||||
|
||||
while (offset + 2 <= totalLen) {
|
||||
uint8_t len = cfgBuf[offset];
|
||||
uint8_t type = cfgBuf[offset + 1];
|
||||
@@ -423,8 +417,8 @@ namespace Drivers::USB::UsbDevice {
|
||||
foundEp = true;
|
||||
}
|
||||
|
||||
// Bluetooth, Mass Storage and RTL-SDR bulk endpoints
|
||||
if (foundBt || currentMsc || foundRadio) {
|
||||
// Bulk endpoints needed by in-kernel Bluetooth and storage drivers.
|
||||
if (foundBt || currentMsc) {
|
||||
if (isIn && xferType == EP_XFER_INTERRUPT && !foundEp) {
|
||||
// HCI event pipe (interrupt IN)
|
||||
dev->InterruptEpNum = ep->bEndpointAddress & 0x0F;
|
||||
@@ -457,6 +451,51 @@ namespace Drivers::USB::UsbDevice {
|
||||
foundBt = true;
|
||||
}
|
||||
|
||||
// No in-kernel class driver recognized this device. Preserve the first
|
||||
// interface and its bulk endpoints so a userspace driver can claim it.
|
||||
// The xHCI slot model currently stores one interface; a future model
|
||||
// can retain every alternate/interface without changing the userspace
|
||||
// claim ABI, which already names the interface number explicitly.
|
||||
bool knownInterface = foundBt || foundMsc ||
|
||||
dev->InterfaceClass == CLASS_HID;
|
||||
if (!knownInterface) {
|
||||
bool inFirstInterface = false;
|
||||
bool haveFirstInterface = false;
|
||||
offset = 0;
|
||||
while (offset + 2 <= totalLen) {
|
||||
uint8_t len = cfgBuf[offset];
|
||||
uint8_t type = cfgBuf[offset + 1];
|
||||
if (len == 0 || offset + len > totalLen) break;
|
||||
|
||||
if (type == DESC_INTERFACE &&
|
||||
offset + sizeof(InterfaceDescriptor) <= totalLen) {
|
||||
if (haveFirstInterface) break;
|
||||
auto* iface = (InterfaceDescriptor*)&cfgBuf[offset];
|
||||
dev->InterfaceClass = iface->bInterfaceClass;
|
||||
dev->InterfaceSubClass = iface->bInterfaceSubClass;
|
||||
dev->InterfaceProtocol = iface->bInterfaceProtocol;
|
||||
dev->InterfaceNumber = iface->bInterfaceNumber;
|
||||
haveFirstInterface = true;
|
||||
inFirstInterface = true;
|
||||
} else if (inFirstInterface && type == DESC_ENDPOINT &&
|
||||
offset + sizeof(EndpointDescriptor) <= totalLen) {
|
||||
auto* ep = (EndpointDescriptor*)&cfgBuf[offset];
|
||||
uint8_t xferType = ep->bmAttributes & EP_XFER_TYPE_MASK;
|
||||
bool isIn = (ep->bEndpointAddress & EP_DIR_IN) != 0;
|
||||
if (xferType == EP_XFER_BULK && isIn && !foundBulkIn) {
|
||||
dev->BulkInEpNum = ep->bEndpointAddress & 0x0F;
|
||||
dev->BulkInMaxPacket = ep->wMaxPacketSize & 0x7FF;
|
||||
foundBulkIn = true;
|
||||
} else if (xferType == EP_XFER_BULK && !isIn && !foundBulkOut) {
|
||||
dev->BulkOutEpNum = ep->bEndpointAddress & 0x0F;
|
||||
dev->BulkOutMaxPacket = ep->wMaxPacketSize & 0x7FF;
|
||||
foundBulkOut = true;
|
||||
}
|
||||
}
|
||||
offset += len;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Step 8: SET_CONFIGURATION
|
||||
// -----------------------------------------------------------------
|
||||
@@ -657,15 +696,20 @@ namespace Drivers::USB::UsbDevice {
|
||||
// -----------------------------------------------------------------
|
||||
// Step 13: Register with the appropriate class driver
|
||||
// -----------------------------------------------------------------
|
||||
if (dev->InterfaceClass == CLASS_HID && dev->InterfaceProtocol == PROTOCOL_KEYBOARD) {
|
||||
if (foundEp && dev->InterfaceClass == CLASS_HID &&
|
||||
dev->InterfaceProtocol == PROTOCOL_KEYBOARD) {
|
||||
dev->KernelDriverBound = true;
|
||||
HidKeyboard::RegisterDevice(slotId);
|
||||
KernelLogStream(OK, "USB") << "Slot " << (uint64_t)slotId << ": HID Boot Keyboard";
|
||||
} else if (dev->InterfaceClass == CLASS_HID && dev->InterfaceProtocol == PROTOCOL_MOUSE) {
|
||||
} else if (foundEp && dev->InterfaceClass == CLASS_HID &&
|
||||
dev->InterfaceProtocol == PROTOCOL_MOUSE) {
|
||||
dev->KernelDriverBound = true;
|
||||
HidMouse::RegisterDevice(slotId);
|
||||
KernelLogStream(OK, "USB") << "Slot " << (uint64_t)slotId << ": HID Boot Mouse";
|
||||
} else if (dev->InterfaceClass == CLASS_WIRELESS &&
|
||||
dev->InterfaceSubClass == SUBCLASS_RF &&
|
||||
dev->InterfaceProtocol == PROTOCOL_BLUETOOTH) {
|
||||
dev->KernelDriverBound = true;
|
||||
Bluetooth::RegisterAdapter(slotId);
|
||||
KernelLogStream(OK, "USB") << "Slot " << (uint64_t)slotId << ": Bluetooth Adapter"
|
||||
<< " VID:" << base::hex << (uint64_t)dev->VendorId
|
||||
@@ -674,15 +718,10 @@ namespace Drivers::USB::UsbDevice {
|
||||
dev->InterfaceSubClass == SUBCLASS_SCSI &&
|
||||
dev->InterfaceProtocol == PROTOCOL_BULK_ONLY &&
|
||||
foundMsc && foundBulkIn && foundBulkOut) {
|
||||
dev->KernelDriverBound = true;
|
||||
MassStorage::RegisterDevice(slotId);
|
||||
KernelLogStream(OK, "USB") << "Slot " << (uint64_t)slotId
|
||||
<< ": USB Mass Storage";
|
||||
} else if (foundRadio && foundBulkIn) {
|
||||
Drivers::USB::Radio::RegisterDevice(slotId);
|
||||
KernelLogStream(OK, "USB") << "Slot " << (uint64_t)slotId
|
||||
<< ": RTL-SDR receiver"
|
||||
<< " VID:" << base::hex << (uint64_t)dev->VendorId
|
||||
<< " PID:" << (uint64_t)dev->ProductId << base::dec;
|
||||
} else if (foundEp) {
|
||||
KernelLogStream(INFO, "USB") << "Slot " << (uint64_t)slotId
|
||||
<< ": USB device, class=" << (uint64_t)dev->InterfaceClass
|
||||
@@ -692,6 +731,9 @@ namespace Drivers::USB::UsbDevice {
|
||||
<< ": Non-HID device, class=" << (uint64_t)devDesc.bDeviceClass;
|
||||
}
|
||||
|
||||
// Publish to userspace only after endpoint configuration and kernel
|
||||
// class-driver binding decisions are complete.
|
||||
dev->Ready = true;
|
||||
return slotId;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user