- Proper implementation of accept/bind l2cap socket interface

- Add more debug info for the KDL debug command
- Request channel pointer also for non l2cap signal frames
- Add locks for packet queues



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34333 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Ruiz Dorantes 2009-11-28 20:03:15 +00:00
parent cf3d8a746f
commit 31f8763031
12 changed files with 367 additions and 183 deletions

View File

@ -6,6 +6,7 @@
#define _BTCOREDATA_H
#include <module.h>
#include <lock.h>
#include <util/DoublyLinkedList.h>
#include <util/DoublyLinkedQueue.h>
@ -30,6 +31,9 @@ typedef enum _connection_status {
#ifdef __cplusplus
struct HciConnection : DoublyLinkedListLinkImpl<HciConnection> {
HciConnection();
virtual ~HciConnection();
hci_id Hid;
struct net_device* ndevice;
net_buffer* currentRxPacket;
@ -44,6 +48,8 @@ struct HciConnection : DoublyLinkedListLinkImpl<HciConnection> {
DoublyLinkedList<L2capChannel> ChannelList;
DoublyLinkedList<L2capFrame> ExpectedResponses;
DoublyLinkedList<L2capFrame> OutGoingFrames;
mutex fLock;
mutex fLockExpected;
};
#else
@ -84,7 +90,7 @@ struct L2capChannel : DoublyLinkedListLinkImpl<L2capChannel> {
uint16 psm;
uint8 ident;
uint8 cfgState;
channel_status state;
ChannelConfiguration* configuration;
L2capEndpoint* endpoint;
@ -154,9 +160,10 @@ struct bluetooth_core_data_module_info {
struct L2capFrame* (*SignalByIdent)(struct HciConnection* conn, uint8 ident);
status_t (*TimeoutSignal)(struct L2capFrame* frame, uint32 timeo);
status_t (*UnTimeoutSignal)(struct L2capFrame* frame);
struct L2capFrame* (*SpawnFrame)(struct HciConnection* conn, net_buffer* buffer, frame_type frame);
struct L2capFrame* (*SpawnFrame)(struct HciConnection* conn, struct L2capChannel* channel, net_buffer* buffer, frame_type frame);
struct L2capFrame* (*SpawnSignal)(struct HciConnection* conn, struct L2capChannel* channel, net_buffer* buffer, uint8 ident, uint8 code);
status_t (*AcknowledgeSignal)(struct L2capFrame* frame);
status_t (*QueueSignal)(struct L2capFrame* frame);
};

View File

@ -34,53 +34,73 @@ ExistConnectionByHandle(uint16 handle, hci_id hid)
static int
DumpHciConnections(int argc, char** argv)
{
HciConnection* conn;
L2capChannel* chan;
HciConnection* conn;
L2capChannel* chan;
L2capFrame* frame;
DoublyLinkedList<HciConnection>::Iterator iterator = sConnectionList.GetIterator();
while (iterator.HasNext()) {
conn = iterator.Next();
kprintf("\tLocalDevice=%lx Destination=%s handle=%#x type=%d outqueue=%ld expected=%ld\n",
kprintf("LocalDevice=%lx Destination=%s handle=%#x type=%d outqueue=%ld expected=%ld\n",
conn->Hid, bdaddrUtils::ToString(conn->destination),
conn->handle, conn->type, conn->OutGoingFrames.Count() , conn->ExpectedResponses.Count());
// each channel
kprintf("\tChannels\n");
DoublyLinkedList<L2capChannel>::Iterator channelIterator = conn->ChannelList.GetIterator();
while (channelIterator.HasNext()) {
chan = channelIterator.Next();
kprintf("\t\tscid=%x dcid=%x state=%x cfg=%x\n", chan->scid,
chan = channelIterator.Next();
kprintf("\t\tscid=%x dcid=%x state=%x cfg=%x\n", chan->scid,
chan->dcid, chan->state, chan->cfgState);
}
// Each outgoing
kprintf("\n\tOutGoingFrames\n");
DoublyLinkedList<L2capFrame>::Iterator frameIterator = conn->OutGoingFrames.GetIterator();
while (frameIterator.HasNext()) {
frame = frameIterator.Next();
kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n", frame->channel->scid,
frame->code, frame->ident, frame->type, frame->buffer);
}
// Each expected
kprintf("\n\tExpectedFrames\n");
DoublyLinkedList<L2capFrame>::Iterator frameExpectedIterator = conn->ExpectedResponses.GetIterator();
while (frameExpectedIterator.HasNext()) {
frame = frameExpectedIterator.Next();
kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n", frame->channel->scid,
frame->code, frame->ident, frame->type, frame->buffer);
}
}
return 0;
}
status_t
PostEvent(net_device* ndev, void* event, size_t size)
{
struct hci_event_header* outgoingEvent = (struct hci_event_header*) event;
status_t err;
// Take actions on certain type of events.
switch (outgoingEvent->ecode) {
case HCI_EVENT_CONN_COMPLETE:
{
struct hci_ev_conn_complete* data = (struct hci_ev_conn_complete*)(outgoingEvent+1);
//TODO: XXX parse handle field
//TODO: XXX parse handle field
HciConnection* conn = AddConnection(data->handle, BT_ACL, &data->bdaddr, ndev->index);
if (conn == NULL)
panic("no mem for conn desc");
conn->ndevice = ndev;
debugf("Registered connection handle=%#x\n",data->handle);
} break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
{
struct hci_ev_disconnection_complete_reply* data =
struct hci_ev_disconnection_complete_reply* data =
(struct hci_ev_disconnection_complete_reply*)(outgoingEvent+1);
RemoveConnection(data->handle, ndev->index);
debugf("unRegistered connection handle=%#x\n",data->handle);
@ -90,13 +110,13 @@ PostEvent(net_device* ndev, void* event, size_t size)
// forward to bluetooth server
port_id port = find_port(BT_USERLAND_PORT_NAME);
if (port != B_NAME_NOT_FOUND) {
err = write_port_etc(port, PACK_PORTCODE(BT_EVENT, ndev->index, -1),
event, size, B_TIMEOUT, 1*1000*1000);
if (err != B_OK)
if (err != B_OK)
debugf("Error posting userland %s\n", strerror(err));
} else {
flowf("ERROR:bluetooth_server not found for posting\n");
err = B_NAME_NOT_FOUND;
@ -115,23 +135,23 @@ bcd_std_ops(int32 op, ...)
switch (op) {
case B_MODULE_INIT:
new (&sConnectionList) DoublyLinkedList<HciConnection>;
add_debugger_command("btConnections", &DumpHciConnections,
add_debugger_command("btConnections", &DumpHciConnections,
"Lists Bluetooth Connections with RemoteDevices & channels");
status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule);
if (status < B_OK) {
return status;
}
return B_OK;
break;
case B_MODULE_UNINIT:
remove_debugger_command("btConnections", &DumpHciConnections);
put_module(NET_BUFFER_MODULE_NAME);
return B_OK;
break;
}
@ -172,7 +192,8 @@ bluetooth_core_data_module_info sBCDModule = {
unTimeoutSignal,
SpawmFrame,
SpawmSignal,
AcknowledgeSignal
AcknowledgeSignal,
QueueSignal,
};

View File

@ -21,20 +21,35 @@
void PurgeChannels(HciConnection* conn);
HciConnection::HciConnection()
{
mutex_init(&fLock, "conn outgoing");
mutex_init(&fLockExpected, "frame expected");
}
HciConnection::~HciConnection()
{
mutex_destroy(&fLock);
mutex_destroy(&fLockExpected);
}
HciConnection*
AddConnection(uint16 handle, int type, bdaddr_t* dst, hci_id hid)
{
// Create connection descriptor
HciConnection* conn = ConnectionByHandle(handle, hid);
if (conn != NULL)
if (conn != NULL)
goto update;
conn = new (std::nothrow) HciConnection;
if (conn == NULL)
goto bail;
memset(conn, 0, sizeof(HciConnection));
//memset(conn, 0, sizeof(HciConnection));
conn->currentRxPacket = NULL;
conn->currentRxExpectedLength = 0;

View File

@ -5,22 +5,27 @@
#define SUBMODULE_COLOR 31
#include <btDebug.h>
#include <lock.h>
L2capFrame*
SignalByIdent(HciConnection* conn, uint8 ident)
{
L2capFrame* frame;
mutex_lock(&conn->fLockExpected);
DoublyLinkedList<L2capFrame>::Iterator iterator = conn->ExpectedResponses.GetIterator();
while (iterator.HasNext()) {
frame = iterator.Next();
if (frame->type == L2CAP_C_FRAME && frame->ident == ident) {
mutex_unlock(&frame->conn->fLockExpected);
return frame;
}
}
mutex_unlock(&conn->fLockExpected);
return NULL;
}
@ -45,7 +50,7 @@ unTimeoutSignal(L2capFrame* frame)
L2capFrame*
SpawmFrame(HciConnection* conn, net_buffer* buffer, frame_type type)
SpawmFrame(HciConnection* conn, L2capChannel* channel, net_buffer* buffer, frame_type type)
{
if (buffer == NULL)
panic("Null Buffer to outgoing queue");
@ -53,13 +58,17 @@ SpawmFrame(HciConnection* conn, net_buffer* buffer, frame_type type)
L2capFrame* frame = new (std::nothrow) L2capFrame;
frame->conn = conn;
frame->channel = NULL; // TODO: needed?
frame->channel = channel; // TODO: maybe only scid needed
frame->buffer = buffer;
frame->type = type;
mutex_lock(&conn->fLock);
conn->OutGoingFrames.Add(frame, true);
mutex_unlock(&conn->fLock);
return frame;
}
@ -73,15 +82,19 @@ SpawmSignal(HciConnection* conn, L2capChannel* channel, net_buffer* buffer, uint
L2capFrame* frame = new (std::nothrow) L2capFrame;
frame->conn = conn;
frame->channel = channel; // TODO: needed?
frame->channel = channel; // TODO: not specific descriptor should be required
frame->buffer = buffer;
frame->type = L2CAP_C_FRAME;
frame->ident = ident;
frame->code = code;
mutex_lock(&conn->fLock);
conn->OutGoingFrames.Add(frame, true);
mutex_unlock(&conn->fLock);
return frame;
}
@ -91,17 +104,36 @@ AcknowledgeSignal(L2capFrame* frame)
{
if (frame != NULL) {
if (frame->type == L2CAP_C_FRAME) {
unTimeoutSignal(frame);
frame->conn->ExpectedResponses.Remove(frame);
mutex_lock(&frame->conn->fLockExpected);
// frame->conn->ExpectedResponses.Remove(frame);
mutex_unlock(&frame->conn->fLockExpected);
}
gBufferModule->free(frame->buffer);
delete frame;
return B_OK;
}
return B_ERROR;
}
status_t
QueueSignal(L2capFrame* frame)
{
if (frame != NULL) {
if (frame->type == L2CAP_C_FRAME) {
mutex_lock(&frame->conn->fLockExpected);
frame->conn->ExpectedResponses.Add(frame);
mutex_unlock(&frame->conn->fLockExpected);
return B_OK;
}
}
return B_ERROR;
}

View File

@ -17,7 +17,7 @@ status_t
unTimeoutSignal(L2capFrame* frame);
L2capFrame*
SpawmFrame(HciConnection* conn, net_buffer* buffer, frame_type frame);
SpawmFrame(HciConnection* conn, L2capChannel* channel, net_buffer* buffer, frame_type frame);
L2capFrame*
SpawmSignal(HciConnection* conn, L2capChannel* channel, net_buffer* buffer, uint8 ident, uint8 code);
@ -25,4 +25,7 @@ SpawmSignal(HciConnection* conn, L2capChannel* channel, net_buffer* buffer, uint
status_t
AcknowledgeSignal(L2capFrame* frame);
status_t
QueueSignal(L2capFrame* frame);
#endif

View File

@ -4,6 +4,7 @@
*/
#include "L2capEndpoint.h"
#include "l2cap_address.h"
#include "l2cap_upper.h"
#include <stdio.h>
#include <string.h>
@ -33,22 +34,23 @@ L2capEndpoint::L2capEndpoint(net_socket* socket)
:
ProtocolSocket(socket),
fConfigurationSet(false),
fPeerEndpoint(NULL),
fAcceptSemaphore(-1),
fPeerEndpoint(NULL),
fChannel(NULL)
{
debugf("[%ld] %p\n", find_thread(NULL), this);
/* Set MTU and flow control settings to defaults */
configuration.imtu = L2CAP_MTU_DEFAULT;
memcpy(&configuration.iflow, &default_qos , sizeof(l2cap_flow_t) );
fConfiguration.imtu = L2CAP_MTU_DEFAULT;
memcpy(&fConfiguration.iflow, &default_qos , sizeof(l2cap_flow_t) );
configuration.omtu = L2CAP_MTU_DEFAULT;
memcpy(&configuration.oflow, &default_qos , sizeof(l2cap_flow_t) );
fConfiguration.omtu = L2CAP_MTU_DEFAULT;
memcpy(&fConfiguration.oflow, &default_qos , sizeof(l2cap_flow_t) );
configuration.flush_timo = L2CAP_FLUSH_TIMO_DEFAULT;
configuration.link_timo = L2CAP_LINK_TIMO_DEFAULT;
fConfiguration.flush_timo = L2CAP_FLUSH_TIMO_DEFAULT;
fConfiguration.link_timo = L2CAP_LINK_TIMO_DEFAULT;
// TODO: XXX not for listening endpoints, imtu should be known first
gStackModule->init_fifo(&fReceivingFifo, "l2cap recvfifo", L2CAP_MTU_DEFAULT);
}
@ -57,6 +59,7 @@ L2capEndpoint::~L2capEndpoint()
{
debugf("[%ld] %p\n", find_thread(NULL), this);
gStackModule->uninit_fifo(&fReceivingFifo);
}
@ -95,7 +98,28 @@ L2capEndpoint::Close()
{
debugf("[%ld] %p\n", find_thread(NULL), this);
return B_OK;
if (fAcceptSemaphore != -1) {
debugf("server socket not handling any channel %p\n", this);
delete_sem(fAcceptSemaphore);
// TODO: Clean needed stuff
// Unbind?
return B_OK;
} else {
// Client endpoint
if (fState == CLOSING) {
debugf("Already closed by peer %p\n", this);
// TODO: Clean needed stuff
return B_OK;
} else {
// Issue Disconnection request over the channel
fState = CLOSED;
return l2cap_upper_dis_req(fChannel);
}
}
}
@ -111,18 +135,18 @@ L2capEndpoint::Free()
status_t
L2capEndpoint::Bind(const struct sockaddr *_address)
{
if (_address == NULL)
panic("null adrresss!");
if (_address == NULL)
return B_ERROR;
if (_address->sa_family != AF_BLUETOOTH )
return EAFNOSUPPORT;
// TODO: Check socladdr_l2cap size
//if (_address->sa_len != sizeof(struct sockaddr_l2cap))
// return EAFNOSUPPORT;
// TODO: Check if that PSM is already bound
// return EADDRINUSE;
// TODO: Check if the PSM is valid, check assigned numbers document for valid
// psm available to applications.
// All PSM values shall be ODD, that is, the least significant bit of the least
@ -136,10 +160,9 @@ L2capEndpoint::Bind(const struct sockaddr *_address)
memcpy(&socket->address, _address, sizeof(struct sockaddr_l2cap));
socket->address.ss_len = sizeof(struct sockaddr_l2cap);
fState = CLOSED;
fState = BOUND;
return B_OK;
}
@ -157,8 +180,8 @@ L2capEndpoint::Listen(int backlog)
{
debugf("[%ld] %p\n", find_thread(NULL), this);
if (fState != CLOSED) {
flowf("Invalid State\n");
if (fState != BOUND) {
debugf("Invalid State %p\n", this);
return B_BAD_VALUE;
}
@ -216,20 +239,17 @@ L2capEndpoint::Accept(net_socket **_acceptedSocket)
// locker.Lock();
status = gSocketModule->dequeue_connected(socket, _acceptedSocket);
if (status != B_OK)
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;
} else {
((L2capEndpoint*)((*_acceptedSocket)->first_protocol))->fState = ESTABLISHED;
// unassign any channel for the parent endpoint
fChannel = NULL;
// we are listening again
fState = LISTEN;
}
} while (status != B_OK);
return status;
@ -255,6 +275,10 @@ L2capEndpoint::Receive(const iovec *vecs, size_t vecCount,
debugf("[%ld] %p Receive(%p, %ld)\n", find_thread(NULL),
this, vecs, vecCount);
if (fState != ESTABLISHED) {
debugf("Invalid State %p\n", this);
return B_BAD_VALUE;
}
return B_OK;
}
@ -263,6 +287,12 @@ L2capEndpoint::Receive(const iovec *vecs, size_t vecCount,
ssize_t
L2capEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer)
{
debugf("e->%p num=%ld, f=%ld)\n", this, numBytes, flags);
if (fState != ESTABLISHED) {
debugf("Invalid State %p\n", this);
return B_BAD_VALUE;
}
return gStackModule->fifo_dequeue_buffer(&fReceivingFifo, flags,
B_INFINITE_TIMEOUT, _buffer);
@ -274,7 +304,7 @@ L2capEndpoint::Sendable()
{
debugf("[%ld] %p\n", find_thread(NULL), this);
return 0;
return B_OK;
}
@ -311,14 +341,31 @@ L2capEndpoint::ForPsm(uint16 psm)
void
L2capEndpoint::BindToChannel(L2capChannel* channel)
{
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);
net_socket* newSocket;
status_t error = gSocketModule->spawn_pending_socket(socket, &newSocket);
if (error != B_OK) {
debugf("Could not spawn child for Endpoint %p\n", this);
// TODO: Handle situation
return;
}
L2capEndpoint* endpoint = (L2capEndpoint*)newSocket->first_protocol;
endpoint->fChannel = channel;
endpoint->fPeerEndpoint = this;
channel->endpoint = endpoint;
debugf("new socket %p/e->%p from parent %p/e->%p\n", newSocket, endpoint, socket, this);
// Provide the channel the configuration set by the user socket
channel->configuration = &fConfiguration;
// It might be used keep the last negotiated channel
// fChannel = channel;
debugf("New endpoint %p for psm %d, schannel %x dchannel %x\n", endpoint,
channel->psm, channel->scid, channel->dcid);
}
@ -328,12 +375,23 @@ 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);
status_t error = gSocketModule->set_connected(socket);
if (error == B_OK) {
release_sem(fPeerEndpoint->fAcceptSemaphore);
} else {
debugf("Could not set child Endpoint %p %s\n", this, strerror(error));
}
return error;
}
status_t
L2capEndpoint::MarkClosed()
{
flowf("\n");
fState = CLOSED;
return B_OK;
}

View File

@ -67,6 +67,7 @@ public:
void BindToChannel(L2capChannel* channel);
status_t MarkEstablished();
status_t MarkClosed();
static L2capEndpoint* ForPsm(uint16 psm);
@ -75,17 +76,16 @@ public:
return fConfigurationSet;
}
ChannelConfiguration configuration;
net_fifo fReceivingFifo;
ChannelConfiguration fConfiguration;
bool fConfigurationSet;
net_fifo fReceivingFifo;
private:
typedef enum {
// establishing a connection
CLOSED,
BOUND,
LISTEN,
SYNCHRONIZE_SENT,
SYNCHRONIZE_RECEIVED,
ESTABLISHED,
// peer closes the connection
@ -101,9 +101,10 @@ private:
mutex fLock;
State fState;
L2capEndpoint* fPeerEndpoint;
sem_id fAcceptSemaphore;
L2capEndpoint* fPeerEndpoint;
L2capChannel* fChannel;
};

View File

@ -64,7 +64,7 @@ l2cap_init_protocol(net_socket* socket)
{
flowf("\n");
L2capEndpoint* protocol = new (std::nothrow) L2capEndpoint(socket);
L2capEndpoint* protocol = new(std::nothrow) L2capEndpoint(socket);
if (protocol == NULL)
return NULL;
@ -79,10 +79,13 @@ l2cap_uninit_protocol(net_protocol* protocol)
{
flowf("\n");
// TODO: Some more checkins / uninit
EndpointList.Remove((L2capEndpoint*)protocol);
L2capEndpoint* endpoint = static_cast<L2capEndpoint*>(protocol);
delete protocol;
// TODO: Some more checkins / uninit
EndpointList.Remove(endpoint);
delete endpoint;
return B_OK;
}

View File

@ -18,6 +18,7 @@
*/
#include <KernelExport.h>
#include <string.h>
#include <lock.h>
#include <NetBufferUtilities.h>
@ -41,7 +42,7 @@ l2cap_receive(HciConnection* conn, net_buffer* buffer)
status_t error = B_OK;
uint16 dcid;
uint16 length;
/* Check packet */
if (buffer->size < sizeof(l2cap_hdr_t)) {
debugf("invalid L2CAP packet. Packet too small, len=%ld\n", buffer->size);
@ -103,19 +104,23 @@ static thread_id sConnectionThread;
void
purge_connection(HciConnection* conn)
{
L2capFrame* frame;
debugf("handle=%d\n",conn->handle);
debugf("handle=%d\n", conn->handle);
mutex_lock(&conn->fLock);
frame = conn->OutGoingFrames.RemoveHead();
mutex_unlock(&conn->fLock);
frame = conn->OutGoingFrames.RemoveHead();
// while ( frame != NULL) {
// Here is the place to decide how many l2cap signals we want to have
// per l2cap packet. 1 ATM
// per l2cap packet. 1 ATM
if (frame->type == L2CAP_C_FRAME) {
btCoreData->TimeoutSignal(frame, bluetooth_l2cap_rtx_timeout);
conn->ExpectedResponses.Add(frame);
btCoreData->QueueSignal(frame);
}
// Add the l2cap header
@ -125,10 +130,11 @@ purge_connection(HciConnection* conn)
NetBufferPrepend<l2cap_hdr_t> bufferHeader(frame->buffer);
status_t status = bufferHeader.Status();
if (status < B_OK) {
// free the buffer
//! continue;
debugf("l2cap header could not be prepended!! frame code=%d\n", frame->code);
return;
}
// fill
bufferHeader->length = htole16(frame->buffer->size - sizeof(l2cap_hdr_t));
switch (frame->type) {
@ -141,17 +147,17 @@ purge_connection(HciConnection* conn)
default:
bufferHeader->dcid = frame->channel->dcid;
break;
}
}
bufferHeader.Sync();
if (btDevices == NULL)
if (get_module(NET_BLUETOOTH_DEVICE_NAME,(module_info**)&btDevices) != B_OK) {
if (btDevices == NULL)
if (get_module(NET_BLUETOOTH_DEVICE_NAME, (module_info**)&btDevices) != B_OK) {
panic("l2cap: cannot get dev module");
} // TODO: someone put it
debugf("dev %p frame %p tolower\n", conn->ndevice, frame->buffer);
frame->buffer->type = conn->handle;
@ -159,7 +165,7 @@ purge_connection(HciConnection* conn)
// frame = conn->OutGoingFrames.RemoveHead();
// }
}
@ -171,36 +177,36 @@ connection_thread(void *)
ssize_t ssizeRead;
HciConnection* conn = NULL;
// TODO: Keep this a static var
port_id fPort = find_port(BLUETOOTH_CONNECTION_SCHED_PORT);
if ( fPort == B_NAME_NOT_FOUND )
if (fPort == B_NAME_NOT_FOUND)
{
panic("BT Connection port has been deleted");
}
while ((ssizePort = port_buffer_size(fPort)) != B_BAD_PORT_ID) {
while ((ssizePort = port_buffer_size(fPort)) != B_BAD_PORT_ID) {
if (ssizePort <= 0) {
debugf("Error %s\n", strerror(ssizePort));
snooze(500*1000);
continue;
}
if (ssizePort > (ssize_t) sizeof(conn)) {
debugf("Message too big %ld\n", ssizePort);
snooze(500*1000);
continue;
}
ssizeRead = read_port(fPort, &code, &conn, ssizePort);
ssizeRead = read_port(fPort, &code, &conn, ssizePort);
if (ssizeRead != ssizePort) {
debugf("Missmatch size port=%ld read=%ld\n", ssizePort, ssizeRead);
snooze(500*1000);
continue;
}
purge_connection(conn);
}
@ -213,12 +219,12 @@ InitializeConnectionPurgeThread()
{
port_id fPort = find_port(BLUETOOTH_CONNECTION_SCHED_PORT);
if ( fPort == B_NAME_NOT_FOUND )
if (fPort == B_NAME_NOT_FOUND)
{
fPort = create_port(16, BLUETOOTH_CONNECTION_SCHED_PORT);
debugf("Connection purge port created %ld\n",fPort);
}
// This thread has to catch up connections before first package is sent.
sConnectionThread = spawn_kernel_thread(connection_thread,
"bluetooth connection purge", B_URGENT_DISPLAY_PRIORITY, NULL);
@ -236,7 +242,7 @@ QuitConnectionPurgeThread()
status_t status;
port_id fPort = find_port(BLUETOOTH_CONNECTION_SCHED_PORT);
if ( fPort != B_NAME_NOT_FOUND )
if (fPort != B_NAME_NOT_FOUND)
close_port(fPort);
flowf("Connection port deleted\n");
@ -246,17 +252,17 @@ QuitConnectionPurgeThread()
void
SchedConnectionPurgeThread(HciConnection* conn)
SchedConnectionPurgeThread(HciConnection* conn)
{
port_id port = find_port(BLUETOOTH_CONNECTION_SCHED_PORT);
HciConnection* temp = conn;
if (port == B_NAME_NOT_FOUND)
if (port == B_NAME_NOT_FOUND)
panic("BT Connection Port Deleted");
status_t error = write_port(port, (uint32) conn, &temp, sizeof(conn));
//debugf("error post %s port=%ld size=%ld\n", strerror(error), port, sizeof(conn));
if (error != B_OK)

View File

@ -137,59 +137,59 @@ l2cap_process_signal_cmd(HciConnection* conn, net_buffer* buffer)
/* Process command processors responsible to delete the command*/
switch (processingCode) {
case L2CAP_CMD_REJ:
l2cap_process_cmd_rej(conn, processingIdent, buffer);
break;
case L2CAP_CMD_REJ:
l2cap_process_cmd_rej(conn, processingIdent, buffer);
break;
case L2CAP_CON_REQ:
l2cap_process_con_req(conn, processingIdent, buffer);
break;
case L2CAP_CON_REQ:
l2cap_process_con_req(conn, processingIdent, buffer);
break;
case L2CAP_CON_RSP:
l2cap_process_con_rsp(conn, processingIdent, buffer);
break;
case L2CAP_CON_RSP:
l2cap_process_con_rsp(conn, processingIdent, buffer);
break;
case L2CAP_CFG_REQ:
l2cap_process_cfg_req(conn, processingIdent, buffer);
break;
case L2CAP_CFG_REQ:
l2cap_process_cfg_req(conn, processingIdent, buffer);
break;
case L2CAP_CFG_RSP:
l2cap_process_cfg_rsp(conn, processingIdent, buffer);
break;
case L2CAP_CFG_RSP:
l2cap_process_cfg_rsp(conn, processingIdent, buffer);
break;
case L2CAP_DISCON_REQ:
l2cap_process_discon_req(conn, processingIdent, buffer);
break;
case L2CAP_DISCON_REQ:
l2cap_process_discon_req(conn, processingIdent, buffer);
break;
case L2CAP_DISCON_RSP:
l2cap_process_discon_rsp(conn, processingIdent, buffer);
break;
case L2CAP_DISCON_RSP:
l2cap_process_discon_rsp(conn, processingIdent, buffer);
break;
case L2CAP_ECHO_REQ:
l2cap_process_echo_req(conn, processingIdent, buffer);
break;
case L2CAP_ECHO_REQ:
l2cap_process_echo_req(conn, processingIdent, buffer);
break;
case L2CAP_ECHO_RSP:
l2cap_process_echo_rsp(conn, processingIdent, buffer);
break;
case L2CAP_ECHO_RSP:
l2cap_process_echo_rsp(conn, processingIdent, buffer);
break;
case L2CAP_INFO_REQ:
l2cap_process_info_req(conn, processingIdent, buffer);
break;
case L2CAP_INFO_REQ:
l2cap_process_info_req(conn, processingIdent, buffer);
break;
case L2CAP_INFO_RSP:
l2cap_process_info_rsp(conn, processingIdent, buffer);
break;
case L2CAP_INFO_RSP:
l2cap_process_info_rsp(conn, processingIdent, buffer);
break;
default:
debugf("unknown L2CAP signaling command, code=%#x, ident=%d\n",
default:
debugf("unknown L2CAP signaling command, code=%#x, ident=%d\n",
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);*/
gBufferModule->free(m);
break;
// 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);*/
gBufferModule->free(m);
break;
}
// Is there still remaining size? processors should have pulled its content...
@ -213,7 +213,7 @@ 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;
L2capChannel* channel;
uint16 dcid, psm;
/* Get con req data */
@ -231,29 +231,29 @@ l2cap_process_con_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
/* Create new channel and send L2CA_ConnectInd
notification to the upper layer protocol.
*/
ch = btCoreData->AddChannel(conn, psm /*, dcid, ident*/);
if (ch == NULL) {
channel = btCoreData->AddChannel(conn, psm /*, dcid, ident*/);
if (channel == NULL) {
flowf("No resources to create channel\n");
return (send_l2cap_con_rej(conn, ident, 0, dcid, L2CAP_NO_RESOURCES));
} else {
debugf("New channel created scid=%d\n", ch->scid);
debugf("New channel created scid=%d\n", channel->scid);
}
ch->dcid = dcid;
ch->ident = ident;
channel->dcid = dcid;
channel->ident = ident;
status_t indicationStatus = l2cap_l2ca_con_ind(ch);
status_t indicationStatus = l2cap_l2ca_con_ind(channel);
if ( indicationStatus == B_OK ) {
//ch->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, ch->scid, dcid, L2CAP_NO_RESOURCES);*/
btCoreData->RemoveChannel(conn, ch->scid);
/* send_l2cap_con_rej(con, ident, channel->scid, dcid, L2CAP_NO_RESOURCES);*/
btCoreData->RemoveChannel(conn, channel->scid);
} else {
send_l2cap_con_rej(conn, ident, ch->scid, dcid, L2CAP_PSM_NOT_SUPPORTED);
btCoreData->RemoveChannel(conn, ch->scid);
send_l2cap_con_rej(conn, ident, channel->scid, dcid, L2CAP_PSM_NOT_SUPPORTED);
btCoreData->RemoveChannel(conn, channel->scid);
}
return (indicationStatus);
@ -688,7 +688,7 @@ reject:
static status_t
l2cap_process_discon_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
{
L2capChannel* ch = NULL;
L2capChannel* channel = NULL;
L2capFrame* cmd = NULL;
net_buffer* buff = NULL;
uint16 scid;
@ -706,26 +706,26 @@ l2cap_process_discon_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
command.Remove();
/* Check if we have this channel and it is in valid state */
ch = btCoreData->ChannelBySourceID(conn, dcid);
if (ch == NULL) {
channel = btCoreData->ChannelBySourceID(conn, dcid);
if (channel == NULL) {
debugf("unexpected L2CAP_DisconnectReq message.Channel does not exist, "
"cid=%d\n", dcid);
goto reject;
}
/* XXX Verify channel state and reject if invalid -- is that true? */
if (ch->state != L2CAP_CHAN_OPEN && ch->state != L2CAP_CHAN_CONFIG &&
ch->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, ch->state);
"state=%d\n", dcid, channel->state);
goto reject;
}
/* Match destination channel ID */
if (ch->dcid != scid || ch->scid != dcid) {
if (channel->dcid != scid || channel->scid != dcid) {
debugf("unexpected L2CAP_DisconnectReq. Channel IDs does not match, "
"channel: scid=%d, dcid=%d, request: scid=%d, dcid=%d\n",
ch->scid, ch->dcid, scid, dcid);
channel->scid, channel->dcid, scid, dcid);
goto reject;
}
@ -736,22 +736,22 @@ l2cap_process_discon_req(HciConnection* conn, uint8 ident, net_buffer* buffer)
*/
flowf("Responding\n");
// inform upper if we were not actually already waiting
if (channel->state != L2CAP_CHAN_W4_L2CAP_DISCON_RSP) {
l2cap_l2ca_discon_ind(channel); // do not care about result
}
/* Send L2CAP_DisconnectRsp */
buff = l2cap_discon_rsp(ident, dcid, scid);
cmd = btCoreData->SpawnSignal(conn, ch, buff, ident, L2CAP_DISCON_RSP);
cmd = btCoreData->SpawnSignal(conn, channel, buff, ident, L2CAP_DISCON_RSP);
if (cmd == NULL)
return ENOMEM;
/* Link command to the queue */
SchedConnectionPurgeThread(conn);
ch->state = L2CAP_CHAN_W4_L2CA_DISCON_RSP;
if (ch->state != L2CAP_CHAN_W4_L2CAP_DISCON_RSP) {
//INDICATION ng_l2cap_l2ca_discon_ind(ch); /* do not care about result */
btCoreData->RemoveChannel(conn, ch->scid);
}
btCoreData->RemoveChannel(conn, channel->scid);
return B_OK;

View File

@ -94,6 +94,7 @@ l2cap_l2ca_cfg_rsp_ind(L2capChannel* channel)
} else {
// nothing special requested
channel->ident = btCoreData->ChannelAllocateIdent(channel->conn);
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);
@ -116,6 +117,13 @@ l2cap_l2ca_cfg_rsp_ind(L2capChannel* channel)
}
status_t
l2cap_l2ca_discon_ind(L2capChannel* channel)
{
return channel->endpoint->MarkClosed();
}
status_t
l2cap_upper_cfg_rsp(L2capChannel* channel)
{
@ -137,6 +145,33 @@ l2cap_upper_con_rsp(HciConnection* conn, L2capChannel* channel)
return B_OK;
}
status_t
l2cap_upper_dis_req(L2capChannel* channel)
{
channel->ident = btCoreData->ChannelAllocateIdent(channel->conn);
net_buffer* buf = l2cap_discon_req(channel->ident, channel->scid, channel->dcid);
L2capFrame* cmd = btCoreData->SpawnSignal(channel->conn, channel, buf,
channel->ident, L2CAP_DISCON_REQ);
if (cmd == NULL) {
gBufferModule->free(buf);
return ENOMEM;
}
channel->state = L2CAP_CHAN_W4_L2CA_DISCON_RSP;
/* Link command to the queue */
SchedConnectionPurgeThread(channel->conn);
return B_OK;
}
#if 0
#pragma mark -
#endif
status_t
l2cap_co_receive(HciConnection* conn, net_buffer* buffer, uint16 dcid)

View File

@ -9,9 +9,12 @@
status_t l2cap_l2ca_con_ind(L2capChannel* channel);
status_t l2cap_l2ca_cfg_rsp_ind(L2capChannel* channel);
status_t l2cap_l2ca_discon_ind(L2capChannel* channel);
status_t l2cap_upper_con_rsp(HciConnection* conn, L2capChannel* channel);
status_t l2cap_upper_cfg_rsp(L2capChannel* channel);
status_t l2cap_upper_dis_req(L2capChannel* channel);
status_t l2cap_co_receive(HciConnection* conn, net_buffer* buffer, uint16 dcid);