From 2487b0a05f502e7410715460f390cc80e7e76fd9 Mon Sep 17 00:00:00 2001 From: wimpie Date: Tue, 04 Jan 2005 01:42:25 +0000 Subject: *** empty log message *** --- (limited to 'noncore/settings') diff --git a/noncore/settings/networksettings2/etc_ppp/ip-up b/noncore/settings/networksettings2/etc_ppp/ip-up new file mode 100755 index 0000000..ec964d0 --- a/dev/null +++ b/noncore/settings/networksettings2/etc_ppp/ip-up @@ -0,0 +1,71 @@ +#!/bin/sh +exec 2> /tmp/IPL +set -x +# +# This script is run by the pppd after the link is established. +# This script is run by the pppd _after_ the link is brought down. +# +# variable DIR determines if it is run after establish (up) or +# after down (down) +# +# It uses run-parts to run scripts in /etc/ppp/ip-$DIR.d +# +# This script is called with the following arguments: +# Arg Name Example +# $1 Interface name ppp0 +# $2 The tty ttyS1 +# $3 The link speed 38400 +# $4 Local IP number 12.34.56.78 +# $5 Peer IP number 12.34.56.99 +# $6 Optional ``ipparam'' value foo + +# The environment is cleared before executing this script +# so the path must be reset +PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin +export PATH + +case $0 in + *ip-up*) + DIR=up + ;; + *ip-down*) + DIR=down + ;; +esac + +# These variables are for the use of the scripts run by run-parts +PPP_IFACE="$1" +PPP_TTY="$2" +PPP_SPEED="$3" +PPP_LOCAL="$4" +PPP_REMOTE="$5" +PPP_IPPARAM="$6" +export PPP_IFACE PPP_TTY PPP_SPEED PPP_LOCAL PPP_REMOTE PPP_IPPARAM + +# as an additional convenience, $PPP_TTYNAME is set to the tty name, +# stripped of /dev/ (if present) for easier matching. +PPP_TTYNAME=`/usr/bin/basename "$2"` +export PPP_TTYNAME + +# If /var/log/ppp-ipupdown.log exists use it for logging. +if [ -e /var/log/ppp-ipupdown.log ]; then + exec > /var/log/ppp-ipupdown.log 2>&1 +fi + +# This script can be used to override the .d files supplied by other packages. +if [ -x /etc/ppp/ip-${DIR}.local ]; then + exec /etc/ppp/ip-${DIR}.local +fi + +run-parts -a "$1" -a "$2" -a "$3" -a "$4" -a "$5" -a "$6" \ + /etc/ppp/ip-${DIR}.d + +if [ "$DIR" = "up" ] +then + # if pon was called with the "quick" argument, stop pppd + if [ -e /var/run/ppp-quick ]; then + rm /var/run/ppp-quick + wait + kill $PPPD_PID + fi +fi diff --git a/noncore/settings/networksettings2/opietooth2/OTDevice.cpp b/noncore/settings/networksettings2/opietooth2/OTDevice.cpp new file mode 100644 index 0000000..62f17a0 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTDevice.cpp @@ -0,0 +1,256 @@ +#include +#include + +#include + +/* OPIE */ +#include +#include +#include + +#include + +using namespace Opie::Core; +using namespace Opietooth2; +using Opie::Core::OProcess; + +OTDevice::OTDevice( OTGateway * _OT ) : QObject(0, "device") { + + // initialize + OT = _OT; + + // detect bluetooth type + QString a, b; // fake + unsigned long c; // fake + detectDeviceType( a, b, c ); + + if( needsAttach() ) { + // requires HCIATTACH + // pid of hciattach + m_hciattachPid = getPidOfHCIAttach(); + + m_hciattach = 0; + + if( m_hciattachPid == 0 ) { + // no pid -> not attached + m_deviceNr = -1; + } else { + // system enabled + // currently no way to figure out which attach produce which + // hci + m_deviceNr = 0; + } + } else { + m_deviceNr = 0; + } +} + +OTDevice::~OTDevice(){ + if( needsAttach() && m_hciattach ) { + // does not auto stop bluetooth + m_hciattach->detach(); + delete m_hciattach; + } +} + +bool OTDevice::attach(){ + + if( needsAttach() && m_hciattachPid == 0 ) { + QString Dev, Mode; + unsigned long Spd; + + detectDeviceType( Dev, Mode, Spd ); + + // not yet started + m_hciattach = new OProcess(); + *m_hciattach << "hciattach"; + *m_hciattach << "-p"; // so that it prints its pid + *m_hciattach << Dev + << Mode + << QString().setNum(Spd); + + connect( m_hciattach, + SIGNAL(receivedStdout(Opie::Core::OProcess*, char*, int ) ), + this, SLOT + (slotStdOut(Opie::Core::OProcess*,char*,int) ) ); + + connect( m_hciattach, + SIGNAL(receivedStderr(Opie::Core::OProcess*, char*, int ) ), + this, SLOT + (slotStdErr(Opie::Core::OProcess*,char*,int) ) ); + + // we need to start this in 'dontcare' mode because + // if qpe exists we want the hci to keep running + if( ! m_hciattach->start( OProcess::DontCare, + OProcess::AllOutput + ) ){ + emit error( tr( "Could not start hciattach" ) ); + delete m_hciattach; + m_hciattach = 0; + return FALSE; + } + } + + return TRUE; +} + +bool OTDevice::detach(){ + + if( needsAttach() && m_hciattachPid ) { + if( m_hciattach ) { + delete m_hciattach; + m_hciattach = 0; + } + + if( kill( m_hciattachPid, 9) < 0 ) { + owarn << "could not stop " << errno << oendl; + emit error( tr( "Could not stop process" ) ); + return FALSE; + } + m_hciattachPid = 0; + emit isEnabled( m_deviceNr, 0 ); + m_deviceNr = -1; + } + + return TRUE; +} + +bool OTDevice::isAttached()const{ + return ! needsAttach() || m_hciattachPid != 0; +} + +bool OTDevice::checkAttach(){ + if( ! needsAttach() ) { + m_deviceNr = 0; + emit isEnabled( 0, 1 ); + return TRUE; + } + + if( m_hciattachPid ) { + QString S; + S.setNum( m_hciattachPid ); + QDir D( "/proc" ); + if( !D.exists( S ) ) { + // down + m_hciattachPid = 0; + emit isEnabled( m_deviceNr, 0 ); + m_deviceNr = -1; + } + } else { + // check + m_hciattachPid = getPidOfHCIAttach(); + if ( m_hciattachPid ) { + m_deviceNr = 0; + emit isEnabled( m_deviceNr, 1 ); + } + } + return m_hciattachPid != 0; +} + +void OTDevice::slotStdOut(OProcess* proc, char* , int ) { + if( proc == m_hciattach ) { + m_hciattach->detach(); + + // system enabled + // currently no way to figure out which attach produce which + // hci + if( m_deviceNr == -1 ) { + m_deviceNr = 0; + emit isEnabled( m_deviceNr, 1 ); + } + } +} + +void OTDevice::slotStdErr(OProcess* proc, char* chars, int len) { + + if(proc == m_hciattach && len >= 1 ){ + // collect output + QCString string( chars, len+1 ); // \0 == +1 + QString m_output; + m_output.append( string.data() ); + owarn << m_output << oendl; + } +} + +pid_t OTDevice::getPidOfHCIAttach( void ) { + + if( needsAttach() ) { + // not yet attached -> perhaps now ? + // load /proc dir and check if command name contains hciattach + QRegExp R("[0-9]+"); + QDir ProcDir( "/proc" ); + QFileInfo FI; + QStringList EL = ProcDir.entryList( QDir::Dirs ); + + // print it out + for ( QStringList::Iterator it = EL.begin(); + it != EL.end(); + ++it ) { + if( R.match( (*it) ) >= 0 ) { + // is pid + + // get command being executed + FI.setFile( ProcDir.path()+"/"+ (*it) + "/exe" ); + + // get the link + if( FI.readLink().right( 9 ) == "hciattach" ) { + // this is hci attach process + + return (*it).toULong(); + break; + } + } + } + } + + return 0; +} + +void OTDevice::detectDeviceType( QString & Device, + QString & Mode, + unsigned long & Speed ) { + + // detect device type and determine parms + owarn << "Detecting device" << oendl; + switch ( ODevice::inst()->model() ) { + case Model_iPAQ_H39xx: + Device = "/dev/tts/1"; + Mode = "bcsp"; + Speed = 921600; + NeedsAttach = 1; + break; + + case Model_iPAQ_H5xxx: + Device = "/dev/tts/1"; + Mode = "any"; + Speed = 921600; + NeedsAttach = 1; + break; + + case Model_GenuineIntel : + Device = ""; + Mode = ""; + Speed = 0; + NeedsAttach = 0; + break; + + default: + Device = "/dev/ttySB0"; + Mode = "bcsp"; + Speed = 230400; + NeedsAttach = 1; + break; + } +} + +QString OTDevice::getRFCommDevicePattern( void ) { + + QDir D( "/dev/bluetooth/rfcomm" ); + if( D.exists() ) { + // devfs + return QString( "/dev/bluetooth/rfcomm/%1" ); + } + + // regular 'dev' directory + return QString( "/dev/rfcomm%1" ); +} diff --git a/noncore/settings/networksettings2/opietooth2/OTDevice.h b/noncore/settings/networksettings2/opietooth2/OTDevice.h new file mode 100644 index 0000000..c2abb09 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTDevice.h @@ -0,0 +1,116 @@ +#ifndef OTDEVICE_H +#define OTDEVICE_H + +#include +#include + +#include + +#include + +// define if you want to use the process hciattach for detection +// #define USEHCIPROC + +class QTimerEvent; + +namespace Opie { + namespace Core { + class OProcess; + } +} + +namespace Opietooth2 { + + /** + * Device takes care of attaching serial + * devices to the blueZ stack. + * After attaching it hciconfig ups it + */ + class OTDevice : public QObject { + + Q_OBJECT + + public: + + /** + * Brings up the device. + * will detech which device is needed + * Usage example: new Device(/dev/ttySB0, csr) + * + */ + OTDevice( OTGateway * _OT ); + + /** + * unloads the device + */ + ~OTDevice(); + + inline OTGateway * gateway() const + { return OT; } + + inline bool needsAttach( void ) const + { return NeedsAttach; } + + inline int deviceNr() const + { return m_deviceNr; } + + /** + * attach the device + * @return bool which is TRUE if command started sucessfully + */ + bool attach(); + + /** + * detach the device + * @return bool which is TRUE if command started sucessfully + */ + bool detach(); + + /** + * Is the device loaded? + * @return bool, if the device is loaded + */ + bool isAttached()const; + + // check current state of attachment + bool checkAttach(); + + // returns pattern that points to the proper + // RFCOMM device file. Put %1 where device nr should be put + // e.g. : /dev/bluetooth/rfcomm/%1 or /def/rfcomm%1 + QString getRFCommDevicePattern(); + + signals: + + /** + * Signals if the attach/detach of the device produced + * errors + * @param Mesg contains an error message + */ + void error( const QString & mesg ); + void isEnabled( int devnr, bool ); + + private slots: + + void slotStdOut(Opie::Core::OProcess*, char*, int ); + void slotStdErr(Opie::Core::OProcess*, char*, int ); + + private: + + void detectDeviceType( QString & Device, + QString & Mode, + unsigned long & Speed ); + pid_t getPidOfHCIAttach( void ); + + Opie::Core::OProcess* m_hciattach; // ptr to hciattach proces + + int m_deviceNr; // x as in hci(x) + pid_t m_hciattachPid; // pid of hciattach program + + // backpointer + OTGateway * OT; + bool NeedsAttach; + }; +}; + +#endif diff --git a/noncore/settings/networksettings2/opietooth2/OTDeviceAddress.cpp b/noncore/settings/networksettings2/opietooth2/OTDeviceAddress.cpp new file mode 100644 index 0000000..7fbfaf4 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTDeviceAddress.cpp @@ -0,0 +1,110 @@ +//-*-c++-*- +/*************************************************************************** + * Copyright (C) 2003 by Fred Schaettgen * + * kdebluetooth@schaettgen.de * + * * + * 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 +#include +#include + +#include + +using namespace Opietooth2; + +//const bdaddr_t OTDeviceAddress::bdaddr_any = {{0,0,0,0,0,0}}; +//const bdaddr_t OTDeviceAddress::bdaddr_local = {{0, 0, 0, 0xff, 0xff, 0xff}}; + +const OTDeviceAddress OTDeviceAddress::invalid = + OTDeviceAddress(); +const OTDeviceAddress OTDeviceAddress::any = + OTDeviceAddress("00:00:00:00:00:00"); +const OTDeviceAddress OTDeviceAddress::local = + OTDeviceAddress("00:00:00:FF:FF:FF"); + +OTDeviceAddress::OTDeviceAddress() { + + IsValid = false; + memset( &BDaddr, 0, sizeof( BDaddr ) ); +} + +OTDeviceAddress::OTDeviceAddress( const bdaddr_t& bdaddr, + bool networkbyteorder) { + setBDAddr( bdaddr, networkbyteorder ); +} + +OTDeviceAddress::OTDeviceAddress(const QString& s) { + + bdaddr_t a; + int ret = str2ba(s.latin1(), &a); + if (ret==0) { + IsValid = true; + bacpy( &BDaddr, &a ); + } else { + IsValid = false; + bacpy( &BDaddr, &(OTDeviceAddress::invalid.getBDAddr()) ) ; + } +} + +QString OTDeviceAddress::toString() const { + char addrbuf[20]; + ba2str(&BDaddr, addrbuf); + return QString(addrbuf); + +} + +void OTDeviceAddress::setBDAddr( const bdaddr_t& bdaddr, + bool networkbyteorder) { + if (networkbyteorder) { + baswap(&BDaddr, &bdaddr); + } else { + bacpy( &BDaddr, &bdaddr ); + } + IsValid = true; +} + +bdaddr_t OTDeviceAddress::getBDAddrInNetworkByteOrder(void) const { + bdaddr_t ret; + baswap(&ret, &BDaddr); + return ret; +} + +bool OTDeviceAddress::operator==(const OTDeviceAddress& b) const { + if ( ! IsValid && ! b.IsValid ) + return true; + return memcmp( &BDaddr, &(b.BDaddr), sizeof( b.BDaddr ) ) == 0; +} + +bool OTDeviceAddress::operator<(const OTDeviceAddress& b) const { + if ( ! IsValid && ! b.IsValid ) + return false; + else if ( ! IsValid && b.IsValid ) + return false; + else if ( IsValid && ! b.IsValid ) + return true; + + if (BDaddr.b[5] != b.BDaddr.b[5]) + return (BDaddr.b[5] < b.BDaddr.b[5]); + + if (BDaddr.b[4] != b.BDaddr.b[4]) + return (BDaddr.b[4] < b.BDaddr.b[4]); + + if (BDaddr.b[3] != b.BDaddr.b[3]) + return (BDaddr.b[3] < b.BDaddr.b[3]); + + if (BDaddr.b[2] != b.BDaddr.b[2]) + return (BDaddr.b[2] < b.BDaddr.b[2]); + + if (BDaddr.b[1] != b.BDaddr.b[1]) + return (BDaddr.b[1] < b.BDaddr.b[1]); + + if (BDaddr.b[0] != b.BDaddr.b[0]) + return (BDaddr.b[0] < b.BDaddr.b[0]); + + return false; +} diff --git a/noncore/settings/networksettings2/opietooth2/OTDeviceAddress.h b/noncore/settings/networksettings2/opietooth2/OTDeviceAddress.h new file mode 100644 index 0000000..8395f37 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTDeviceAddress.h @@ -0,0 +1,108 @@ +//-*-c++-*- +/*************************************************************************** + * Copyright (C) 2003 by Fred Schaettgen * + * kdebluetooth@0xF.de * + * * + * 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. * + ***************************************************************************/ + +#ifndef OTDEVICEADDRESS_H +#define OTDEVICEADDRESS_H + +#include +#include + +namespace Opietooth2 { + +/** Represents a Bluetooth device address. + * This class allows easy conversion of Bluetooth addresses + * from and to strings. It also works with the bdaddr_t type + * used by BlueZ. + * The class offers a comparsion and less-than operator, so + * that it can be used a key in an STL map or similar. + * The string conversion functions of BlueZ are used internally, + * so the string format is the same than for BlueZ's ba2str(). + */ +class OTDeviceAddress { + +public: + + /** Default constructor. + The resulting address is equal to DeviceAddress::invalid. + */ + OTDeviceAddress(); + + /** Initialize the object with a BlueZ bdaddr_t. + @param bdaddr address + @param networkbyteorder if true, bdaddr is assumed to be in + network byte order and converted to host byte order first. + */ + explicit OTDeviceAddress( const bdaddr_t& bdaddr, + bool networkbyteorder = false + ); + + /** Initializes the object with an address given as a string. + The string must be in a format which is understood by the + BlueZ str2ba function, like 00:61:58:4C:E6:AD. Case doesn't matter. + @param s address string + */ + explicit OTDeviceAddress(const QString& s); + + /** convert the address to a string. + @return address string + */ + QString toString() const; + + /** Converts the DeviceAddress into a BlueZ bdaddr_t. + @param networkbyteorder if true, the address is returned + in network byte order. + @return the address as bdaddr_t + */ + inline const bdaddr_t & getBDAddr( void ) const + { return BDaddr; } + bdaddr_t getBDAddrInNetworkByteOrder() const; + void setBDAddr( const bdaddr_t& bdaddr, + bool networkbyteorder = false + ); + + /** Less-than-operator. + Mainly there to use DeviceAddress inside STL containers, + like STL sets or as a key in a STL map. + @param b the DeviceAddress to compare to (right hand side) + @return true if this < b, false otherwise. + */ + bool operator<(const OTDeviceAddress& b) const; + + /** Equality operator. + Tests two device addresses for equality. + @param b the DeviceAddress to compare to (right hand side) + @return true if this and b have the same address or + if both are invalid, false otherwise + */ + bool operator==(const OTDeviceAddress& b) const; + + inline bool operator!=(const OTDeviceAddress& b) const + { return ! ( *this == b ); } + + /** The address 00:00:00:FF:FF:FF */ + static const OTDeviceAddress local; + + /** The address 00:00:00:00:00:00 */ + static const OTDeviceAddress any; + + /** An address tagged as invalid */ + static const OTDeviceAddress invalid; + +protected: + + bdaddr_t BDaddr; + bool IsValid; + +}; + +} + +#endif diff --git a/noncore/settings/networksettings2/opietooth2/OTDriver.cpp b/noncore/settings/networksettings2/opietooth2/OTDriver.cpp new file mode 100644 index 0000000..8bd7919 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTDriver.cpp @@ -0,0 +1,744 @@ +/*************************************************************************** + * 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 +#include + +#include +#include + +#include +#include +#include + +using namespace Opietooth2; + +static struct { + const char *str; + unsigned short rev; +} csr_map[] = { + { "HCI 11.2 (bc01b)", 114 }, + { "HCI 11.3 (bc01b)", 115 }, + { "HCI 12.1 (bc01b)", 119 }, + { "HCI 12.3 (bc01b)", 134 }, + { "HCI 12.7 (bc01b)", 188 }, + { "HCI 12.8 (bc01b)", 218 }, + { "HCI 12.9 (bc01b)", 283 }, + { "HCI 13.10 (bc01b)", 309 }, + { "HCI 13.11 (bc01b)", 351 }, + { "HCI 16.4 (bc01b)", 523 }, + { "HCI 14.3 (bc02x)", 272 }, + { "HCI 14.6 (bc02x)", 336 }, + { "HCI 14.7 (bc02x)", 373 }, + { "HCI 14.8 (bc02x)", 487 }, + { "HCI 15.3 (bc02x)", 443 }, + { "HCI 16.4 (bc02x)", 525 }, + { NULL, 0} +}; + +static char *services[] = { "Positioning", + "Networking", + "Rendering", + "Capturing", + "Object Transfer", + "Audio", + "Telephony", + "Information" }; + +static char *major_devices[] = { "Miscellaneous", + "Computer", + "Phone", + "LAN Access", + "Audio/Video", + "Peripheral", + "Imaging", + "Uncategorized" }; + + +typedef struct { + short Minor; + const char * Description; +} ClassMap_t; + +static ClassMap_t MapMiscClass[] = { + { -1, "" } +}; + +static ClassMap_t MapUnclassifiedClass[] = { + { -1, "" } +}; + +static ClassMap_t MapComputerClass[] = { + { 0, "Uncategorized" } , + { 1, "Desktop workstation" } , + { 2, "Server" } , + { 3, "Laptop" } , + { 4, "Handheld" } , + { 5, "Palm" } , + { 6, "Wearable" }, + { -1, 0 } +}; + +static ClassMap_t MapPhoneClass[] = { + { 0, "Uncategorized" }, + { 1, "Cellular" }, + { 2, "Cordless" }, + { 3, "Smart phone" }, + { 4, "Wired modem or voice gateway" }, + { 5, "Common ISDN Access" }, + { 6, "Sim Card Reader" }, + { -1, 0 } +}; + +static ClassMap_t MapAVClass[] = { + { 0, "Uncategorized" }, + { 1, "Device conforms to the Headset profile" }, + { 2, "Hands-free" }, + { 3, 0 }, + { 4, "Microphone" }, + { 5, "Loudspeaker" }, + { 6, "Headphones" }, + { 7, "Portable Audio" }, + { 8, "Car Audio" }, + { 9, "Set-top box" }, + { 10, "HiFi Audio Device" }, + { 11, "VCR" }, + { 12, "Video Camera" }, + { 13, "Camcorder" }, + { 14, "Video Monitor" }, + { 15, "Video Display and Loudspeaker" }, + { 16, "Video Conferencing" }, + { 17, 0 }, + { 18, "Gaming/Toy" }, + { -1, 0 } +}; + +static ClassMap_t MapPeripheralClass[] = { + { 16, "Keyboard" }, + { 32, "Pointing device" }, + { 48, "Combo keyboard/pointing device" }, + { -1, 0 } +}; + +typedef struct { + int Major; + ClassMap_t * Map; +} MainClassMap_t; + +static MainClassMap_t MainClasses[] = { + { 0, MapMiscClass }, + { 1, MapComputerClass }, + { 2, MapPhoneClass }, + { 3, 0 }, // special case + { 4, MapAVClass }, + { 5, MapPeripheralClass }, + { 6, 0 }, // special case + { 63, MapUnclassifiedClass }, + { -1, 0 } +}; + +OTDriver::OTDriver( OTGateway * _OT, struct hci_dev_info* di) : QObject( _OT ), Address() { + OT = _OT; + IsUp = 0; + Socket = 0; + + init(di); + owarn << "Driver " << devname() << oendl; + + AutoClose = new QTimer( this ); + connect( AutoClose, + SIGNAL( timeout() ), + this, + SLOT( SLOT_CloseFd() ) + ); +} + +OTDriver::~OTDriver() { + closeSocket(); + SLOT_CloseFd(); +} + +void OTDriver::SLOT_CloseFd( void ){ + if ( isOpen() ) { + AutoClose->stop(); + ::close( fd() ); + setfd( -1 ); + } +} + +void OTDriver::init(struct hci_dev_info* di) { + + Dev = di->name; + + setDevId(di->dev_id); + setType(di->type); + setFlags(di->flags); + Address.setBDAddr( di->bdaddr ); + setFeatures(di->features); + setfd( -1 ); // not open + + Manufacturer = ""; +} + +// internal reinitialize +void OTDriver::reinit() { + bool Old; + Old = IsUp; + + if( currentState() < 0 ) + return; + + if( Old != IsUp ) { + // state changes + emit stateChange( this, IsUp ); + } +} + +// requested by application +int OTDriver::currentState() { + struct hci_dev_info di; + + // uint16_t tmp_dev_id = device_info.dev_id; + // bzero(&device_info,sizeof(struct hci_dev_info)); + // device_info.dev_id = tmp_dev_id; + + memset( &di, 0, sizeof( di ) ); + di.dev_id = Dev_id; + if( ioctl( OT->getSocket(), HCIGETDEVINFO, (void*)&di) < 0 ) { + SLOT_CloseFd(); + return -1; + } else { + // load new info + init(&di); + } + + return IsUp; +} + +bool OTDriver::open() { + + // (re)start single shot close + AutoClose->start( 30000, TRUE ); + + if( isOpen() ) + // is open + return 1; + + setfd(hci_open_dev(devId())); + + if (fd() < 0) { + emit error( tr( "Can't open device %1. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) + ); + return 0; + } + + return 1; +} + +QString OTDriver::name() { + char name[1000]; + + if( ! open() ) { + return tr("Cannot open"); + } + + if (hci_read_local_name( fd(), sizeof(name), name, 1000) < 0) { + if (errno != ETIMEDOUT) { + emit error( tr("Can't read local name on %1. %2 : %3. Default to %4" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ). + arg( devname() ) + ); + } // ETIMEDOUT error is quite normal, device is down ... I think ! :) + strcpy(name,devname().latin1()); + } + return QString(name); +} + +void OTDriver::setFlags(unsigned long flags) { + + // kdDebug() << "Setting OTDriver Values ..." << endl; + IsUp = BTVALUE(hci_test_bit(HCI_UP, &flags)); + + if (isUp()) { + setIScan(BTVALUE(hci_test_bit(HCI_ISCAN, &flags))); + setPScan(BTVALUE(hci_test_bit(HCI_PSCAN, &flags))); + setAuthentication(BTVALUE(hci_test_bit(HCI_AUTH, &flags))); + setEncryption(BTVALUE(hci_test_bit(HCI_ENCRYPT, &flags))); + } else { + setIScan(BT_UNKNOWN); + setPScan(BT_UNKNOWN); + setAuthentication(BT_UNKNOWN); + setEncryption(BT_UNKNOWN); + } +} + +QString OTDriver::revision() { + + struct hci_version ver; + + if( ! open() ) { + return tr("Cannot open"); + } + + if (hci_read_local_version(fd(), &ver, 1000) < 0) { + emit error( tr( "Can't read revision info on %1. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + return QString(); + } + + setManufacturer(ver.manufacturer); + + switch (ver.manufacturer) { + case 0: + return getRevEricsson(); + break; + case 10: + return getRevCsr(ver.hci_rev); + break; + default: + return tr( "Unsupported manufacturer" ); + break; + } +} + +QString OTDriver::getRevEricsson() { + + char revision[102]; + struct hci_request rq; + + if( ! open() ) { + return QString( "Cannot open" ); + } + + memset(&rq, 0, sizeof(rq)); + rq.ogf = 0x3f; + rq.ocf = 0x000f; + rq.cparam = NULL; + rq.clen = 0; + rq.rparam = &revision; + rq.rlen = sizeof(revision); + + if (hci_send_req(fd(), &rq, 1000) < 0) { + emit error( tr( "Can't read revision info on %1. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + return QString(); + } + + return QString( revision+1 ); +} + +QString OTDriver::getRevCsr( unsigned short rev) { + + int i; + + for (i = 0; csr_map[i].str; i++) + if (csr_map[i].rev == rev) { + return QString( csr_map[i].str ); + } + + return tr( "Unknown firmware" ); +} + +int OTDriver::reset() { + + if( ! open() ) { + return 0; + } + + if( ioctl(fd(), HCIDEVRESET, devId()) < 0 ) { + if( errno != EALREADY ) { + emit error( tr( "Reset failed for %1. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + if (errno == EACCES) { + return EACCES; + } + } + } + return 0; +} + +void OTDriver::setUp( bool M ) { + if( M && ! isUp() ) { + bringUp(); + } else if( ! M && isUp() ) { + bringDown(); + } +} + +void OTDriver::bringUp() { + + owarn << "bringUp : " << Dev << oendl; + + if( ! open() ) { + return; + } + + if (! isUp()) { + if( ioctl(fd(), HCIDEVUP, devId()) < 0 ) { + if( errno != EALREADY ) { + emit error( tr( "Cannot bring interface %1 up. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + } + return; + } + // have to wait a bit for the 'up' to become active + QTimer::singleShot( 3000, this, SLOT( reinit() ) ); + } +} + +void OTDriver::bringDown() { + + owarn << "bringDown : " << Dev << oendl; + + if( ! open() ) { + return; + } + + if ( isUp() ) { + if( ioctl(fd(), HCIDEVDOWN, devId()) < 0 ) { + if( errno != EALREADY ) { + emit error( tr( "Cannot bring interface %1 down. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + } + return; + } + reinit(); + } +} + +void OTDriver::setScanMode(bool iscan, bool pscan) { + + struct hci_dev_req dr; + + if( ! open() ) { + return; + } + + dr.dev_id = devId(); + dr.dev_opt = SCAN_DISABLED; + + if( iscan&&(!pscan) ) + dr.dev_opt = SCAN_INQUIRY; + else if( pscan&&(!iscan) ) + dr.dev_opt = SCAN_PAGE; + else if( pscan&&iscan ) + dr.dev_opt = SCAN_PAGE | SCAN_INQUIRY; + + if( ioctl(fd(), HCISETSCAN, (unsigned long)&dr) < 0 ) { + if( errno != EALREADY ) { + emit error( tr( "Can't set scan mode on %1. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + } + return; + } + + reinit(); +} + +void OTDriver::changeDevName(const char* name) { + + if( ! open() ) { + return; + } + + if (hci_write_local_name(fd(), name, 1000) < 0) { + emit error( tr( "Can't change local name on %1. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + } +} + +void OTDriver::changeAuthentication(bool _auth) { + struct hci_dev_req dr; + + if( ! open() ) { + return; + } + + dr.dev_id = devId(); + dr.dev_opt = _auth?AUTH_ENABLED:AUTH_DISABLED; + + if (ioctl(fd(),HCISETAUTH,(unsigned long)&dr) < 0) { + if( errno != EALREADY ) { + emit error( tr( "Can't change authentication on %1. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + } + return; + } + reinit(); +} + +void OTDriver::changeEncryption(bool _encrypt) { + struct hci_dev_req dr; + + if( ! open() ) { + return; + } + + dr.dev_id = devId(); + dr.dev_opt = _encrypt?ENCRYPT_P2P:ENCRYPT_DISABLED; + + if (ioctl(fd(),HCISETENCRYPT,(unsigned long)&dr) < 0) { + if( errno != EALREADY ) { + emit error( tr( "Can't change encryption on %1. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + } + return; + } + + reinit(); +} + +void OTDriver::changeClass ( unsigned char service, + unsigned char major, + unsigned char minor ) { + unsigned long cod = 0; + cod = (service << 16) | + (major << 8) | + (minor ) ; + + if( ! open() ) { + return; + } + + if ( hci_write_class_of_dev(fd(),cod,1000) < 0 ) { + emit error( tr( "Can't change class informations for %1. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + return; + } +} + +void OTDriver::getClass( QString & service, + QString & device ) { + unsigned char cls[3]; + + if( ! open() ) { + return; + } + + if ( hci_read_class_of_dev(fd(),cls,1000) < 0 ) { + emit error( tr( "Can't read class information for %1. %2 : %3" ). + arg( devname() ). + arg( errno ). + arg( strerror(errno) ) ); + return; + } + + if( cls[2] ) { + int first = 1; + for ( unsigned int s = 0; s < sizeof(*services); s++) { + if (cls[2] & (1 << s)) { + if( !first ) + service += ", "; + service += services[s]; + first = 0; + } + } + } else { + service = "unspecified"; + } + + MainClassMap_t * MCM = MainClasses; + int major = cls[1] & 0x1f; + int minor = cls[0] >> 2; + + if( (unsigned)(cls[1] & 0x1f) > sizeof(*major_devices)) { + device = tr("Invalid Device Class"); + return; + } + + device = major_devices[cls[1] & 0x1f]; + + while( MCM->Major != -1 ) { + if( major == MCM->Major ) { + // this class + ClassMap_t * CM = MCM->Map; + if( MCM->Map ) { + while( CM->Minor != -1 ) { + if( minor == CM->Minor ) { + break; + } + CM ++; + } + device = CM->Description; + } else { + // special case + if( major == 3 ) { + /* lan access */ + if( minor == 0 ) { + device = "Uncategorized"; + } else { + switch( minor / 8 ) { + case 0: + device = "Fully available"; + break; + case 1: + device = "1-17% utilized"; + break; + case 2: + device = "17-33% utilized"; + break; + case 3: + device = "33-50% utilized"; + break; + case 4: + device = "50-67% utilized"; + break; + case 5: + device = "67-83% utilized"; + break; + case 6: + device = "83-99% utilized"; + break; + case 7: + device = "No service available"; + break; + } + } + } else if( major == 6 ) { /* imaging */ + if (minor & 4) + device = "Display"; + if (minor & 8) + device = "Camera"; + if (minor & 16) + device = "Scanner"; + if (minor & 32) + device = "Printer"; + } + } + break; + } + MCM ++; + } + + if( MCM->Major == -1 ) { + device = "Unknown (reserved) minor device class"; + } +} + +QString OTDriver::strType() { + return QString( hci_dtypetostr(Type) ); +} + +void OTDriver::setFeatures( unsigned char * _f) { + Features = lmp_featurestostr(_f, NULL, 255); +} + +void OTDriver::setManufacturer(int compid) { + Manufacturer = bt_compidtostr(compid); +} + +OTHCISocket * OTDriver::openSocket( void ) { + if( ! Socket ) { + owarn << "Open HCI socket to " << devname() << oendl; + Socket = new OTHCISocket( this ); + } + return Socket; +} + +void OTDriver::closeSocket( void ) { + if( Socket ) { + owarn << "Close HCI socket to " << devname() << oendl; + delete Socket; + Socket = 0; + } +} + +QString OTDriver::getPeerName( const OTDeviceAddress & PAddr ) { + QString S; + char name[100 ]; + + if( ! open() ) { + return QString("N/A"); + } + + if( hci_read_remote_name( fd(), + &(PAddr.getBDAddr()), + sizeof(name), + name, + 100000 ) < 0 ) { + return QString( "N/A" ); + } + + return QString( name ); +} + +long OTDriver::getLinkQuality( const OTDeviceAddress & Addr ) { + struct hci_conn_info_req *cr; + struct hci_request rq; + read_rssi_rp rp; + uint16_t handle; + + if( ! open() ) { + return 0; + } + + cr = (struct hci_conn_info_req *)malloc( + sizeof(*cr) + sizeof(struct hci_conn_info)); + if (!cr) + return 0; + + bacpy( &(cr->bdaddr), &(Addr.getBDAddr()) ); + cr->type = ACL_LINK; + + if (ioctl( fd(), HCIGETCONNINFO, (unsigned long) cr) < 0) { + owarn << "Get connection info failed" << oendl; + free(cr); + return 0; + } + + handle = htobs(cr->conn_info->handle); + + free(cr); + + memset(&rq, 0, sizeof(rq)); + rq.ogf = OGF_STATUS_PARAM; + rq.ocf = OCF_READ_RSSI; + rq.cparam = &handle; + rq.clen = 2; + rq.rparam = &rp; + rq.rlen = GET_LINK_QUALITY_RP_SIZE; + + if (hci_send_req( fd(), &rq, 100) < 0) { + owarn << "Get connection info failed" << oendl; + return 0; + } + + if( rp.status ) { + owarn << QString().sprintf("HCI get_link_quality cmd failed (0x%2.2X)", rp.status) << oendl; + return 0; + } + + return rp.rssi+50; +} diff --git a/noncore/settings/networksettings2/opietooth2/OTDriver.h b/noncore/settings/networksettings2/opietooth2/OTDriver.h new file mode 100644 index 0000000..b54ffdf --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTDriver.h @@ -0,0 +1,232 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#ifndef OTDRIVER_H +#define OTDRIVER_H + +/* + * This class handles the connection with the BlueZ libraries, implements + * most of the bluetooth-related functions and owns the KBTDevice class + * that is a single local bluetooth device representation. + * It is used as a Singleton pattern thru the getDefaultConnector() method. + * + */ +#include +#include +#include + +#include + +namespace Opietooth2 { + +class OTGateway; +class OTHCISocket; +class OTDeviceAddress; +class OTPeer; + +/* + * This is the representation of a + * Bluetooth device for the local + * machine. + */ +class OTDriver : public QObject { + + Q_OBJECT + +public: + + OTDriver( OTGateway * Ot, struct hci_dev_info* di); + ~OTDriver(); + + inline OTGateway * gateway() const + { return OT; } + + /* + * Initializes the device using the passed hci_dev_info + * struct, contining the basic information in order to + * talk with the pyisical device. + */ + void init(struct hci_dev_info* di); + + /* + * Open the device and obtains a file descriptor to id + * return if open + */ + bool open(); + + OTHCISocket * openSocket(); + + void closeSocket(); + + /* + * Return true if the device is opened. + */ + int isOpen() + { return Fd != -1; }; + + /* + * Calls the ioctl(HCIDEVRESET) in order to + * reset the device. + */ + int reset(); + + // set Up if true and not yet up + void setUp( bool Mode ); + + /* + * Turn the device up and the reinitializes the device. + * If the device is already up, nothing is done. + */ + void bringUp(); + + /* + * Turn the device down and the reinitializes the device. + * If the device is already down, nothing is done. + */ + void bringDown(); + + // is the device UP now + bool isUp() const + { return IsUp; } + + // get current state + // return 1 if UP, 0 if DOWN, -1 if ERROR + int currentState(); + + /* + * Returns the name of the device. If the device is + * down, the device id is returned. + */ + QString name(); + + int devId() const + { return Dev_id; }; + + /* + * Returns the string representation of the device id, + * with the same format of the hciconfig tool. + */ + QString devname() + { return Dev; }; + + /* + * Returns the file descriptor for the local + * connection to this device + */ + int fd() const + { return Fd; }; + void setfd(int _fd) + { Fd = _fd; }; + + void setType(int _type) + { Type = _type; }; + int type() const + { return Type; }; + QString strType(); + + int iscan() const + { return Iscan; } + void setIScan(int _iscan) + { Iscan = _iscan; } + + int pscan() const + { return Pscan; } + void setPScan(int _pscan) + { Pscan = _pscan; } + + int authentication() const + { return Auth; } + void setAuthentication(int _auth) + { Auth = _auth; } + + int encryption() const + { return Encrypt; } + void setEncryption(int _encrypt) + { Encrypt = _encrypt; } + + void setDevId(int _dev_id) + { Dev_id = _dev_id; }; + void setDev(char* _dev) + { Dev = _dev; }; + + void setFlags( unsigned long flags); + + const OTDeviceAddress & address() + { return Address; } + + void setFeatures( unsigned char * _f); + QString features() + { return Features; } + + void setManufacturer(int compid); + QString manufacturer() + { return Manufacturer; } + + QString revision(); + + void setScanMode(bool iscan, bool pscan); + void setClass(unsigned long cls); + + void changeDevName(const char* name); + void changeEncryption(bool _encryption); + void changeAuthentication(bool _auth); + + void getClass( QString & service, + QString & device ); + void changeClass( unsigned char service, + unsigned char major, + unsigned char minor); + + QString getPeerName( const OTDeviceAddress & PAddr ); + + // address must be connected to this driver + long getLinkQuality( const OTDeviceAddress & Address ); + +signals : + + void error( const QString & ); + void stateChange( OTDriver * , bool ); + void driverDisappeared( OTDriver * ); + +private slots : + + /* + * Reinitializes the device, obtaining a fresh + * hci_dev_info structure. + */ + void reinit(); + void SLOT_CloseFd(); + +private: + + QString getRevEricsson(); + QString getRevCsr(unsigned short rev); + + QString Name; + QString Dev; + QString Revision; + QString Manufacturer; + OTDeviceAddress Address; + QString Features; + QTimer * AutoClose; + + int Dev_id,Fd,Type; + bool IsUp; + int Iscan,Pscan,Auth,Encrypt; + + // socket bound to this device + OTHCISocket * Socket; + + // backpointer to opietooth system + OTGateway * OT; +}; + +} +#endif diff --git a/noncore/settings/networksettings2/opietooth2/OTDriverList.cpp b/noncore/settings/networksettings2/opietooth2/OTDriverList.cpp new file mode 100644 index 0000000..f703834 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTDriverList.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + * 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 +#include + +#include + +#include +#include +#include + +using namespace Opietooth2; + +OTDriverList::OTDriverList( OTGateway * _OT ) : QVector() { + + OT = _OT; + setAutoDelete( true ); +} + +OTDriverList::~OTDriverList() { +} + +void OTDriverList::update() { + + struct hci_dev_list_req *dl; + struct hci_dev_req *dr; + struct hci_dev_info di; + int cur; + + dl = 0; + cur = 0; + do { + cur += 5; + + dl = (struct hci_dev_list_req*) + ::realloc( dl, sizeof( struct hci_dev_list_req ) + + ( cur * sizeof(struct hci_dev_req) ) + ); + + if( dl == 0 ) { + // memory problem + exit(1); + } + + dl->dev_num = cur; + + if( ioctl( OT->getSocket(), HCIGETDEVLIST, (void*)dl) ) { + owarn << "WARNING : cannot read device list. " + << errno + << strerror( errno ) << oendl; + return; + } + + // if num == cur perhaps we did not get all devices yet + } while( dl->dev_num == cur ); + + if( dl->dev_num != count() ) { + // new or missing devices + clear(); + + dr = dl->dev_req; + resize( dl->dev_num ); + + for( cur=0; cur < dl->dev_num; cur ++) { + memset( &di, 0, sizeof( di ) ); + di.dev_id = (dr+cur)->dev_id; + + // get device info + if( ioctl( OT->getSocket(), HCIGETDEVINFO, (void*)&di) != 0 ) + continue; // uh ? + insert( cur, new OTDriver( OT, &di ) ); + } + + owarn << "Found " << count() << " devices" << oendl; + + ::free( dl ); + } +} diff --git a/noncore/settings/networksettings2/opietooth2/OTDriverList.h b/noncore/settings/networksettings2/opietooth2/OTDriverList.h new file mode 100644 index 0000000..c98ffa0 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTDriverList.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#ifndef OTDRIVERLIST_H +#define OTDRIVERLIST_H + +#include + +namespace Opietooth2 { + +class OTDriver; +class OTGateway; + +class OTDriverList : public QVector { + +public: + + OTDriverList( OTGateway * _OT ); + ~OTDriverList(); + + inline OTGateway * gateway() const + { return OT; } + + void update(); + +private: + + // backpointer + OTGateway * OT; +}; + +} +#endif diff --git a/noncore/settings/networksettings2/opietooth2/OTGateway.cpp b/noncore/settings/networksettings2/opietooth2/OTGateway.cpp new file mode 100644 index 0000000..2d13ce9 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTGateway.cpp @@ -0,0 +1,773 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +using namespace Opietooth2; + +// single instance +OTGateway * OTGateway::SingleGateway = 0; +int OTGateway::UseCount = 0; + +OTGateway * OTGateway::getOTGateway( void ) { + if(SingleGateway == 0 ) { + SingleGateway = new OTGateway(); + } + + UseCount ++; + return SingleGateway; +} + +void OTGateway::releaseOTGateway( void ) { + UseCount --; + if( UseCount == 0 ) { + delete SingleGateway; + SingleGateway = 0; + } +} + +// open bluetooth system +OTGateway::OTGateway( void ) : QObject( 0, "OTGateway" ), + AllDrivers( this ), + AllPeers() { + + ErrorConnectCount = 0; + TheOTDevice = 0; + Scanning = 0; + AllPeersModified = 0; + AllPeers.setAutoDelete( TRUE ); + + if ( ( HciCtl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) { + SLOT_ShowError( tr( "error opening hci socket" ) ); + return; + } + + // load all known devices + updateDrivers(); + + // load all peers we have ever seen + loadKnownPeers(); + + // iterate over drivers and find active connections + // adding/updating peers + loadActiveConnections(); + + // check every 4 seconds the state of BT + timerEvent(0); + RefreshTimer = -1; + setRefreshTimer( 4000 ); + + // load known link keys + readLinkKeys(); +} + +// close bluetooth system +OTGateway::~OTGateway( void ) { + + if( AllPeersModified ) { + saveKnownPeers(); + } + + if( Scanning ) + delete Scanning; + + if( TheOTDevice ) + delete TheOTDevice; + + if( HciCtl >= 0 ) { + ::close( HciCtl ); + } +} + +void OTGateway::setRefreshTimer( int T ) { + if( RefreshTimer != -1 ) { + killTimer( RefreshTimer ); + } + + if( T == 0 ) + T = 4000; + RefreshTimer = startTimer( T ); +} + +OTDevice * OTGateway::getOTDevice( ) { + if( TheOTDevice == 0 ) { + // load bluetooth device and check state + TheOTDevice = new OTDevice( this ); + connect( TheOTDevice, + SIGNAL( isEnabled( int, bool ) ), + this, + SLOT( SLOT_Enabled( int, bool ) ) ); + + connect( TheOTDevice, + SIGNAL( error( const QString & ) ), + this, + SLOT( SLOT_ShowError( const QString & ) ) ); + } + + return TheOTDevice; +} + +// start bluetooth (if stopped) +// return TRUE if started +void OTGateway::SLOT_SetEnabled( bool Mode ) { + if( Mode ) { + SLOT_Enable(); + return; + } + SLOT_Disable(); +} + +void OTGateway::SLOT_Enable() { + getOTDevice()->attach(); +} + +void OTGateway::SLOT_Disable() { + getOTDevice()->detach(); +} + +bool OTGateway::needsEnabling() { + return getOTDevice()->needsAttach(); +} + +bool OTGateway::isEnabled() { + if( getOTDevice()->deviceNr() >= 0 && + driver( getOTDevice()->deviceNr() )->isUp() ) + return TRUE; + + // else check system + return getOTDevice()->isAttached(); +} + +void OTGateway::SLOT_ShowError( const QString & S ) { + + owarn << S << oendl; + + if( ErrorConnectCount > 0 ) { + // pass error + emit error( QString( "

