Skip to content

Conversation

@cormoran
Copy link
Contributor

If tx buffer became full when sending PRC response, framing byte can be skipped and communication gets stuck. This patch adds wait for putting EOF failure and adds error handling for putting SOF failure.

I hit this error when sending keylayout data on BLE gatt. Waiting in the loop practically resolved the issue.

PR check-list

  • Branch has a clean commit history
  • Additional tests are included, if changing behaviors/core code that is testable.
  • Proper Copyright + License headers added to applicable files (Generally, we stick to "The ZMK Contributors" for copyrights to help avoid churn when files get edited)
  • Pre-commit used to check formatting of files, commit messages, etc.
  • Includes any necessary documentation changes.

If tx buffer became full when sending PRC response, framing byte can be skipped
and communication gets stuck. This patch adds wait for putting EOF failure and
adds error handling for putting SOF failure.
@cormoran cormoran requested a review from a team as a code owner January 25, 2026 11:19
LOG_ERR("RPC TX buffer full");
k_mutex_unlock(&rpc_transport_mutex);
return -ENOMEM;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Treating SOF put failure as error sounds fine? I've never hit error here yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on the fence here, whether there should be any attempt to retry a few times, and then return -ENOMEM if that fails? Would give the underlying transport a chance to empty the ring buffer to free space. I'd suggest we try that.

In the case of a failure, I usually prefer, when locking involved, to create a new local at the top of the function int ret = 0; and then in this branch, set ret = -ENOMEM; goto exit and update the exit: to return ret instead.

@petejohanson petejohanson added this to the v0.4.0 milestone Jan 27, 2026
Copy link
Contributor

@petejohanson petejohanson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! A few thoughts.

LOG_ERR("RPC TX buffer full");
k_mutex_unlock(&rpc_transport_mutex);
return -ENOMEM;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on the fence here, whether there should be any attempt to retry a few times, and then return -ENOMEM if that fails? Would give the underlying transport a chance to empty the ring buffer to free space. I'd suggest we try that.

In the case of a failure, I usually prefer, when locking involved, to create a new local at the top of the function int ret = 0; and then in this branch, set ret = -ENOMEM; goto exit and update the exit: to return ret instead.

framing_byte = FRAMING_EOF;
ring_buf_put(&rpc_tx_buf, &framing_byte, 1);
// If response is large, tx buffer can be full for async transport.
while (ring_buf_put(&rpc_tx_buf, &framing_byte, 1) == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should ideally "give up" after a certain period/number of tries, and return, so we don't get stuck in an infinite loop, IMHO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants