Skip to content

Commit 8b3eb36

Browse files
jerryyang35fabiobaltieri
authored andcommitted
Bluetooth: RFCOMM: Add RPN command sending support
Add support for Remote Port Negotiation (RPN) commands in the RFCOMM. This allows applications to configure the serial port parameters over RFCOMM connections, such as baud rate, data bits, stop bits, parity and flow control. Changes include: - Add enumerations for RPN parameters (baud rate, data bits, stop bits, parity) - Add a public API function bt_rfcomm_send_rpn_cmd() to send RPN commands - Add shell command to test RPN with default parameters This functionality is required by certain Bluetooth profiles that use RFCOMM and need to configure serial port parameters. Signed-off-by: Jiawei Yang <jiawei.yang_1@nxp.com>
1 parent 6126aa1 commit 8b3eb36

File tree

4 files changed

+145
-25
lines changed

4 files changed

+145
-25
lines changed

include/zephyr/bluetooth/classic/rfcomm.h

+76
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,72 @@ struct bt_rfcomm_server {
155155
struct bt_rfcomm_server *_next;
156156
};
157157

158+
/** @brief RFCOMM RPN baud rate values */
159+
enum {
160+
BT_RFCOMM_RPN_BAUD_RATE_2400 = 0x0,
161+
BT_RFCOMM_RPN_BAUD_RATE_4800 = 0x1,
162+
BT_RFCOMM_RPN_BAUD_RATE_7200 = 0x2,
163+
BT_RFCOMM_RPN_BAUD_RATE_9600 = 0x3,
164+
BT_RFCOMM_RPN_BAUD_RATE_19200 = 0x4,
165+
BT_RFCOMM_RPN_BAUD_RATE_38400 = 0x5,
166+
BT_RFCOMM_RPN_BAUD_RATE_57600 = 0x6,
167+
BT_RFCOMM_RPN_BAUD_RATE_115200 = 0x7,
168+
BT_RFCOMM_RPN_BAUD_RATE_230400 = 0x8
169+
};
170+
171+
/** @brief RFCOMM RPN data bit values */
172+
enum {
173+
BT_RFCOMM_RPN_DATA_BITS_5 = 0x0,
174+
BT_RFCOMM_RPN_DATA_BITS_6 = 0x1,
175+
BT_RFCOMM_RPN_DATA_BITS_7 = 0x2,
176+
BT_RFCOMM_RPN_DATA_BITS_8 = 0x3
177+
};
178+
179+
/** @brief RFCOMM RPN stop bit values */
180+
enum {
181+
BT_RFCOMM_RPN_STOP_BITS_1 = 0,
182+
BT_RFCOMM_RPN_STOP_BITS_1_5 = 1
183+
};
184+
185+
/** @brief RFCOMM RPN parity bit values */
186+
enum {
187+
BT_RFCOMM_RPN_PARITY_NONE = 0x0,
188+
BT_RFCOMM_RPN_PARITY_ODD = 0x1,
189+
BT_RFCOMM_RPN_PARITY_EVEN = 0x3,
190+
BT_RFCOMM_RPN_PARITY_MARK = 0x5,
191+
BT_RFCOMM_RPN_PARITY_SPACE = 0x7
192+
};
193+
194+
/** @brief Combine data bits, stop bits and parity into a single line settings byte
195+
*
196+
* @param data Data bits value (0-3)
197+
* @param stop Stop bits value (0-1)
198+
* @param parity Parity value (0-7)
199+
*
200+
* @return Combined line settings byte
201+
*/
202+
#define BT_RFCOMM_SET_LINE_SETTINGS(data, stop, parity) ((data & 0x3) | \
203+
((stop & 0x1) << 2) | \
204+
((parity & 0x7) << 3))
205+
206+
#define BT_RFCOMM_RPN_FLOW_NONE 0x00
207+
#define BT_RFCOMM_RPN_XON_CHAR 0x11
208+
#define BT_RFCOMM_RPN_XOFF_CHAR 0x13
209+
210+
/* Set 1 to all the param mask except reserved */
211+
#define BT_RFCOMM_RPN_PARAM_MASK_ALL 0x3f7f
212+
213+
/** @brief RFCOMM Remote Port Negotiation (RPN) structure */
214+
struct bt_rfcomm_rpn {
215+
uint8_t dlci;
216+
uint8_t baud_rate;
217+
uint8_t line_settings;
218+
uint8_t flow_control;
219+
uint8_t xon_char;
220+
uint8_t xoff_char;
221+
uint16_t param_mask;
222+
} __packed;
223+
158224
/** @brief Register RFCOMM server
159225
*
160226
* Register RFCOMM server for a channel, each new connection is authorized
@@ -214,6 +280,16 @@ int bt_rfcomm_dlc_disconnect(struct bt_rfcomm_dlc *dlc);
214280
*/
215281
struct net_buf *bt_rfcomm_create_pdu(struct net_buf_pool *pool);
216282

