Make a bit more elegant the processing of bluetooth events
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31015 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,160 @@
|
|||||||
|
#ifndef PORTLISTENER_H_
|
||||||
|
#define PORTLISTENER_H_
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename TYPE,
|
||||||
|
ssize_t MAX_MESSAGE_SIZE = 256,
|
||||||
|
size_t MAX_MESSAGE_DEEP = 16,
|
||||||
|
uint32 PRIORITY = B_URGENT_DISPLAY_PRIORITY>
|
||||||
|
class PortListener {
|
||||||
|
|
||||||
|
typedef status_t (*port_listener_func)(TYPE*, int32, size_t);
|
||||||
|
|
||||||
|
struct PortListenerInfo {
|
||||||
|
port_id* port;
|
||||||
|
port_listener_func func;
|
||||||
|
} fInformation;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
PortListener(const char* name, port_listener_func handler)
|
||||||
|
{
|
||||||
|
fInformation.func = handler;
|
||||||
|
fInformation.port = &fPort;
|
||||||
|
|
||||||
|
InitCheck();
|
||||||
|
fPortName = strdup(name);
|
||||||
|
fThreadName = strdup(name);
|
||||||
|
fThreadName = strcat(fThreadName, " thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~PortListener() {
|
||||||
|
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
close_port(fPort);
|
||||||
|
// Closing the port should provoke the thread to finish
|
||||||
|
wait_for_thread(fThread, &status);
|
||||||
|
|
||||||
|
delete fThreadName;
|
||||||
|
delete fPortName;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t TriggerCode(int32 code) {
|
||||||
|
|
||||||
|
return write_port(fPort, code, NULL, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t InitCheck() {
|
||||||
|
|
||||||
|
// Create Port
|
||||||
|
fPort = find_port(fPortName);
|
||||||
|
if (fPort == B_NAME_NOT_FOUND) {
|
||||||
|
fPort = create_port(MAX_MESSAGE_DEEP, fPortName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fPort < B_OK)
|
||||||
|
return fPort;
|
||||||
|
|
||||||
|
// Create Thread
|
||||||
|
|
||||||
|
fThread = find_thread(fThreadName);
|
||||||
|
if (fThread < B_OK) {
|
||||||
|
#ifdef KERNEL_LAND
|
||||||
|
fThread = spawn_kernel_thread((thread_func)&PortListener<TYPE,MAX_MESSAGE_SIZE,
|
||||||
|
MAX_MESSAGE_DEEP, PRIORITY>::threadFunction, fThreadName, PRIORITY, &fInformation);
|
||||||
|
#else
|
||||||
|
fThread = spawn_thread((thread_func)&PortListener<TYPE,MAX_MESSAGE_SIZE,
|
||||||
|
MAX_MESSAGE_DEEP, PRIORITY>::threadFunction, fThreadName, PRIORITY, &fInformation);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fThread < B_OK)
|
||||||
|
return fThread;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t Launch() {
|
||||||
|
|
||||||
|
status_t check = InitCheck();
|
||||||
|
|
||||||
|
if (check < B_OK)
|
||||||
|
return check;
|
||||||
|
|
||||||
|
return resume_thread(fThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t Stop() {
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
wait_for_thread(fThread, &status);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
port_id fPort;
|
||||||
|
thread_id fThread;
|
||||||
|
char* fThreadName;
|
||||||
|
char* fPortName;
|
||||||
|
|
||||||
|
static int32 threadFunction(void* data)
|
||||||
|
{
|
||||||
|
ssize_t ssizePort;
|
||||||
|
ssize_t ssizeRead;
|
||||||
|
status_t status = B_OK;
|
||||||
|
int32 code;
|
||||||
|
|
||||||
|
port_id* port = ((struct PortListenerInfo*)data)->port;
|
||||||
|
port_listener_func handler = ((struct PortListenerInfo*)data)->func;
|
||||||
|
|
||||||
|
|
||||||
|
TYPE* buffer = (TYPE*)malloc(MAX_MESSAGE_SIZE);
|
||||||
|
|
||||||
|
while ((ssizePort = port_buffer_size(*port)) != B_BAD_PORT_ID) {
|
||||||
|
|
||||||
|
if (ssizePort <= 0) {
|
||||||
|
snooze(500*1000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssizePort > MAX_MESSAGE_SIZE) {
|
||||||
|
snooze(500*1000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssizeRead = read_port(*port, &code, (void*)buffer, ssizePort);
|
||||||
|
|
||||||
|
if (ssizeRead != ssizePort)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
status = handler(buffer, code, ssizePort);
|
||||||
|
|
||||||
|
if (status != B_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
if (ssizePort == B_BAD_PORT_ID) // the port dissapeared
|
||||||
|
return ssizePort;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // PortListener
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PORTLISTENER_H_
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
|
||||||
*
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "BPortNot.h"
|
|
||||||
#include "Output.h"
|
|
||||||
|
|
||||||
#include "BluetoothServer.h"
|
|
||||||
#include "LocalDeviceImpl.h"
|
|
||||||
|
|
||||||
#include <bluetooth/HCI/btHCI_event.h>
|
|
||||||
#include <bluetooth/HCI/btHCI_transport.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
BPortNot::BPortNot(BluetoothServer* app, const char* name) {
|
|
||||||
|
|
||||||
ourapp = (BluetoothServer*) app;
|
|
||||||
|
|
||||||
fPort = find_port(name);
|
|
||||||
if ( fPort == B_NAME_NOT_FOUND )
|
|
||||||
{
|
|
||||||
fPort = create_port(256, name);
|
|
||||||
Output::Instance()->Post("Event Listener Port Created\n",BLACKBOARD_GENERAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
BPortNot::loop()
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
size_t ssize;
|
|
||||||
int32 code;
|
|
||||||
|
|
||||||
struct hci_event_header *hdr;
|
|
||||||
|
|
||||||
LocalDeviceImpl* ld;
|
|
||||||
|
|
||||||
while (code != HCI_HAIKU_EVENT_SERVER_QUITTING) {
|
|
||||||
|
|
||||||
size = port_buffer_size(fPort);
|
|
||||||
|
|
||||||
/* TODO: Consider using snb_buff like structure here or
|
|
||||||
max event size to prevent mallocs & frees */
|
|
||||||
hdr = (struct hci_event_header *) malloc(size);
|
|
||||||
ssize = read_port(fPort, &code, hdr, size);
|
|
||||||
|
|
||||||
if (size != ssize) {
|
|
||||||
Output::Instance()->Post("Event size not matching", BLACKBOARD_GENERAL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size <= 0) {
|
|
||||||
Output::Instance()->Post("Suspicious empty event", BLACKBOARD_GENERAL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we only handle events
|
|
||||||
if (GET_PORTCODE_TYPE(code)!= BT_EVENT) {
|
|
||||||
Output::Instance()->Post("Wrong type frame code", BLACKBOARD_GENERAL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ld = ourapp->LocateLocalDeviceImpl(GET_PORTCODE_HID(code));
|
|
||||||
if (ld == NULL) {
|
|
||||||
Output::Instance()->Post("LocalDevice could not be fetched", BLACKBOARD_GENERAL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ld->HandleEvent(hdr);
|
|
||||||
|
|
||||||
|
|
||||||
// free the event
|
|
||||||
free(hdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
|
||||||
*
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BT_PORT_NOTIFICATION
|
|
||||||
#define _BT_PORT_NOTIFICATION
|
|
||||||
|
|
||||||
#include <OS.h>
|
|
||||||
|
|
||||||
class BluetoothServer;
|
|
||||||
|
|
||||||
class BPortNot {
|
|
||||||
|
|
||||||
public:
|
|
||||||
BPortNot(BluetoothServer* app, const char* name) ;
|
|
||||||
void loop();
|
|
||||||
|
|
||||||
port_id fPort;
|
|
||||||
port_id sdp_request_port;
|
|
||||||
thread_id sdp_server_thread;
|
|
||||||
|
|
||||||
BluetoothServer* ourapp;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
* Copyright 2007-2009 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
* Copyright 2007-2009 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||||
* Copyright 2008 Mika Lindqvist, monni1995_at_gmail.com
|
* Copyright 2008 Mika Lindqvist, monni1995_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 <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -28,6 +27,28 @@
|
|||||||
#include "Output.h"
|
#include "Output.h"
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DispatchEvent(struct hci_event_header* header, int32 code, size_t size)
|
||||||
|
{
|
||||||
|
// we only handle events
|
||||||
|
if (GET_PORTCODE_TYPE(code)!= BT_EVENT) {
|
||||||
|
Output::Instance()->Post("Wrong type frame code", BLACKBOARD_GENERAL);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch the LocalDevice who belongs this event
|
||||||
|
LocalDeviceImpl* lDeviceImplementation = ((BluetoothServer*)be_app)->LocateLocalDeviceImpl(GET_PORTCODE_HID(code));
|
||||||
|
if (lDeviceImplementation == NULL) {
|
||||||
|
Output::Instance()->Post("LocalDevice could not be fetched", BLACKBOARD_GENERAL);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
lDeviceImplementation->HandleEvent(header);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BluetoothServer::BluetoothServer() : BApplication(BLUETOOTH_SIGNATURE)
|
BluetoothServer::BluetoothServer() : BApplication(BLUETOOTH_SIGNATURE)
|
||||||
{
|
{
|
||||||
Output::Instance()->Run();
|
Output::Instance()->Run();
|
||||||
@@ -42,9 +63,9 @@ BluetoothServer::BluetoothServer() : BApplication(BLUETOOTH_SIGNATURE)
|
|||||||
fDeviceManager = new DeviceManager();
|
fDeviceManager = new DeviceManager();
|
||||||
fLocalDevicesList.MakeEmpty();
|
fLocalDevicesList.MakeEmpty();
|
||||||
|
|
||||||
// TODO: Some events should be handled faster than in KL...
|
fEventListener2 = new BluetoothPortListener(BT_USERLAND_PORT_NAME,
|
||||||
fEventListener = spawn_thread(notification_Thread, "BT port listener" ,
|
(BluetoothPortListener::port_listener_func)&DispatchEvent);
|
||||||
B_URGENT_DISPLAY_PRIORITY , this);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,13 +101,12 @@ void BluetoothServer::ReadyToRun(void)
|
|||||||
fDeviceManager->StartMonitoringDevice("bluetooth/h3");
|
fDeviceManager->StartMonitoringDevice("bluetooth/h3");
|
||||||
fDeviceManager->StartMonitoringDevice("bluetooth/h4");
|
fDeviceManager->StartMonitoringDevice("bluetooth/h4");
|
||||||
fDeviceManager->StartMonitoringDevice("bluetooth/h5");
|
fDeviceManager->StartMonitoringDevice("bluetooth/h5");
|
||||||
// Launch the notifier thread
|
|
||||||
if ( resume_thread(fEventListener) != B_OK )
|
|
||||||
{
|
|
||||||
Output::Instance()->Post("Bluetooth port listener failed\n", BLACKBOARD_GENERAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Output::Instance()->Post("Bluetooth server Ready\n", BLACKBOARD_GENERAL);
|
if (fEventListener2->Launch() != B_OK)
|
||||||
|
Output::Instance()->Post("Bluetooth port listener failed\n", BLACKBOARD_GENERAL);
|
||||||
|
else
|
||||||
|
Output::Instance()->Post("Bluetooth server Ready\n", BLACKBOARD_GENERAL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -175,6 +195,7 @@ void BluetoothServer::MessageReceived(BMessage *message)
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
LocalDeviceImpl*
|
LocalDeviceImpl*
|
||||||
BluetoothServer::LocateDelegateFromMessage(BMessage* message)
|
BluetoothServer::LocateDelegateFromMessage(BMessage* message)
|
||||||
{
|
{
|
||||||
@@ -369,16 +390,6 @@ BluetoothServer::HandleGetProperty(BMessage* message, BMessage* reply)
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
BluetoothServer::notification_Thread(void* data)
|
|
||||||
{
|
|
||||||
BPortNot notifierd((BluetoothServer*)data, BT_USERLAND_PORT_NAME);
|
|
||||||
|
|
||||||
notifierd.loop();
|
|
||||||
return B_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
BluetoothServer::sdp_server_Thread(void* data)
|
BluetoothServer::sdp_server_Thread(void* data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,20 +9,21 @@
|
|||||||
#define _BLUETOOTH_SERVER_APP_H
|
#define _BLUETOOTH_SERVER_APP_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <Application.h>
|
|
||||||
#include <OS.h>
|
|
||||||
#include <ObjectList.h>
|
|
||||||
|
|
||||||
#include "BPortNot.h"
|
#include <Application.h>
|
||||||
#include "HCIDelegate.h"
|
#include <ObjectList.h>
|
||||||
#include "DeviceManager.h"
|
#include <OS.h>
|
||||||
#include "LocalDeviceImpl.h"
|
|
||||||
|
|
||||||
#include <bluetooth/bluetooth.h>
|
#include <bluetooth/bluetooth.h>
|
||||||
#include <bluetooth/HCI/btHCI.h>
|
#include <bluetooth/HCI/btHCI.h>
|
||||||
#include <bluetooth/HCI/btHCI_transport.h>
|
#include <bluetooth/HCI/btHCI_transport.h>
|
||||||
#include <bluetooth/HCI/btHCI_command.h>
|
#include <bluetooth/HCI/btHCI_command.h>
|
||||||
|
|
||||||
|
#include "HCIDelegate.h"
|
||||||
|
#include "DeviceManager.h"
|
||||||
|
#include "LocalDeviceImpl.h"
|
||||||
|
|
||||||
|
#include <PortListener.h>
|
||||||
|
|
||||||
#define BT "bluetooth_server: "
|
#define BT "bluetooth_server: "
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ typedef enum {
|
|||||||
#define BLACKBOARD_LD(X) (BLACKBOARD_END+X-HCI_DEVICE_INDEX_OFFSET)
|
#define BLACKBOARD_LD(X) (BLACKBOARD_END+X-HCI_DEVICE_INDEX_OFFSET)
|
||||||
|
|
||||||
typedef BObjectList<LocalDeviceImpl> LocalDevicesList;
|
typedef BObjectList<LocalDeviceImpl> LocalDevicesList;
|
||||||
|
typedef PortListener<struct hci_event_header> BluetoothPortListener;
|
||||||
|
|
||||||
class BluetoothServer : public BApplication
|
class BluetoothServer : public BApplication
|
||||||
{
|
{
|
||||||
@@ -52,9 +53,7 @@ public:
|
|||||||
|
|
||||||
virtual void AppActivated(bool act);
|
virtual void AppActivated(bool act);
|
||||||
virtual void MessageReceived(BMessage *message);
|
virtual void MessageReceived(BMessage *message);
|
||||||
|
|
||||||
|
|
||||||
static int32 notification_Thread(void* data);
|
|
||||||
static int32 sdp_server_Thread(void* data);
|
static int32 sdp_server_Thread(void* data);
|
||||||
|
|
||||||
/* Messages reply */
|
/* Messages reply */
|
||||||
@@ -66,7 +65,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
LocalDeviceImpl* LocateLocalDeviceImpl(hci_id hid);
|
LocalDeviceImpl* LocateLocalDeviceImpl(hci_id hid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
LocalDeviceImpl* LocateDelegateFromMessage(BMessage* message);
|
LocalDeviceImpl* LocateDelegateFromMessage(BMessage* message);
|
||||||
@@ -74,12 +73,13 @@ private:
|
|||||||
void ShowWindow(BWindow* pWindow);
|
void ShowWindow(BWindow* pWindow);
|
||||||
|
|
||||||
LocalDevicesList fLocalDevicesList;
|
LocalDevicesList fLocalDevicesList;
|
||||||
// UI
|
|
||||||
|
|
||||||
// Notification system
|
// Notification system
|
||||||
thread_id fEventListener;
|
BluetoothPortListener* fEventListener2;
|
||||||
|
|
||||||
DeviceManager* fDeviceManager;
|
DeviceManager* fDeviceManager;
|
||||||
|
|
||||||
BPoint fCenter;
|
BPoint fCenter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ AddResources bluetooth_server : server-bluetooth.rdef ;
|
|||||||
|
|
||||||
Server bluetooth_server
|
Server bluetooth_server
|
||||||
:
|
:
|
||||||
BPortNot.cpp
|
|
||||||
BluetoothServer.cpp
|
BluetoothServer.cpp
|
||||||
# CommandManager.cpp
|
|
||||||
DeviceManager.cpp
|
DeviceManager.cpp
|
||||||
HCIControllerAccessor.cpp
|
HCIControllerAccessor.cpp
|
||||||
HCITransportAccessor.cpp
|
HCITransportAccessor.cpp
|
||||||
|
|||||||
Reference in New Issue
Block a user