/***************************************************************************
 *   Copyright (C) 2003 by Mattia Merzi                                    *
 *   ottobit@ferrara.linux.it                                              *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#include "BluezConnector.h"
#include "BluezConnectorKBTDevice.cpp"
#include <kdebug.h>

BluezConnector* BluezConnector::_instance = 0;
int cur_dev = 0;

BluezConnector* BluezConnector::getDefaultConnector()
{
    kdDebug() << "getDefaultConnector()" << endl;
    if (_instance == 0)
    {
        _instance = new BluezConnector();
    }
    return _instance;
}

void BluezConnector::Update()
{
    kdDebug() << "Update !" << endl;
    delete _instance;
    _instance = 0;
    getDefaultConnector();
}

BluezConnector::BluezConnector()
{
    kdDebug() << "BluezConnector" << endl;
    if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0)
    {
        kdDebug() << "error opening hci socket" << endl;
        dev_num = 0;
    }
    else
    {
        cur_dev = 0;
        HCIGetDeviceList();
    }
}

BluezConnector::~BluezConnector()
{
    int i;
    for (i=0;i<countDevices();i++)
    {
        delete devices[i];
    }
    kdDebug() << "BluezConnector: RIP" << endl;
}

void BluezConnector::HCIGetDeviceList()
{
    struct hci_dev_list_req *dl;
    struct hci_dev_req *dr;
    struct hci_dev_info di;
    int i;

    if(!(dl = (struct hci_dev_list_req*)
              malloc(HCI_MAX_DEV*sizeof(struct hci_dev_req)+sizeof(uint16_t))))
    {
        exit(1);
    }

    dl->dev_num = HCI_MAX_DEV;
    dr = dl->dev_req;

    if( ioctl(ctl, HCIGETDEVLIST, (void*)dl) )
    {
        exit(1);
    }

    dev_num=dl->dev_num;
    for(i=0; i< dl->dev_num; i++)
    {
        di.dev_id = (dr+i)->dev_id;
        if( ioctl(ctl, HCIGETDEVINFO, (void*)&di) )
            continue;  // uh ?
        addDevInfo(i, &di);
    }
}

void BluezConnector::addDevInfo(int ord, struct hci_dev_info* di)
{
    BluezConnector::KBTDevice* tmp = new BluezConnector::KBTDevice(di);
    devices[ord] = tmp;
    ord++;
}

void BluezConnector::nextDevice() {
    if (cur_dev != countDevices())
        cur_dev++;
}

int BluezConnector::setCurrentDevice(const char* _name) {
    int i;
    for (i=0;i<countDevices();i++)
    {
        if ((!strcmp(devices[i]->getName(),_name))||
                (!strcmp(devices[i]->getDev(), _name)))
        {
            kdDebug() << "found !" << endl;
            cur_dev = i;
            return 1;
        }
    }
    kdDebug() << "!! WARNING !!" << endl << "Device not found in list!" << endl;
    return 0;
}