283+
/**
284+
* @brief Send Remote Port Negotiation command
285+
*
286+
* @param dlc Pointer to the RFCOMM DLC
287+
* @param rpn Pointer to the RPN parameters to send
288+
*
289+
* @return 0 on success, negative error code on failure
290+
*/
291+
int bt_rfcomm_send_rpn_cmd(struct bt_rfcomm_dlc *dlc, struct bt_rfcomm_rpn *rpn);
292+
217293
#ifdef __cplusplus
218294
}
219295
#endif

subsys/bluetooth/host/classic/rfcomm.c

+32
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,38 @@ static int rfcomm_send_rpn(struct bt_rfcomm_session *session, uint8_t cr,
730730
return rfcomm_send(session, buf);
731731
}
732732

733+
int bt_rfcomm_send_rpn_cmd(struct bt_rfcomm_dlc *dlc, struct bt_rfcomm_rpn *rpn)
734+
{
735+
struct bt_rfcomm_session *session;
736+
737+
if (!dlc || !rpn) {
738+
return -EINVAL;
739+
}
740+
741+
/* Validate baud rate */
742+
if (rpn->baud_rate > BT_RFCOMM_RPN_BAUD_RATE_230400) {
743+
LOG_ERR("Invalid baud rate: %u", rpn->baud_rate);
744+
return -EINVAL;
745+
}
746+
747+
session = dlc->session;
748+
if (!session) {
749+
return -ENOTCONN;
750+
}
751+
752+
if (dlc->state != BT_RFCOMM_STATE_CONNECTED) {
753+
return -ENOTCONN;
754+
}
755+
756+
LOG_DBG("dlc %p", dlc);
757+
758+
/* Set DLCI in the RPN command */
759+
rpn->dlci = BT_RFCOMM_SET_ADDR(dlc->dlci, 1);
760+
761+
/* Send the RPN command */
762+
return rfcomm_send_rpn(session, BT_RFCOMM_MSG_CMD_CR, rpn);
763+
}
764+
733765
static int rfcomm_send_test(struct bt_rfcomm_session *session, uint8_t cr,
734766
uint8_t *pattern, uint8_t len)
735767
{

subsys/bluetooth/host/classic/rfcomm_internal.h

-25
Original file line numberDiff line numberDiff line change
@@ -90,38 +90,13 @@ struct bt_rfcomm_rls {
9090
} __packed;
9191

9292
#define BT_RFCOMM_RPN 0x24
93-
struct bt_rfcomm_rpn {
94-
uint8_t dlci;
95-
uint8_t baud_rate;
96-
uint8_t line_settings;
97-
uint8_t flow_control;
98-
uint8_t xon_char;
99-
uint8_t xoff_char;
100-
uint16_t param_mask;
101-
} __packed;
10293

10394
#define BT_RFCOMM_TEST 0x08
10495
#define BT_RFCOMM_NSC 0x04
10596

10697
#define BT_RFCOMM_FCON 0x28
10798
#define BT_RFCOMM_FCOFF 0x18
10899

109-
/* Default RPN Settings */
110-
#define BT_RFCOMM_RPN_BAUD_RATE_9600 0x03
111-
#define BT_RFCOMM_RPN_DATA_BITS_8 0x03
112-
#define BT_RFCOMM_RPN_STOP_BITS_1 0x00
113-
#define BT_RFCOMM_RPN_PARITY_NONE 0x00
114-
#define BT_RFCOMM_RPN_FLOW_NONE 0x00
115-
#define BT_RFCOMM_RPN_XON_CHAR 0x11
116-
#define BT_RFCOMM_RPN_XOFF_CHAR 0x13
117-
118-
/* Set 1 to all the param mask except reserved */
119-
#define BT_RFCOMM_RPN_PARAM_MASK_ALL 0x3f7f
120-
121-
#define BT_RFCOMM_SET_LINE_SETTINGS(data, stop, parity) ((data & 0x3) | \
122-
((stop & 0x1) << 2) | \
123-
((parity & 0x7) << 3))
124-
125100
/* DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 */
126101
#define BT_RFCOMM_DEFAULT_V24_SIG 0x8d
127102

