6static const char*
TAG =
"UsbManager";
48uint8_t UsbManager::activeHidCount()
const {
50 for (
const auto& entry : entries_) {
51 if (entry.active) count++;
63 return activeHidCount() < MAX_ACTIVE_HID;
73 return def.hasOut ? 2 : 1;
80uint8_t UsbManager::endpointsInUse()
const {
81 uint8_t n = CDC_ENDPOINTS;
82 for (
const auto& entry : entries_) {
83 if (entry.active) n += interfaceEndpoints(entry.def);
85 if (mscActive_) n += MSC_ENDPOINTS;
98 const uint8_t idx =
static_cast<uint8_t
>(type);
99 if (idx >= (
sizeof(entries_) /
sizeof(entries_[0])))
return false;
101 auto& entry = entries_[idx];
103 if (entry.owner && moduleName && strcmp(entry.owner, moduleName) == 0) {
106 LOG_W(
TAG,
"Interface %d already owned by %s", idx, entry.owner ? entry.owner :
"?");
110 if (!canActivate(type)) {
111 LOG_W(
TAG,
"HID interface limit reached (max %d)", MAX_ACTIVE_HID);
115 if (endpointsInUse() + interfaceEndpoints(def) > MAX_ENDPOINTS) {
116 LOG_W(
TAG,
"USB endpoint budget exhausted (have %d/%d, +%d)",
117 endpointsInUse(), MAX_ENDPOINTS, interfaceEndpoints(def));
122 entry.owner = moduleName;
124 activeMask_ |= (1u << idx);
125 LOG_I(
TAG,
"Registered HID interface %d for %s", idx, moduleName ? moduleName :
"?");
136 const uint8_t idx =
static_cast<uint8_t
>(type);
137 if (idx >= (
sizeof(entries_) /
sizeof(entries_[0])))
return;
139 auto& entry = entries_[idx];
140 if (!entry.active)
return;
141 if (entry.owner && moduleName && strcmp(entry.owner, moduleName) != 0) {
142 LOG_W(
TAG,
"Interface %d owned by %s, not %s", idx,
143 entry.owner ? entry.owner :
"?", moduleName ? moduleName :
"?");
147 entry.active =
false;
148 entry.owner =
nullptr;
150 activeMask_ &= ~(1u << idx);
151 LOG_I(
TAG,
"Unregistered HID interface %d", idx);
160 needsReplug_ =
false;
165 const auto& entry = entries_[
static_cast<uint8_t
>(type)];
166 if (!entry.active)
return;
167 defs[count++] = entry.def;
174 bool replug_needed =
false;
176 if (!ok || replug_needed) {
189 if (mscOwner_ && owner && strcmp(mscOwner_, owner) == 0)
return true;
190 LOG_W(
TAG,
"MSC already owned by %s", mscOwner_ ? mscOwner_ :
"?");
193 if (endpointsInUse() + MSC_ENDPOINTS > MAX_ENDPOINTS) {
194 LOG_W(
TAG,
"USB endpoint budget exhausted for MSC (have %d/%d)",
195 endpointsInUse(), MAX_ENDPOINTS);
200 LOG_I(
TAG,
"Registered MSC for %s", owner ? owner :
"?");
210 if (!mscActive_)
return;
211 if (mscOwner_ && owner && strcmp(mscOwner_, owner) != 0) {
212 LOG_W(
TAG,
"MSC owned by %s, not %s", mscOwner_, owner ? owner :
"?");
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_W(tag, fmt,...)
#define LOG_I(tag, fmt,...)
bool init() override
Initializes USB manager service state.
bool registerMassStorage(const char *owner)
Registers the single USB Mass Storage LUN and re-enumerates.
bool registerInterface(UsbHidInterface type, const char *moduleName, const UsbInterfaceSpec &def)
Registers a HID interface request from a module.
bool start() override
Starts USB manager service state.
void unregisterMassStorage(const char *owner)
Unregisters the MSC LUN and re-enumerates (drive disappears).
static UsbManager & instance()
Returns singleton USB manager instance.
void unregisterInterface(UsbHidInterface type, const char *moduleName)
Unregisters a previously registered HID interface.
void stop() override
Stops USB manager service state.
bool applyConfiguration()
Applies current interface set to USB HID stack.
void usb_hid_set_msc(bool active)
Adds or removes the MSC interface and re-enumerates the device.
bool usb_hid_apply_config(const UsbInterfaceDef *defs, size_t count, bool *needs_replug)
Applies the runtime interface configuration and optionally triggers re-enumeration.