" ) + S + "

" ); + return; + } + + QMessageBox::warning( 0, + tr("OTGateway error"), + S ); +} + +void OTGateway::connectNotify( const char * S ) { + if( strcmp( S, "error(const QString&)" ) == 0 ) { + ErrorConnectCount ++; + } +} + +void OTGateway::disconnectNotify( const char * S ) { + if( strcmp( S, "error(const QString&)" ) == 0 ) { + ErrorConnectCount --; + } +} + +void OTGateway::timerEvent( QTimerEvent * ) { + + OTDriver * D; + unsigned int oldc = AllDrivers.count(); + bool old; + + AllDrivers.update(); + + if( oldc != AllDrivers.count() ) { + updateDrivers(); + } else { + for( unsigned int i = 0; + i < AllDrivers.count(); + i ++ ) { + D = AllDrivers[i]; + old = D->isUp(); + if( D->currentState() >= 0 ) { + if( old != D->isUp() ) { + emit stateChange( D, D->isUp() ); + } + } else { + // if one driver is unable to provide info + // we refresh all devices + updateDrivers(); + return; + } + } + } +} + +void OTGateway::SLOT_Enabled( int id, bool Up ) { + owarn << "device " << id << " state " << Up << oendl; + if( Up ) { + // device is up -> detect it + updateDrivers(); + if( (unsigned)id >= AllDrivers.count() ) { + // to make sure that the driver really IS detected + AllDrivers[id]->bringUp(); + } + } // if DOWN device already down + emit deviceEnabled( Up ); +} + +void OTGateway::updateDrivers( void ) { + OTDriver * D; + + AllDrivers.update(); + + owarn << "updated drivers. now " << AllDrivers.count() << oendl; + + // connect signals for each driver + for( unsigned int i = 0; + i < AllDrivers.count(); + i ++ ) { + D = AllDrivers[i]; + + connect( D, + SIGNAL( error( const QString & ) ), + this, + SLOT( SLOT_ShowError( const QString & ) ) + ); + + connect( D, + SIGNAL( stateChange( OTDriver *, bool ) ), + this, + SIGNAL( stateChange( OTDriver *, bool ) ) + ); + + connect( D, + SIGNAL( driverDisappeared( OTDriver * ) ), + this, + SLOT( SLOT_DriverDisappeared( OTDriver * ) ) + ); + } + + // verify main device too + if( TheOTDevice ) + TheOTDevice->checkAttach(); + + // set to default scanning hardware + setScanWith( 0 ); + + emit driverListChanged(); +} + +void OTGateway::SLOT_DriverDisappeared( OTDriver * D ) { + owarn << "Driver " << D->devname() << " when offline" << oendl; + updateDrivers(); +} + +void OTGateway::scanNeighbourhood( OTDriver * D ) { + + if( Scanning ) { + stopScanOfNeighbourhood(); + } + + if( D ) { + setScanWith( D ); + } + + Scanning = new OTInquiry( scanWith() ); + + connect( Scanning, + SIGNAL( peerFound( OTPeer *, bool )), + this, + SLOT( SLOT_PeerDetected( OTPeer *, bool ) ) + ); + connect( Scanning, + SIGNAL( finished()), + this, + SLOT( SLOT_FinishedDetecting() ) + ); + + // start scanning + Scanning->inquire( 30.0 ); +} + +OTPeer* OTGateway::findPeer( const OTDeviceAddress & Addr ) { + for( unsigned int i = 0 ; i < AllPeers.count(); i ++ ) { + if( AllPeers[i]->address() == Addr ) { + return AllPeers[i]; + } + } + return 0; +} + +OTDriver* OTGateway::findDriver( const OTDeviceAddress & Addr ) { + for( unsigned int i = 0 ; i < AllDrivers.count(); i ++ ) { + if( AllDrivers[i]->address() == Addr ) { + return AllDrivers[i]; + } + } + return 0; +} + +void OTGateway::SLOT_PeerDetected( OTPeer * P, bool IsNew ) { + + if( IsNew ) { + // new peer + owarn << "New peer " << P->name() << oendl; + addPeer( P ); + } + + emit detectedPeer( P, IsNew ); +} + +void OTGateway::addPeer( OTPeer * P ) { + AllPeers.resize( AllPeers.size()+1); + AllPeers.insert( AllPeers.size()-1, P ); + AllPeersModified = 1; +} + +void OTGateway::removePeer( OTPeer * P ) { + int i = AllPeers.find( P ); + if( i ) { + AllPeers.remove( i ); + AllPeersModified = 1; + } +} + +void OTGateway::stopScanOfNeighbourhood( void ) { + if( Scanning ) { + delete Scanning; + Scanning = 0; + } +} + +void OTGateway::SLOT_FinishedDetecting() { + stopScanOfNeighbourhood(); + emit finishedDetecting(); +} + +const char * OTGateway::deviceTypeToName( int cls ) { + switch ( (cls & 0x001F00) >> 8) { + case 0x00: + return "misc"; + case 0x01: + return "computer"; + case 0x02: + return "phone"; + case 0x03: + return "lan"; + case 0x04: + return "av"; + case 0x05: + return "peripheral"; + case 0x06: + return "imaging"; + case 0x07: + default : + break; + } + return "unknown"; +} + +PANConnectionVector OTGateway::getPANConnections( void ) { + PANConnectionVector V; + + struct bnep_connlist_req req; + struct bnep_conninfo ci[48]; + + V.setAutoDelete(TRUE); + + int ctl = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP); + if (ctl < 0) { + owarn << "Failed to open control socket" << oendl; + return V; + } + + req.cnum = 48; + req.ci = ci; + if (ioctl(ctl, BNEPGETCONNLIST, &req)) { + owarn << "Failed to get connection list" << oendl; + ::close( ctl ); + return V; + } + + for ( unsigned i=0; i < req.cnum; i++) { + V.resize( V.size() + 1 ); + if( ci[i].role == BNEP_SVC_PANU ) { + // we are the client + V.insert( V.size()-1, new OTPANConnection( + ci[i].device, + batostr((bdaddr_t *) ci[i].dst) + ) ); + } + } + + ::close( ctl ); + return V; +} + +struct link_key { + bdaddr_t sba; + bdaddr_t dba; + uint8_t key[16]; + uint8_t type; + time_t time; +}; + +void OTGateway::readLinkKeys( void ) { + + struct link_key k; + int rv; + + AllKeys.truncate(0); + + QFile F( "/etc/bluetooth/link_key" ); + + if( ! F.open( IO_ReadOnly ) ) { + emit error( tr("Cannot open link_key file") ); + return; + } + + while( 1 ) { + rv = F.readBlock( (char *)&k, sizeof( k ) ); + if( rv == 0 ) + // EOF + break; + + if( rv < 0 ) { + emit error( tr("Read error in link key file") ); + } + + AllKeys.resize( AllKeys.size()+1 ); + AllKeys[ AllKeys.size()-1 ].From.setBDAddr( k.sba ); + AllKeys[ AllKeys.size()-1 ].To.setBDAddr( k.dba ); + } +} + +bool OTGateway::removeLinkKey( unsigned int Index ) { + OTLinkKey & LK = AllKeys[Index]; + + struct link_key k; + int rv; + + QFile F( "/etc/bluetooth/link_key" ); + QFile OutF( "/etc/bluetooth/newlink_key" ); + + if( ! F.open( IO_ReadOnly ) ) { + emit error( tr("Cannot open link_key file") ); + return 0; + } + + if( ! OutF.open( IO_WriteOnly | IO_Truncate ) ) { + emit error( tr("Cannot open temporary link_key file") ); + return 0; + } + + while( 1 ) { + rv = F.readBlock( (char *)&k, sizeof( k ) ); + if( rv == 0 ) + // EOF + break; + + if( rv < 0 ) { + emit error( tr("Read error in link key file") ); + return 0; + } + + if( LK.from() != OTDeviceAddress( k.sba ) || + LK.to() != OTDeviceAddress( k.dba ) ) { + // copy + OutF.writeBlock( (char *)&k, sizeof( k ) ); + } // else remove this key + } + + // rename files + QDir D( "/etc/bluetooth" ); + + D.remove( "link_key" ); + D.rename( "newlink_key", "link_key" ); + + // restart hcid + system( "/etc/init.d/hcid stop" ); + system( "/etc/init.d/hcid start" ); + + // remove from table + if( Index < (AllKeys.size()-1) ) { + // collapse array + AllKeys[Index] = AllKeys[AllKeys.size()-1]; + } + + // remove last element + AllKeys.resize( AllKeys.size()-1 ); + + return 1; +} + +#define MAXCONNECTIONS 10 +void OTGateway::loadActiveConnections( void ) { + + struct hci_conn_list_req *cl; + struct hci_conn_info *ci; + OTDeviceAddress Addr; + OTPeer * P; + + if (!(cl = (struct hci_conn_list_req *)malloc( + MAXCONNECTIONS * sizeof(*ci) + sizeof(*cl)))) { + emit error( tr("Can't allocate memory") ); + return; + } + memset( cl, 0, MAXCONNECTIONS * sizeof(*ci) + sizeof(*cl) ); + + for( unsigned int i = 0; + i < AllDrivers.count(); + i ++ ) { + + if( ! AllDrivers[i]->isUp() ) { + continue; + } + + // driver is up -> check connections + cl->dev_id = AllDrivers[i]->devId(); + cl->conn_num = MAXCONNECTIONS; + ci = cl->conn_info; + + if (ioctl( getSocket(), HCIGETCONNLIST, (void *) cl)) { + emit error( tr("Can't get connection list") ); + break; + } + + for ( int k = 0; k < cl->conn_num; k++, ci++) { + + if( ci->state != BT_CONNECTED ) { + // not yet connected + continue; + } + + Addr.setBDAddr( ci->bdaddr ); + P = findPeer( Addr ); + if( ! P ) { + // peer not yet known -> add + P = new OTPeer( this ); + addPeer( P ); + P->setAddress( Addr ); + // infoQueue.push_back(info); + P->setName( AllDrivers[i]->getPeerName( Addr ) ); + } + P->setState( OTPeer::Peer_Up ); + P->setConnectedTo( AllDrivers[i] ); + } + } + + free( cl ); +} + +void OTGateway::loadKnownPeers( void ) { + QDir SaveDir = QDir::home(); + + if( ! SaveDir.exists( "Settings" ) ) { + return; + } + SaveDir.cd( "Settings" ); + + if( ! SaveDir.exists( "opietooth" ) ) { + return; + } + SaveDir.cd( "opietooth" ); + + QFile F( SaveDir.path() + "/SeenDevices.conf" ); + + if( F.open( IO_ReadOnly ) ) { + QTextStream TS(&F); + long count; + + count = TS.readLine().toLong(); + + while( count > 0 ) { + addPeer( new OTPeer( TS, this ) ); + count --; + } + } + + AllPeersModified = 0; +} + +void OTGateway::saveKnownPeers( void ) { + QDir SaveDir = QDir::home(); + + if( ! SaveDir.exists( "Settings" ) ) { + SaveDir.mkdir( "Settings" ); + } + SaveDir.cd( "Settings" ); + + if( ! SaveDir.exists( "opietooth" ) ) { + SaveDir.mkdir( "opietooth" ); + } + SaveDir.cd( "opietooth" ); + + QFile F( SaveDir.path() + "/SeenDevices.conf" ); + + if( F.open( IO_WriteOnly | IO_Truncate ) ) { + QTextStream TS(&F); + QString S; + + TS << AllPeers.count() << endl; + + for( unsigned int i = 0; + i < AllPeers.count(); + i ++ ) { + AllPeers[i]->save( TS ); + } + AllPeersModified = 0; + } + AllPeersModified = 0; +} + +int OTGateway::connectedToRFCommChannel( const OTDeviceAddress & Addr, + int channel ) { + + int s; + + if( (s = ::socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM)) < 0 ) { + emit error( tr("Can't open RFCOMM control socket") ); + return 0; + } + + // get all rfcomm devices + { struct rfcomm_dev_list_req *dl; + struct rfcomm_dev_info *di, *dr; + int i; + + dl = (struct rfcomm_dev_list_req *)alloca( + sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di)); + memset( dl, 0, sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di) ); + dl->dev_num = RFCOMM_MAX_DEV; + di = dl->dev_info; + + if( ::ioctl(s, RFCOMMGETDEVLIST, (void *) dl) < 0) { + emit error( tr("Can't get device list") ); + ::close( s ); + return 0; + } + + dr = di; + for (i = 0; i < dl->dev_num; i++, dr++) { + // connected to Peer + if( Addr == OTDeviceAddress( dr->dst ) && + channel == dr->channel && + ( dr->state != 0 ) + ) { + // return device ID + return dr->id; + } + } + } + + // no device + return -1; +} + +static int byID( struct rfcomm_dev_info * d1, + struct rfcomm_dev_info * d2 ) { + return d1->id - d2->id; +} + +int OTGateway::getFreeRFCommDevice( void ) { + + int s; + + if( (s = ::socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM)) < 0 ) { + emit error( tr("Can't open RFCOMM control socket") ); + return 0; + } + + // get all rfcomm devices + { struct rfcomm_dev_list_req *dl; + struct rfcomm_dev_info *di, *dr; + int i; + + dl = (struct rfcomm_dev_list_req *)alloca( + sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di)); + + dl->dev_num = RFCOMM_MAX_DEV; + di = dl->dev_info; + + if( ::ioctl(s, RFCOMMGETDEVLIST, (void *) dl) < 0) { + emit error( tr("Can't get device list") ); + ::close( s ); + return 0; + } + + // s + if( dl->dev_num ) { + qsort( di, sizeof(struct rfcomm_dev_info), + dl->dev_num, (int(*)(const void*,const void*))byID ); + int id = 0; + + dr = di; + // find lowest free device number + for (i = 0; i < dl->dev_num; i++, dr++) { + if( id != dr->id ) { + return id; + } + id ++; + } + return id; + } else { + return 0; + } + } +} + +int OTGateway::releaseRFCommDevice( int devnr ) { + + int s; + + if( (s = ::socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM)) < 0 ) { + emit error( tr("Can't open RFCOMM control socket") ); + return 0; + } + + // get all rfcomm devices + { struct rfcomm_dev_list_req *dl; + struct rfcomm_dev_info *di, *dr; + int i; + + dl = (struct rfcomm_dev_list_req *)alloca( + sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di)); + memset( dl, 0, sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di) ); + dl->dev_num = RFCOMM_MAX_DEV; + di = dl->dev_info; + + if( ::ioctl(s, RFCOMMGETDEVLIST, (void *) dl) < 0) { + emit error( tr("Can't get device list") ); + ::close( s ); + return 0; + } + + dr = di; + for (i = 0; i < dl->dev_num; i++, dr++) { + if( dr->id == devnr ) { + // still in connection list + struct rfcomm_dev_req req; + int err; + + memset(&req, 0, sizeof(req)); + req.dev_id = devnr; + + if ((err = ioctl(s, RFCOMMRELEASEDEV, &req)) < 0 ) { + return err; + } + return 0; + } + } + } + + // no device -> nothing to release eiterh + return 0; +} + diff --git a/noncore/settings/networksettings2/opietooth2/OTGateway.h b/noncore/settings/networksettings2/opietooth2/OTGateway.h new file mode 100644 index 0000000..a47cefb --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTGateway.h @@ -0,0 +1,200 @@ +#ifndef OTGATEWAY_H +#define OTGATEWAY_H + +#include +#include +#include + +#include +#include + +class QPixmap; + +namespace Opietooth2 { + +class OTDriverList; +class OTDriver; +class OTDevice; +class OTPeer; +class OTInquiry; +class OTPANConnection; +class OTLinkKey; + +typedef QVector PeerVector; +typedef QVector PANConnectionVector; +typedef QArray LinkKeyArray; + +class OTLinkKey { + +public : + + OTLinkKey( const OTDeviceAddress & F, + const OTDeviceAddress & T ) { + From = F; + To = T; + } + + const OTDeviceAddress & to() + { return To; } + const OTDeviceAddress & from() + { return From; } + + OTDeviceAddress From; + OTDeviceAddress To; +}; + +class OTPANConnection { + +public : + + OTPANConnection( const QString & Dev, const QString & CT ) { + Device = Dev; + ConnectedTo = CT; + } + + QString Device; + QString ConnectedTo; +}; + + +class OTGateway : public QObject { + + Q_OBJECT + +public : + + // single instance + static OTGateway * getOTGateway( void ); + static void releaseOTGateway( void ); + // convert device type as class to name for that class + static const char * deviceTypeToName( int Cls ); + + // open bluetooth system + OTGateway( void ); + // close bluetooth system + ~OTGateway( void ); + + // get access to system device + OTDevice * getOTDevice(); + + // return true if this device needs enabling of bluetooth + bool needsEnabling(); + // return true if system is running + bool isEnabled(); + void setRefreshTimer( int MilleSecs ); + // return socket to HCI raw layer + inline int getSocket() + { return HciCtl; } + + OTDriverList & getDriverList() + { return AllDrivers; } + OTDriver * driver( int nr ) + { return AllDrivers[nr]; } + void updateDrivers(); + + PANConnectionVector getPANConnections(); + + // scan neighbourhood using device + void scanNeighbourhood( OTDriver * D = 0 ); + void stopScanOfNeighbourhood(void ); + void setScanWith( OTDriver * D = 0 ) + { ScanWith = (D) ? D : + (AllDrivers.count() ) ? AllDrivers[0] : 0; } + OTDriver * scanWith( void ) + { return ScanWith; } + + // get list of all detected peers + inline const PeerVector & peers( void ) + { return AllPeers; } + // ping peer to see if it is up + bool isPeerUp( const OTDeviceAddress & PAddr, + int timeoutInSec = 1, + int timeoutInUSec = 0, + int retry = 1 ); + OTPeer * findPeer( const OTDeviceAddress & Addr ); + void removePeer( OTPeer * P ); + void addPeer( OTPeer * P ); + + OTDriver * findDriver( const OTDeviceAddress & Addr ); + + inline const LinkKeyArray & getLinkKeys() const + { return AllKeys; } + bool removeLinkKey( unsigned int index ); + + // return device number if we are connected over any device + // to the channel + // else returns -1 + int connectedToRFCommChannel( const OTDeviceAddress & Addr, int channel ); + int getFreeRFCommDevice( void ); + // return 0 if properly released + int releaseRFCommDevice( int DevNr ); + +public slots : + + // start bluetooth system + void SLOT_SetEnabled( bool ); + void SLOT_Enable(); + void SLOT_Disable(); + + // show error + void SLOT_ShowError( const QString & ); + + void SLOT_Enabled( int, bool ); + void SLOT_DriverDisappeared( OTDriver * ); + void SLOT_PeerDetected( OTPeer *, bool ); + void SLOT_FinishedDetecting(); + +signals : + + // any error + void error( const QString & ); + + // signal state of bluetooth driver + void stateChange( OTDriver * D, bool State ); + + // sent when list of drivers changees + void driverListChanged(); + + // sent when bluetooth on device is enabled + void deviceEnabled( bool ); + + // sent when a (new if bool = TRUE) peer is detected + void detectedPeer( OTPeer *, bool ); + + // end of detection process + void finishedDetecting(); + +protected : + + void connectNotify( const char * Signal ); + void disconnectNotify( const char * Signal ); + + void timerEvent( QTimerEvent * ); + +private : + + void loadActiveConnections( void ); + void loadKnownPeers( void ); + void saveKnownPeers( void ); + bool isConnectedTo( int devid, + const OTDeviceAddress & Address ); + + void readLinkKeys(); + + static OTGateway * SingleGateway; + static int UseCount; + + OTDriver * ScanWith; + OTDriverList AllDrivers; + OTDevice * TheOTDevice; + int HciCtl; + int ErrorConnectCount; + int RefreshTimer; + OTInquiry * Scanning; + bool AllPeersModified; + PeerVector AllPeers; + LinkKeyArray AllKeys; +}; +}; + +#endif diff --git a/noncore/settings/networksettings2/opietooth2/OTHCISocket.cpp b/noncore/settings/networksettings2/opietooth2/OTHCISocket.cpp new file mode 100644 index 0000000..471c3bf --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTHCISocket.cpp @@ -0,0 +1,274 @@ +//-*-c++-*- +/*************************************************************************** + * Copyright (C) 2003 by Fred Schaettgen * + * kdebluetooth@schaettgen.de * + * * + * 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 +#include +#include +#include + +#include + +// #include "deviceaddress.h" +#include +#include + +using namespace Opietooth2; + +OTHCISocket::OTHCISocket( OTDriver * D ) : + QObject( D, D->devname() ) { + BStatusSet = false; + Driver = D; + HCIReadNotifier = 0; +} + +OTHCISocket::~OTHCISocket() { + close(); +} + +void OTHCISocket::close() { + owarn << "OTHCISocket::close()" << oendl; + if( HCIReadNotifier ) { + delete HCIReadNotifier; + } + + if( HCISocket.isValid() ) { + HCISocket.close(); + } +} + +bool OTHCISocket::open() { + + owarn << "OTHCISocket::open()" << oendl; + int s; + + s = ::socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + + if (s < 0) { + emit error( tr( "Error creating socket on %1 : %2 %3"). + arg( Driver->devname() ). + arg( errno ). + arg( strerror(errno) ) + ); + return false; + } + + /* Bind socket to the HCI device */ + struct sockaddr_hci sa; + sa.hci_family = AF_BLUETOOTH; + sa.hci_dev = Driver->devId(); + if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { + ::close(s); + emit error( tr( "Error binding to socket to %1 : %2 %3"). + arg( Driver->devname() ). + arg( errno ). + arg( strerror(errno) ) + ); + return false; + } + + struct hci_filter flt; + hci_filter_clear(&flt); + hci_filter_set_ptype(HCI_EVENT_PKT, &flt); + hci_filter_all_events(&flt); + if( setsockopt(s, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0 ) { + ::close(s); + emit error( tr( "HCI filter setup failed on %1 : %2 %3"). + arg( Driver->devname() ). + arg( errno ). + arg( strerror(errno) ) + ); + return false; + } + + if( HCIReadNotifier ) { + delete HCIReadNotifier; + } + + HCISocket.setSocket(s, QSocketDevice::Datagram); + HCIReadNotifier = new QSocketNotifier( + s, QSocketNotifier::Read, this); + + connect( HCIReadNotifier, + SIGNAL(activated(int)), + this, + SLOT(slotSocketActivated()) + ); + + //connect(hciSocket, SIGNAL(error(int)), + // this, SLOT(slotSocketError(int))); + //connect(hciSocket, SIGNAL(connectionClosed()), + // this, SLOT(slotConnectionClosed())); + //hciSocket->setSocket(s); + + return true; +} + +void OTHCISocket::slotSocketError(int e) { + close(); + emit error( tr( "HCI socket error 0x%1 on %1 : %2 %3"). + arg(e,2,16). + arg( Driver->devname() ). + arg( errno ). + arg( strerror(errno) ) + ); +} + +void OTHCISocket::slotSocketActivated() { + + QSocketDevice::Error err = HCISocket.error(); + + if( (err == QSocketDevice::NoError ) && + ( HCISocket.isValid() ) ) { + //kdDebug() << "HCI socket ready read." << endl; + + unsigned char buf[512]; + int psize = HCISocket.readBlock((char*)buf, 512); + + if (psize <= 0) { + slotSocketError(HCISocket.error()); + HCISocket.close(); + return; + } + + //unsigned char packetType = buf[0]; + unsigned char eventCode = buf[1]; + unsigned char len = buf[2]; + + if (psize-3 == len) { + + QByteArray databuf; + databuf.duplicate((char*)(buf+3), len); + emit event(eventCode, databuf); + if (eventCode == EVT_CMD_STATUS) { + updateStatus( databuf ); + } + } else { + owarn << "Error reading hci packet: packetSize(" + << psize + << ")-3 != dataSize(" + << len + << ")" + << oendl; + } + } else if (err == QSocketDevice::NoError) { + slotConnectionClosed(); + } else { + HCISocket.close(); + slotSocketError(err); + } +} + +void OTHCISocket::updateStatus(const QByteArray& data) { + + QDataStream stream(data, IO_ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + Q_UINT8 status, dummy; + Q_UINT16 opcode; + + BStatusSet = true; + + stream >> status >> dummy >> opcode; + //kdDebug() << "updatestatus opcode=" << uint32_t(opcode) << endl; + LastStatus = status; + LastStatusOgf = cmd_opcode_ogf(opcode); + LastStatusOcf = cmd_opcode_ocf(opcode); +} + +void OTHCISocket::slotConnectionClosed() { + owarn << "HCI connection closed." << oendl; + emit connectionClosed(); +} + +void OTHCISocket::readEvent() { + + if (HCIReadNotifier) { + slotSocketActivated(); + } +} + +bool OTHCISocket::sendCommand( unsigned char ogf, + unsigned short ocf, + QByteArray buf + ) { + QBuffer packet; + QDataStream stream(&packet); + + stream.setByteOrder(QDataStream::LittleEndian); + packet.open(IO_WriteOnly); + + if (buf.size() > 255) return false; + + //kdDebug() << "sendCommand. ogf=" << ogf << " ocf=" << ocf << endl; + Q_UINT16 opcode = cmd_opcode_pack(ogf, ocf); + Q_UINT8 pType = HCI_COMMAND_PKT; + Q_UINT8 buflen = buf.size(); + + stream << pType << opcode << buflen; + stream.writeRawBytes(buf.data(), buflen); + packet.close(); + HCISocket.writeBlock((const char*)packet.buffer(), + packet.buffer().size()); + return true; +} + +bool OTHCISocket::readStatus( unsigned char ogf, + unsigned short ocf, + int *status, + int timeout_ms) { + QTimer timer; + + timer.start(timeout_ms, true); + BStatusSet = false; + + while (timer.isActive() && HCISocket.isValid()) { + + owarn << "OTHCISocket::readStatus()" << oendl; + bool timeout = false; + + if( HCISocket.bytesAvailable() == 0) { + int rv = HCISocket.waitForMore(timeout_ms); + timeout = (rv == 0); + } + + if (!timeout) { + slotSocketActivated(); + } + + if( BStatusSet == true && + ogf == LastStatusOgf && + ocf == LastStatusOcf) { + *status = LastStatus; + owarn << "OTHCISocket::readStatus(ogf=" + << ogf + << ",ocf=" + << ocf + << ",timeout=" + << LastStatus + << ")" + << oendl; + return true; + } + } + + owarn << "OTHCISocket::readStatus(ogf=" + << ogf + << ",ocf=" + << ocf + << ",timeout=" + << LastStatus + << ") : timeout " + << oendl; + return false; +} + +int OTHCISocket::socket() { + return HCISocket.socket(); +} diff --git a/noncore/settings/networksettings2/opietooth2/OTHCISocket.h b/noncore/settings/networksettings2/opietooth2/OTHCISocket.h new file mode 100644 index 0000000..d508078 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTHCISocket.h @@ -0,0 +1,116 @@ +//-*-c++-*- +/*************************************************************************** + * Copyright (C) 2003 by Fred Schaettgen * + * kdebluetooth@schaettgen.de * + * * + * 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. * + ***************************************************************************/ + +#ifndef OTHCISOCKET_H +#define OTHCISOCKET_H + +#include +#include +#include +#include + +class QSocket; + +namespace Opietooth2 { + +/** Bluetooth HCI Socket class. + * This class provides socket level access to the Bluez HCI layer. + * It is set up to filter out all but HCI event packets, since more + * is only allowed for privileged users. + * @todo writeHciEvent() function + * @todo error handling + */ + +class OTDriver; + +class OTHCISocket : public QObject { + + Q_OBJECT + +public: + + OTHCISocket( OTDriver * ConnectTo ); + virtual ~OTHCISocket(); + + /** Opens a HCI socket for the given + @return true if sucessfully opened, false otherwise + */ + virtual bool open(); + + /** Closes the HCI socket. */ + virtual void close(); + + bool sendCommand( unsigned char ogf, + unsigned short ocf, + QByteArray buf + ); + bool readStatus( unsigned char ogf, + unsigned short ocf, + int *status, + int timeout_ms = 1000); + + /** Reads whole HCI packet. + @param packetType [out] The packet type. Should always be ... + @param eventCode [out] The event code. + @param buflen [in/out] The maximum size of the buffer / the number of + bytes written into the buffer. + @param paramBuf pointer to a buffer for the HCI event packet + @return true if successful + */ + /*bool readEvent(unsigned char &packetType, + unsigned char &eventCode, unsigned char &buflen, + char* paramBuf);*/ + + enum Error { ErrSocket = 1 }; + + /** Forces reading the next event packet. */ + void readEvent( void ); + + /** Returns the internal socket */ + int socket( void ); + + inline QSocketDevice & socketDevice() + { return HCISocket; } + + inline OTDriver * driver() const + { return Driver; } + +signals: + + void event( unsigned char eventCode, QByteArray buf); + void error( QString message ); + void connectionClosed( ); + +private: + + void updateStatus( const QByteArray& data ); + + //QSocketDevice hciSocket; + QGuardedPtr HCIReadNotifier; + QSocketDevice HCISocket; + OTDriver * Driver ; + + bool BStatusSet; + unsigned short LastStatusOcf; + unsigned char LastStatusOgf; + int LastStatus; + +private slots: + + void slotSocketActivated(); + void slotSocketError(int); + void slotConnectionClosed(); + +}; + +}; + +#endif diff --git a/noncore/settings/networksettings2/opietooth2/OTIcons.cpp b/noncore/settings/networksettings2/opietooth2/OTIcons.cpp new file mode 100644 index 0000000..8b58b75 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTIcons.cpp @@ -0,0 +1,120 @@ +#include + +#include +#include + +using namespace Opietooth2; + +OTIcons::OTIcons() : deviceIcons(), serviceIcons() { + + // still need to find out real ids + deviceIcons.insert( "unknown", "unknown_16" ); + deviceIcons.insert( "misc", "misc_16" ); + deviceIcons.insert( "computer", "computer_16" ); + deviceIcons.insert( "phone", "phone_16" ); + deviceIcons.insert( "lan", "network_16" ); + deviceIcons.insert( "audiovideo", "audio_16" ); + deviceIcons.insert( "peripheral", "print_16" ); + deviceIcons.insert( "imaging", "other_16" ); + + serviceIcons.insert( 0x1101 , "serial_16" ); //SerialPort + serviceIcons.insert( 0x1102 , "network_16" ); //LANAccessUsingPPP + serviceIcons.insert( 0x1103 , "network_16"); //DialupNetworking + serviceIcons.insert( 0x1104 , "sync_16" ); //IrMCSync + serviceIcons.insert( 0x1105 , "obex_16" ); //OBEXObjectPush + serviceIcons.insert( 0x1106 , "obex_16" ); //OBEXFileTransfer + serviceIcons.insert( 0x1107 , "sync_16" ); //IrMCSyncCommand + serviceIcons.insert( 0x1108 , "phone_16"); // Headset + serviceIcons.insert( 0x1109 , "phone_16"); // CordlessTelephony + serviceIcons.insert( 0x110A , "audio_16"); // AudioSource + serviceIcons.insert( 0x110B , "audio_16"); // AudioSink + //serviceIcons.insert( 0x110C , "remotecontrol_16" ); // remote control target --- + //serviceIcons.insert( 0x110D , "audio_16" ); // advanced audio distribution --- + //serviceIcons.insert( 0x110E , "remotecontrol_16" ); // remote control --- + //serviceIcons.insert( 0x110F , "video_16" ); // video conferencing --- + //serviceIcons.insert( 0x1110 , "audio_16" ); // intercom --- + serviceIcons.insert( 0x1111 , "fax_16" ); //Fax + serviceIcons.insert( 0x1112 , "audio_16"); //HeadsetAudioGateway + //serviceIcons.insert( 0x1113 , "wap_16" ); // WAP --- + //serviceIcons.insert( 0x1114 , "wap_16" ); // WAP client --- + serviceIcons.insert( 0x1115 , "network_16"); // Network Access Point (PANU) + serviceIcons.insert( 0x1116 , "network_16"); // Network Access Point (NAP) + serviceIcons.insert( 0x1117 , "network_16"); // Network Access Point (GN) + serviceIcons.insert( 0x1118 , "print_16" ); // direct printing + serviceIcons.insert( 0x1119 , "print_16" ); // reference printing + //serviceIcons.insert( 0x111A , "image_16" ); // imaging --- + //serviceIcons.insert( 0x111B , "image_16" ); // imaging responder --- + //serviceIcons.insert( 0x111C , "image_16" ); // imaging automatic archive --- + //serviceIcons.insert( 0x111D , "image_16" ); // imaging referenced objects --- + //serviceIcons.insert( 0x111E , "handsfree_16" ); // handsfree --- + //serviceIcons.insert( 0x111F , "handsfree_16" ); // handsfree audio gateway --- + serviceIcons.insert( 0x1120 , "print_16" ); // direct printing referenced object service + //serviceIcons.insert( 0x1121 , "handsfree_16" ); // reflected UI --- + serviceIcons.insert( 0x1122 , "print_16" ); // basic printing + serviceIcons.insert( 0x1123 , "print_16" ); // printing status + //serviceIcons.insert( 0x1124 , "handsfree_16" ); // human interface device service --- + //serviceIcons.insert( 0x1125 , "handsfree_16" ); // hardcopy cable replacement --- + serviceIcons.insert( 0x1126 , "print_16" ); // HCR print + serviceIcons.insert( 0x1127 , "print_16" ); // HCR scan + serviceIcons.insert( 0x1128 , "phone_16" ); // Common_ISDN_Access + //serviceIcons.insert( 0x1129 , "audio_16" ); // video conferencing GW --- + //serviceIcons.insert( 0x112C , "audio_16" ); // audio video --- + //serviceIcons.insert( 0x112D , "phone_16" ); // SIM access --- + serviceIcons.insert( 0x1201 , "network_16" ); //GenericNetworking + serviceIcons.insert( 0x1202 , "folder_16" ); //GenericFileTransfer + serviceIcons.insert( 0x1203 , "audio_16" ); //GenericAudio + serviceIcons.insert( 0x1204 , "phone_16" ); //GenericTelephony + //serviceIcons.insert( 0x1303 , "video_16" ); // video source --- + //serviceIcons.insert( 0x1304 , "video_16" ); // video sink --- + + Modems.resize( 3 ); + Modems[0].setUUID32( 0x1101 ); // SerialPort + Modems[1].setUUID32( 0x1102 ); // Lan access using PPP + Modems[2].setUUID32( 0x1103 ); // DialupNetworking + + Networks.resize( 3 ); + Networks[0].setUUID32( 0x1115 ); // PANU + Networks[1].setUUID32( 0x1116 ); // NAP + Networks[2].setUUID32( 0x1117 ); // GN +} + +OTIcons::~OTIcons() { +} + +QPixmap OTIcons::deviceIcon( const QString & deviceClass ) { + + QString iconName; + + QMap::Iterator it; + + it = deviceIcons.find( deviceClass ); + iconName = it.data(); + + if ( iconName.isEmpty() ) { + iconName = "unknown_16"; + } + return loadPixmap( iconName, 1 ); +} + +QPixmap OTIcons::serviceIcon( int serviceClass, bool & found ) { + + QString iconName; + + QMap::Iterator it; + + it = serviceIcons.find( serviceClass ); + iconName = it.data(); + + if ( iconName.isEmpty() ) { + iconName = "unknown_16"; + found = 0 ; + } else + found = 1 ; + return loadPixmap( iconName, 1 ); +} + +QPixmap OTIcons::loadPixmap( const QString & name, bool Sub ) { + return( Resource::loadPixmap( "opietooth/" + + QString( (Sub) ? "icons/" : "" ) + + name ) ); +} diff --git a/noncore/settings/networksettings2/opietooth2/OTIcons.h b/noncore/settings/networksettings2/opietooth2/OTIcons.h new file mode 100644 index 0000000..ee10831 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTIcons.h @@ -0,0 +1,54 @@ +#ifndef OTICONLOADER_H +#define OTICONLOADER_H + +#include +#include +#include + +namespace Opietooth2 { + +class OTIcons { + +public: + + OTIcons(); + ~OTIcons(); + + /** + * Returns an icon depending on device class + * @param deviceClass the device class name + * @return the pixmap + */ + QPixmap deviceIcon( const QString & ); + + /** + * Returns an icon depending on service id + * @param serviceClass the service id + * @return the pixmap + * @return true if found + */ + QPixmap serviceIcon( int, bool & ); + + // returns all UUID that represent channels with modem function + const UUIDVector & modems() + { return Modems; } + + // returns all UUID that represent channels with network + const UUIDVector & network() + { return Networks; } + + // set Sub to find icons in .../Icons dir + QPixmap loadPixmap( const QString &, bool Sub = 0 ); + +private: + + // first ist id, second is icon name + QMap deviceIcons; + QMap serviceIcons; + UUIDVector Modems; + UUIDVector Networks; + +}; +} + +#endif diff --git a/noncore/settings/networksettings2/opietooth2/OTInquiry.cpp b/noncore/settings/networksettings2/opietooth2/OTInquiry.cpp new file mode 100644 index 0000000..8e94bbc --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTInquiry.cpp @@ -0,0 +1,219 @@ +//-*-c++-*- +/*************************************************************************** + * Copyright (C) 2003 by Fred Schaettgen * + * kdebluetooth@schaettgen.de * + * * + * 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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +using namespace Opietooth2; + +#define max(a,b) (((a)>(b)) ? (a) : (b)) +#define min(a,b) (((a)>(b)) ? (b) : (a)) + +OTInquiry::OTInquiry( OTDriver * Drv ) : QObject( Drv ) { + + reset(); + + InquiryTimeoutTimer = new QTimer(this); + + connect( InquiryTimeoutTimer, + SIGNAL(timeout()), + this, + SLOT(slotInquiryTimeout())); + + Driver = Drv; + Socket = Drv->openSocket(); + Socket->open(); + + connect( Socket, + SIGNAL( event(unsigned char, QByteArray)), + this, + SLOT(slotHCIEvent(unsigned char, QByteArray))); +} + +OTInquiry::~OTInquiry() { + stopInquiring(); +} + +void OTInquiry::stopInquiring( void ) { + if( Socket ) { + owarn << "Stop inquiry" << oendl; + Driver->closeSocket(); + Socket = 0; + } +} + +bool OTInquiry::inquire( double timeout, int numResponses, int lap) { + + QByteArray cmdBuf(5); + + cmdBuf[0] = lap & 0xFF; + cmdBuf[1] = (lap >> 8) & 0xFF; + cmdBuf[2] = (lap >> 16) & 0xFF; + cmdBuf[3] = max(0x01, min(0x30, int(timeout/1.28))); + cmdBuf[4] = (unsigned char)numResponses; + + owarn << "Send HCI inquiry command. wait for " << cmdBuf[3] << oendl; + + Socket->sendCommand(0x01, 0x0001, cmdBuf); + + int status; + + if( Socket->readStatus(0x01, 0x0001, &status)) { + if (status == 0) { + SuccessfullyStarted = true; + InquiryTimeoutTimer->start( int(1000*(timeout+1.0)), true); + return true; + } + else { + QString S =QString().sprintf( "%x", status ); + owarn << "OTInquiry::inquiry() failed: 0x" << S << oendl; + emit finished(); + return false; + } + } else { + owarn << "OTInquiry::inquiry(): Timeout." << oendl; + return false; + } +} + +bool OTInquiry::isInquiring() { + return InquiryTimeoutTimer->isActive(); +} + +bool OTInquiry::isFinished() { + return SuccessfullyStarted && SuccessfullyEnded; +} + +void OTInquiry::reset() { + + SuccessfullyStarted = false; + SuccessfullyEnded = false; + //addrCache.clear(); + //infoQueue.clear(); +} + + +void OTInquiry::onPeerFound( OTPeer * Peer, bool IsNew ) { + emit peerFound( Peer, IsNew ); +} + +void OTInquiry::slotInquiryTimeout() { + emit error( tr( "Timeout while waiting for end of inquiry.") ); +} + +void OTInquiry::slotHCIEvent(unsigned char eventCode, QByteArray buf) { + + owarn << "OTInquiry: hci packet received: eventCode=" + << (unsigned int)eventCode + << " packetLength=" + << (unsigned int)buf.size() + << oendl; + + unsigned char *data = (unsigned char*)buf.data(); + switch (eventCode) { + case EVT_INQUIRY_COMPLETE: + { unsigned char status = data[0]; + owarn << "EVT_INQUIRY_COMPLETE status=" << status << oendl; + InquiryTimeoutTimer->stop(); + if (status == 0) { + if( SuccessfullyStarted == true) { + owarn << "OTInquiry ended successfully" << oendl; + SuccessfullyEnded = true; + } + emit finished(); + } + else { + emit error( tr( "OTInquiry completed with error (code %1)" ). + arg(status)); + } + } + break; + case EVT_INQUIRY_RESULT: + { int numResults = data[0]; + OTPeer * P = 0; + bool IsNew; + OTDeviceAddress Addr; + QString N; + + inquiry_info *results = (inquiry_info*)(data+1); + + for (int n=0; ngateway()->findPeer( Addr ); + + if( P ) { + // peer known + if( P->state() != OTPeer::Peer_Up ) { + P->setState( OTPeer::Peer_Up ); + } + IsNew = 0; + } else { + IsNew = 1; + // push the address to the address queue + // where it can be consumed by nextNeighbour() + P = new OTPeer( Driver->gateway() ); + P->setState( OTPeer::Peer_Up ); // we just detected it + P->setAddress( Addr ); + //if( addrCache.find(info.addr) == addrCache.end()) { + // addrCache.insert(info.addr); + + P->setDeviceClass( (results[n].dev_class[0] << 16) | + (results[n].dev_class[1] << 8) | + (results[n].dev_class[2] << 0) ); + // infoQueue.push_back(info); + P->setName( Driver->getPeerName( Addr ) ); + } + + // call the handler. Emits a signal if not overwritten + onPeerFound( P, IsNew ); + + // } + } + } + break; + case EVT_CMD_STATUS : + { int status = data[0]; + int numHciCmdPkts = data[1]; + int cmdOpcode = *((uint16_t*)(data+2)); + owarn << "EVT_CMD_STATUS status=" + << status + << " numPkts=" + << numHciCmdPkts + << " cmdOpcode=" + << cmdOpcode + << oendl; + if (cmdOpcode == OCF_INQUIRY) { + + } + } + break; + } +} diff --git a/noncore/settings/networksettings2/opietooth2/OTInquiry.h b/noncore/settings/networksettings2/opietooth2/OTInquiry.h new file mode 100644 index 0000000..f7bdeec --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTInquiry.h @@ -0,0 +1,178 @@ +//-*-c++-*- +/*************************************************************************** + * Copyright (C) 2003 by Fred Schaettgen * + * kdebluetooth@schaettgen.de * + * * + * 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. * + ***************************************************************************/ + +#ifndef OTINQUIRY_H +#define OTINQUIRY_H + +#include +#include + +#include +#include + +#include + +// #include +// #include + +namespace Opietooth2 { + +class QSocket; +class QDateTime; + +class OTDriver; +class OTHCISocket; + +/** Scans for nearby bluetooth devices. + * This class provides an asynchronous interface to the + * inquriy HCI command. To scan for other devices, connect + * to the signals neighbourFound() and finished() and call + * inquiry(). Inquiry results are signalled as soon as they arrive, + * so the information can be displayed before the whole inquiry + * process is finished. + * Still no connections should be set up before + * the finished() signal was sent (hmm, is this always true..?) + */ + +class OTInquiry : public QObject { + + Q_OBJECT + +public: + + /** Constructor. + @param owner The owning parent object + */ + OTInquiry( OTDriver* Drv ); + + /** Destructor. */ + virtual ~OTInquiry(); + + // General/Unlimited Inquiry Access Code + static const int GIAC = 0x9E8B33; + + // Limited Dedicated Inquiry Access Code + static const int LIAC = 0x9E8B00; + + /** Starts the inquiry. + if you start inquiry several times without calling clear(), + you will receive each result only once. + @param timeout duration of the inquiry in seconds. + It will be rounded to the next multiple of 1.28 sec, + with a maximum of 61.44 sec. + @param lap + */ + bool inquire( double timeout = 8.0, + int numResponses = 0, + int lap = GIAC); + + void stopInquiring( ); + + /** Enters periodic inquiry mode. + An inquiry will be started at a random time in the intervall + between minduration and maxduration. + @param minduration minimum time between two inquiries. Rounded to + a multiple of 1.28, (3.84 <= d <= 83884.8) + @param maxduration maximum time between two inquiries. Rounded to + a multiple of 1.28, (3.84 <= d <= 83884.8) + @param timeout duration of the inquiry in seconds. + It will be rounded to the next multiple of 1.28 sec, + with a maximum of 61.44 sec. + @param numResponses Number of responses after which the inquiry + will be stopped. 0 means no limit. + @param lap + */ + /* + void inquirePeriodically( double minduration, + double maxduration, + double timeout = 8.0, + int numResponses = 0, + int lap = LIAC + ); +*/ + /** checks if there the inquiry is running currently + @return true if there is an inquiry running + which was started by this object. + @todo possibility to check for "foreign" inquiries. Deal with + the fact that we can receive foreign inquiry results. + */ + bool isInquiring(); + + /** This function returns true after after an inquiry was + started, results were received and the inquiry ended successfully. + This can be the case without calling inquiry() at all, because + results of inquiries started by other programs are also processed. + */ + bool isFinished(); + + /** Resets the list of received results and sets + isInquiryComplete() to false. + */ + void reset(); + + inline OTDriver * driver() const + { return Driver; } + +protected: + + /** Called when a new neighbour was found. The default + implementation emits the neighbourFound signal. + @param bdaddr the address found. + */ + virtual void onPeerFound( OTPeer * Peer, bool ); + + enum ErrorCode { + InquiryFinishedTimeout = 0x0100 + }; + +signals : + + void peerFound( OTPeer *, bool ); + + /** Emitted after an inquiry has finished successfully. + If the inquiry was canceled, no finished signals is emitted. + This signal can be emitted without having called inquiry, since + other processes may have started an inquiry. + */ + void finished(); + + /** Emitted instead of finished if an error occured after + calling inquiry() or periodicInquiryMode() + @param code error code. + @param message Error message + */ + void error( QString message ); + +private: + + // std::set addrCache; + // double currentTimeout; + // QByteArray* buf; + // QSocket* hciSocket; + QGuardedPtr Socket; + OTDriver * Driver; + + //QDateTime *startTime; + QTimer *InquiryTimeoutTimer; + + // std::deque infoQueue; + bool SuccessfullyStarted; + bool SuccessfullyEnded; + +private slots: + + void slotInquiryTimeout(); + void slotHCIEvent(unsigned char eventCode, QByteArray buf); + +}; + +} +#endif diff --git a/noncore/settings/networksettings2/opietooth2/OTMainGUI.ui b/noncore/settings/networksettings2/opietooth2/OTMainGUI.ui new file mode 100644 index 0000000..5584cd9 --- a/dev/null +++ b/noncore/settings/networksettings2/opietooth2/OTMainGUI.ui @@ -0,0 +1,378 @@ + +OTMainGUI + + QWidget + + name + OTMainGUI + + + geometry + + 0 + 0 + 240 + 385 + + + + caption + Bluetooth Manager + + + + margin + 11 + + + spacing + 6 + + + QLayoutWidget + + name + Layout4 + + + + margin + 0 + + + spacing + 6 + + + + name + Spacer4_2 + + + orientation + Horizontal + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QCheckBox + + name + MustBeEnabled_CB + + + text + Bluetooth Enabled + + + + + + QLabel + + name + TextLabel5 + + + sizePolicy + + 0 + 1 + + + + text + Use device : + + + + + name + Spacer7 + + + orientation + Horizontal + + + sizeType + Fixed + + + sizeHint + + 20 + 20 + + + + + + name + Spacer7_2 + + + orientation + Horizontal + + + sizeType + Fixed + + + sizeHint + + 20 + 20 + + + + + + name + Spacer7_3 + + + orientation + Horizontal + + + sizeType + Fixed + + + sizeHint + + 20 + 20 + + + + + QLabel + + name + TextLabel1 + + + sizePolicy + + 7 + 1 + + + + text + Select to manage your local Bluetooth hardware + + + alignment + WordBreak|AlignVCenter|AlignLeft + + + wordwrap + + + + QLabel + + name + TextLabel1_2 + + + sizePolicy + + 7 + 1 + + + + text + Select to scan the bluetooth network for reachable devices using the selected local device + + + alignment + WordBreak|AlignVCenter|AlignLeft + + + wordwrap + + + + + name + Spacer4 + + + orientation + Horizontal + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QComboBox + + name + DeviceList_CB + + + sizePolicy + + 7 + 0 + + + + + QLabel + + name + TextLabel1_2_2 + + + sizePolicy + + 7 + 1 + + + + text + Select to manage all pairings known on the local device to any remote device regardless if it is currently reachable or not + + + alignment + WordBreak|AlignVCenter|AlignLeft + + + wordwrap + + + + + name + Spacer5_2 + + + orientation + Horizontal + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QPushButton + + name + Scan_But + + + text + Scan Neighbourhood + + + + QPushButton + + name + Pairing_But + + + text + Manage Pairing + + + + QPushButton + + name + ManageLocalHW_But + + + text + Local Bluetooth hardware + + + + + name + Spacer5_2_2 + + + orientation + Horizontal + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + ManageLocalHW_But + clicked() + OTMainGUI + SLOT_Manage() + + + Scan_But + clicked() + OTMainGUI + SLOT_Scan() + + + MustBeEnabled_CB + toggled(bool) + OTMainGUI + SLOT_EnableBluetooth(bool) + + + Pairing_But + clicked() + OTMainGUI + SLOT_Pairing() + + SLOT_EnableBluetooth(bool) + SLOT_Manage() + SLOT_Scan() + SLOT_Pairing() + + -- cgit v0.9.0.2