subsys/bluetooth/host/classic/shell/rfcomm.c

+37
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,42 @@ static int cmd_disconnect(const struct shell *sh, size_t argc, char *argv[])
232232
return err;
233233
}
234234

235+
static int cmd_send_rpn(const struct shell *sh, size_t argc, char *argv[])
236+
{
237+
int err;
238+
struct bt_rfcomm_rpn rpn;
239+
240+
if (!rfcomm_dlc.session) {
241+
shell_error(sh, "Not connected");
242+
return -ENOEXEC;
243+
}
244+
245+
/* Initialize RPN with default values */
246+
memset(&rpn, 0, sizeof(rpn));
247+
248+
/* Set default values for RPN parameters */
249+
rpn.baud_rate = BT_RFCOMM_RPN_BAUD_RATE_9600;
250+
rpn.line_settings = BT_RFCOMM_SET_LINE_SETTINGS(
251+
BT_RFCOMM_RPN_DATA_BITS_8,
252+
BT_RFCOMM_RPN_STOP_BITS_1,
253+
BT_RFCOMM_RPN_PARITY_NONE);
254+
rpn.flow_control = BT_RFCOMM_RPN_FLOW_NONE;
255+
rpn.xon_char = BT_RFCOMM_RPN_XON_CHAR;
256+
rpn.xoff_char = BT_RFCOMM_RPN_XOFF_CHAR;
257+
rpn.param_mask = BT_RFCOMM_RPN_PARAM_MASK_ALL;
258+
259+
shell_print(sh, "Sending RFCOMM RPN command with default settings");
260+
261+
err = bt_rfcomm_send_rpn_cmd(&rfcomm_dlc, &rpn);
262+
if (err < 0) {
263+
shell_error(sh, "Unable to send RPN command: %d", err);
264+
return -ENOEXEC;
265+
}
266+
267+
shell_print(sh, "RFCOMM RPN command sent successfully");
268+
return 0;
269+
}
270+
235271
#define HELP_NONE "[none]"
236272
#define HELP_ADDR_LE "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>"
237273

@@ -240,6 +276,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(rfcomm_cmds,
240276
SHELL_CMD_ARG(connect, NULL, "<channel>", cmd_connect, 2, 0),
241277
SHELL_CMD_ARG(disconnect, NULL, HELP_NONE, cmd_disconnect, 1, 0),
242278
SHELL_CMD_ARG(send, NULL, "<number of packets>", cmd_send, 2, 0),
279+
SHELL_CMD_ARG(rpn, NULL, "Send RPN command with default settings", cmd_send_rpn, 1, 0),
243280
SHELL_SUBCMD_SET_END
244281
);
245282

0 commit comments

Comments
 (0)