Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OTHCISocket.cpp

Go to the documentation of this file.
00001 //-*-c++-*-
00002 /***************************************************************************
00003  *   Copyright (C) 2003 by Fred Schaettgen                                 *
00004  *   kdebluetooth@schaettgen.de                                            *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  ***************************************************************************/
00011 
00012 #include <qbuffer.h>
00013 #include <qtimer.h>
00014 #include <qdatastream.h>
00015 #include <opie2/odebug.h>
00016 
00017 #include <bluezlib.h>
00018 
00019 // #include "deviceaddress.h"
00020 #include <OTHCISocket.h>
00021 #include <OTDriver.h>
00022 
00023 using namespace Opietooth2;
00024 
00025 OTHCISocket::OTHCISocket( OTDriver * D ) :
00026                             QObject( D, D->devname() ) {
00027     BStatusSet = false;
00028     Driver = D;
00029     HCIReadNotifier = 0;
00030 }
00031 
00032 OTHCISocket::~OTHCISocket() {
00033     close();
00034 }
00035 
00036 void OTHCISocket::close() {
00037     odebug << "OTHCISocket::close()" << oendl;
00038     if( HCIReadNotifier ) {
00039         delete HCIReadNotifier;
00040     }
00041 
00042     if( HCISocket.isValid() ) {
00043         HCISocket.close();
00044     }
00045 }
00046 
00047 bool OTHCISocket::open() {
00048 
00049     odebug << "OTHCISocket::open()" << oendl;
00050     int s;
00051 
00052     s = ::socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
00053 
00054     if (s < 0) {
00055       emit error( tr( "Error creating socket on %1 : %2 %3").
00056                     arg( Driver->devname() ).
00057                     arg( errno ).
00058                     arg( strerror(errno) )
00059                 );
00060       return false;
00061     }
00062 
00063     /* Bind socket to the HCI device */
00064     struct sockaddr_hci sa;
00065     sa.hci_family = AF_BLUETOOTH;
00066     sa.hci_dev = Driver->devId();
00067     if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
00068       ::close(s);
00069       emit error( tr( "Error binding to socket to %1 : %2 %3").
00070                     arg( Driver->devname() ).
00071                     arg( errno ).
00072                     arg( strerror(errno) )
00073                 );
00074       return false;
00075     }
00076 
00077     struct hci_filter flt;
00078     hci_filter_clear(&flt);
00079     hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
00080     hci_filter_all_events(&flt);
00081     if( setsockopt(s, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0 ) {
00082       ::close(s);
00083       emit error( tr( "HCI filter setup failed on %1 : %2 %3").
00084                     arg( Driver->devname() ).
00085                     arg( errno ).
00086                     arg( strerror(errno) )
00087                 );
00088       return false;
00089     }
00090 
00091     if( HCIReadNotifier ) {
00092       delete HCIReadNotifier;
00093     }
00094 
00095     HCISocket.setSocket(s, QSocketDevice::Datagram);
00096     HCIReadNotifier = new QSocketNotifier(
00097                   s, QSocketNotifier::Read, this);
00098 
00099     connect( HCIReadNotifier, 
00100              SIGNAL(activated(int)),
00101              this, 
00102              SLOT(slotSocketActivated())
00103            );
00104 
00105     //connect(hciSocket, SIGNAL(error(int)),
00106     //    this, SLOT(slotSocketError(int)));
00107     //connect(hciSocket, SIGNAL(connectionClosed()),
00108     //    this, SLOT(slotConnectionClosed()));
00109     //hciSocket->setSocket(s);
00110 
00111     return true;
00112 }
00113 
00114 void OTHCISocket::slotSocketError(int e) {
00115     close();
00116     emit error( tr( "HCI socket error 0x%1 on %1 : %2 %3").
00117                     arg(e,2,16).
00118                     arg( Driver->devname() ).
00119                     arg( errno ).
00120                     arg( strerror(errno) )
00121                 );
00122 }
00123 
00124 void OTHCISocket::slotSocketActivated() {
00125 
00126     QSocketDevice::Error err = HCISocket.error();
00127 
00128     if( (err == QSocketDevice::NoError ) && 
00129         ( HCISocket.isValid() ) ) {
00130       //kdDebug() << "HCI socket ready read." << endl;
00131 
00132       unsigned char buf[512];
00133       int psize = HCISocket.readBlock((char*)buf, 512);
00134 
00135       if (psize <= 0) {
00136         slotSocketError(HCISocket.error());
00137         HCISocket.close();
00138         return;
00139       }
00140 
00141       //unsigned char packetType = buf[0];
00142       unsigned char eventCode = buf[1];
00143       unsigned char len = buf[2];
00144 
00145       if (psize-3 == len) {
00146 
00147         QByteArray databuf;
00148         databuf.duplicate((char*)(buf+3), len);
00149         emit event(eventCode, databuf);
00150         if (eventCode == EVT_CMD_STATUS) {
00151           updateStatus( databuf );
00152         }
00153       } else {
00154         odebug << "Error reading hci packet: packetSize("
00155               << psize
00156               << ")-3 != dataSize("
00157               << len
00158               << ")" 
00159               << oendl;
00160       }
00161     } else if (err == QSocketDevice::NoError) {
00162       slotConnectionClosed();
00163     } else {
00164         HCISocket.close();
00165         slotSocketError(err);
00166     }
00167 }
00168 
00169 void OTHCISocket::updateStatus(const QByteArray& data) {
00170 
00171     QDataStream stream(data, IO_ReadOnly);
00172     stream.setByteOrder(QDataStream::LittleEndian);
00173     Q_UINT8 status, dummy;
00174     Q_UINT16 opcode;
00175 
00176     BStatusSet = true;
00177 
00178     stream >> status >> dummy >> opcode;
00179     //kdDebug() << "updatestatus opcode=" << uint32_t(opcode) << endl;
00180     LastStatus = status;
00181     LastStatusOgf = cmd_opcode_ogf(opcode);
00182     LastStatusOcf = cmd_opcode_ocf(opcode);
00183 }
00184 
00185 void OTHCISocket::slotConnectionClosed() {
00186     odebug << "HCI connection closed." << oendl;
00187     emit connectionClosed();
00188 }
00189 
00190 void OTHCISocket::readEvent() {
00191 
00192     if (HCIReadNotifier) {
00193         slotSocketActivated();
00194     }
00195 }
00196 
00197 bool OTHCISocket::sendCommand( unsigned char ogf,
00198                                unsigned short ocf, 
00199                                QByteArray buf
00200                              ) {
00201     QBuffer packet;
00202     QDataStream stream(&packet);
00203 
00204     stream.setByteOrder(QDataStream::LittleEndian);
00205     packet.open(IO_WriteOnly);
00206 
00207     if (buf.size() > 255) return false;
00208 
00209     //kdDebug() << "sendCommand. ogf=" << ogf << " ocf=" << ocf << endl;
00210     Q_UINT16 opcode = cmd_opcode_pack(ogf, ocf);
00211     Q_UINT8 pType = HCI_COMMAND_PKT;
00212     Q_UINT8 buflen = buf.size();
00213 
00214     stream << pType << opcode << buflen;
00215     stream.writeRawBytes(buf.data(), buflen);
00216     packet.close();
00217     HCISocket.writeBlock((const char*)packet.buffer(), 
00218                          packet.buffer().size());
00219     return true;
00220 }
00221 
00222 bool OTHCISocket::readStatus( unsigned char ogf, 
00223                               unsigned short ocf, 
00224                               int *status, 
00225                               int timeout_ms) {
00226     QTimer timer;
00227 
00228     timer.start(timeout_ms, true);
00229     BStatusSet = false;
00230 
00231     while (timer.isActive() && HCISocket.isValid()) {
00232 
00233         odebug << "OTHCISocket::readStatus()" << oendl;
00234         bool timeout = false;
00235 
00236         if( HCISocket.bytesAvailable() == 0) {
00237           int rv = HCISocket.waitForMore(timeout_ms);
00238           timeout = (rv == 0);
00239         }
00240 
00241         if (!timeout) {
00242           slotSocketActivated();
00243         }
00244 
00245         if( BStatusSet == true && 
00246             ogf == LastStatusOgf && 
00247             ocf == LastStatusOcf) {
00248             *status = LastStatus;
00249             odebug << "OTHCISocket::readStatus(ogf="
00250                   << ogf
00251                   << ",ocf="
00252                   << ocf
00253                   << ",timeout="
00254                   << LastStatus
00255                   << ")"
00256                   << oendl;
00257             return true;
00258         }
00259     }
00260 
00261     odebug << "OTHCISocket::readStatus(ogf="
00262           << ogf
00263           << ",ocf="
00264           << ocf
00265           << ",timeout="
00266           << LastStatus
00267           << ") : timeout "
00268           << oendl;
00269     return false;
00270 }
00271 
00272 int OTHCISocket::socket() {
00273     return HCISocket.socket();
00274 }

Generated on Sat Nov 5 16:17:55 2005 for OPIE by  doxygen 1.4.2