This change fixes NuttX’s CMake support when NuttX is embedded
in another project via add_subdirectory(). CMake’s CMAKE_SOURCE_DIR
and CMAKE_BINARY_DIR refer to the outermost project, causing NuttX
to access its .config, generated files, host tools, and build artifacts
in the parent project’s directories. The fix introduces NUTTX_DIR and
NUTTX_BINARY_DIR, based on CMAKE_CURRENT_SOURCE_DIR and
CMAKE_CURRENT_BINARY_DIR, and consistently uses them for NuttX
self-references while preserving existing standalone builds. It fixes
the Kconfig initialization failure reported in #19697 and allows an
embedded sim:nsh build to configure, build, and boot successfully.
The change affects only the CMake build system (not Make or Kconfig
defaults), requires the corresponding nuttx-apps change, and does not
extend add_subdirectory() support to cross-compiled non-sim boards due
to CMake’s toolchain-file limitation.
Fixes#19697.
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Alan Carvalho de Assis <acassis@gmail.com>
HIDKBD_NOGETREPORT reads keyboard reports with DRVR_ASYNCH(), and that
macro is only defined when USBHOST_ASYNCH is set. The option selected
neither, so turning it on by itself fails at the call site with no hint
that a second option was meant to come with it.
Select it. Every in-tree configuration that sets NOGETREPORT already
resolves USBHOST_ASYNCH: ci20:jumbo and sama5d3-xplained:bluetooth
through USBHOST_HUB, and the two linum-stm32h753bi configurations by
setting it directly. No existing build changes.
The two that set it directly no longer can, since a selected symbol is
no longer settable, so savedefconfig drops the line. Their defconfigs
are normalized here to keep them canonical.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
usbhost_destroy() unregisters the keyboard unconditionally, and it runs
for a device that never got as far as being registered as well: an
enumeration that failed part way through, or a device unplugged while it
was still being set up.
The upper half does not tolerate that call. It asserts that the lower
half carries the state keyboard_register() puts there, so a keyboard that
fails to come up takes the system down with an assertion rather than
being cleaned up and forgotten. Seen on a low speed keyboard that
attaches and then does not finish enumerating.
The state the registration leaves behind is what says whether there is
anything to undo, so look at it first.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
Since 00010089b8 uart_writev() takes the data one byte at a time with
uio_copyto() plus uio_advance(). Both of them walk the iovec list and
redo the byte counters for every single byte, so most of the work is
bookkeeping rather than copying. On slow cores this is what limits how
fast the TX buffer can be filled.
Take a pointer to the current iovec segment and read the bytes straight
from it, and move the uio forward once per segment instead of once per
byte. nseg counts only the bytes that really went into the buffer: it
is increased at the end of a loop pass, and that step is skipped when
uart_putxmitchar() fails.
Measured on nRF52840 (Cortex-M4, 64 MHz), 8 MiB write() to a CDC/ACM
port: 223 KB/s to 481 KB/s.
Signed-off-by: raiden00pl <raiden00@railab.me>
Assisted-by: Claude Code
Add Kconfig, Make.defs, and CMakeLists.txt entries for the ondemand governor so it can be enabled via CONFIG_DEVFREQ_GOV_ONDEMAND.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
When CONFIG_LIBC_BACKTRACE_DEPTH is not set or <= 0, backtrace_get()
is a macro that always sets depth to 0, making the for-loop body
unreachable (Coverity CID 8405332 DEADCODE).
Wrap backtrace_get() call, the loop, and related variable declarations
with #if CONFIG_LIBC_BACKTRACE_DEPTH > 0 to eliminate the dead code
and avoid unused variable warnings.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
QOS_REQ_MIN should return the highest value among all min requests
(most restrictive lower bound), but plist_first returns the lowest.
QOS_REQ_MAX should return the lowest value among all max requests
(most restrictive upper bound), but plist_last returns the highest.
This caused qos constraints to be ineffective. For example, two
requests (32, 208000) and (104000, 104000) would merge to (32, 208000)
instead of the correct (104000, 104000).
Fix by using plist_last for QOS_REQ_MIN and plist_first for QOS_REQ_MAX.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
The cached devfreq->cur may become stale when the hardware frequency is
changed externally (e.g. by another core or governor). This causes
driver_target to incorrectly skip frequency transitions when the target
matches the cached value but differs from the actual hardware frequency.
Use driver->get_frequency() to read the real hardware frequency for the
unchanged check, and sync devfreq->cur on match to keep the cache correct.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
When devfreq_gov_ondemand_stop() is called from idle task context,
work_cancel() is used instead of work_cancel_sync(), which does not
wait for the currently running worker to complete. If
devfreq_gov_ondemand_exit() then frees governor_data, the worker
may still be accessing it, causing a use-after-free crash.
Fix this by:
- Nullifying dev->governor_data under dev->lock in exit before freeing.
- Moving the governor_data read inside dev->lock in the worker and
adding a NULL check to bail out early if data has been freed.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
When multiple QoS requests have no overlapping frequency range (min > max), the previous behavior always clamped to the lower frequency. Add a conflict_policy field to devfreq_driver_s so callers can choose between DEVFREQ_CONFLICT_PREFER_HIGH (default, choose higher freq) and DEVFREQ_CONFLICT_PREFER_LOW (choose lower freq) at registration.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
Add the ability to set frequency constraints via procfs write.
Supported formats:
echo <min>,<max> > /proc/devfreq/<name> - set frequency range
echo 0,0 > /proc/devfreq/<name> - remove constraint
The QoS request is bound to the devfreq device lifetime so that
shell commands like echo (which open, write, close immediately)
work correctly. Leading whitespace in the write buffer is skipped
to handle extra writes from nsh echo (e.g. trailing newline).
Also add write permissions in devfreq_stat() and a procfs_qos
field in devfreq_s guarded by CONFIG_DEVFREQ_PROCFS.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
(cherry picked from commit 70ae195c84f35a4d0b85fcc14187989b60fc0280)
we may call devfreq_find_by_name() in pm_callback, and shouldn't call nxmutex_lock() in idle_loop, so replace mutex to spinlock.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
Add devfreq ondemand governor that scales device frequency based on CPU load. When CPU load exceeds the configured threshold, frequency is set to maximum; otherwise it is scaled proportionally.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
It's better not to use global governor, as modifying one device will cause all devices' governor to be modified.
Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
This commit introduces a devfreq framework to manage device frequency
scaling. The framework includes the following features:
1.devfreq governor
- provide governor ops, including init, start, stop, exit
- default governor, performance & powersave
- customized governor, device can provide governor when register
2.runtime register and unregister
- device can runtime register & unregister, search by name
3.suspend and resume
- suspend and resume frequency scaling
4.notify
- register & unregister notifier callback, notify frequency changes
5.qos support
- simplified QoS, manage multiple freq range request
- including init, add/remove/update request, get value
Signed-off-by: guanyi <guanyi@xiaomi.com>
The RAM log is the natural home for boot messages, yet writing to it
during early boot could crash the system it was meant to describe.
ramlog_addbuf took the critical section on every write, and
enter_critical_section consults the current task; on ports whose
first syslog output happens before the task lists exist, that lookup
walks uninitialized state and faults. The notification path was
worse still, locking a scheduler that did not exist yet.
Guard both. Before the task lists exist, plain interrupt masking
protects the buffer just as well, since there is only one thread of
control; and readers are only notified once there is an operating
system to notify them through. The bytes land in the buffer either
way, so nothing logged before the OS is ready is lost.
Found on the EIC7700X port, which logs from its start routine before
the MMU is up: enabling RAMLOG_SYSLOG there turned the boot into a
silent wedge two characters in. With this change the same
configuration boots and `dmesg` replays the full early history.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
A host that enumerates a device says nothing about it unless the whole of
CONFIG_DEBUG_USB_INFO is on, and then it says a great deal else besides.
The quietest case is the one that matters most: a device no class driver
claims produces no output at all, so a user with an unsupported device
sees exactly what a user with no device sees.
Add CONFIG_USBHOST_ANNOUNCE, reporting each device once, in the shape a
reader is likely to recognise from other systems: where it is, what it is,
its vendor, product and release, and the maker, product and serial number
it reports in its own string descriptors. Those cost a control transfer
each, so they are read only where a report was asked for, and only once
the device is addressed.
The report is made after binding rather than from within it, because a
composite device never reaches the class lookup: usbhost_composite() is
tried first and binds it. Whether a driver claimed the device is tracked
rather than read from the returned status, which the per interface loop
sets to OK whatever happened.
The port is given as the path from the root hub, and the path names the
bus, because a device on the first port of a hub and one on the first port
of a controller are otherwise reported identically. struct
usbhost_roothubport_s gains that bus number for the purpose; a driver that
does not set it reports zero, which is the only bus it has.
Class codes are translated where a name is more use than a number, which
includes the HID boot protocols, so a keyboard is reported as a keyboard.
Default n, so no existing configuration changes.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
cdcacm_sndpacket() runs from task context and from the bulk IN
completion callback, which may be interrupt context. cdcuart_dmasend()
advances the xmit tail non-atomically, so a completion arriving mid
setup re-sends the same region and advances the tail past the head,
re-transmitting a ring of stale data.
c497c5feb0 dropped the critical section that used to cover this.
Restore it with priv->lock held across the setup and EP_SUBMIT; the
submit must stay inside to keep request order. cdcuart_dmasend() now
runs with the lock held, so its own acquisition is removed.
The race needs the writer to keep the ring non-empty across
completions, so it only appears at high sustained write rates. On
nRF52840, 131072-byte writes were received as ~147600 bytes - one extra
CDCACM_TXBUFSIZE of stale data per hit. With this change the host
receives exactly what was sent.
Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
The registry is a singly linked list of static structures, so registering
one of them a second time does not add a second entry: it points that
entry's own link at itself, and the list stops having an end.
Nothing notices while every device that turns up matches something near
the head, because the search returns before it reaches the loop. The
first device that matches nothing at all, meaning anything without a
class driver built in, walks the list to look for it and never comes back,
holding the registry lock. On a multiprocessor the rest of the system
follows it down: every other processor that touches the registry spins,
and on the one measured here that included the console, so a board with a
USB keyboard and no keyboard driver came up and then answered nothing.
Registering twice is easy to do by accident. drivers_initialize() calls
usbhost_drivers_initialize(), which registers every class the
configuration selected, and board code that also registers one, which
many boards do, gets a second call for free.
So look before linking, and treat a repeat registration as the no-op the
caller expected it to be.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
The control transfer trace entry names the controller "HXCI", so a log of
an enumeration reads as though a different controller were involved. One
neighbouring entry also spells the port "RHport" where the rest of the
table spells it "RHPort".
Text only. No trace identifier or argument changes.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
The xHCI driver traces endpoint allocation with XHCI_VTRACE2_EPALLOC, but
that id is in neither the enumeration nor the string table, so the driver
does not compile once verbose tracing is turned on:
usbhost_xhci_pci.c:3285: 'XHCI_VTRACE2_EPALLOC' undeclared
It builds today only because usbhost_vtrace2() collapses to a macro that
discards its arguments unless HAVE_USBHOST_TRACE_VERBOSE is defined, which
is what stops anyone finding this until they go looking for a trace.
Add the id and the string to match, keeping the two tables in step.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
A drive that has been anywhere near another operating system almost
always carries a partition table rather than a filesystem starting at
sector zero, so the single block device this driver registers is usually
the one thing nobody can mount. A USB stick written with an installer
image is a good example: sector zero holds a protective MBR, and what
somebody wants is the EFI system partition several gigabytes in.
Read the table and give each partition a block device of its own beside
the whole drive, named the way every other system names them. The
parsing is already in the tree and understands both MBR and GPT; this
only calls it and registers what it finds.
The whole-drive node stays exactly where it was, for anyone who wants
the raw thing or whose drive really does hold a bare filesystem.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
Add a lower-half driver for the Microchip MCP4451 quad digital
potentiometer. Wiper and terminal control access is provided through
the common potentiometer interface, raw register access through
chip-specific ioctl commands.
Signed-off-by: raiden00pl <raiden00@railab.me>
Assisted-by: Claude Code
Add a common upper-half character driver for digital potentiometers
with a generic set of ioctl commands (wiper set/get, terminal control,
device properties) that can be shared by chip-specific lower halves.
Signed-off-by: raiden00pl <raiden00@railab.me>
Assisted-by: Claude Code
cdcuart_txempty() held priv->lock across EP_POLL(), which re-enters the
class through cdcacm_wrcomplete() and takes that same non-recursive lock,
and then took it a second time to read nwrq. Release it after the
disconnected check, matching cdcuart_txready()/cdcuart_rxavailable().
Fixes: cc067ab199 ("drivers/usbdev/cdcacm.c: Use small lock to protect cdcacm")
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
- The frequency step was truncated to 61 Hz, while it is FXOSC/(2**19),
about 61.035 Hz. The error puts a 915 MHz channel more than 500 kHz away
from the requested frequency, outside its own bandwidth.
- The low or high frequency front end was left at its reset value, so a board
wired for 868 or 915 MHz neither transmitted nor received.
- sx127x_rx_watchdog() is only used by the FSK and OOK path but was compiled
whenever receive support was on, so a LoRa only configuration failed to
build with -Werror. nrf52840-dk:sx127x is such a configuration.
Adds the sync word, the default bandwidth and the default spreading factor as
configuration options, all defaulting to the previous behaviour, and a page
for the driver under components/drivers.
Assisted-by: Claude Code 4.8
Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
Character driver for the Semtech SX1301, the baseband processor of a LoRaWAN
gateway, and the two SX125x radios it drives. Received packets come from
read(), downlinks go to write(), and the channel plan, the start and the stop
are ioctls.
The interface is device independent, in nuttx/wireless/lpwan/lora_gw.h with
the commands in the common WLIOC_GW_* space, so another concentrator driver
can implement it and the same application drive it.
Adds a lorawan_gw configuration for the Nucleo F746ZG with a shield of the
LRWAN_GS_HF1 family. Off by default (LPWAN_SX1301).
Assisted-by: Claude Code 4.8
Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
Add support for ST7123 touchscreen controller (I2C only).
It requires board level init to register a callback, as polling
mode is not supported.
Signed-off-by: Filipe Cavalcanti <filipe.cavalcanti@espressif.com>
Add support for the Microchip 24CW160 (2048B, 32-byte pages, 2-byte
data address)
Signed-off-by: raiden00pl <raiden00@railab.me>
Assisted-by: Claude Code
A fetch() only lower half is always ready, so a subscriber that asked for
a rate with SNIOC_SET_INTERVAL got no pacing from poll(): the descriptor
reported POLLIN on every pass and the application had to sleep out the
period itself. That does not compose. An application polling several
topics reads them sequentially from one thread, so per read sleeps
serialize: three topics at 10 Hz sleeping 100 ms each yield 3.3 Hz per
topic rather than 10.
Pace it where poll() can act on it instead. A subscriber that never
requested a rate stays always ready, and one that did becomes ready once
per its own interval, driven by a watchdog armed in sensor_poll(). This
is the fetch() side of what sensor_is_updated() already does for a
pushing lower half, so both models now honor a requested rate the same
way.
The wdog_s lives in sensor_user_s rather than in the device, so each
subscriber is paced at its own interval instead of at the minimum across
all of them, and the timer only runs while somebody is polling. The
expiry runs in timer context and takes no lock: poll_notify() is safe
from an interrupt handler, and a teardown that raced it has already
cleared fds, which makes both the notify and the re-arm no-ops. Teardown
therefore just cancels the watchdog where it clears fds, and a watchdog
keeps this off the work queue entirely, which a fetch() only sensor
exists to avoid.
sensor_close() needs nothing of its own: poll_setup() holds a reference
on the file for the duration of the poll, so file_close() cannot run
until poll_teardown() has called sensor_poll() with setup false, and that
already cancelled the watchdog.
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
A fetch() only lower half reads the device on demand, so its data is
always available and there is never anything to wait for. The upper half
did not reflect that: poll() only reported POLLIN when the descriptor was
opened O_NONBLOCK, and a blocking read() waited on buffersem, which is
only posted when the lower half drives notify_event from an interrupt of
its own.
A fetch() only sensor with no interrupt therefore never satisfied
poll()/read() at all. This is not hypothetical: in the in tree
nucleo-h563zi:dts configuration CONFIG_STM32_DTS_TRIGGER defaults to 0,
which selects stm32_dts_fetch(), and no CONFIG_STM32_DTS_ITEN_* option is
enabled, so the DTS interrupt never fires. A blocking read() on that
sensor waits forever, even though stm32_dts_fetch() performs a complete
software triggered measurement on its own and needs no interrupt at all.
Applications had to work around this by forcing O_NONBLOCK on the
descriptor themselves, see apache/nuttx-apps#3686.
Drop the O_NONBLOCK special case in both paths: sensor_poll() now always
reports POLLIN for a fetch only sensor and sensor_read() calls fetch()
directly instead of waiting. Update the sensor_ops_s::fetch
documentation, which described the old contract.
With the wait gone, buffersem has no waiters left. Its only two readers
were the ones removed here, both in the fetch path: the wait in
sensor_read() and the nxsem_get_value() in sensor_poll(). The remaining
nxsem_post() calls in sensor_push_event() and sensor_notify_event() had
nothing left to wake, so drop the semaphore and those posts as well.
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
The driver had two modes selected by CONFIG_SENSORS_L3GD20_BUFFER_SIZE:
with a buffer it pushed samples from a work queue, and without one it
exposed fetch() while still using the data ready interrupt to signal
readiness through notify_event.
That second mode misuses the fetch interface. fetch() means the data is
read from the device on demand and is therefore always available, while
an interrupt driven sensor is exactly what push_event is for. Mixing the
two forces the upper half to guess whether a fetch() only lower half
will ever notify, and it makes poll() unusable in a multi descriptor
loop, because the descriptor reports ready while the read still has to
wait for the next interrupt.
Drop the fetch path and always use the work queue and push_event, which
is what the driver already did by default since BUFFER_SIZE defaults to
1. CONFIG_SENSORS_L3GD20_BUFFER_SIZE gains a range of 1 to 32, as a zero
sized buffer no longer has a meaning, and SCHED_HPWORK is now selected
unconditionally because the work queue is always used.
No in tree configuration enables this driver and the previous default
already took the push path, so no defconfig changes are needed.
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
fetch() timestamps a sample when the application asks for it, not when
the device measured it, and reads accel and gyro separately so the two
topics never share an instant. Add an optional push mode behind
CONFIG_SENSORS_MPU6050_INT: the board supplies mpu6050_config_s::attach,
the handler timestamps and defers to HPWORK, and the worker reads once
and pushes both topics. The I2C read cannot run in the interrupt.
The mode is chosen at build time, so fetch() is simply left out of the
ops table and out of the build when the option is set: an instance uses
one model or the other, never the mixture that made poll() unusable on
l3gd20. A board that enables it without attach fails with -EINVAL.
Also set CONFIG so the DLPF is on. Left at reset the gyroscope output is
8 kHz, not 1 kHz, so SMPLRT_DIV 9 gave 800 Hz rather than the documented
100 Hz; measured 833 Hz before and 101 Hz after. fetch() hid this since
the application set the pace.
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
RNDIS reports Ethernet packet sizing to the host through NDIS OIDs.
OID_GEN_MAXIMUM_FRAME_SIZE is the MTU-style value and excludes the
link-layer header, while CONFIG_NET_ETH_PKTSIZE includes the Ethernet
header.
Report the frame size as CONFIG_NET_ETH_PKTSIZE - ETH_HDRLEN, and
report OID_GEN_MAXIMUM_TOTAL_SIZE as CONFIG_NET_ETH_PKTSIZE instead of
a hardcoded 2048.
Assisted-by: OpenAI Codex:GPT-5
Signed-off-by: shichunma <shichunma@bestechnic.com>
Currently, the `read` function of the watchdog device is dummy and
does nothing. Although this is fine, it's not useful at all from a
userspace perspective, where you may want to check the current WDOG
status.
A wrapper around the `ioctl` `WDIOC_GETSTATUS` has been added as
the `read` function for the WDOG.
Signed-off-by: Javier Alonso <javieralonso@geotab.com>
- ISO1H812G is *output* only expander, not input.
- Warning make sense when we try to set the expander the wrong way.
Signed-off-by: Jiri Vlasak <jvlasak@elektroline.cz>
The matrix driver reported every key with KEYBOARD_PRESS and
KEYBOARD_RELEASE, so a board whose matrix has arrows or function keys
had no way to say so: the keycode ranges overlap the character range,
and the event type is what tells them apart.
A keymap entry is a uint32_t, so wrap the entry in KMATRIX_SPECIAL() to
declare that it holds a value from enum kbd_keycode_e. Existing keymaps
hold characters and are unaffected.
While here, drop the cast that truncated the keycode to sixteen bits,
and default the device to /dev/kbd0. Applications look for a keyboard
under that name, and /dev/keypad0 kept the matrix out of reach of every
one of them.
Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
The driver kept a character device, a ring buffer, a poll waiter list
and an encoder of its own, in parallel with everything the keyboard
upper half already provides. A USB keyboard was therefore the one
keyboard an application could not read like any other.
Register with keyboard_register() and report with keyboard_event(),
which removes the private character device and the four hundred lines
that served it. Special keys are reported with the SPEC event types
carrying a keycode, so an application no longer has to guess whether a
value in the character range is a character or an arrow key.
HIDKBD_ENCODED and HIDKBD_NODEBOUNCE go away with the code they guarded.
Encoding is now inherent to the event, and the previous report is no
longer an optimisation: a HID keyboard reports the keys that are down
rather than the transitions, so it is what tells a new press from a key
still held, and what tells that a key has been released.
Reporting the modifiers as keys is new, so it is behind
HIDKBD_REPORT_MODIFIERS and off by default.
Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
Both switches end with a bare default label and no statement after it,
which a compiler is entitled to reject: a label has to label something.
GCC for MIPS does, and the file is new enough that no configuration had
compiled it yet.
The next commit makes USBHOST_HIDKBD select INPUT_KEYBOARD, which pulls
this file into twenty five configurations for the first time, ci20:jumbo
among them, so fix it here rather than let that commit break them.
Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
The USB HID keyboard driver is about to report through the upper half
rather than through a character device of its own, which changes what
read() returns from a byte stream to struct keyboard_event_s. Ten
in-tree configurations have an application that consumes the byte
stream.
Add INPUT_KEYBOARD_BYTESTREAM, which renders each event with the
keyboard codec instead of copying the event structure, so those
applications keep working while they are converted.
Only the press events are rendered. A byte stream has no way to say
that a key came up, which is exactly what a keyboard reporting through a
character device has always delivered, so this reproduces the previous
behaviour rather than adding to it.
Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
As analyzed, the NuttX initial keyboard API design uses event
type KBD_SPECPRESS/KBD_SPECREL to deliver special keys
and KBD_PRESS/KBD_RELEASE to deliver ASCII codes.
But it seems that this design choice has not been followed
in virtio-input, goldfish_events and sim_keyboard designs
and result is that external keyboard special keys events
are mapped to KEYCODE_xxx values which start from 0 and
overlaps with ASCII keys.
The issue is tracked under #19527 number.
This set of changes correct events reporting for mentioned
keyboards to report right event type for special keys.
The solution is only partial at this phase.
Virtual and more complex keyboards usually deliver
key pressures as scancodes (key position on keyboard)
and mapping to ASCII for keys which corresponds to letter
and other similar keys lacks mapping of national alphabets,
second row symbols and switch to capital letter according
to modifiers.
Signed-off-by: Pavel Pisa <pisa@fel.cvut.cz>
The USB device controller drivers invoke CLASS_DISCONNECT() on every
USB bus reset, and a bus reset is the first step of normal host
enumeration. Every other class driver (cdcacm, usbmsc, rndis)
re-asserts DEV_CONNECT() at the end of its disconnect() handler so
that the device remains attached; cdcecm and cdcncm did not, so on
controllers that soft-disconnect around bus reset (e.g. rp2040, which
drops the pull-up in its bus-reset handler) a standalone CDC-ECM or
CDC-NCM device is left soft-disconnected by the first bus reset and
never enumerates on the host.
Mirror the cdcacm behavior and perform the soft connect in the
disconnect() methods, unless part of a composite device (composite.c
already re-connects in its own disconnect handler).
Fixes the standalone CDC-ECM case of issue #15880.
Validated on raspberrypi-pico (RP2040): with this change a standalone
CONFIG_NET_CDCECM device that previously never appeared on the host
enumerates via cdc_ether and pings with 0% loss. cdcncm has the
identical defect and receives the identical fix.
Signed-off-by: Ricard Rosson <ricard@groundbits.com>
Co-authored-by: Xiang Xiao <xiaoxiang781216@gmail.com>
Assisted-by: Claude (Anthropic Claude Code)
syslog_write_foreach() compares an unsigned count against a signed
accumulator:
size_t nwritten = 0;
ssize_t nwritten_max = -EIO;
...
if (nwritten > nwritten_max)
{
nwritten_max = nwritten;
}
return nwritten_max;
The usual arithmetic conversions promote nwritten_max to size_t, so -EIO
becomes 4294967291 on a 32-bit target, and the comparison is never true.
nwritten_max keeps its initial value and the function returns -EIO no
matter how many bytes actually went out. Observed under gdb on a running
target: nwritten == 64, nwritten_max == -5, (nwritten > nwritten_max) == 0.
Most callers discard the result -- syslog() itself returns void -- so this
is normally invisible. It becomes fatal when /dev/console is backed by
syslog_console_write(), because then stdio acts on it.
lib_fflush_unlocked() sees a negative return, sets __FS_FLAG_ERROR and
returns early, before resetting fs_bufpos. The bytes have already been
emitted, but the buffer is never cleared, so every subsequent stdio call
re-flushes the same CONFIG_STDIO_BUFFER_SIZE bytes. The console fills
with one repeated fragment and the system makes no further progress.
Reaching that state needs CONFIG_CONSOLE_SYSLOG=y together with no driver
claiming /dev/console ahead of syslog_console_init(). Three in-tree
defconfigs qualify: x86/qemu-i486:ostest, renesas/skp16c26:ostest and
x86_64/qemu-intel64:earlyfb. The other 56 CONSOLE_SYSLOG configurations
have a serial console that registers /dev/console first, which is why this
has gone unnoticed.
Introduced by 1685e8ff7b ("syslog: avoid an infinite loop if one channel
fails"), which changed nwritten_max from size_t to ssize_t = -EIO so that
an all-channels-failed case could be reported. Give nwritten the same type
so the comparison is signed, which preserves that intent: nwritten_max
stays -EIO only when no channel wrote anything. nwritten is never negative,
so the remaining comparisons against buflen are unaffected.
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
During the Toybox port to NuttX, Claude noticed that changes in the
menuconfig weren't taking affect. This issue exists for a long time on
NuttX, in fact BayLibre's presentation from 2017 make jokes about our
building system not been reliable:
https://www.youtube.com/watch?v=XUJK2htXxKw&t=320s
Stale archive members from $(AR)'s additive-only behavior can linger
after Kconfig toggles change which files provide a symbol, causing dead
weight or "multiple definition" link errors on incremental builds.
Fixed by splitting ARCHIVE into two macros: ARCHIVE keeps the original
additive behavior for apps/libapps.a, which many independent
subdirectories contribute to across a build, while the new
ARCHIVE_REBUILD deletes then archives for the far more common case
of a single Makefile building its own self-contained $(OBJS)
- all 39 such call sites now use it.
Assisted-By: Claude Sonnet 5
Signed-off-by: Alan C. Assis <acassis@gmail.com>
The reference manual (section 3.2.1) states the user has to
read GLERR and INTERR registers to clear their bits and release
ERR pin after the startup sequence. Error bits are set to 1 after
the startup if external power supply is used.
Not clearing the bits leads to subsequent read call errors if VBB
errors are checked.
Signed-off-by: Michal Lenc <michallenc@seznam.cz>
cdcncm_send() defers each transmit with MSEC2TICK(CDCNCM_DGRAM_COMBINE_PERIOD)
(1 ms). MSEC2TICK() rounds up to the system tick, so at the default 100 Hz tick
the "1 ms" coalescing window becomes a full 10 ms tick (10-20 ms with phase),
adding that latency to every single-datagram reply (ICMP echo, TCP ACK, one-MSS
HTTP segment) and dominating the CDC-NCM round-trip time.
The window only coalesces datagrams appended within the same synchronous TX
burst (already queued before the worker runs), so an inter-burst delay adds
latency without batching benefit in the common case. Fire the transmit worker
immediately (delay 0); within-burst coalescing is preserved.
On RP2350 (Pico 2 W) USB-NIC at 100 Hz tick: ping RTT 21.7 -> 2.8 ms, a 257 KB
HTTP download 5.79 -> 0.92 s (44.5 -> 279 KB/s).
Signed-off-by: Ricard Rosson <ricard@groundbits.com>
Assisted-by: Claude (Anthropic Claude Code)
Signed-off-by: Ricard Rosson <ricard@groundbits.com>