Skip to content

fix: correct FTMS Control Point error codes per Bluetooth spec#189

Open
cwklurks wants to merge 2 commits intoJaapvanEkris:mainfrom
cwklurks:fix/ftms-control-point-error-codes
Open

fix: correct FTMS Control Point error codes per Bluetooth spec#189
cwklurks wants to merge 2 commits intoJaapvanEkris:mainfrom
cwklurks:fix/ftms-control-point-error-codes

Conversation

@cwklurks
Copy link

Fixes three issues in FitnessMachineControlPointCharacteristic:

  1. reset, startOrResume, and stopOrPause without prior requestControl returned opCodeNotSupported (0x02) — should be controlNotPermitted (0x05) per FTMS spec
  2. stopOrPause with an invalid control parameter returned opCodeNotSupported — should be invalidParameter (0x03)
  3. stopOrPause with a truncated 1-byte buffer threw RangeError, preventing indicate()/callback() from firing and hanging the BLE stack

Also cleans up dead fallthrough code — all handled cases now return explicitly so only default produces opCodeNotSupported.

Adds 11 uvu tests for the control point characteristic.

The FTMS Control Point characteristic returned wrong result codes in
several cases:

- reset/startOrResume/stopOrPause without prior requestControl returned
  opCodeNotSupported (0x02) instead of controlNotPermitted (0x05)
- stopOrPause with invalid parameter (not 1 or 2) returned
  opCodeNotSupported instead of invalidParameter (0x03)
- stopOrPause with a truncated 1-byte buffer caused a RangeError crash
  (buffer underflow) that prevented indicate+callback from being called,
  hanging the BLE stack

Also removes dead fallthrough code — all handled cases now return
explicitly, so only the default case produces opCodeNotSupported.

Adds 11 uvu tests covering all control point code paths.
@JaapvanEkris JaapvanEkris added this to the 0.9.7 milestone Feb 18, 2026
Copy link
Collaborator

@Abasz Abasz 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 your contributions. Can you please test FTMS with EXR and ErgZone ?

Technically your changes should not make a different but the connection and communication flow sometimes not perfect on the other side and they apply logic that may break things (like sending reset randomly which ORM for instance cant or don not want to handle etc.)

Also the nested if else statement flow is getting quite difficult to understand (this is not your code its the way it was implemented originally :)) and I wonder whether you are willing to update things to use guard clauses instead (like in the case ControlPointOpCode.stopOrPause: { case where we could simply use this.#controlled for the guard)

Thanks!

return this.#buildResponse(opCode, ResultOpCode.success)
} else {
log.error('FTMS: startOrResume attempted before RequestControl')
return this.#buildResponse(opCode, ResultOpCode.controlNotPermitted)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This needs to be specifically tested as ErgZone had issues with the start and resume flow.

Copy link
Owner

Choose a reason for hiding this comment

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

This needs to be specifically tested as ErgZone had issues with the start and resume flow.

I can test with EXR and ErgZone in the weekend.

@cwklurks
Copy link
Author

Thank you! I refactored to use guard clauses across all three cases (reset, startOrResume, stopOrPause). Also flattened the nested if/else if inside stopOrPause into sequential guards while I was at it.

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.

3 participants

Comments