Implement a bit further the sockets interface
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33320 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Ruiz Dorantes, oliver-ruiz.dorantes_at_gmail.com
|
||||
/*
|
||||
* Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#include "L2capEndpoint.h"
|
||||
#include "l2cap_address.h"
|
||||
@@ -15,6 +12,9 @@
|
||||
|
||||
#include <bluetooth/L2CAP/btL2CAP.h>
|
||||
#define BT_DEBUG_THIS_MODULE
|
||||
#define MODULE_NAME "l2cap"
|
||||
#define SUBMODULE_NAME "Endpoint"
|
||||
#define SUBMODULE_COLOR 32
|
||||
#include <btDebug.h>
|
||||
|
||||
|
||||
@@ -32,10 +32,12 @@ absolute_timeout(bigtime_t timeout)
|
||||
L2capEndpoint::L2capEndpoint(net_socket* socket)
|
||||
:
|
||||
ProtocolSocket(socket),
|
||||
fConfigurationSet(false),
|
||||
fPeerEndpoint(NULL),
|
||||
fAcceptSemaphore(-1)
|
||||
fAcceptSemaphore(-1),
|
||||
fChannel(NULL)
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::L2capEndpoint()\n", find_thread(NULL), this);
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
/* Set MTU and flow control settings to defaults */
|
||||
configuration.imtu = L2CAP_MTU_DEFAULT;
|
||||
@@ -47,16 +49,13 @@ L2capEndpoint::L2capEndpoint(net_socket* socket)
|
||||
configuration.flush_timo = L2CAP_FLUSH_TIMO_DEFAULT;
|
||||
configuration.link_timo = L2CAP_LINK_TIMO_DEFAULT;
|
||||
|
||||
configurationSet = false;
|
||||
|
||||
gStackModule->init_fifo(&fReceivingFifo, "l2cap recvfifo", L2CAP_MTU_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
L2capEndpoint::~L2capEndpoint()
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::~L2capEndpoint()\n", find_thread(NULL), this);
|
||||
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
}
|
||||
|
||||
@@ -64,7 +63,7 @@ L2capEndpoint::~L2capEndpoint()
|
||||
status_t
|
||||
L2capEndpoint::Init()
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Init()\n", find_thread(NULL), this);
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -73,7 +72,7 @@ L2capEndpoint::Init()
|
||||
void
|
||||
L2capEndpoint::Uninit()
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Uninit()\n", find_thread(NULL), this);
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
}
|
||||
|
||||
@@ -81,7 +80,7 @@ L2capEndpoint::Uninit()
|
||||
status_t
|
||||
L2capEndpoint::Open()
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Open()\n", find_thread(NULL), this);
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
status_t error = ProtocolSocket::Open();
|
||||
if (error != B_OK)
|
||||
@@ -94,7 +93,7 @@ L2capEndpoint::Open()
|
||||
status_t
|
||||
L2capEndpoint::Close()
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Close()\n", find_thread(NULL), this);
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -103,7 +102,7 @@ L2capEndpoint::Close()
|
||||
status_t
|
||||
L2capEndpoint::Free()
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Free()\n", find_thread(NULL), this);
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -137,7 +136,7 @@ L2capEndpoint::Bind(const struct sockaddr *_address)
|
||||
memcpy(&socket->address, _address, sizeof(struct sockaddr_l2cap));
|
||||
socket->address.ss_len = sizeof(struct sockaddr_l2cap);
|
||||
|
||||
fState = LISTEN;
|
||||
fState = CLOSED;
|
||||
|
||||
return B_OK;
|
||||
|
||||
@@ -147,7 +146,7 @@ L2capEndpoint::Bind(const struct sockaddr *_address)
|
||||
status_t
|
||||
L2capEndpoint::Unbind()
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Unbind()\n", find_thread(NULL), this);
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -156,12 +155,20 @@ L2capEndpoint::Unbind()
|
||||
status_t
|
||||
L2capEndpoint::Listen(int backlog)
|
||||
{
|
||||
if (fState != CLOSED)
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
if (fState != CLOSED) {
|
||||
flowf("Invalid State\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
fAcceptSemaphore = create_sem(0, "tcp accept");
|
||||
if (fAcceptSemaphore < B_OK)
|
||||
fAcceptSemaphore = create_sem(0, "l2cap serv accept");
|
||||
if (fAcceptSemaphore < B_OK) {
|
||||
flowf("Semaphore could not be created\n");
|
||||
return ENOBUFS;
|
||||
}
|
||||
|
||||
gSocketModule->set_max_backlog(socket, backlog);
|
||||
|
||||
fState = LISTEN;
|
||||
|
||||
@@ -190,12 +197,42 @@ L2capEndpoint::Connect(const struct sockaddr *_address)
|
||||
status_t
|
||||
L2capEndpoint::Accept(net_socket **_acceptedSocket)
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Accept()\n", find_thread(NULL), this);
|
||||
debugf("[%ld]\n", find_thread(NULL));
|
||||
|
||||
bigtime_t timeout = absolute_timeout(socket->receive.timeout);
|
||||
// MutexLocker locker(fLock);
|
||||
|
||||
TOUCH(timeout);
|
||||
return B_OK;
|
||||
status_t status;
|
||||
bigtime_t timeout = absolute_timeout(300*1000*1000);
|
||||
|
||||
do {
|
||||
// locker.Unlock();
|
||||
|
||||
status = acquire_sem_etc(fAcceptSemaphore, 1, B_ABSOLUTE_TIMEOUT
|
||||
| B_CAN_INTERRUPT, timeout);
|
||||
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
// locker.Lock();
|
||||
status = gSocketModule->dequeue_connected(socket, _acceptedSocket);
|
||||
|
||||
if (status != B_OK)
|
||||
debugf("Could not dequeue socket %s\n", strerror(status));
|
||||
|
||||
//TODO: Establish relationship with the negotiated channel by the parent endpoint
|
||||
((L2capEndpoint*)socket)->fChannel = fChannel;
|
||||
|
||||
// point parent
|
||||
((L2capEndpoint*)socket)->fPeerEndpoint = this;
|
||||
|
||||
// unassign any channel for the parent endpoint
|
||||
fChannel = NULL;
|
||||
|
||||
fState = LISTEN;
|
||||
|
||||
} while (status != B_OK);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +240,7 @@ ssize_t
|
||||
L2capEndpoint::Send(const iovec *vecs, size_t vecCount,
|
||||
ancillary_data_container *ancillaryData)
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Send(%p, %ld, %p)\n", find_thread(NULL),
|
||||
debugf("[%ld] %p Send(%p, %ld, %p)\n", find_thread(NULL),
|
||||
this, vecs, vecCount, ancillaryData);
|
||||
|
||||
return B_OK;
|
||||
@@ -215,7 +252,7 @@ L2capEndpoint::Receive(const iovec *vecs, size_t vecCount,
|
||||
ancillary_data_container **_ancillaryData, struct sockaddr *_address,
|
||||
socklen_t *_addressLength)
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Receive(%p, %ld)\n", find_thread(NULL),
|
||||
debugf("[%ld] %p Receive(%p, %ld)\n", find_thread(NULL),
|
||||
this, vecs, vecCount);
|
||||
|
||||
|
||||
@@ -227,15 +264,15 @@ ssize_t
|
||||
L2capEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer)
|
||||
{
|
||||
|
||||
return gStackModule->fifo_dequeue_buffer(&fReceivingFifo, flags, B_INFINITE_TIMEOUT, _buffer);
|
||||
|
||||
return gStackModule->fifo_dequeue_buffer(&fReceivingFifo, flags,
|
||||
B_INFINITE_TIMEOUT, _buffer);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
L2capEndpoint::Sendable()
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Sendable()\n", find_thread(NULL), this);
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -244,7 +281,7 @@ L2capEndpoint::Sendable()
|
||||
ssize_t
|
||||
L2capEndpoint::Receivable()
|
||||
{
|
||||
debugf("[%ld] %p->L2capEndpoint::Receivable()\n", find_thread(NULL), this);
|
||||
debugf("[%ld] %p\n", find_thread(NULL), this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -253,8 +290,7 @@ L2capEndpoint::Receivable()
|
||||
L2capEndpoint*
|
||||
L2capEndpoint::ForPsm(uint16 psm)
|
||||
{
|
||||
|
||||
L2capEndpoint* endpoint;
|
||||
L2capEndpoint* endpoint;
|
||||
|
||||
DoublyLinkedList<L2capEndpoint>::Iterator iterator = EndpointList.GetIterator();
|
||||
|
||||
@@ -275,8 +311,29 @@ L2capEndpoint::ForPsm(uint16 psm)
|
||||
void
|
||||
L2capEndpoint::BindToChannel(L2capChannel* channel)
|
||||
{
|
||||
|
||||
this->channel = channel;
|
||||
channel->configuration = &configuration;
|
||||
fChannel = channel;
|
||||
fChannel->endpoint = this;
|
||||
|
||||
fChannel->configuration = &configuration;
|
||||
|
||||
debugf("Endpoint %p for psm %d, schannel %x dchannel %x\n", this,
|
||||
channel->psm, channel->scid, channel->dcid);
|
||||
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
L2capEndpoint::MarkEstablished()
|
||||
{
|
||||
debugf("Endpoint %p for psm %d, schannel %x dchannel %x\n", this,
|
||||
fChannel->psm, fChannel->scid, fChannel->dcid);
|
||||
|
||||
net_socket* newSocket;
|
||||
status_t error = gSocketModule->spawn_pending_socket(socket, &newSocket);
|
||||
|
||||
gSocketModule->set_connected(newSocket);
|
||||
|
||||
release_sem(fAcceptSemaphore);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Ruiz Dorantes, oliver-ruiz.dorantes_at_gmail.com
|
||||
/*
|
||||
* Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef L2CAP_ENDPOINT_H
|
||||
#define L2CAP_ENDPOINT_H
|
||||
@@ -47,17 +44,18 @@ public:
|
||||
mutex_unlock(&fLock);
|
||||
}
|
||||
|
||||
status_t Bind(const struct sockaddr *_address);
|
||||
status_t Unbind();
|
||||
status_t Listen(int backlog);
|
||||
status_t Connect(const struct sockaddr *address);
|
||||
status_t Accept(net_socket **_acceptedSocket);
|
||||
status_t Bind(const struct sockaddr *_address);
|
||||
status_t Unbind();
|
||||
status_t Listen(int backlog);
|
||||
status_t Connect(const struct sockaddr *address);
|
||||
status_t Accept(net_socket **_acceptedSocket);
|
||||
|
||||
ssize_t Send(const iovec *vecs, size_t vecCount,
|
||||
ancillary_data_container *ancillaryData);
|
||||
ssize_t Receive(const iovec *vecs, size_t vecCount,
|
||||
ancillary_data_container **_ancillaryData,
|
||||
struct sockaddr *_address, socklen_t *_addressLength);
|
||||
|
||||
ssize_t Send(const iovec *vecs, size_t vecCount,
|
||||
ancillary_data_container *ancillaryData);
|
||||
ssize_t Receive(const iovec *vecs, size_t vecCount,
|
||||
ancillary_data_container **_ancillaryData, struct sockaddr *_address,
|
||||
socklen_t *_addressLength);
|
||||
ssize_t ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer);
|
||||
ssize_t Sendable();
|
||||
ssize_t Receivable();
|
||||
@@ -67,15 +65,19 @@ public:
|
||||
|
||||
status_t Shutdown(int direction);
|
||||
|
||||
void BindToChannel(L2capChannel* channel);
|
||||
|
||||
static L2capEndpoint* ForPsm(uint16 psm);
|
||||
|
||||
ChannelConfiguration configuration;
|
||||
L2capChannel* channel;
|
||||
|
||||
bool configurationSet;
|
||||
net_fifo fReceivingFifo;
|
||||
void BindToChannel(L2capChannel* channel);
|
||||
status_t MarkEstablished();
|
||||
|
||||
static L2capEndpoint* ForPsm(uint16 psm);
|
||||
|
||||
bool RequiresConfiguration()
|
||||
{
|
||||
return fConfigurationSet;
|
||||
}
|
||||
|
||||
ChannelConfiguration configuration;
|
||||
net_fifo fReceivingFifo;
|
||||
bool fConfigurationSet;
|
||||
|
||||
private:
|
||||
typedef enum {
|
||||
@@ -101,7 +103,7 @@ private:
|
||||
State fState;
|
||||
L2capEndpoint* fPeerEndpoint;
|
||||
sem_id fAcceptSemaphore;
|
||||
|
||||
L2capChannel* fChannel;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -126,9 +126,7 @@ l2cap_connect(net_protocol* protocol, const struct sockaddr* address)
|
||||
status_t
|
||||
l2cap_accept(net_protocol* protocol, struct net_socket** _acceptedSocket)
|
||||
{
|
||||
flowf("\n");
|
||||
|
||||
return EOPNOTSUPP;
|
||||
return ((L2capEndpoint*)protocol)->Accept(_acceptedSocket);
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +158,7 @@ l2cap_setsockopt(net_protocol* protocol, int level, int option,
|
||||
{
|
||||
flowf("\n");
|
||||
|
||||
((L2capEndpoint*)protocol)->configurationSet = true;
|
||||
((L2capEndpoint*)protocol)->fConfigurationSet = true;
|
||||
|
||||
/* return protocol->next->module->setsockopt(protocol->next, level, option, value, length); */
|
||||
return EOPNOTSUPP;
|
||||
|
||||
@@ -100,7 +100,8 @@ l2cap_process_cmd_rej(HciConnection* conn, uint8 ident, net_buffer* buffer);
|
||||
status_t
|
||||
l2cap_process_signal_cmd(HciConnection* conn, net_buffer* buffer)
|
||||
{
|
||||
net_buffer* m = buffer;
|
||||
net_buffer* m = buffer;
|
||||
|
||||
debugf("Signal size=%ld\n", buffer->size);
|
||||
|
||||
while (m != NULL) {
|
||||
@@ -212,8 +213,8 @@ l2cap_process_signal_cmd(HciConnection* conn, net_buffer* buffer)
|
||||
static status_t
|
||||
l2cap_process_con_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
||||
{
|
||||
L2capChannel* ch;
|
||||
uint16 dcid, psm;
|
||||
L2capChannel* ch;
|
||||
uint16 dcid, psm;
|
||||
|
||||
/* Get con req data */
|
||||
NetBufferHeaderReader<l2cap_con_req_cp> command(buffer);
|
||||
@@ -262,9 +263,9 @@ l2cap_process_con_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
||||
static status_t
|
||||
l2cap_process_con_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
||||
{
|
||||
L2capFrame* cmd = NULL;
|
||||
uint16 scid, dcid, result, status;
|
||||
status_t error = 0;
|
||||
L2capFrame* cmd = NULL;
|
||||
uint16 scid, dcid, result, status;
|
||||
status_t error = 0;
|
||||
|
||||
/* Get command parameters */
|
||||
NetBufferHeaderReader<l2cap_con_rsp_cp> command(buffer);
|
||||
@@ -359,7 +360,7 @@ reject:
|
||||
static option_status
|
||||
getNextSignalOption(net_buffer* nbuf, size_t* off, l2cap_cfg_opt_t* hdr, l2cap_cfg_opt_val_t* val)
|
||||
{
|
||||
int hint;
|
||||
int hint;
|
||||
size_t len = nbuf->size - (*off);
|
||||
|
||||
if (len == 0)
|
||||
@@ -425,16 +426,16 @@ getNextSignalOption(net_buffer* nbuf, size_t* off, l2cap_cfg_opt_t* hdr, l2cap_c
|
||||
static status_t
|
||||
l2cap_process_cfg_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
||||
{
|
||||
L2capChannel* channel = NULL;
|
||||
uint16 dcid;
|
||||
uint16 respond;
|
||||
uint16 result;
|
||||
L2capChannel* channel = NULL;
|
||||
uint16 dcid;
|
||||
uint16 respond;
|
||||
uint16 result;
|
||||
|
||||
l2cap_cfg_opt_t hdr;
|
||||
l2cap_cfg_opt_t hdr;
|
||||
l2cap_cfg_opt_val_t val;
|
||||
|
||||
size_t off;
|
||||
status_t error = 0;
|
||||
size_t off;
|
||||
status_t error = 0;
|
||||
|
||||
|
||||
debugf("configuration=%ld\n", buffer->size);
|
||||
@@ -554,14 +555,14 @@ reject:
|
||||
static status_t
|
||||
l2cap_process_cfg_rsp(HciConnection *conn, uint8 ident, net_buffer *buffer)
|
||||
{
|
||||
L2capFrame *cmd = NULL;
|
||||
uint16 scid, cflag, result;
|
||||
L2capFrame *cmd = NULL;
|
||||
uint16 scid, cflag, result;
|
||||
|
||||
l2cap_cfg_opt_t hdr;
|
||||
l2cap_cfg_opt_val_t val;
|
||||
l2cap_cfg_opt_t hdr;
|
||||
l2cap_cfg_opt_val_t val;
|
||||
|
||||
size_t off;
|
||||
status_t error = 0;
|
||||
size_t off;
|
||||
status_t error = 0;
|
||||
|
||||
NetBufferHeaderReader<l2cap_cfg_rsp_cp> command(buffer);
|
||||
status_t status = command.Status();
|
||||
@@ -655,7 +656,7 @@ l2cap_process_cfg_rsp(HciConnection *conn, uint8 ident, net_buffer *buffer)
|
||||
btCoreData->TimeoutSignal(cmd, bluetooth_l2cap_rtx_timeout);
|
||||
else {
|
||||
/* Send L2CA_Config response to the upper layer protocol */
|
||||
//INDICATION error = ng_l2cap_l2ca_cfg_rsp(cmd->channel, cmd->token, result);
|
||||
error = l2cap_upper_cfg_rsp(cmd->channel /*, cmd->token, result*/);
|
||||
if (error != 0) {
|
||||
/*
|
||||
* XXX FIXME what to do here? we were not able to send
|
||||
@@ -668,10 +669,7 @@ l2cap_process_cfg_rsp(HciConnection *conn, uint8 ident, net_buffer *buffer)
|
||||
|
||||
btCoreData->RemoveChannel(conn, cmd->channel->scid);
|
||||
}
|
||||
cmd->channel->cfgState |= L2CAP_CFG_OUT;
|
||||
if ((cmd->channel->cfgState & L2CAP_CFG_BOTH) == L2CAP_CFG_BOTH) {
|
||||
cmd->channel->state = L2CAP_CHAN_OPEN;
|
||||
}
|
||||
|
||||
btCoreData->AcknowledgeSignal(cmd);
|
||||
}
|
||||
|
||||
@@ -770,7 +768,7 @@ reject:
|
||||
static status_t
|
||||
l2cap_process_discon_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
||||
{
|
||||
L2capFrame *cmd = NULL;
|
||||
L2capFrame* cmd = NULL;
|
||||
int16 scid, dcid;
|
||||
status_t error = 0;
|
||||
|
||||
@@ -827,7 +825,7 @@ out:
|
||||
static status_t
|
||||
l2cap_process_echo_req(HciConnection *conn, uint8 ident, net_buffer *buffer)
|
||||
{
|
||||
L2capFrame *cmd = NULL;
|
||||
L2capFrame* cmd = NULL;
|
||||
|
||||
cmd = btCoreData->SpawnSignal(conn, NULL, l2cap_echo_req(ident, NULL, 0), ident, L2CAP_ECHO_RSP);
|
||||
if (cmd == NULL) {
|
||||
@@ -917,8 +915,8 @@ static status_t
|
||||
l2cap_process_info_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
||||
{
|
||||
l2cap_info_rsp_cp* cp = NULL;
|
||||
L2capFrame* cmd = NULL;
|
||||
status_t error = B_OK;
|
||||
L2capFrame* cmd = NULL;
|
||||
status_t error = B_OK;
|
||||
|
||||
/* Get command parameters */
|
||||
NetBufferHeaderReader<l2cap_info_rsp_cp> command(buffer);
|
||||
@@ -950,8 +948,7 @@ l2cap_process_info_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer)
|
||||
switch (command->type) {
|
||||
|
||||
case L2CAP_CONNLESS_MTU:
|
||||
/*
|
||||
// TODO: Check specs ??
|
||||
/* TODO: Check specs ??
|
||||
if (conn->rx_pkt->m_pkthdr.len == sizeof(uint16)) {
|
||||
*mtod(conn->rx_pkt, uint16 *) = le16toh(*mtod(conn->rx_pkt,uint16 *));
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
*/
|
||||
#include <KernelExport.h>
|
||||
#include <NetBufferUtilities.h>
|
||||
@@ -31,17 +30,17 @@ l2cap_l2ca_con_ind(L2capChannel* channel)
|
||||
}
|
||||
|
||||
// Pair Channel with endpoint
|
||||
channel->endpoint = endpoint;
|
||||
endpoint->BindToChannel(channel);
|
||||
|
||||
debugf("Endpoint %p bound for psm %d, schannel %x dchannel %x\n",endpoint, channel->psm, channel->scid, channel->dcid);
|
||||
|
||||
net_buffer* buf = l2cap_con_rsp(channel->ident, channel->scid, channel->dcid, L2CAP_SUCCESS, L2CAP_NO_INFO);
|
||||
L2capFrame* cmd = btCoreData->SpawnSignal(channel->conn, channel, buf, channel->ident, L2CAP_CON_RSP);
|
||||
net_buffer* buf = l2cap_con_rsp(channel->ident, channel->scid, channel->dcid,
|
||||
L2CAP_SUCCESS, L2CAP_NO_INFO);
|
||||
L2capFrame* cmd = btCoreData->SpawnSignal(channel->conn, channel, buf,
|
||||
channel->ident, L2CAP_CON_RSP);
|
||||
if (cmd == NULL) {
|
||||
gBufferModule->free(buf);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
// we can move to configuration...
|
||||
channel->state = L2CAP_CHAN_CONFIG;
|
||||
|
||||
@@ -54,12 +53,16 @@ l2cap_l2ca_con_ind(L2capChannel* channel)
|
||||
status_t
|
||||
l2cap_l2ca_cfg_rsp_ind(L2capChannel* channel)
|
||||
{
|
||||
// if our configuration has not been yet send ..
|
||||
// if our configuration has not been yet sent ...
|
||||
if(!(channel->cfgState & L2CAP_CFG_OUT_SENT)) {
|
||||
// send config_rsp
|
||||
|
||||
net_buffer* buf = l2cap_cfg_rsp(channel->ident, channel->dcid, 0, L2CAP_SUCCESS, NULL);
|
||||
L2capFrame* cmd = btCoreData->SpawnSignal(channel->conn, channel, buf, channel->ident, L2CAP_CFG_RSP);
|
||||
// TODO: check if we can handle this conf
|
||||
|
||||
// send config_rsp
|
||||
net_buffer* buf = l2cap_cfg_rsp(channel->ident, channel->dcid, 0,
|
||||
L2CAP_SUCCESS, NULL);
|
||||
L2capFrame* cmd = btCoreData->SpawnSignal(channel->conn, channel, buf,
|
||||
channel->ident, L2CAP_CFG_RSP);
|
||||
if (cmd == NULL) {
|
||||
gBufferModule->free(buf);
|
||||
channel->state = L2CAP_CHAN_CLOSED;
|
||||
@@ -67,7 +70,7 @@ l2cap_l2ca_cfg_rsp_ind(L2capChannel* channel)
|
||||
}
|
||||
|
||||
flowf("Sending cfg resp\n");
|
||||
/* Link command to the queue */
|
||||
// Link command to the queue
|
||||
SchedConnectionPurgeThread(channel->conn);
|
||||
|
||||
// set status
|
||||
@@ -82,22 +85,26 @@ l2cap_l2ca_cfg_rsp_ind(L2capChannel* channel)
|
||||
if ((channel->cfgState & L2CAP_CFG_BOTH) == L2CAP_CFG_BOTH) {
|
||||
// Channel can be declared open
|
||||
channel->state = L2CAP_CHAN_OPEN;
|
||||
channel->endpoint->MarkEstablished();
|
||||
|
||||
} else {
|
||||
// send configuration Request by our side
|
||||
if (channel->endpoint->configurationSet) {
|
||||
if (channel->endpoint->RequiresConfiguration()) {
|
||||
// TODO: define complete configuration packet
|
||||
|
||||
} else {
|
||||
// nothing special requested
|
||||
net_buffer* buf = l2cap_cfg_req(channel->ident, channel->dcid, 0, NULL);
|
||||
L2capFrame* cmd = btCoreData->SpawnSignal(channel->conn, channel, buf, channel->ident, L2CAP_CFG_REQ);
|
||||
L2capFrame* cmd = btCoreData->SpawnSignal(channel->conn, channel, buf,
|
||||
channel->ident, L2CAP_CFG_REQ);
|
||||
if (cmd == NULL) {
|
||||
gBufferModule->free(buf);
|
||||
channel->state = L2CAP_CHAN_CLOSED;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
flowf("Sending cfg req\n");
|
||||
|
||||
// Link command to the queue
|
||||
SchedConnectionPurgeThread(channel->conn);
|
||||
|
||||
@@ -109,6 +116,19 @@ l2cap_l2ca_cfg_rsp_ind(L2capChannel* channel)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_upper_cfg_rsp(L2capChannel* channel)
|
||||
{
|
||||
channel->cfgState |= L2CAP_CFG_OUT;
|
||||
if ((channel->cfgState & L2CAP_CFG_BOTH) == L2CAP_CFG_BOTH) {
|
||||
channel->state = L2CAP_CHAN_OPEN;
|
||||
return channel->endpoint->MarkEstablished();
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_upper_con_rsp(HciConnection* conn, L2capChannel* channel)
|
||||
{
|
||||
@@ -121,6 +141,7 @@ l2cap_upper_con_rsp(HciConnection* conn, L2capChannel* channel)
|
||||
status_t
|
||||
l2cap_co_receive(HciConnection* conn, net_buffer* buffer, uint16 dcid)
|
||||
{
|
||||
debugf("Handle %d To dcid %d\n", conn->handle, dcid);
|
||||
|
||||
L2capChannel* channel = btCoreData->ChannelBySourceID(conn, dcid);
|
||||
|
||||
@@ -134,7 +155,22 @@ l2cap_co_receive(HciConnection* conn, net_buffer* buffer, uint16 dcid)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
flowf("Enqueue to fifo\n");
|
||||
return gStackModule->fifo_enqueue_buffer(&channel->endpoint->fReceivingFifo, buffer);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_cl_receive(HciConnection* conn, net_buffer* buffer, uint16 psm)
|
||||
{
|
||||
|
||||
L2capEndpoint* endpoint = L2capEndpoint::ForPsm(psm);
|
||||
|
||||
if (endpoint == NULL) {
|
||||
debugf("no enpoint bound with psm %d\n", psm);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
flowf("Enqueue to fifo\n");
|
||||
return gStackModule->fifo_enqueue_buffer(&endpoint->fReceivingFifo, buffer);
|
||||
|
||||
}
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
#include "l2cap_internal.h"
|
||||
|
||||
status_t l2cap_l2ca_con_ind(L2capChannel* channel);
|
||||
status_t l2cap_upper_con_rsp(HciConnection* conn, L2capChannel* channel);
|
||||
status_t l2cap_l2ca_cfg_rsp_ind(L2capChannel* channel);
|
||||
|
||||
status_t l2cap_upper_con_rsp(HciConnection* conn, L2capChannel* channel);
|
||||
status_t l2cap_upper_cfg_rsp(L2capChannel* channel);
|
||||
|
||||
|
||||
status_t l2cap_co_receive(HciConnection* conn, net_buffer* buffer, uint16 dcid);
|
||||
status_t l2cap_cl_receive(HciConnection* conn, net_buffer* buffer, uint16 psm);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user