allow to send Modem Status, Line Status, and configure remote port configuration

This commit is contained in:
matthias.ringwald@gmail.com 2014-01-11 22:02:41 +00:00
parent 1128f4d8d0
commit 4bc547b2b5
2 changed files with 136 additions and 7 deletions

View File

@ -621,6 +621,17 @@ static int rfcomm_send_uih_pn_response(rfcomm_multiplexer_t *multiplexer, uint8_
return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
}
static int rfcomm_send_uih_rls_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t line_status) {
uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
uint8_t payload[4];
uint8_t pos = 0;
payload[pos++] = BT_RFCOMM_RLS_CMD;
payload[pos++] = 2 << 1 | 1; // len
payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
payload[pos++] = line_status;
return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
}
static int rfcomm_send_uih_rls_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t line_status) {
uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
uint8_t payload[4];
@ -632,6 +643,23 @@ static int rfcomm_send_uih_rls_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dl
return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
}
static int rfcomm_send_uih_rpn_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) {
uint8_t payload[10];
uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
uint8_t pos = 0;
payload[pos++] = BT_RFCOMM_RPN_CMD;
payload[pos++] = 8 << 1 | 1; // len
payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
payload[pos++] = rpn_data->baud_rate;
payload[pos++] = rpn_data->flags;
payload[pos++] = rpn_data->flow_control;
payload[pos++] = rpn_data->xon;
payload[pos++] = rpn_data->xoff;
payload[pos++] = rpn_data->parameter_mask_0;
payload[pos++] = rpn_data->parameter_mask_1;
return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
}
static int rfcomm_send_uih_rpn_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) {
uint8_t payload[10];
uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
@ -1519,13 +1547,13 @@ static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_chann
if (event->type == CH_EVT_RCVD_RPN_REQ){
// default rpn rsp
rfcomm_rpn_data_t rpn_data;
rpn_data.baud_rate = 0xa0; /* 9600 bps */
rpn_data.flags = 0x03; /* 8-n-1 */
rpn_data.flow_control = 0; /* no flow control */
rpn_data.xon = 0xd1; /* XON */
rpn_data.xoff = 0xd3; /* XOFF */
rpn_data.parameter_mask_0 = 0x7f; /* parameter mask, all values set */
rpn_data.parameter_mask_1 = 0x3f; /* parameter mask, all values set */
rpn_data.baud_rate = RPN_BAUD_9600; /* 9600 bps */
rpn_data.flags = 0x03; /* 8-n-1 */
rpn_data.flow_control = 0; /* no flow control */
rpn_data.xon = 0xd1; /* XON */
rpn_data.xoff = 0xd3; /* XOFF */
rpn_data.parameter_mask_0 = 0x7f; /* parameter mask, all values set */
rpn_data.parameter_mask_1 = 0x3f; /* parameter mask, all values set */
memcpy(&channel->rpn_data, &rpn_data, sizeof(rfcomm_rpn_data_t));
rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
return;
@ -1909,6 +1937,45 @@ int rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
return result;
}
// Sends Local Lnie Status, see LINE_STATUS_..
int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status){
rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
if (!channel){
log_error("rfcomm_send_local_line_status cid 0x%02x doesn't exist!\n", rfcomm_cid);
return 0;
}
return rfcomm_send_uih_rls_cmd(channel->multiplexer, channel->dlci, line_status);
}
// Sned local modem status. see MODEM_STAUS_..
int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status){
rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
if (!channel){
log_error("rfcomm_send_modem_status cid 0x%02x doesn't exist!\n", rfcomm_cid);
return 0;
}
return rfcomm_send_uih_msc_cmd(channel->multiplexer, channel->dlci, modem_status);
}
// Configure remote port
int rfcomm_send_port_configuration(uint16_t rfcomm_cid, rpn_baud_t baud_rate, rpn_data_bits_t data_bits, rpn_stop_bits_t stop_bits, rpn_parity_t parity, rpn_flow_control_t flow_control){
rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
if (!channel){
log_error("rfcomm_send_modem_status cid 0x%02x doesn't exist!\n", rfcomm_cid);
return 0;
}
rfcomm_rpn_data_t rpn_data;
rpn_data.baud_rate = baud_rate;
rpn_data.flags = data_bits | (stop_bits << 2) | (parity << 3);
rpn_data.flow_control = flow_control;
rpn_data.xon = 0;
rpn_data.xoff = 0;
rpn_data.parameter_mask_0 = 0x1f; // all but xon/xoff
rpn_data.parameter_mask_1 = 0x3f; // all flow control options
return rfcomm_send_uih_rpn_cmd(channel->multiplexer, channel->dlci, &rpn_data);
}
void rfcomm_create_channel2(void * connection, bd_addr_t *addr, uint8_t server_channel, uint8_t incoming_flow_control, uint8_t initial_credits){
log_info("RFCOMM_CREATE_CHANNEL addr %s channel #%u flow control %u init credits %u\n", bd_addr_to_str(*addr), server_channel,
incoming_flow_control, initial_credits);

View File

@ -55,6 +55,59 @@ extern "C" {
#define RFCOMM_RLS_STATUS_INVALID 0xff
// Line Status
#define LINE_STATUS_NO_ERROR 0x00
#define LINE_STATUS_OVERRUN_ERROR 0x03
#define LINE_STATUS_PARITY_ERORR 0x05
#define LINE_STATUS_FRAMING_ERROR 0x09
// Modem Status Flags
#define MODEM_STATUS_FC 0x02
#define MODEM_STATUS_RTC 0x04
#define MODEM_STATUS_RTR 0x08
#define MODEM_STATUS_IC 0x40
#define MODEM_STATUS_DV 0x80
typedef enum rpn_baud {
RPN_BAUD_2400 = 0,
RPN_BAUD_4800,
RPN_BAUD_7200,
RPN_BAUD_9600,
RPN_BAUD_19200,
RPN_BAUD_38400,
RPN_BAUD_57600,
RPN_BAUD_115200,
RPN_BAUD_230400
} rpn_baud_t;
typedef enum rpn_data_bits {
RPN_DATA_BITS_5 = 0,
RPN_DATA_BITS_6 = 0,
RPN_DATA_BITS_7 = 0,
RPN_DATA_BITS_8 = 0
} rpn_data_bits_t;
typedef enum rpn_stop_bits {
RPN_STOP_BITS_1_0 = 0,
RPN_STOP_BITS_1_5
} rpn_stop_bits_t;
typedef enum rpn_parity {
RPN_PARITY_NONE = 0,
RPN_PARITY_ODD = 1,
RPN_PARITY_EVEN = 3,
RPN_PARITY_MARK = 5,
RPN_PARITY_SPACE = 7,
} rpn_parity_t;
typedef enum rpn_flow_control {
RPN_FLOW_CONTROL_XONXOFF_ON_INPUT = 1 << 0,
RPN_FLOW_CONTROL_XONXOFF_ON_OUTPUT = 1 << 1,
RPN_FLOW_CONTROL_RTR_ON_INPUT = 1 << 2,
RPN_FLOW_CONTROL_RTR_ON_OUTPUT = 1 << 3,
RPN_FLOW_CONTROL_RTC_ON_INPUT = 1 << 4,
RPN_FLOW_CONTROL_RTC_ON_OUTPUT = 1 << 5,
} rpn_flow_control_t;
// private structs
typedef enum {
@ -323,6 +376,15 @@ void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits);
// Sends RFCOMM data packet to the RFCOMM channel with given identifier.
int rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len);
// Sends Local Lnie Status, see LINE_STATUS_..
int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status);
// Sned local modem status. see MODEM_STAUS_..
int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status);
// Configure remote port
int rfcomm_send_port_configuration(uint16_t rfcomm_cid, rpn_baud_t baud_rate, rpn_data_bits_t data_bits, rpn_stop_bits_t stop_bits, rpn_parity_t parity, rpn_flow_control_t flow_control);
#if defined __cplusplus
}
#endif