-rw-r--r-- | noncore/net/opietooth/lib/bt-serial.c | 308 | ||||
-rw-r--r-- | noncore/net/opietooth/lib/bt-serial.h | 57 | ||||
-rw-r--r-- | noncore/net/opietooth/lib/forwarder.cc | 203 | ||||
-rw-r--r-- | noncore/net/opietooth/lib/forwarder.h | 45 | ||||
-rw-r--r-- | noncore/net/opietooth/lib/lib.pro | 6 | ||||
-rw-r--r-- | noncore/net/opietooth/manager/bluebase.cpp | 61 | ||||
-rw-r--r-- | noncore/net/opietooth/manager/bluebase.h | 4 | ||||
-rw-r--r-- | noncore/net/opietooth/manager/bluetoothbase.ui | 182 |
8 files changed, 851 insertions, 15 deletions
diff --git a/noncore/net/opietooth/lib/bt-serial.c b/noncore/net/opietooth/lib/bt-serial.c new file mode 100644 index 0000000..d1a65a2 --- a/dev/null +++ b/noncore/net/opietooth/lib/bt-serial.c @@ -0,0 +1,308 @@ +/* $Id$ + * Bluetooth serial forwarder functions implementation + * + * (c) Copyright 2006 GPL + * + * This software is provided under the GNU public license, incorporated + * herein by reference. The software is provided without warranty or + * support. + */ +#include "bt-serial.h" +#include <errno.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <bluetooth/bluetooth.h> +#include <bluetooth/rfcomm.h> +#include <bluetooth/sdp.h> +#include <bluetooth/sdp_lib.h> +#include <termios.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> + +static int hserv = -1; //Server socket +sdp_session_t* session = NULL; //session with an SDP server + +static sdp_session_t* register_service(uint8_t rfchannel) +{ + int err = 0; + sdp_profile_desc_t profile[1]; + uint32_t service_uuid_int[] = { 0, 0, 0, 0xABCD }; + const char *service_name = "Serial forwarder"; + const char *service_dsc = "Serial forwarder"; + const char *service_prov = "OPIE team"; + uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid, service_uuid; + sdp_list_t* l2cap_list = 0; + sdp_list_t* rfcomm_list = 0; + sdp_list_t* root_list = 0; + sdp_list_t* proto_list = 0; + sdp_list_t* access_proto_list = 0; + sdp_list_t* profile_list = 0; + sdp_list_t* service_list = 0; + sdp_data_t* channel = 0; + sdp_record_t* record = sdp_record_alloc(); + sdp_session_t* lsession = 0; + + // set the general service ID + sdp_uuid128_create(&svc_uuid, &service_uuid_int); + sdp_set_service_id(record, svc_uuid); + // make the service record publicly browsable + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root_list = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups( record, root_list ); + + // set l2cap information + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + l2cap_list = sdp_list_append( 0, &l2cap_uuid ); + proto_list = sdp_list_append( 0, l2cap_list ); + + // set rfcomm information + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + channel = sdp_data_alloc(SDP_UINT8, &rfchannel); + rfcomm_list = sdp_list_append( 0, &rfcomm_uuid ); + sdp_list_append( rfcomm_list, channel ); + sdp_list_append( proto_list, rfcomm_list ); + + // attach protocol information to service record + access_proto_list = sdp_list_append( 0, proto_list ); + sdp_set_access_protos( record, access_proto_list ); + + sdp_uuid16_create(&service_uuid, SERIAL_PORT_SVCLASS_ID); + service_list = sdp_list_append( 0, &service_uuid ); + sdp_set_service_classes(record, service_list); + + profile[0].version = 0x0100; + sdp_uuid16_create(&profile[0].uuid, SERIAL_PORT_PROFILE_ID); + profile_list = sdp_list_append(0, &profile[0]); + sdp_set_profile_descs(record, profile_list); + + // set the name, provider, and description + sdp_set_info_attr(record, service_name, service_prov, service_dsc); + + // connect to the local SDP server, register the service record, and + // disconnect + lsession = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); + if (lsession == NULL) + goto errout; + err = sdp_record_register(lsession, record, 0); + if (err) { + sdp_close(lsession); + lsession = NULL; + } +errout: + // cleanup + sdp_data_free( channel ); + sdp_list_free( l2cap_list, 0 ); + sdp_list_free( rfcomm_list, 0 ); + sdp_list_free( root_list, 0 ); + sdp_list_free( access_proto_list, 0 ); + sdp_list_free( profile_list, 0 ); + sdp_list_free( service_list, 0 ); + + return lsession; +} + +/* + * Function opens and configures serial port + * portName - name of the serial port + * return 0 on success, -1 on error + */ +int openSerial(const char* portName) +{ + struct termios tc; //port attributes + int hserial = -1; //serial port handler + int result; //function call result + if ((hserial = open(portName, O_RDWR)) < 0) + goto errout; + if ((result = tcgetattr(hserial, &tc)) < 0) + goto errout; + cfmakeraw(&tc); + cfsetispeed(&tc, B9600); + cfsetospeed(&tc, B9600); + if ((result = tcsetattr(hserial, TCSANOW, &tc)) < 0) + goto errout; + if (result == 0) + errno = 0; +errout: + if (errno) { + if (hserial >= 0) { + close(hserial); + hserial = -1; + } + } + return hserial; +} + +/* + * bt_serialStart + * Function starts bt-serial service + * return 0 success -1 on error + */ +int bt_serialStart(void) +{ + struct sockaddr_rc loc_addr; //server address + int i; //just an index variable + int result = 0; //function call result + if (hserv >= 0) + return 0; + hserv = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + // bind socket to port 1 of the first available + // local bluetooth adapter + memset(&loc_addr, 0, sizeof(struct sockaddr_rc)); + loc_addr.rc_family = AF_BLUETOOTH; + loc_addr.rc_bdaddr = *BDADDR_ANY; + for (i = 1; i < 32; i++) { + loc_addr.rc_channel = (uint8_t)i; + if (!(result = bind(hserv, + (struct sockaddr *)&loc_addr, + sizeof(loc_addr))) || errno == EINVAL) { + break; + } + } + if (result != 0) + goto errout; + else + errno = 0; + if (listen(hserv, 1) < 0) + goto errout; + session = register_service(loc_addr.rc_channel); +errout: + if (errno) { + result = errno; + close(hserv); + hserv = -1; + if (session != NULL) + sdp_close(session); + errno = result; + result = -1; + } + return result; +} + +/* + * bt_serialStop + * Function stops bt-serial service + * return device handler on success -1 on error + */ +int bt_serialStop(void) +{ + int result = 0; //Function call result + + if (hserv >= 0) { + result = close(hserv); + hserv = -1; + if (session != NULL) + sdp_close(session); + } + return result; +} + +/* + * btWrite + * hbt - handler of the BT connection + * buf - buffer to write + * plen - total length to write (and zero it!!!) + * return number of bytes written on success or -1 + */ +int btWrite(int hbt, uint8_t* buf, int* plen) +{ + int result; //Function call result + const suseconds_t writeDelay = 100000L; //wait after writing + result = write(hbt, buf, *plen); +#ifdef _DEBUG_ + printf("ser->bt %d\n", *plen); +#endif + *plen = 0; + usleep(writeDelay); + return result; +} + +/* + * bt_serialForward + * Function forwards data received from bt-connection to serial and backward + * conn - connection handler + * portName - name of the serial port to open + * return 0 success -1 on error + */ +/* + * This function has a hack. My BT adapter hangs if you try to write small + * portions of data to it to often. That's why we either wait for big enough + * (> wrThresh) portion of data from a serial port and write it to BT or + * wait for a timeout (tv). + */ +int bt_serialForward(BTSerialConn* conn, const char* portName) +{ + int result; //Function call result + fd_set inSet; //Set we scan for input + uint8_t inBuf[1500]; //buffer we read and write + uint8_t outBuf[1500]; //buffer we read and write + int outBytes; //bytes to be written to bt + int nbytes = 0; //number of bytes we could read + int maxfd; //maximal filehandler + struct timeval tv; //time we shall wait for select + const int wrThresh = 250; //threshold after which we send packet to bt + const suseconds_t waitDelay = 200000L; //Time (us) we wait for data + struct sockaddr_rc rem_addr; //client address + int len = sizeof(rem_addr); //argument length + + if (conn == NULL) { + errno = EINVAL; + return -1; + } + memset(&rem_addr, 0, sizeof(struct sockaddr_rc)); + conn->bt_handler = -1; + conn->ser_handler = -1; + conn->bt_handler = accept(hserv, (struct sockaddr *)&rem_addr, &len); + if (conn->bt_handler < 0) + return -1; + conn->ser_handler = openSerial(portName); + if (conn->ser_handler < 0) + return -1; +#ifdef _DEBUG_ + printf("Connect!\n"); +#endif + + FD_ZERO(&inSet); + maxfd = (conn->bt_handler > conn->ser_handler)? conn->bt_handler: + conn->ser_handler; + outBytes = 0; + do { + FD_SET(conn->bt_handler, &inSet); + FD_SET(conn->ser_handler, &inSet); + tv.tv_sec = 0; + tv.tv_usec = waitDelay; + result = select(maxfd + 1, &inSet, NULL, NULL, &tv); + if (result > 0) { + if (FD_ISSET(conn->bt_handler, &inSet)) { + if ((nbytes = read(conn->bt_handler, inBuf, sizeof(inBuf))) > 0) + result = write(conn->ser_handler, inBuf, nbytes); +#ifdef _DEBUG_ + printf("bt->ser %d\n", nbytes); +#endif + } + if (FD_ISSET(conn->ser_handler, &inSet)) { + if ((nbytes = read(conn->ser_handler, + outBuf + outBytes, sizeof(outBuf) - outBytes)) > 0) { + outBytes += nbytes; + if (outBytes > wrThresh) + result = btWrite(conn->bt_handler, outBuf, &outBytes); + } + } + } else if (result == 0) { + if (outBytes > 0) + result = btWrite(conn->bt_handler, outBuf, &outBytes); + } + } while (result == 0 || (result > 0 && nbytes > 0)); + if (nbytes <= 0) + result = -1; + close(conn->bt_handler); + close(conn->ser_handler); +#ifdef _DEBUG_ + printf("Disconnect!\n"); +#endif + return 0; +} + +//eof diff --git a/noncore/net/opietooth/lib/bt-serial.h b/noncore/net/opietooth/lib/bt-serial.h new file mode 100644 index 0000000..737e2a0 --- a/dev/null +++ b/noncore/net/opietooth/lib/bt-serial.h @@ -0,0 +1,57 @@ +/* $Id$ + * Bluetooth serial forwarder functions declaration + * + * (c) Copyright 2006 GPL + * + * This software is provided under the GNU public license, incorporated + * herein by reference. The software is provided without warranty or + * support. + */ +#ifndef _BT_SERIAL_H_ +#define _BT_SERIAL_H_ +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct //bt-serial connection handler +{ + int bt_handler; //Bluetooth connection handler + int ser_handler; //serial port handler +} BTSerialConn; + +/* + * bt_serialStart + * Function starts bt-serial service + * return 0 success -1 on error + */ +int bt_serialStart(void); + +/* + * bt_serialForward + * Function forwards data received from bt-connection to serial and backward + * conn - connection handler + * portName - name of the port to connect + * return 0 success -1 on error + */ +int bt_serialForward(BTSerialConn* conn, const char* portName); + +/* + * bt_serialStop + * Function stops bt-serial service + * return device handler on success -1 on error + */ +int bt_serialStop(void); + +/* + * Function opens and configures serial port + * portName - name of the serial port + * return 0 on success, -1 on error + */ +int openSerial(const char* portName); + +#ifdef __cplusplus +} +#endif + +#endif +//eof diff --git a/noncore/net/opietooth/lib/forwarder.cc b/noncore/net/opietooth/lib/forwarder.cc new file mode 100644 index 0000000..c38f5b8 --- a/dev/null +++ b/noncore/net/opietooth/lib/forwarder.cc @@ -0,0 +1,203 @@ +/* $Id$ + * Bluetooth serial forwarder class implementation + * + * (c) Copyright 2006 GPL + * + * This software is provided under the GNU public license, incorporated + * herein by reference. The software is provided without warranty or + * support. + */ +#include "bt-serial.h" +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> +#include <stdlib.h> +#include <fcntl.h> +#include <qapplication.h> +#include <opie2/oprocctrl.h> +#include "forwarder.h" +using namespace OpieTooth; +using namespace Opie::Core; +using namespace Opie::Core::Internal; + +SerialForwarder::SerialForwarder(QString& devName, int dspeed) : + OProcess(), device(devName), speed(dspeed) +{ + status = false; +} + +SerialForwarder::~SerialForwarder() +{ + stop(); +} + + +bool SerialForwarder::start(RunMode runmode, Communication comm) +{ + int htmp; //temporary device + int result; //call result + + if ( runs ) + { + return false; // cannot start a process that is already running + // or if no executable has been assigned + } + //First, check if serial device is usable + htmp = ::openSerial(device); + if (htmp < 0) + return false; + close(htmp); + + run_mode = runmode; + status = 0; + + if(::bt_serialStart() < 0) + return false; + + if ( !setupCommunication( comm ) ) + qWarning( "Could not setup Communication!" ); + + // We do this in the parent because if we do it in the child process + // gdb gets confused when the application runs from gdb. + uid_t uid = getuid(); + gid_t gid = getgid(); +#ifdef HAVE_INITGROUPS + + struct passwd *pw = getpwuid( uid ); +#endif + + int fd[ 2 ]; + if ( 0 > pipe( fd ) ) + { + fd[ 0 ] = fd[ 1 ] = 0; // Pipe failed.. continue + } + + runs = true; + + QApplication::flushX(); + + // WABA: Note that we use fork() and not vfork() because + // vfork() has unclear semantics and is not standardized. + pid_ = fork(); + + if ( 0 == pid_ ) + { + if ( fd[ 0 ] ) + close( fd[ 0 ] ); + if ( !runPrivileged() ) + { + setgid( gid ); +#if defined( HAVE_INITGROUPS) + + if ( pw ) + initgroups( pw->pw_name, pw->pw_gid ); +#endif + + setuid( uid ); + } + // The child process + if ( !commSetupDoneC() ) + qWarning( "Could not finish comm setup in child!" ); + + setupEnvironment(); + + // Matthias + if ( run_mode == DontCare ) + setpgid( 0, 0 ); + // restore default SIGPIPE handler (Harri) + struct sigaction act; + sigemptyset( &( act.sa_mask ) ); + sigaddset( &( act.sa_mask ), SIGPIPE ); + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + sigaction( SIGPIPE, &act, 0L ); + + // We set the close on exec flag. + // Closing of fd[1] indicates that the execvp succeeded! + if ( fd[ 1 ] ) + fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC ); + do { + BTSerialConn conn; //Connection handler + if ( fd[ 1 ] ) { + ::close(fd[1]); + fd[1] = 0; + } + result = ::bt_serialForward(&conn, device); + } while(result == 0); + + char resultByte = 1; + if ( fd[ 1 ] ) + write( fd[ 1 ], &resultByte, 1 ); + _exit( -1 ); + } + else if ( -1 == pid_ ) + { + // forking failed + + runs = false; + return false; + } + else + { + if ( fd[ 1 ] ) + close( fd[ 1 ] ); + // the parent continues here + + // Discard any data for stdin that might still be there + input_data = 0; + + // Check whether client could be started. + if ( fd[ 0 ] ) + for ( ;; ) + { + char resultByte; + int n = ::read( fd[ 0 ], &resultByte, 1 ); + if ( n == 1 ) + { + // Error + runs = false; + close( fd[ 0 ] ); + pid_ = 0; + return false; + } + if ( n == -1 ) + { + if ( ( errno == ECHILD ) || ( errno == EINTR ) ) + continue; // Ignore + } + break; // success + } + if ( fd[ 0 ] ) + close( fd[ 0 ] ); + + if ( !commSetupDoneP() ) // finish communication socket setup for the parent + qWarning( "Could not finish comm setup in parent!" ); + + if ( run_mode == Block ) + { + commClose(); + + // The SIGCHLD handler of the process controller will catch + // the exit and set the status + while ( runs ) + { + OProcessController::theOProcessController-> + slotDoHousekeeping( 0 ); + } + runs = FALSE; + emit processExited( this ); + } + } + return true; +} + +/* + * Stop forwarding process + */ +int SerialForwarder::stop() +{ + kill(SIGTERM); + ::bt_serialStop(); + return 0; +} +//eof diff --git a/noncore/net/opietooth/lib/forwarder.h b/noncore/net/opietooth/lib/forwarder.h new file mode 100644 index 0000000..f90ed70 --- a/dev/null +++ b/noncore/net/opietooth/lib/forwarder.h @@ -0,0 +1,45 @@ +/* $Id$ + * Bluetooth serial forwarder class declaration + * + * (c) Copyright 2006 GPL + * + * This software is provided under the GNU public license, incorporated + * herein by reference. The software is provided without warranty or + * support. + */ +#ifndef OpieTooth_Forwarder_H +#define OpieTooth_Forwarder_H +#include <qobject.h> +#include <qstring.h> +#include <unistd.h> +#include <signal.h> +#include <opie2/oprocess.h> +namespace Opie { + namespace Core { + class OProcess; + namespace Internal { + class OProcessController; + } + } +}; + +namespace OpieTooth { + class SerialForwarder : public Opie::Core::OProcess { + + Q_OBJECT + + protected: + QString device; //Name of the device + int speed; //device speed to set + public: + SerialForwarder(QString& devName, int speed); + ~SerialForwarder(); + //Function starts the forwarding process + virtual bool start( RunMode runmode = NotifyOnExit, + Communication comm = NoCommunication ); + //Stop the forwarding process + int stop(); + }; +}; +#endif +//eof diff --git a/noncore/net/opietooth/lib/lib.pro b/noncore/net/opietooth/lib/lib.pro index 9d3c14d..781bf15 100644 --- a/noncore/net/opietooth/lib/lib.pro +++ b/noncore/net/opietooth/lib/lib.pro @@ -1,10 +1,12 @@ TEMPLATE = lib CONFIG += qte warn_on -HEADERS = connection.h parser.h device.h manager.h remotedevice.h services.h startpanconnection.h startdunconnection.h -SOURCES = connection.cpp parser.cc device.cc manager.cc remotedevice.cc services.cc startpanconnection.cpp startdunconnection.cpp +HEADERS = connection.h parser.h device.h manager.h remotedevice.h services.h \ + startpanconnection.h startdunconnection.h bt-serial.h forwarder.h +SOURCES = connection.cpp parser.cc device.cc manager.cc remotedevice.cc services.cc \ + startpanconnection.cpp startdunconnection.cpp bt-serial.c forwarder.cc TARGET = opietooth1 INCLUDEPATH += $(OPIEDIR)/include . DESTDIR = $(OPIEDIR)/lib LIBS += -lopiecore2 include( $(OPIEDIR)/include.pro ) diff --git a/noncore/net/opietooth/manager/bluebase.cpp b/noncore/net/opietooth/manager/bluebase.cpp index 0649514..9ec5bf8 100644 --- a/noncore/net/opietooth/manager/bluebase.cpp +++ b/noncore/net/opietooth/manager/bluebase.cpp @@ -1,682 +1,743 @@ /* * bluebase.cpp * * --------------------- * * copyright : (c) 2002 by Maximilian Reiß * email : max.reiss@gmx.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 "bluebase.h" #include "scandialog.h" #include "hciconfwrapper.h" #include "devicehandler.h" #include "btconnectionitem.h" #include "rfcommassigndialogimpl.h" +#include "forwarder.h" +#include <termios.h> +#include <string.h> +#include <errno.h> /* OPIE */ #include <qpe/qpeapplication.h> #include <qpe/resource.h> #include <qpe/config.h> #include <opie2/odebug.h> using namespace Opie::Core; /* QT */ #include <qframe.h> #include <qlabel.h> #include <qpushbutton.h> #include <qlayout.h> #include <qvariant.h> #include <qimage.h> #include <qpixmap.h> #include <qtabwidget.h> #include <qscrollview.h> #include <qvbox.h> #include <qmessagebox.h> +#include <qcombobox.h> #include <qcheckbox.h> #include <qlineedit.h> #include <qlistview.h> #include <qdir.h> #include <qpopupmenu.h> #include <qtimer.h> #include <qlist.h> /* STD */ #include <remotedevice.h> #include <services.h> #include <stdlib.h> using namespace OpieTooth; +//Array of possible speeds of the serial port +struct SerSpeed { + const char* str; //string value + int val; //value itself +} speeds[] = { + { "150", B150 }, { "300", B300 }, { "600", B600 }, { "1200", B1200 }, + { "2400", B2400 }, { "4800", B4800 }, { "9600", B9600 }, + { "19200", B19200 }, { "38400", B38400 }, { "57600", B57600 }, + { "115200", B115200} +}; BlueBase::BlueBase( QWidget* parent, const char* name, WFlags fl ) : BluetoothBase( parent, name, fl ) { m_localDevice = new Manager( "hci0" ); connect( PushButton2, SIGNAL( clicked() ), this, SLOT(startScan() ) ); connect( configApplyButton, SIGNAL(clicked() ), this, SLOT(applyConfigChanges() ) ); connect( rfcommBindButton, SIGNAL( clicked() ), this, SLOT( rfcommDialog() ) ); connect( devicesView, SIGNAL( clicked(QListViewItem*)), this, SLOT( startServiceActionClicked(QListViewItem*) ) ); connect( devicesView, SIGNAL( rightButtonClicked(QListViewItem*,const QPoint&,int) ), this, SLOT(startServiceActionHold(QListViewItem*,const QPoint&,int) ) ); connect( m_localDevice , SIGNAL( foundServices(const QString&,Services::ValueList) ), this, SLOT( addServicesToDevice(const QString&,Services::ValueList) ) ); connect( m_localDevice, SIGNAL( available(const QString&,bool) ), this, SLOT( deviceActive(const QString&,bool) ) ); connect( m_localDevice, SIGNAL( connections(ConnectionState::ValueList) ), this, SLOT( addConnectedDevices(ConnectionState::ValueList) ) ); connect( m_localDevice, SIGNAL( signalStrength(const QString&,const QString&) ), this, SLOT( addSignalStrength(const QString&,const QString&) ) ); + connect(runButton, SIGNAL(clicked()), this, SLOT(doForward())); // let hold be rightButtonClicked() QPEApplication::setStylusOperation( devicesView->viewport(), QPEApplication::RightOnHold); QPEApplication::setStylusOperation( connectionsView->viewport(), QPEApplication::RightOnHold); //Load all icons needed m_offPix = Resource::loadPixmap( "opietooth/notconnected" ); m_onPix = Resource::loadPixmap( "opietooth/connected" ); m_findPix = Resource::loadPixmap( "opietooth/find" ); QPalette pal = this->palette(); QColor col = pal.color( QPalette::Active, QColorGroup::Background ); pal.setColor( QPalette::Active, QColorGroup::Button, col ); pal.setColor( QPalette::Inactive, QColorGroup::Button, col ); pal.setColor( QPalette::Normal, QColorGroup::Button, col ); pal.setColor( QPalette::Disabled, QColorGroup::Button, col ); this->setPalette( pal ); setCaption( tr( "Bluetooth Manager" ) ); readConfig(); initGui(); devicesView->setRootIsDecorated(true); m_iconLoader = new BTIconLoader(); writeToHciConfig(); addConnectedDevices(); readSavedDevices(); addServicesToDevices(); QTimer::singleShot( 3000, this, SLOT( addServicesToDevices() ) ); + forwarder = NULL; + serDevName->setText(tr("/dev/ircomm0")); + for (unsigned int i = 0; i < (sizeof(speeds) / sizeof(speeds[0])); i++) { + serSpeed->insertItem(speeds[i].str); + } + serSpeed->setCurrentItem((sizeof(speeds) / sizeof(speeds[0])) - 1); } /** * Reads all options from the config file */ void BlueBase::readConfig() { Config cfg( "bluetoothmanager" ); cfg.setGroup( "bluezsettings" ); m_deviceName = cfg.readEntry( "name" , "No name" ); // name the device should identify with m_defaultPasskey = cfg.readEntryCrypt( "passkey" , "" ); // <- hmm, look up how good the trolls did that, maybe too weak m_useEncryption = cfg.readBoolEntry( "useEncryption" , TRUE ); m_enableAuthentification = cfg.readBoolEntry( "enableAuthentification" , TRUE ); m_enablePagescan = cfg.readBoolEntry( "enablePagescan" , TRUE ); m_enableInquiryscan = cfg.readBoolEntry( "enableInquiryscan" , TRUE ); } /** * Writes all options to the config file */ void BlueBase::writeConfig() { Config cfg( "bluetoothmanager" ); cfg.setGroup( "bluezsettings" ); cfg.writeEntry( "name" , m_deviceName ); cfg.writeEntryCrypt( "passkey" , m_defaultPasskey ); cfg.writeEntry( "useEncryption" , m_useEncryption ); cfg.writeEntry( "enableAuthentification" , m_enableAuthentification ); cfg.writeEntry( "enablePagescan" , m_enablePagescan ); cfg.writeEntry( "enableInquiryscan" , m_enableInquiryscan ); writeToHciConfig(); } /** * Modify the hcid.conf file to our needs */ void BlueBase::writeToHciConfig() { owarn << "writeToHciConfig" << oendl; HciConfWrapper hciconf ( "/etc/bluetooth/hcid.conf" ); hciconf.load(); hciconf.setPinHelper( QPEApplication::qpeDir() + "bin/bluepin" ); hciconf.setName( m_deviceName ); hciconf.setEncrypt( m_useEncryption ); hciconf.setAuth( m_enableAuthentification ); hciconf.setPscan( m_enablePagescan ); hciconf.setIscan( m_enableInquiryscan ); hciconf.save(); } /** * Read the list of already known devices */ void BlueBase::readSavedDevices() { QValueList<RemoteDevice> loadedDevices; DeviceHandler handler; loadedDevices = handler.load(); addSearchedDevices( loadedDevices ); } /** * Write the list of already known devices */ void BlueBase::writeSavedDevices() { QListViewItemIterator it( devicesView ); BTListItem* item; BTDeviceItem* device; RemoteDevice::ValueList list; for ( ; it.current(); ++it ) { item = (BTListItem*)it.current(); if(item->typeId() != BTListItem::Device ) continue; device = (BTDeviceItem*)item; list.append( device->remoteDevice() ); } /* * if not empty save the List through DeviceHandler */ if ( list.isEmpty() ) return; DeviceHandler handler; handler.save( list ); } /** * Set up the gui */ void BlueBase::initGui() { StatusLabel->setText( status() ); // maybe move it to getStatus() cryptCheckBox->setChecked( m_useEncryption ); authCheckBox->setChecked( m_enableAuthentification ); pagescanCheckBox->setChecked( m_enablePagescan ); inquiryscanCheckBox->setChecked( m_enableInquiryscan ); deviceNameLine->setText( m_deviceName ); passkeyLine->setText( m_defaultPasskey ); // set info tab setInfo(); } /** * Get the status informations and returns it * @return QString the status informations gathered */ QString BlueBase::status()const { QString infoString = tr( "<b>Device name : </b> Ipaq" ); infoString += QString( "<br><b>" + tr( "MAC adress: " ) +"</b> No idea" ); infoString += QString( "<br><b>" + tr( "Class" ) + "</b> PDA" ); return (infoString); } /** * Read the current values from the gui and invoke writeConfig() */ void BlueBase::applyConfigChanges() { m_deviceName = deviceNameLine->text(); m_defaultPasskey = passkeyLine->text(); m_useEncryption = cryptCheckBox->isChecked(); m_enableAuthentification = authCheckBox->isChecked(); m_enablePagescan = pagescanCheckBox->isChecked(); m_enableInquiryscan = inquiryscanCheckBox->isChecked(); writeConfig(); QMessageBox::information( this, tr("Test") , tr("Changes were applied.") ); } /** * Launch Rfcomm Bind dialog * */ void BlueBase::rfcommDialog() { RfcommAssignDialog rfcommAssign ( this, "RfcommAssignDialog", true, WStyle_ContextHelp ); if ( QPEApplication::execDialog( &rfcommAssign ) == QDialog::Accepted ) { rfcommAssign.saveConfig(); } } /** * Add fresh found devices from scan dialog to the listing * */ void BlueBase::addSearchedDevices( const QValueList<RemoteDevice> &newDevices ) { BTDeviceItem * deviceItem; QValueList<RemoteDevice>::ConstIterator it; for( it = newDevices.begin(); it != newDevices.end() ; ++it ) { if (find( (*it) )) // is already inserted continue; deviceItem = new BTDeviceItem( devicesView , (*it) ); deviceItem->setPixmap( 1, m_findPix ); deviceItem->setExpandable ( true ); // look if device is avail. atm, async deviceActive( (*it) ); } } /** * Action that is toggled on entrys on click */ void BlueBase::startServiceActionClicked( QListViewItem */*item*/ ) {} /** * Action that are toggled on hold (mostly QPopups i guess) */ void BlueBase::startServiceActionHold( QListViewItem * item, const QPoint & point, int /*column*/ ) { if (!item ) return; QPopupMenu *menu = new QPopupMenu(); if ( static_cast<BTListItem*>( item )->type() == "device") { QPopupMenu *groups = new QPopupMenu(); menu->insertItem( static_cast<BTDeviceItem*>( item )->name(), 0 ); menu->insertSeparator( 1 ); menu->insertItem( tr( "&Rescan services" ), 2); // menu->insertItem( tr( "&Add to group" ), groups, 3); menu->insertItem( tr( "&Delete"), 4); int ret = menu->exec( point, 0); switch(ret) { case -1: break; case 2: addServicesToDevice( static_cast<BTDeviceItem*>( item ) ); break; case 4: // deletes childs too delete item; break; } // delete groups; } /* * We got service sensitive PopupMenus in our factory * We will create one through the factory and will insert * our Separator + ShowInfo into the menu or create a new * one if the factory returns 0 * PopupMenu deletion is kind of weird. * If escaped( -1 ) or any of our items were chosen we'll * delete the PopupMenu otherwise it's the responsibility of * the PopupMenu to delete itself * */ else if ( ((BTListItem*)item)->type() == "service") { BTServiceItem* service = (BTServiceItem*)item; QMap<int, QString> list = service->services().classIdList(); QMap<int, QString>::Iterator it = list.begin(); QPopupMenu *popup =0l; if ( it != list.end() ) { owarn << "Searching id " << it.key() << " " << it.data().latin1() << "" << oendl; popup = m_popHelper.find( it.key(), service->services(), (BTDeviceItem*)service->parent() ); } else { owarn << "Empty" << oendl; } if ( popup == 0l ) { owarn << "factory returned 0l" << oendl; popup = new QPopupMenu(); } int test1 = popup->insertItem( tr("Test1:"), 2); int ret = popup->exec( point ); owarn << "returned from exec() " << oendl; if ( ret == -1 ) { ; } else if ( ret == test1 ) { ; } delete popup; } delete menu; } void BlueBase::addServicesToDevices() { odebug << "BlueBase::addServicesToDevices()" << oendl; BTDeviceItem* item = (BTDeviceItem*) devicesView->firstChild(); while ( item ) { addServicesToDevice( item ); item = (BTDeviceItem*) static_cast<QListViewItem*>( item )->nextSibling(); } } /** * Search and display avail. services for a device (on expand from device listing) * @param item the service item returned */ void BlueBase::addServicesToDevice( BTDeviceItem * item ) { odebug << "BlueBase::addServicesToDevice" << oendl; // row of mac adress text(3) RemoteDevice device = item->remoteDevice(); m_deviceList.insert( item->mac() , item ); // and some time later I get a signal foundServices( const QString& device, Services::ValueList ); back m_localDevice->searchServices( device ); } /** * @param device the mac address of the remote device * @param servicesList the list with the service the device has. */ void BlueBase::addServicesToDevice( const QString& device, Services::ValueList servicesList ) { odebug << "BlueBase::fill services list" << oendl; QMap<QString,BTDeviceItem*>::Iterator it; BTDeviceItem* deviceItem = 0; // get the right devices which requested the search it = m_deviceList.find( device ); if( it == m_deviceList.end() ) return; deviceItem = it.data(); // remove previous entries QList<QListViewItem> tempList; tempList.setAutoDelete( true ); QListViewItem * child = deviceItem->firstChild(); while( child ) { tempList.append( child ); child = child->nextSibling(); } tempList.clear(); QValueList<OpieTooth::Services>::Iterator it2; BTServiceItem* serviceItem; if (!servicesList.isEmpty() ) { // add services QMap<int, QString> list; QMap<int, QString>::Iterator classIt; for( it2 = servicesList.begin(); it2 != servicesList.end(); ++it2 ) { serviceItem = new BTServiceItem( deviceItem, (*it2) ); list = (*it2).classIdList(); classIt = list.begin(); int classId=0; if ( classIt != list.end() ) { classId = classIt.key(); } serviceItem->setPixmap( 0, m_iconLoader->serviceIcon( classId ) ); } } else { Services s1; s1.setServiceName( tr("no services found") ); serviceItem = new BTServiceItem( deviceItem, s1 ); } // now remove them from the list m_deviceList.remove( it ); } void BlueBase::addSignalStrength() { QListViewItemIterator it( connectionsView ); for ( ; it.current(); ++it ) { m_localDevice->signalStrength( ((BTConnectionItem*)it.current() )->connection().mac() ); } QTimer::singleShot( 5000, this, SLOT( addSignalStrength() ) ); } void BlueBase::addSignalStrength( const QString& mac, const QString& strength ) { QListViewItemIterator it( connectionsView ); for ( ; it.current(); ++it ) { if( ((BTConnectionItem*)it.current())->connection().mac() == mac ) { ((BTConnectionItem*)it.current() )->setSignalStrength( strength ); } } } /** * Add the existing connections (pairs) to the connections tab. * This one triggers the search */ void BlueBase::addConnectedDevices() { m_localDevice->searchConnections(); QTimer::singleShot( 5000, this, SLOT( addSignalStrength() ) ); } /** * This adds the found connections to the connection tab. * @param connectionList the ValueList with all current connections */ void BlueBase::addConnectedDevices( ConnectionState::ValueList connectionList ) { QValueList<OpieTooth::ConnectionState>::Iterator it; BTConnectionItem * connectionItem; if ( !connectionList.isEmpty() ) { for (it = connectionList.begin(); it != connectionList.end(); ++it) { QListViewItemIterator it2( connectionsView ); bool found = false; for ( ; it2.current(); ++it2 ) { if( ( (BTConnectionItem*)it2.current())->connection().mac() == (*it).mac() ) { found = true; } } if ( found == false ) { connectionItem = new BTConnectionItem( connectionsView, (*it) ); if( m_deviceList.find((*it).mac()).data() ) { connectionItem->setName( m_deviceList.find( (*it).mac()).data()->name() ); } } } QListViewItemIterator it2( connectionsView ); for ( ; it2.current(); ++it2 ) { bool found = false; for (it = connectionList.begin(); it != connectionList.end(); ++it) { if( ( ((BTConnectionItem*)it2.current())->connection().mac() ) == (*it).mac() ) { found = true; } } if ( !found ) { delete it2.current(); } } } else { connectionsView->clear(); ConnectionState con; con.setMac( tr("No connections found") ); connectionItem = new BTConnectionItem( connectionsView , con ); } // recall connection search after some time QTimer::singleShot( 15000, this, SLOT( addConnectedDevices() ) ); } /** * Find out if a device can currently be reached * @param device */ void BlueBase::deviceActive( const RemoteDevice &device ) { // search by mac, async, gets a signal back // We should have a BTDeviceItem there or where does it get added to the map -zecke m_localDevice->isAvailable( device.mac() ); } /** * The signal catcher. Set the avail. status on device. * @param device - the mac address * @param connected - if it is avail. or not */ void BlueBase::deviceActive( const QString& device, bool connected ) { odebug << "deviceActive slot" << oendl; QMap<QString,BTDeviceItem*>::Iterator it; it = m_deviceList.find( device ); if( it == m_deviceList.end() ) return; BTDeviceItem* deviceItem = it.data(); if ( connected ) { deviceItem->setPixmap( 1, m_onPix ); } else { deviceItem->setPixmap( 1, m_offPix ); } m_deviceList.remove( it ); } /** * Open the "scan for devices" dialog */ void BlueBase::startScan() { ScanDialog *scan = new ScanDialog( this, "ScanDialog", true, WDestructiveClose ); QObject::connect( scan, SIGNAL( selectedDevices(const QValueList<RemoteDevice>&) ), this, SLOT( addSearchedDevices(const QValueList<RemoteDevice>&) ) ); QPEApplication::showDialog( scan ); } /** * Set the informations about the local device in information Tab */ void BlueBase::setInfo() { StatusLabel->setText( status() ); } /** * Decontructor */ BlueBase::~BlueBase() { writeSavedDevices(); delete m_iconLoader; } /** * find searches the ListView for a BTDeviceItem containig * the same Device if found return true else false * @param dev RemoteDevice to find * @return returns true if found */ bool BlueBase::find( const RemoteDevice& rem ) { QListViewItemIterator it( devicesView ); BTListItem* item; BTDeviceItem* device; for (; it.current(); ++it ) { item = (BTListItem*) it.current(); if ( item->typeId() != BTListItem::Device ) continue; device = (BTDeviceItem*)item; if ( rem.equals( device->remoteDevice() ) ) return true; } return false; // not found } + +/** + * Start process of the cell phone forwarding + */ +void BlueBase::doForward() +{ + if (forwarder && forwarder->isRunning()) { + runButton->setText("start gateway"); + forwarder->stop(); + delete forwarder; + forwarder = NULL; + return; + } + QString str = serDevName->text(); + forwarder = new SerialForwarder(str, speeds[serSpeed->currentItem()].val); + connect(forwarder, SIGNAL(processExited(Opie::Core::OProcess*)), + this, SLOT(forwardExited(Opie::Core::OProcess*))); + if (forwarder->start(OProcess::NotifyOnExit) < 0) { + QMessageBox::critical(this, tr("Forwarder Error"), + tr("Forwarder start error:") + tr(strerror(errno))); + return; + } + runButton->setText("stop gateway"); +} + +/** + * React on the process end + */ +void BlueBase::forwardExit(Opie::Core::OProcess* proc) +{ + if (proc->exitStatus() != 0) + QMessageBox::critical(this, tr("Forwarder Error"), + tr("Forwarder start error")); + delete proc; + forwarder = NULL; + runButton->setText("start gateway"); +} + +//eof diff --git a/noncore/net/opietooth/manager/bluebase.h b/noncore/net/opietooth/manager/bluebase.h index 48883d2..0128a88 100644 --- a/noncore/net/opietooth/manager/bluebase.h +++ b/noncore/net/opietooth/manager/bluebase.h @@ -1,102 +1,106 @@ #ifndef BLUEBASE_H #define BLUEBASE_H #include <qvariant.h> #include <qwidget.h> #include <qscrollview.h> #include <qsplitter.h> #include <qlist.h> #include <qpixmap.h> #include "bluetoothbase.h" #include "btserviceitem.h" #include "btdeviceitem.h" #include "popuphelper.h" #include "bticonloader.h" +#include "forwarder.h" #include <remotedevice.h> #include <manager.h> class QVBox; class QHBoxLayout; class QGridLayout; class QFrame; class QLabel; class QPushButton; class QTabWidget; class QCheckBox; class BTConnectionItem; namespace OpieTooth { class BlueBase : public BluetoothBase { Q_OBJECT public: BlueBase( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); ~BlueBase(); static QString appName() { return QString::fromLatin1("bluetooth-manager"); } protected: private slots: void startScan(); private: bool find( const RemoteDevice& device ); void readConfig(); void writeConfig(); void readSavedDevices(); void writeSavedDevices(); void writeToHciConfig(); QString status()const; void initGui(); void setInfo(); PopupHelper m_popHelper; Manager *m_localDevice; QMap<QString,BTDeviceItem*> m_deviceList; void deviceActive( const RemoteDevice &device ); QString m_deviceName; QString m_defaultPasskey; bool m_useEncryption; bool m_enableAuthentification; bool m_enablePagescan; bool m_enableInquiryscan; QPixmap m_offPix; QPixmap m_onPix; QPixmap m_findPix; BTIconLoader *m_iconLoader; + SerialForwarder* forwarder; private slots: void addSearchedDevices( const QValueList<RemoteDevice> &newDevices ); void addServicesToDevices(); void addServicesToDevice( BTDeviceItem *item ); void addServicesToDevice( const QString& device, Services::ValueList ); void addConnectedDevices(); void addConnectedDevices( ConnectionState::ValueList ); void startServiceActionClicked( QListViewItem *item ); void startServiceActionHold( QListViewItem *, const QPoint &, int ); void deviceActive( const QString& mac, bool connected ); void applyConfigChanges(); + void doForward(); + void forwardExit(Opie::Core::OProcess* proc); void addSignalStrength(); void addSignalStrength( const QString& mac, const QString& strengh ); void rfcommDialog(); }; } #endif diff --git a/noncore/net/opietooth/manager/bluetoothbase.ui b/noncore/net/opietooth/manager/bluetoothbase.ui index cbde3c6..a5e2c6f 100644 --- a/noncore/net/opietooth/manager/bluetoothbase.ui +++ b/noncore/net/opietooth/manager/bluetoothbase.ui @@ -1,382 +1,538 @@ <!DOCTYPE UI><UI> <class>BluetoothBase</class> <widget> <class>QWidget</class> <property stdset="1"> <name>name</name> <cstring>BluetoothBase</cstring> </property> <property stdset="1"> <name>geometry</name> <rect> <x>0</x> <y>0</y> - <width>293</width> - <height>382</height> + <width>268</width> + <height>368</height> </rect> </property> <property stdset="1"> <name>caption</name> <string>Form1</string> </property> - <property> - <name>layoutMargin</name> - </property> - <property> - <name>layoutSpacing</name> - </property> - <grid> + <vbox> <property stdset="1"> <name>margin</name> - <number>4</number> + <number>0</number> </property> <property stdset="1"> <name>spacing</name> - <number>2</number> + <number>0</number> </property> - <widget row="0" column="0" > + <widget> <class>QTabWidget</class> <property stdset="1"> <name>name</name> <cstring>Status</cstring> </property> <property> <name>layoutMargin</name> </property> <property> <name>layoutSpacing</name> </property> <widget> <class>QWidget</class> <property stdset="1"> <name>name</name> <cstring>tab</cstring> </property> <attribute> <name>title</name> <string>Devices</string> </attribute> <vbox> <property stdset="1"> <name>margin</name> <number>4</number> </property> <property stdset="1"> <name>spacing</name> <number>2</number> </property> <widget> <class>QListView</class> <column> <property> <name>text</name> <string>Device Name</string> </property> <property> <name>clickable</name> <bool>true</bool> </property> <property> <name>resizeable</name> <bool>true</bool> </property> </column> <column> <property> <name>text</name> <string>Online</string> </property> <property> <name>clickable</name> <bool>true</bool> </property> <property> <name>resizeable</name> <bool>true</bool> </property> </column> <property stdset="1"> <name>name</name> <cstring>devicesView</cstring> </property> </widget> <widget> <class>QPushButton</class> <property stdset="1"> <name>name</name> <cstring>PushButton2</cstring> </property> <property stdset="1"> <name>sizePolicy</name> <sizepolicy> <hsizetype>0</hsizetype> <vsizetype>0</vsizetype> </sizepolicy> </property> <property stdset="1"> <name>text</name> <string>&Rescan Devices</string> </property> </widget> </vbox> </widget> <widget> <class>QWidget</class> <property stdset="1"> <name>name</name> <cstring>tab</cstring> </property> <attribute> <name>title</name> <string>Connections</string> </attribute> <vbox> <property stdset="1"> <name>margin</name> <number>4</number> </property> <property stdset="1"> <name>spacing</name> <number>2</number> </property> <widget> <class>QListView</class> <column> <property> <name>text</name> <string>Device Name</string> </property> <property> <name>clickable</name> <bool>true</bool> </property> <property> <name>resizeable</name> <bool>true</bool> </property> </column> <column> <property> <name>text</name> <string>Connection type</string> </property> <property> <name>clickable</name> <bool>true</bool> </property> <property> <name>resizeable</name> <bool>true</bool> </property> </column> <column> <property> <name>text</name> <string>Signal</string> </property> <property> <name>clickable</name> <bool>true</bool> </property> <property> <name>resizeable</name> <bool>true</bool> </property> </column> <property stdset="1"> <name>name</name> <cstring>connectionsView</cstring> </property> </widget> </vbox> </widget> <widget> <class>QWidget</class> <property stdset="1"> <name>name</name> <cstring>tab</cstring> </property> <attribute> <name>title</name> <string>Config</string> </attribute> <grid> <property stdset="1"> <name>margin</name> <number>4</number> </property> <property stdset="1"> <name>spacing</name> <number>2</number> </property> <widget row="1" column="0" > <class>QPushButton</class> <property stdset="1"> <name>name</name> <cstring>rfcommBindButton</cstring> </property> <property stdset="1"> <name>text</name> <string>&Edit RFCOMM Bind Table</string> </property> </widget> <widget row="0" column="0" > <class>QGroupBox</class> <property stdset="1"> <name>name</name> <cstring>GroupBox1</cstring> </property> <property stdset="1"> <name>title</name> <string>Bluetooth Basic Config</string> </property> <property> <name>layoutMargin</name> </property> <property> <name>layoutSpacing</name> </property> <grid> <property stdset="1"> <name>margin</name> <number>4</number> </property> <property stdset="1"> <name>spacing</name> <number>2</number> </property> <widget row="6" column="0" rowspan="1" colspan="2" > <class>QPushButton</class> <property stdset="1"> <name>name</name> <cstring>configApplyButton</cstring> </property> <property stdset="1"> <name>text</name> <string>Apply</string> </property> </widget> <widget row="2" column="0" rowspan="1" colspan="2" > <class>QCheckBox</class> <property stdset="1"> <name>name</name> <cstring>authCheckBox</cstring> </property> <property stdset="1"> <name>text</name> <string>enable authentification</string> </property> </widget> <widget row="3" column="0" rowspan="1" colspan="2" > <class>QCheckBox</class> <property stdset="1"> <name>name</name> <cstring>cryptCheckBox</cstring> </property> <property stdset="1"> <name>text</name> <string>enable encryption</string> </property> </widget> <widget row="4" column="0" rowspan="1" colspan="2" > <class>QCheckBox</class> <property stdset="1"> <name>name</name> <cstring>pagescanCheckBox</cstring> </property> <property stdset="1"> <name>text</name> <string>Enable Page scan</string> </property> </widget> <widget row="5" column="0" rowspan="1" colspan="2" > <class>QCheckBox</class> <property stdset="1"> <name>name</name> <cstring>inquiryscanCheckBox</cstring> </property> <property stdset="1"> <name>text</name> <string>Enable Inquiry scan</string> </property> </widget> <widget row="0" column="0" > <class>QLabel</class> <property stdset="1"> <name>name</name> <cstring>deviceNameLabel</cstring> </property> <property stdset="1"> <name>text</name> <string>Device Name</string> </property> </widget> <widget row="1" column="0" > <class>QLabel</class> <property stdset="1"> <name>name</name> <cstring>passkeyLabel</cstring> </property> <property stdset="1"> <name>text</name> <string>Default Passkey</string> </property> </widget> <widget row="0" column="1" > <class>QLineEdit</class> <property stdset="1"> <name>name</name> <cstring>deviceNameLine</cstring> </property> </widget> <widget row="1" column="1" > <class>QLineEdit</class> <property stdset="1"> <name>name</name> <cstring>passkeyLine</cstring> </property> <property stdset="1"> <name>echoMode</name> <enum>Password</enum> </property> </widget> </grid> </widget> </grid> </widget> <widget> <class>QWidget</class> <property stdset="1"> <name>name</name> <cstring>tab</cstring> </property> <attribute> <name>title</name> <string>Status</string> </attribute> <vbox> <property stdset="1"> <name>margin</name> <number>4</number> </property> <property stdset="1"> <name>spacing</name> <number>2</number> </property> <widget> <class>QLabel</class> <property stdset="1"> <name>name</name> <cstring>StatusLabel</cstring> </property> <property stdset="1"> <name>text</name> <string>Status Label</string> </property> </widget> </vbox> </widget> + <widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>tab</cstring> + </property> + <attribute> + <name>title</name> + <string>Phone</string> + </attribute> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>0</number> + </property> + <widget> + <class>QGroupBox</class> + <property stdset="1"> + <name>name</name> + <cstring>cellForwarder</cstring> + </property> + <property stdset="1"> + <name>title</name> + <string>Cell Forwarder</string> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>11</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout9</cstring> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout5</cstring> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>serDevLabel</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Serial device:</string> + </property> </widget> - </grid> + <widget> + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>serDevName</cstring> + </property> + </widget> + </hbox> + </widget> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout6</cstring> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>serSpeedLabel</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Speed:</string> + </property> + </widget> + <widget> + <class>QComboBox</class> + <property stdset="1"> + <name>name</name> + <cstring>serSpeed</cstring> + </property> + </widget> + </hbox> </widget> + <widget> + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>runButton</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>start gateway</string> + </property> + </widget> + </vbox> + </widget> + </vbox> + </widget> + </vbox> + </widget> + </widget> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>QWidget</class> + <header location="local">qwidget.h</header> + <sizehint> + <width>100</width> + <height>100</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>7</hordata> + <verdata>7</verdata> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image> + <name>image0</name> + <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data> + </image> +</images> </UI> |