00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
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
00106
00107
00108
00109
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
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
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
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
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 }