root/src/servers/bluetooth/DeviceManager.cpp
#include <Application.h>
#include <Autolock.h>
#include <String.h>

#include <Directory.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <Path.h>
#include <NodeMonitor.h>


#include <image.h>
#include <stdio.h>
#include <string.h>

#include "DeviceManager.h"
#include "LocalDeviceImpl.h"

#include "Debug.h"
#include "BluetoothServer.h"

#include <bluetoothserver_p.h>


void
DeviceManager::MessageReceived(BMessage* msg)
{
        if (msg->what == B_NODE_MONITOR) {
                int32 opcode;
                if (msg->FindInt32("opcode", &opcode) == B_OK) {
                        switch (opcode) {
                                case B_ENTRY_CREATED:
                                case B_ENTRY_MOVED:
                                {
                                        entry_ref ref;
                                        const char *name;
                                        BDirectory dir;

                                        TRACE_BT("Something new in the bus ... ");

                                        if ((msg->FindInt32("device", &ref.device)!=B_OK)
                                                || (msg->FindInt64("directory", &ref.directory)!=B_OK)
                                                || (msg->FindString("name",     &name) != B_OK))
                                                return;

                                        TRACE_BT("DeviceManager: -> %s\n", name);

                                        ref.set_name(name);

                                        // Check if     the     entry is a File or a directory
                                        if (dir.SetTo(&ref) == B_OK) {
                                                printf("%s: Entry %s is taken as a dir\n", __FUNCTION__, name);
                                            node_ref nref;
                                            dir.GetNodeRef(&nref);
                                                AddDirectory(&nref);

                                        } else {
                                                printf("%s: Entry %s is taken as a file\n", __FUNCTION__, name);
                        AddDevice(&ref);
                                        }
                                }
                                break;
                                case B_ENTRY_REMOVED:
                                {
                                        TRACE_BT("Something removed from the bus ...\n");

                                }
                                break;
                                case B_STAT_CHANGED:
                                case B_ATTR_CHANGED:
                                case B_DEVICE_MOUNTED:
                                case B_DEVICE_UNMOUNTED:
                                default:
                                        BLooper::MessageReceived(msg);
                                break;
                        }
                }
        }
}


status_t
DeviceManager::AddDirectory(node_ref *nref)
{
        BDirectory directory(nref);
        status_t status = directory.InitCheck();
        if (status != B_OK)     {
                TRACE_BT("AddDirectory::Initcheck Failed\n");
                return status;
        }

        status = watch_node(nref, B_WATCH_DIRECTORY, this);
        if (status != B_OK)     {
                TRACE_BT("AddDirectory::watch_node      Failed\n");
                return status;
        }

//      BPath path(*nref);
//      BString str(path.Path());
//
//      TRACE_BT("DeviceManager: Exploring entries in %s\n", str.String());

        entry_ref ref;
        status_t error;
        while ((error = directory.GetNextRef(&ref))     == B_OK) {
                // its suposed to be devices ...
                AddDevice(&ref);
        }

        TRACE_BT("DeviceManager: Finished exploring entries(%s)\n", strerror(error));

        return (error == B_OK || error == B_ENTRY_NOT_FOUND)?B_OK:error;
}


status_t
DeviceManager::RemoveDirectory(node_ref* nref)
{
        BDirectory directory(nref);
        status_t status = directory.InitCheck();
        if (status != B_OK)
                return status;

        status = watch_node(nref, B_STOP_WATCHING, this);
        if (status != B_OK)
                return status;

        BEntry entry;
        while (directory.GetNextEntry(&entry, true)     == B_OK) {
                entry_ref ref;
                entry.GetRef(&ref);
                BMessage msg(B_NODE_MONITOR);
                msg.AddInt32("opcode", B_ENTRY_REMOVED);
                msg.AddInt32("device", nref->device);
                msg.AddInt64("directory", nref->node);
                msg.AddString("name", ref.name);
                //addon->fDevice->Control(NULL, NULL, msg.what, &msg);
        }

        return B_OK;
}


status_t
DeviceManager::AddDevice(entry_ref* ref)
{
        BPath path(ref);
        BString* str = new BString(path.Path());

        BMessage* msg = new     BMessage(BT_MSG_ADD_DEVICE);
        msg->AddInt32("opcode", B_ENTRY_CREATED);
        msg->AddInt32("device", ref->device);
        msg->AddInt64("directory", ref->directory);

        msg->AddString("name", *str     );

        TRACE_BT("DeviceManager: Device %s registered\n", path.Path());
        return be_app_messenger.SendMessage(msg);
}


