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