|
|
|
@ -45,13 +45,13 @@ typedef enum _option_status {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
l2cap_flow_t default_qos = {
|
|
|
|
|
/* flags */ 0x0,
|
|
|
|
|
/* flags */ 0x0,
|
|
|
|
|
/* service_type */ HCI_SERVICE_TYPE_BEST_EFFORT,
|
|
|
|
|
/* token_rate */ 0xffffffff, /* maximum */
|
|
|
|
|
/* token_rate */ 0xffffffff, /* maximum */
|
|
|
|
|
/* token_bucket_size */ 0xffffffff, /* maximum */
|
|
|
|
|
/* peak_bandwidth */ 0x00000000, /* maximum */
|
|
|
|
|
/* latency */ 0xffffffff, /* don't care */
|
|
|
|
|
/* delay_variation */ 0xffffffff /* don't care */
|
|
|
|
|
/* peak_bandwidth */ 0x00000000, /* maximum */
|
|
|
|
|
/* latency */ 0xffffffff, /* don't care */
|
|
|
|
|
/* delay_variation */ 0xffffffff /* don't care */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -124,8 +124,9 @@ l2cap_process_signal_cmd(HciConnection* conn, net_buffer* buffer)
|
|
|
|
|
|
|
|
|
|
/* Verify command length */
|
|
|
|
|
if (buffer->size < commandHeader->length) {
|
|
|
|
|
debugf("invalid L2CAP signaling command, code=%#x, ident=%d, length=%d, buffer size=%ld\n",
|
|
|
|
|
commandHeader->code, commandHeader->ident, commandHeader->length, buffer->size);
|
|
|
|
|
debugf("invalid L2CAP signaling command, code=%#x, ident=%d,"
|
|
|
|
|
" length=%d, buffer size=%ld\n", commandHeader->code,
|
|
|
|
|
commandHeader->ident, commandHeader->length, buffer->size);
|
|
|
|
|
gBufferModule->free(buffer);
|
|
|
|
|
return (EMSGSIZE);
|
|
|
|
|
}
|
|
|
|
@ -186,8 +187,10 @@ l2cap_process_signal_cmd(HciConnection* conn, net_buffer* buffer)
|
|
|
|
|
processingCode, processingIdent);
|
|
|
|
|
|
|
|
|
|
// Send L2CAP_CommandRej. Do not really care about the result
|
|
|
|
|
// ORD: Remiaining commands in the same packet are also to be rejected
|
|
|
|
|
/*send_l2cap_reject(con, processingIdent, L2CAP_REJ_NOT_UNDERSTOOD, 0, 0, 0);*/
|
|
|
|
|
// ORD: Remiaining commands in the same packet are also to
|
|
|
|
|
// be rejected?
|
|
|
|
|
// send_l2cap_reject(con, processingIdent,
|
|
|
|
|
// L2CAP_REJ_NOT_UNDERSTOOD, 0, 0, 0);
|
|
|
|
|
gBufferModule->free(m);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -228,9 +231,8 @@ l2cap_process_con_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
|
|
|
|
|
command.Remove(); // pull the command body
|
|
|
|
|
|
|
|
|
|
/* Create new channel and send L2CA_ConnectInd
|
|
|
|
|
notification to the upper layer protocol.
|
|
|
|
|
*/
|
|
|
|
|
// Create new channel and send L2CA_ConnectInd
|
|
|
|
|
// notification to the upper layer protocol.
|
|
|
|
|
channel = btCoreData->AddChannel(conn, psm /*, dcid, ident*/);
|
|
|
|
|
if (channel == NULL) {
|
|
|
|
|
flowf("No resources to create channel\n");
|
|
|
|
@ -245,7 +247,7 @@ l2cap_process_con_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
status_t indicationStatus = l2cap_l2ca_con_ind(channel);
|
|
|
|
|
|
|
|
|
|
if ( indicationStatus == B_OK ) {
|
|
|
|
|
//channel->state = L2CAP_CHAN_W4_L2CA_CON_RSP;
|
|
|
|
|
// channel->state = L2CAP_CHAN_W4_L2CA_CON_RSP;
|
|
|
|
|
|
|
|
|
|
} else if (indicationStatus == B_NO_MEMORY) {
|
|
|
|
|
/* send_l2cap_con_rej(con, ident, channel->scid, dcid, L2CAP_NO_RESOURCES);*/
|
|
|
|
@ -279,22 +281,28 @@ l2cap_process_con_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
status = le16toh(command->status);
|
|
|
|
|
|
|
|
|
|
command.Remove(); // pull the command body
|
|
|
|
|
|
|
|
|
|
debugf("dcid=%d scid=%d result=%d status%d\n", dcid, scid, result, status);
|
|
|
|
|
|
|
|
|
|
/* Check if we have pending command descriptor */
|
|
|
|
|
cmd = btCoreData->SignalByIdent(conn, ident);
|
|
|
|
|
if (cmd == NULL) {
|
|
|
|
|
debugf("unexpected L2CAP_ConnectRsp command. ident=%d, con_handle=%d\n", ident, conn->handle);
|
|
|
|
|
debugf("unexpected L2CAP_ConnectRsp command. ident=%d, "
|
|
|
|
|
"con_handle=%d\n", ident, conn->handle);
|
|
|
|
|
return ENOENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Verify channel state, if invalid - do nothing */
|
|
|
|
|
if (cmd->channel->state != L2CAP_CHAN_W4_L2CAP_CON_RSP) {
|
|
|
|
|
debugf("unexpected L2CAP_ConnectRsp. Invalid channel state, cid=%d, state=%d\n", scid, cmd->channel->state);
|
|
|
|
|
debugf("unexpected L2CAP_ConnectRsp. Invalid channel state, "
|
|
|
|
|
"cid=%d, state=%d\n", scid, cmd->channel->state);
|
|
|
|
|
goto reject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Verify CIDs and send reject if does not match */
|
|
|
|
|
if (cmd->channel->scid != scid) {
|
|
|
|
|
debugf("unexpected L2CAP_ConnectRsp. Channel IDs do not match, scid=%d(%d)\n", cmd->channel->scid, scid);
|
|
|
|
|
debugf("unexpected L2CAP_ConnectRsp. Channel IDs do not match, "
|
|
|
|
|
"scid=%d(%d)\n", cmd->channel->scid, scid);
|
|
|
|
|
goto reject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -318,9 +326,10 @@ l2cap_process_con_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
btCoreData->TimeoutSignal(cmd, bluetooth_l2cap_ertx_timeout);
|
|
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
|
// INDICATION error = ng_l2cap_l2ca_con_rsp(cmd->channel, cmd->token, result, status);
|
|
|
|
|
// INDICATION error = ng_l2cap_l2ca_con_rsp(cmd->channel, cmd->token,
|
|
|
|
|
// result, status);
|
|
|
|
|
// if (error != B_OK)
|
|
|
|
|
// btCoreData->RemoveChannel(conn, cmd->channel->scid);
|
|
|
|
|
// btCoreData->RemoveChannel(conn, cmd->channel->scid);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
@ -340,7 +349,8 @@ l2cap_process_con_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
|
|
|
|
|
/* XXX do we have to remove the channel on error? */
|
|
|
|
|
if (error != 0 || result != L2CAP_SUCCESS) {
|
|
|
|
|
debugf("failed to open L2CAP channel, result=%d, status=%d\n", result, status);
|
|
|
|
|
debugf("failed to open L2CAP channel, result=%d, status=%d\n",
|
|
|
|
|
result, status);
|
|
|
|
|
btCoreData->RemoveChannel(conn, cmd->channel->scid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -358,7 +368,8 @@ reject:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static option_status
|
|
|
|
|
getNextSignalOption(net_buffer* nbuf, size_t* off, l2cap_cfg_opt_t* hdr, l2cap_cfg_opt_val_t* val)
|
|
|
|
|
getNextSignalOption(net_buffer* nbuf, size_t* off, l2cap_cfg_opt_t* hdr,
|
|
|
|
|
l2cap_cfg_opt_val_t* val)
|
|
|
|
|
{
|
|
|
|
|
int hint;
|
|
|
|
|
size_t len = nbuf->size - (*off);
|
|
|
|
@ -383,12 +394,11 @@ getNextSignalOption(net_buffer* nbuf, size_t* off, l2cap_cfg_opt_t* hdr, l2cap_c
|
|
|
|
|
gBufferModule->read(nbuf, *off, val, L2CAP_OPT_MTU_SIZE);
|
|
|
|
|
val->mtu = le16toh(val->mtu);
|
|
|
|
|
*off += L2CAP_OPT_MTU_SIZE;
|
|
|
|
|
flowf("mtu specified\n");
|
|
|
|
|
debugf("mtu %d specified\n", val->mtu);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case L2CAP_OPT_FLUSH_TIMO:
|
|
|
|
|
if (hdr->length != L2CAP_OPT_FLUSH_TIMO_SIZE ||
|
|
|
|
|
len < hdr->length)
|
|
|
|
|
if (hdr->length != L2CAP_OPT_FLUSH_TIMO_SIZE || len < hdr->length)
|
|
|
|
|
return BAD_OPTION_LENGTH;
|
|
|
|
|
|
|
|
|
|
gBufferModule->read(nbuf, *off, val, L2CAP_OPT_FLUSH_TIMO_SIZE);
|
|
|
|
@ -437,11 +447,10 @@ l2cap_process_cfg_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
size_t off;
|
|
|
|
|
status_t error = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debugf("configuration=%ld\n", buffer->size);
|
|
|
|
|
|
|
|
|
|
/* Get command parameters */
|
|
|
|
|
NetBufferHeaderReader<l2cap_cfg_req_cp> command(buffer);
|
|
|
|
|
NetBufferHeaderReader<l2cap_cfg_req_cp> command(buffer);
|
|
|
|
|
status_t status = command.Status();
|
|
|
|
|
if (status < B_OK) {
|
|
|
|
|
return ENOBUFS;
|
|
|
|
@ -450,22 +459,26 @@ l2cap_process_cfg_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
dcid = le16toh(command->dcid);
|
|
|
|
|
respond = L2CAP_OPT_CFLAG(le16toh(command->flags));
|
|
|
|
|
|
|
|
|
|
command.Remove(); // pull configuration header
|
|
|
|
|
command.Remove(); // pull configuration header
|
|
|
|
|
|
|
|
|
|
/* Check if we have this channel and it is in valid state */
|
|
|
|
|
channel = btCoreData->ChannelBySourceID(conn, dcid);
|
|
|
|
|
if (channel == NULL) {
|
|
|
|
|
debugf("unexpected L2CAP_ConfigReq command. Channel does not exist, cid=%d\n", dcid);
|
|
|
|
|
debugf("unexpected L2CAP_ConfigReq command. "
|
|
|
|
|
"Channel does not exist, cid=%d\n", dcid);
|
|
|
|
|
goto reject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Verify channel state */
|
|
|
|
|
if (channel->state != L2CAP_CHAN_CONFIG && channel->state != L2CAP_CHAN_OPEN) {
|
|
|
|
|
debugf("unexpected L2CAP_ConfigReq. Invalid channel state, cid=%d, state=%d\n", dcid, channel->state);
|
|
|
|
|
if (channel->state != L2CAP_CHAN_CONFIG
|
|
|
|
|
&& channel->state != L2CAP_CHAN_OPEN) {
|
|
|
|
|
debugf("unexpected L2CAP_ConfigReq. Invalid channel state, "
|
|
|
|
|
"cid=%d, state=%d\n", dcid, channel->state);
|
|
|
|
|
goto reject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (channel->state == L2CAP_CHAN_OPEN) { /* Re-configuration */
|
|
|
|
|
channel->cfgState = 0; // Reset configuration state
|
|
|
|
|
channel->state = L2CAP_CHAN_CONFIG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -486,7 +499,8 @@ l2cap_process_cfg_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case L2CAP_OPT_QOS:
|
|
|
|
|
memcpy(&val.flow, &channel->configuration->iflow, sizeof(channel->configuration->iflow));
|
|
|
|
|
memcpy(&val.flow, &channel->configuration->iflow,
|
|
|
|
|
sizeof(channel->configuration->iflow));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: /* Ignore unknown hint option */
|
|
|
|
@ -507,9 +521,11 @@ l2cap_process_cfg_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debugf("Pulled %ld of configuration fields respond=%d remaining=%ld\n", off, respond, buffer->size);
|
|
|
|
|
debugf("Pulled %ld of configuration fields respond=%d remaining=%ld\n",
|
|
|
|
|
off, respond, buffer->size);
|
|
|
|
|
gBufferModule->remove_header(buffer, off);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Now check and see if we have to respond. If everything was OK then
|
|
|
|
|
* respond contain "C flag" and (if set) we will respond with empty
|
|
|
|
@ -527,7 +543,7 @@ l2cap_process_cfg_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
error = send_l2cap_cfg_rsp(conn, ident, channel->dcid, result, buffer);
|
|
|
|
|
if (error != 0) {
|
|
|
|
|
// TODO:
|
|
|
|
|
//INDICATION ng_l2cap_l2ca_discon_ind(ch);
|
|
|
|
|
// INDICATION ng_l2cap_l2ca_discon_ind(ch);
|
|
|
|
|
btCoreData->RemoveChannel(conn, channel->scid);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@ -553,9 +569,9 @@ reject:
|
|
|
|
|
|
|
|
|
|
/* Process L2CAP_ConfigRsp command */
|
|
|
|
|
static status_t
|
|
|
|
|
l2cap_process_cfg_rsp(HciConnection *conn, uint8 ident, net_buffer *buffer)
|
|
|
|
|
l2cap_process_cfg_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
{
|
|
|
|
|
L2capFrame *cmd = NULL;
|
|
|
|
|
L2capFrame* cmd = NULL;
|
|
|
|
|
uint16 scid, cflag, result;
|
|
|
|
|
|
|
|
|
|
l2cap_cfg_opt_t hdr;
|
|
|
|
@ -564,7 +580,7 @@ l2cap_process_cfg_rsp(HciConnection *conn, uint8 ident, net_buffer *buffer)
|
|
|
|
|
size_t off;
|
|
|
|
|
status_t error = 0;
|
|
|
|
|
|
|
|
|
|
NetBufferHeaderReader<l2cap_cfg_rsp_cp> command(buffer);
|
|
|
|
|
NetBufferHeaderReader<l2cap_cfg_rsp_cp> command(buffer);
|
|
|
|
|
status_t status = command.Status();
|
|
|
|
|
if (status < B_OK) {
|
|
|
|
|
return ENOBUFS;
|
|
|
|
@ -576,23 +592,28 @@ l2cap_process_cfg_rsp(HciConnection *conn, uint8 ident, net_buffer *buffer)
|
|
|
|
|
|
|
|
|
|
command.Remove();
|
|
|
|
|
|
|
|
|
|
debugf("scid=%d cflag=%d result=%d\n", scid, cflag, result);
|
|
|
|
|
|
|
|
|
|
/* Check if we have this command */
|
|
|
|
|
cmd = btCoreData->SignalByIdent(conn, ident);
|
|
|
|
|
if (cmd == NULL) {
|
|
|
|
|
debugf("unexpected L2CAP_ConfigRsp command. ident=%d, con_handle=%d\n", ident, conn->handle);
|
|
|
|
|
debugf("unexpected L2CAP_ConfigRsp command. ident=%d, con_handle=%d\n",
|
|
|
|
|
ident, conn->handle);
|
|
|
|
|
gBufferModule->free(buffer);
|
|
|
|
|
return ENOENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Verify CIDs and send reject if does not match */
|
|
|
|
|
if (cmd->channel->scid != scid) {
|
|
|
|
|
debugf("unexpected L2CAP_ConfigRsp.Channel ID does not match, scid=%d(%d)\n", cmd->channel->scid, scid);
|
|
|
|
|
debugf("unexpected L2CAP_ConfigRsp.Channel ID does not match, "
|
|
|
|
|
"scid=%d(%d)\n", cmd->channel->scid, scid);
|
|
|
|
|
goto reject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Verify channel state and reject if invalid */
|
|
|
|
|
if (cmd->channel->state != L2CAP_CHAN_CONFIG) {
|
|
|
|
|
debugf("unexpected L2CAP_ConfigRsp. Invalid channel state, scid=%d, state=%d\n", cmd->channel->scid, cmd->channel->state);
|
|
|
|
|
debugf("unexpected L2CAP_ConfigRsp. Invalid channel state, scid=%d, "
|
|
|
|
|
"state=%d\n", cmd->channel->scid, cmd->channel->state);
|
|
|
|
|
goto reject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -628,7 +649,7 @@ l2cap_process_cfg_rsp(HciConnection *conn, uint8 ident, net_buffer *buffer)
|
|
|
|
|
|
|
|
|
|
case L2CAP_OPT_QOS:
|
|
|
|
|
memcpy(&val.flow, &cmd->channel->configuration->oflow,
|
|
|
|
|
sizeof(cmd->channel->configuration->oflow));
|
|
|
|
|
sizeof(cmd->channel->configuration->oflow));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: /* Ignore unknown hint option */
|
|
|
|
@ -643,8 +664,8 @@ l2cap_process_cfg_rsp(HciConnection *conn, uint8 ident, net_buffer *buffer)
|
|
|
|
|
* upper layer know and do not wait for more options.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
debugf("failed to parse configuration options, error=%ld\n", error);
|
|
|
|
|
//INDICATION
|
|
|
|
|
debugf("fail parsing configuration options, error=%ld\n", error);
|
|
|
|
|
// INDICATION
|
|
|
|
|
result = L2CAP_UNKNOWN;
|
|
|
|
|
cflag = 0;
|
|
|
|
|
|
|
|
|
@ -709,13 +730,14 @@ l2cap_process_discon_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
channel = btCoreData->ChannelBySourceID(conn, dcid);
|
|
|
|
|
if (channel == NULL) {
|
|
|
|
|
debugf("unexpected L2CAP_DisconnectReq message.Channel does not exist, "
|
|
|
|
|
"cid=%d\n", dcid);
|
|
|
|
|
"cid=%x\n", dcid);
|
|
|
|
|
goto reject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX Verify channel state and reject if invalid -- is that true? */
|
|
|
|
|
if (channel->state != L2CAP_CHAN_OPEN && channel->state != L2CAP_CHAN_CONFIG &&
|
|
|
|
|
channel->state != L2CAP_CHAN_W4_L2CAP_DISCON_RSP) {
|
|
|
|
|
if (channel->state != L2CAP_CHAN_OPEN
|
|
|
|
|
&& channel->state != L2CAP_CHAN_CONFIG
|
|
|
|
|
&& channel->state != L2CAP_CHAN_W4_L2CAP_DISCON_RSP) {
|
|
|
|
|
debugf("unexpected L2CAP_DisconnectReq. Invalid channel state, cid=%d, "
|
|
|
|
|
"state=%d\n", dcid, channel->state);
|
|
|
|
|
goto reject;
|
|
|
|
@ -788,20 +810,23 @@ l2cap_process_discon_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
/* Check if we have pending command descriptor */
|
|
|
|
|
cmd = btCoreData->SignalByIdent(conn, ident);
|
|
|
|
|
if (cmd == NULL) {
|
|
|
|
|
debugf("unexpected L2CAP_DisconnectRsp command. ident=%d, con_handle=%d\n", ident, conn->handle);
|
|
|
|
|
debugf("unexpected L2CAP_DisconnectRsp command. ident=%d, "
|
|
|
|
|
"con_handle=%d\n", ident, conn->handle);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Verify channel state, do nothing if invalid */
|
|
|
|
|
if (cmd->channel->state != L2CAP_CHAN_W4_L2CAP_DISCON_RSP) {
|
|
|
|
|
debugf("unexpected L2CAP_DisconnectRsp. Invalid channel state, cid=%d, state=%d\n", scid, cmd->channel->state);
|
|
|
|
|
debugf("unexpected L2CAP_DisconnectRsp. Invalid state, cid=%d, "
|
|
|
|
|
"state=%d\n", scid, cmd->channel->state);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Verify CIDs and send reject if does not match */
|
|
|
|
|
if (cmd->channel->scid != scid || cmd->channel->dcid != dcid) {
|
|
|
|
|
debugf("unexpected L2CAP_DisconnectRsp. Channel IDs do not match, scid=%d(%d), dcid=%d(%d)\n",
|
|
|
|
|
cmd->channel->scid, scid, cmd->channel->dcid, dcid);
|
|
|
|
|
debugf("unexpected L2CAP_DisconnectRsp. Channel IDs do not match, "
|
|
|
|
|
"scid=%d(%d), dcid=%d(%d)\n", cmd->channel->scid, scid,
|
|
|
|
|
cmd->channel->dcid, dcid);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -827,7 +852,8 @@ l2cap_process_echo_req(HciConnection *conn, uint8 ident, net_buffer *buffer)
|
|
|
|
|
{
|
|
|
|
|
L2capFrame* cmd = NULL;
|
|
|
|
|
|
|
|
|
|
cmd = btCoreData->SpawnSignal(conn, NULL, l2cap_echo_req(ident, NULL, 0), ident, L2CAP_ECHO_RSP);
|
|
|
|
|
cmd = btCoreData->SpawnSignal(conn, NULL, l2cap_echo_req(ident, NULL, 0),
|
|
|
|
|
ident, L2CAP_ECHO_RSP);
|
|
|
|
|
if (cmd == NULL) {
|
|
|
|
|
gBufferModule->free(buffer);
|
|
|
|
|
return ENOMEM;
|
|
|
|
@ -845,7 +871,7 @@ static status_t
|
|
|
|
|
l2cap_process_echo_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
{
|
|
|
|
|
L2capFrame* cmd = NULL;
|
|
|
|
|
status_t error = 0;
|
|
|
|
|
status_t error = 0;
|
|
|
|
|
|
|
|
|
|
/* Check if we have this command */
|
|
|
|
|
cmd = btCoreData->SignalByIdent(conn, ident);
|
|
|
|
@ -855,12 +881,13 @@ l2cap_process_echo_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//INDICATION error = ng_l2cap_l2ca_ping_rsp(cmd->conn, cmd->token, L2CAP_SUCCESS, conn->rx_pkt);
|
|
|
|
|
// INDICATION error = ng_l2cap_l2ca_ping_rsp(cmd->conn, cmd->token,
|
|
|
|
|
// L2CAP_SUCCESS, conn->rx_pkt);
|
|
|
|
|
btCoreData->AcknowledgeSignal(cmd);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
debugf("unexpected L2CAP_EchoRsp command. Requested ident does not exist, ident=%d\n", ident);
|
|
|
|
|
debugf("unexpected L2CAP_EchoRsp command. ident does not exist, "
|
|
|
|
|
"ident=%d\n", ident);
|
|
|
|
|
gBufferModule->free(buffer);
|
|
|
|
|
error = B_ERROR;
|
|
|
|
|
}
|
|
|
|
@ -875,7 +902,7 @@ l2cap_process_info_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
{
|
|
|
|
|
L2capFrame* cmd = NULL;
|
|
|
|
|
net_buffer* buf = NULL;
|
|
|
|
|
uint16 type;
|
|
|
|
|
uint16 type;
|
|
|
|
|
|
|
|
|
|
/* Get command parameters */
|
|
|
|
|
NetBufferHeaderReader<l2cap_info_req_cp> command(buffer);
|
|
|
|
@ -884,14 +911,17 @@ l2cap_process_info_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
return ENOBUFS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//command->type = le16toh(mtod(conn->rx_pkt, ng_l2cap_info_req_cp *)->type);
|
|
|
|
|
// ??
|
|
|
|
|
// command->type = le16toh(mtod(conn->rx_pkt,
|
|
|
|
|
// ng_l2cap_info_req_cp *)->type);
|
|
|
|
|
type = le16toh(command->type);
|
|
|
|
|
|
|
|
|
|
command.Remove();
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
case L2CAP_CONNLESS_MTU:
|
|
|
|
|
buf = l2cap_info_rsp(ident, L2CAP_CONNLESS_MTU, L2CAP_SUCCESS, L2CAP_MTU_DEFAULT);
|
|
|
|
|
buf = l2cap_info_rsp(ident, L2CAP_CONNLESS_MTU, L2CAP_SUCCESS,
|
|
|
|
|
L2CAP_MTU_DEFAULT);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
@ -919,7 +949,7 @@ l2cap_process_info_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
status_t error = B_OK;
|
|
|
|
|
|
|
|
|
|
/* Get command parameters */
|
|
|
|
|
NetBufferHeaderReader<l2cap_info_rsp_cp> command(buffer);
|
|
|
|
|
NetBufferHeaderReader<l2cap_info_rsp_cp> command(buffer);
|
|
|
|
|
status_t status = command.Status();
|
|
|
|
|
if (status < B_OK) {
|
|
|
|
|
return ENOBUFS;
|
|
|
|
@ -933,7 +963,8 @@ l2cap_process_info_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
/* Check if we have pending command descriptor */
|
|
|
|
|
cmd = btCoreData->SignalByIdent(conn, ident);
|
|
|
|
|
if (cmd == NULL) {
|
|
|
|
|
debugf("unexpected L2CAP_InfoRsp command. Requested ident does not exist, ident=%d\n", ident);
|
|
|
|
|
debugf("unexpected L2CAP_InfoRsp command. Requested ident does not "
|
|
|
|
|
"exist, ident=%d\n", ident);
|
|
|
|
|
gBufferModule->free(buffer);
|
|
|
|
|
return ENOENT;
|
|
|
|
|
}
|
|
|
|
@ -1007,7 +1038,7 @@ l2cap_process_cmd_rej(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case L2CAP_DISCON_REQ:
|
|
|
|
|
//INDICATION l2cap_l2ca_discon_rsp(cmd->channel,cmd->token,cp->reason);
|
|
|
|
|
//INDICATION l2cap_l2ca_discon_rsp(cmd->channel, cmd->token, cp->reason);
|
|
|
|
|
btCoreData->RemoveChannel(conn, cmd->channel->scid);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -1020,7 +1051,7 @@ l2cap_process_cmd_rej(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
debugf("unexpected L2CAP_CommandRej. Unexpected L2CAP command opcode=%d\n", cmd->code);
|
|
|
|
|
debugf("unexpected L2CAP_CommandRej. Unexpected opcode=%d\n", cmd->code);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1040,11 +1071,12 @@ l2cap_process_cmd_rej(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
send_l2cap_reject(HciConnection* conn, uint8 ident, uint16 reason,
|
|
|
|
|
uint16 mtu, uint16 scid, uint16 dcid)
|
|
|
|
|
uint16 mtu, uint16 scid, uint16 dcid)
|
|
|
|
|
{
|
|
|
|
|
L2capFrame* cmd = NULL;
|
|
|
|
|
|
|
|
|
|
cmd = btCoreData->SpawnSignal(conn, NULL, l2cap_cmd_rej(ident, reason, mtu, scid, dcid), ident, L2CAP_CMD_REJ);
|
|
|
|
|
cmd = btCoreData->SpawnSignal(conn, NULL, l2cap_cmd_rej(ident, reason,
|
|
|
|
|
mtu, scid, dcid), ident, L2CAP_CMD_REJ);
|
|
|
|
|
if (cmd == NULL)
|
|
|
|
|
return ENOMEM;
|
|
|
|
|
|
|
|
|
@ -1056,11 +1088,13 @@ send_l2cap_reject(HciConnection* conn, uint8 ident, uint16 reason,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
send_l2cap_con_rej(HciConnection* conn, uint8 ident, uint16 scid, uint16 dcid, uint16 result)
|
|
|
|
|
send_l2cap_con_rej(HciConnection* conn, uint8 ident, uint16 scid, uint16 dcid,
|
|
|
|
|
uint16 result)
|
|
|
|
|
{
|
|
|
|
|
L2capFrame* cmd = NULL;
|
|
|
|
|
|
|
|
|
|
cmd = btCoreData->SpawnSignal(conn, NULL, l2cap_con_rsp(ident, scid, dcid, result, 0), ident, L2CAP_CON_RSP);
|
|
|
|
|
cmd = btCoreData->SpawnSignal(conn, NULL,
|
|
|
|
|
l2cap_con_rsp(ident, scid, dcid, result, 0), ident, L2CAP_CON_RSP);
|
|
|
|
|
if (cmd == NULL)
|
|
|
|
|
return ENOMEM;
|
|
|
|
|
|
|
|
|
@ -1072,12 +1106,13 @@ send_l2cap_con_rej(HciConnection* conn, uint8 ident, uint16 scid, uint16 dcid, u
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
send_l2cap_cfg_rsp(HciConnection* conn, uint8 ident, uint16 scid, uint16 result, net_buffer* opt)
|
|
|
|
|
send_l2cap_cfg_rsp(HciConnection* conn, uint8 ident, uint16 scid,
|
|
|
|
|
uint16 result, net_buffer* opt)
|
|
|
|
|
{
|
|
|
|
|
L2capFrame* cmd = NULL;
|
|
|
|
|
|
|
|
|
|
cmd = btCoreData->SpawnSignal(conn, NULL, l2cap_cfg_rsp(ident, scid, 0, result, opt),
|
|
|
|
|
ident, L2CAP_CFG_RSP);
|
|
|
|
|
cmd = btCoreData->SpawnSignal(conn, NULL,
|
|
|
|
|
l2cap_cfg_rsp(ident, scid, 0, result, opt), ident, L2CAP_CFG_RSP);
|
|
|
|
|
if (cmd == NULL) {
|
|
|
|
|
gBufferModule->free(opt);
|
|
|
|
|
return ENOMEM;
|
|
|
|
|