DeviceManager::DeviceManager() :
        fLock("device manager")
{

}


DeviceManager::~DeviceManager()
{

}


void
DeviceManager::LoadState()
{
        if (!Lock())
                return;
        Run();
        Unlock();
}


void
DeviceManager::SaveState()
{

}


status_t
DeviceManager::StartMonitoringDevice(const char *device)
{

        status_t err;
        node_ref nref;
        BDirectory directory;
        BPath path("/dev");

        /* Build the path */
        if ((err = path.Append(device)) != B_OK) {
                printf("DeviceManager::StartMonitoringDevice BPath::Append() error %s: %s\n", path.Path(), strerror(err));
                return err;
        }

        /* Check the path */
        if ((err = directory.SetTo(path.Path())) !=     B_OK) {
                /* Entry not there ... */
                if (err != B_ENTRY_NOT_FOUND) { // something else we cannot     handle
                        printf("DeviceManager::StartMonitoringDevice SetTo error %s: %s\n",     path.Path(), strerror(err));
                        return err;
                }
                /* Create it */
                if ((err = create_directory(path.Path(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != B_OK
                        || (err = directory.SetTo(path.Path())) != B_OK) {
                        printf("DeviceManager::StartMonitoringDevice CreateDirectory error %s: %s\n", path.Path(), strerror(err));
                        return err;
                }
        }

        // get noderef
        if ((err = directory.GetNodeRef(&nref)) != B_OK) {
                printf("DeviceManager::StartMonitoringDevice GetNodeRef error %s: %s\n", path.Path(), strerror(err));
                return err;
        }

        // start monitoring     the     root
        status_t error = watch_node(&nref, B_WATCH_DIRECTORY, this);
        if (error != B_OK)
                return error;

        TRACE_BT("DeviceManager: %s     path being monitored\n", path.Path());

        // We are monitoring the root we may have already directories inside
        // to be monitored
        entry_ref driverRef;
        while ((error = directory.GetNextRef(&driverRef)) == B_OK) {

                // its suposed to be directories that needs     to be monitored...
                BNode driverNode(&driverRef);
                node_ref driverNRef;
                driverNode.GetNodeRef(&driverNRef);
                AddDirectory(&driverNRef);
        }

    TRACE_BT("DeviceManager: Finished exploring entries(%s)\n", strerror(error));

#if     0
        HCIDelegate     *tmphd = NULL;
        int32 i = 0;

        // TODO!! ask the server if     this needs to be monitored

        while ((tmphd = (HCIDelegate *)fDelegatesList.ItemAt(i++)) !=NULL) {

                /* Find out     the     reference*/
                node_ref *dnref = (node_ref     *)tmphd->fMonitoredRefs ;
                if (*dnref == nref)     {
                        printf("StartMonitoringDevice already monitored\n");
                        alreadyMonitored = true;
                        break;
                }

        }
#endif

        return B_OK;
}


status_t
DeviceManager::StopMonitoringDevice(const char *device)
{
        status_t err;
        node_ref nref;
        BDirectory directory;
        BPath path("/dev");
        if (((err =     path.Append(device)) != B_OK)
                || ((err = directory.SetTo(path.Path())) !=     B_OK)
                || ((err = directory.GetNodeRef(&nref)) != B_OK))
                return err;

        // test if still monitored
/*
        bool stillMonitored     = false;
        int32 i = 0;
        while ((tmpaddon = (_BDeviceAddOn_ *)fDeviceAddons.ItemAt(i++)) !=NULL) {
                if (addon == tmpaddon)
                        continue;

                int32 j=0;
                node_ref *dnref = NULL;
                while ((dnref = (node_ref *)tmpaddon->fMonitoredRefs.ItemAt(j++)) != NULL) {
                        if (*dnref == nref)     {
                                stillMonitored = true;
                                break;
                        }
                }
                if (stillMonitored)
                        break;
        }

        // remove from list
        node_ref *dnref = NULL;
        int32 j=0;
        while ((dnref = (node_ref *)addon->fMonitoredRefs.ItemAt(j)) != NULL) {
                if (*dnref == nref)     {
                        addon->fMonitoredRefs.RemoveItem(j);
                        delete dnref;
                        break;
                }
                j++;
        }

        // stop monitoring if needed
        if (!stillMonitored) {
                if ((err = RemoveDirectory(&nref, addon)) != B_OK)
                        return err;
        }
*/
        return B_OK;
}