fix: move RTL-SDR to userspace
This commit is contained in:
1 parent
b1f1cfe32b
commit
5cd5c2e6be
35 files changed
+1922
-1592
No files matched your search
@@ -10,7 +10,7 @@
|
||||
#include "HidKeyboard.hpp"
|
||||
#include "HidMouse.hpp"
|
||||
#include "MassStorage.hpp"
|
||||
#include "Radio/RtlSdr.hpp"
|
||||
#include "UserUsb.hpp"
|
||||
#include <Pci/Pci.hpp>
|
||||
#include <Terminal/Terminal.hpp>
|
||||
#include <CppLib/Stream.hpp>
|
||||
@@ -167,8 +167,7 @@ namespace Drivers::USB::Xhci {
|
||||
// nesting (a callback invoked from THIS core's PollEvents); a different
|
||||
// core merely polling must not make a process-context transfer skip its
|
||||
// wait -- that returned CC_SUCCESS before the device filled the buffer
|
||||
// (observed as garbled RTL-SDR register reads while the BT firmware
|
||||
// download was polling on another core).
|
||||
// (observed as corrupted USB control reads while another core was polling).
|
||||
static std::atomic<int> g_pollOwnerCpu{-1};
|
||||
|
||||
// Serialises non-nested (waiting) control transfers so only one EP0
|
||||
@@ -198,7 +197,7 @@ namespace Drivers::USB::Xhci {
|
||||
// re-arms the SAME buffer at the ring tail, so the endpoint is never without
|
||||
// a place to DMA. This closes the gap that single-outstanding bulk IN leaves
|
||||
// between completion and re-arm, during which the device FIFO overflows
|
||||
// (the RTL-SDR ~88% sample-drop at 2.048 Msps). PoolCount==0 => the legacy
|
||||
// under sustained high-rate input. PoolCount==0 selects the legacy
|
||||
// single-buffer path above (used by Bluetooth ACL), unchanged.
|
||||
static constexpr uint32_t BULK_IN_POOL_MAX = 16;
|
||||
static uint8_t* g_bulkInPool[MAX_SLOTS + 1][BULK_IN_POOL_MAX] = {};
|
||||
@@ -206,6 +205,7 @@ namespace Drivers::USB::Xhci {
|
||||
static uint32_t g_bulkInPoolCount[MAX_SLOTS + 1] = {}; // outstanding URBs (0=off)
|
||||
static uint32_t g_bulkInPoolHead[MAX_SLOTS + 1] = {}; // next buffer to complete
|
||||
static uint32_t g_bulkInPoolXferLen[MAX_SLOTS + 1] = {}; // bytes per transfer
|
||||
static kcp::Spinlock g_bulkInPoolLocks[MAX_SLOTS + 1];
|
||||
|
||||
// Transfer callbacks for non-HID class drivers (per slot)
|
||||
static TransferCallback g_transferCallbacks[MAX_SLOTS + 1] = {};
|
||||
@@ -590,15 +590,19 @@ namespace Drivers::USB::Xhci {
|
||||
// buffer is safe -- it will not be DMA'd into again
|
||||
// until the other PoolCount-1 transfers ahead of it
|
||||
// complete (~PoolCount ms of slack).
|
||||
uint32_t i = g_bulkInPoolHead[slotId];
|
||||
uint32_t reqLen = g_bulkInPoolXferLen[slotId];
|
||||
uint32_t len = (residual < reqLen) ? (reqLen - residual) : 0;
|
||||
g_transferCallbacks[slotId](slotId, epDci,
|
||||
g_bulkInPool[slotId][i], len, completionCode);
|
||||
QueueBulkInTransfer(slotId, g_bulkInPool[slotId][i],
|
||||
g_bulkInPoolPhys[slotId][i], reqLen);
|
||||
g_bulkInPoolHead[slotId] =
|
||||
(i + 1) % g_bulkInPoolCount[slotId];
|
||||
g_bulkInPoolLocks[slotId].Acquire();
|
||||
uint32_t poolCount = g_bulkInPoolCount[slotId];
|
||||
if (poolCount > 0) {
|
||||
uint32_t i = g_bulkInPoolHead[slotId];
|
||||
uint32_t reqLen = g_bulkInPoolXferLen[slotId];
|
||||
uint32_t len = (residual < reqLen) ? (reqLen - residual) : 0;
|
||||
g_transferCallbacks[slotId](slotId, epDci,
|
||||
g_bulkInPool[slotId][i], len, completionCode);
|
||||
QueueBulkInTransfer(slotId, g_bulkInPool[slotId][i],
|
||||
g_bulkInPoolPhys[slotId][i], reqLen);
|
||||
g_bulkInPoolHead[slotId] = (i + 1) % poolCount;
|
||||
}
|
||||
g_bulkInPoolLocks[slotId].Release();
|
||||
} else if (epDci == bulkInDci && g_transferCallbacks[slotId]) {
|
||||
// Bulk IN — dispatch via registered callback.
|
||||
// len = actually-transferred bytes (requested -
|
||||
@@ -1149,13 +1153,18 @@ namespace Drivers::USB::Xhci {
|
||||
// single-buffer start relies on.
|
||||
void PrimeBulkInStream(uint8_t slotId) {
|
||||
if (slotId == 0 || slotId > MAX_SLOTS || !g_devices[slotId].Active) return;
|
||||
g_bulkInPoolLocks[slotId].Acquire();
|
||||
uint32_t n = g_bulkInPoolCount[slotId];
|
||||
if (n == 0) return;
|
||||
if (n == 0) {
|
||||
g_bulkInPoolLocks[slotId].Release();
|
||||
return;
|
||||
}
|
||||
g_bulkInPoolHead[slotId] = 0;
|
||||
uint32_t len = g_bulkInPoolXferLen[slotId];
|
||||
for (uint32_t i = 0; i < n; i++)
|
||||
QueueBulkInTransfer(slotId, g_bulkInPool[slotId][i],
|
||||
g_bulkInPoolPhys[slotId][i], len);
|
||||
g_bulkInPoolLocks[slotId].Release();
|
||||
}
|
||||
|
||||
void StartBulkInStream(uint8_t slotId, uint32_t xferLen, uint32_t numBuffers) {
|
||||
@@ -1195,15 +1204,27 @@ namespace Drivers::USB::Xhci {
|
||||
for (uint32_t i = 0; i < numBuffers; i++)
|
||||
QueueBulkInTransfer(slotId, g_bulkInPool[slotId][i],
|
||||
g_bulkInPoolPhys[slotId][i], xferLen);
|
||||
g_bulkInPoolLocks[slotId].Acquire();
|
||||
g_bulkInPoolCount[slotId] = numBuffers;
|
||||
g_bulkInPoolLocks[slotId].Release();
|
||||
}
|
||||
|
||||
bool IsBulkInStreamActive(uint8_t slotId) {
|
||||
if (slotId == 0 || slotId > MAX_SLOTS) return false;
|
||||
g_bulkInPoolLocks[slotId].Acquire();
|
||||
bool active = g_bulkInPoolCount[slotId] != 0;
|
||||
g_bulkInPoolLocks[slotId].Release();
|
||||
return active;
|
||||
}
|
||||
|
||||
void StopBulkInStream(uint8_t slotId) {
|
||||
if (slotId == 0 || slotId > MAX_SLOTS) return;
|
||||
// Disarm the rotation; any late completion now takes the (no-op for SDR)
|
||||
// legacy path and is not re-armed. Buffers are retained for reuse.
|
||||
g_bulkInPoolLocks[slotId].Acquire();
|
||||
bool wasArmed = g_bulkInPoolCount[slotId] != 0;
|
||||
g_bulkInPoolCount[slotId] = 0;
|
||||
g_bulkInPoolLocks[slotId].Release();
|
||||
if (!wasArmed) return;
|
||||
|
||||
// Flush the up-to-PoolCount TRBs still pending on the ring: Stop
|
||||
@@ -1437,9 +1458,7 @@ namespace Drivers::USB::Xhci {
|
||||
}
|
||||
|
||||
static void UnregisterClassDriver(uint8_t slotId, const UsbDeviceInfo& dev) {
|
||||
if (Radio::IsRtlSdr(dev.VendorId, dev.ProductId)) {
|
||||
Radio::UnregisterDevice(slotId);
|
||||
} else if (dev.InterfaceClass == UsbDevice::CLASS_MASS_STORAGE) {
|
||||
if (dev.InterfaceClass == UsbDevice::CLASS_MASS_STORAGE) {
|
||||
MassStorage::UnregisterDevice(slotId);
|
||||
} else if (dev.InterfaceClass == UsbDevice::CLASS_HID &&
|
||||
dev.InterfaceProtocol == UsbDevice::PROTOCOL_KEYBOARD) {
|
||||
@@ -1559,6 +1578,7 @@ namespace Drivers::USB::Xhci {
|
||||
// Device disconnected — deactivate its slot
|
||||
for (uint8_t s = 1; s <= MAX_SLOTS; s++) {
|
||||
if (g_devices[s].Active && g_devices[s].PortId == port + 1) {
|
||||
UserUsb::DeviceDisconnected(s);
|
||||
UnregisterClassDriver(s, g_devices[s]);
|
||||
g_devices[s].Active = false;
|
||||
g_transferCallbacks[s] = nullptr;
|
||||
|
||||
Reference in new issue
Block a user