summaryrefslogtreecommitdiff
path: root/noncore/settings/networksettings2/opietooth2/OTHCISocket.cpp
Unidiff
Diffstat (limited to 'noncore/settings/networksettings2/opietooth2/OTHCISocket.cpp') (more/less context) (show whitespace changes)
-rw-r--r--noncore/settings/networksettings2/opietooth2/OTHCISocket.cpp274
1 files changed, 274 insertions, 0 deletions
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 @@
1//-*-c++-*-
2/***************************************************************************
3 * Copyright (C) 2003 by Fred Schaettgen *
4 * kdebluetooth@schaettgen.de *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 ***************************************************************************/
11
12#include <qbuffer.h>
13#include <qtimer.h>
14#include <qdatastream.h>
15#include <opie2/odebug.h>
16
17#include <bluezlib.h>
18
19// #include "deviceaddress.h"
20#include <OTHCISocket.h>
21#include <OTDriver.h>
22
23using namespace Opietooth2;
24
25OTHCISocket::OTHCISocket( OTDriver * D ) :
26 QObject( D, D->devname() ) {
27 BStatusSet = false;
28 Driver = D;
29 HCIReadNotifier = 0;
30}
31
32OTHCISocket::~OTHCISocket() {
33 close();
34}
35
36void OTHCISocket::close() {
37 owarn << "OTHCISocket::close()" << oendl;
38 if( HCIReadNotifier ) {
39 delete HCIReadNotifier;
40 }
41
42 if( HCISocket.isValid() ) {
43 HCISocket.close();
44 }
45}
46
47bool OTHCISocket::open() {
48
49 owarn << "OTHCISocket::open()" << oendl;
50 int s;
51
52 s = ::socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
53
54 if (s < 0) {
55 emit error( tr( "Error creating socket on %1 : %2 %3").
56 arg( Driver->devname() ).
57 arg( errno ).
58 arg( strerror(errno) )
59 );
60 return false;
61 }
62
63 /* Bind socket to the HCI device */
64 struct sockaddr_hci sa;
65 sa.hci_family = AF_BLUETOOTH;
66 sa.hci_dev = Driver->devId();
67 if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
68 ::close(s);
69 emit error( tr( "Error binding to socket to %1 : %2 %3").
70 arg( Driver->devname() ).
71 arg( errno ).
72 arg( strerror(errno) )
73 );
74 return false;
75 }
76
77 struct hci_filter flt;
78 hci_filter_clear(&flt);
79 hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
80 hci_filter_all_events(&flt);
81 if( setsockopt(s, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0 ) {
82 ::close(s);
83 emit error( tr( "HCI filter setup failed on %1 : %2 %3").
84 arg( Driver->devname() ).
85 arg( errno ).
86 arg( strerror(errno) )
87 );
88 return false;
89 }
90
91 if( HCIReadNotifier ) {
92 delete HCIReadNotifier;
93 }
94
95 HCISocket.setSocket(s, QSocketDevice::Datagram);
96 HCIReadNotifier = new QSocketNotifier(
97 s, QSocketNotifier::Read, this);
98
99 connect( HCIReadNotifier,
100 SIGNAL(activated(int)),
101 this,
102 SLOT(slotSocketActivated())
103 );
104
105 //connect(hciSocket, SIGNAL(error(int)),
106 // this, SLOT(slotSocketError(int)));
107 //connect(hciSocket, SIGNAL(connectionClosed()),
108 // this, SLOT(slotConnectionClosed()));
109 //hciSocket->setSocket(s);
110
111 return true;
112}
113
114void OTHCISocket::slotSocketError(int e) {
115 close();
116 emit error( tr( "HCI socket error 0x%1 on %1 : %2 %3").
117 arg(e,2,16).
118 arg( Driver->devname() ).
119 arg( errno ).
120 arg( strerror(errno) )
121 );
122}
123
124void OTHCISocket::slotSocketActivated() {
125
126 QSocketDevice::Error err = HCISocket.error();
127
128 if( (err == QSocketDevice::NoError ) &&
129 ( HCISocket.isValid() ) ) {
130 //kdDebug() << "HCI socket ready read." << endl;
131
132 unsigned char buf[512];
133 int psize = HCISocket.readBlock((char*)buf, 512);
134
135 if (psize <= 0) {
136 slotSocketError(HCISocket.error());
137 HCISocket.close();
138 return;
139 }
140
141 //unsigned char packetType = buf[0];
142 unsigned char eventCode = buf[1];
143 unsigned char len = buf[2];
144
145 if (psize-3 == len) {
146
147 QByteArray databuf;
148 databuf.duplicate((char*)(buf+3), len);
149 emit event(eventCode, databuf);
150 if (eventCode == EVT_CMD_STATUS) {
151 updateStatus( databuf );
152 }
153 } else {
154 owarn << "Error reading hci packet: packetSize("
155 << psize
156 << ")-3 != dataSize("
157 << len
158 << ")"
159 << oendl;
160 }
161 } else if (err == QSocketDevice::NoError) {
162 slotConnectionClosed();
163 } else {
164 HCISocket.close();
165 slotSocketError(err);
166 }
167}
168
169void OTHCISocket::updateStatus(const QByteArray& data) {
170
171 QDataStream stream(data, IO_ReadOnly);
172 stream.setByteOrder(QDataStream::LittleEndian);
173 Q_UINT8 status, dummy;
174 Q_UINT16 opcode;
175
176 BStatusSet = true;
177
178 stream >> status >> dummy >> opcode;
179 //kdDebug() << "updatestatus opcode=" << uint32_t(opcode) << endl;
180 LastStatus = status;
181 LastStatusOgf = cmd_opcode_ogf(opcode);
182 LastStatusOcf = cmd_opcode_ocf(opcode);
183}
184
185void OTHCISocket::slotConnectionClosed() {
186 owarn << "HCI connection closed." << oendl;
187 emit connectionClosed();
188}
189
190void OTHCISocket::readEvent() {
191
192 if (HCIReadNotifier) {
193 slotSocketActivated();
194 }
195}
196
197bool OTHCISocket::sendCommand( unsigned char ogf,
198 unsigned short ocf,
199 QByteArray buf
200 ) {
201 QBuffer packet;
202 QDataStream stream(&packet);
203
204 stream.setByteOrder(QDataStream::LittleEndian);
205 packet.open(IO_WriteOnly);
206
207 if (buf.size() > 255) return false;
208
209 //kdDebug() << "sendCommand. ogf=" << ogf << " ocf=" << ocf << endl;
210 Q_UINT16 opcode = cmd_opcode_pack(ogf, ocf);
211 Q_UINT8 pType = HCI_COMMAND_PKT;
212 Q_UINT8 buflen = buf.size();
213
214 stream << pType << opcode << buflen;
215 stream.writeRawBytes(buf.data(), buflen);
216 packet.close();
217 HCISocket.writeBlock((const char*)packet.buffer(),
218 packet.buffer().size());
219 return true;
220}
221
222bool OTHCISocket::readStatus( unsigned char ogf,
223 unsigned short ocf,
224 int *status,
225 int timeout_ms) {
226 QTimer timer;
227
228 timer.start(timeout_ms, true);
229 BStatusSet = false;
230
231 while (timer.isActive() && HCISocket.isValid()) {
232
233 owarn << "OTHCISocket::readStatus()" << oendl;
234 bool timeout = false;
235
236 if( HCISocket.bytesAvailable() == 0) {
237 int rv = HCISocket.waitForMore(timeout_ms);
238 timeout = (rv == 0);
239 }
240
241 if (!timeout) {
242 slotSocketActivated();
243 }
244
245 if( BStatusSet == true &&
246 ogf == LastStatusOgf &&
247 ocf == LastStatusOcf) {
248 *status = LastStatus;
249 owarn << "OTHCISocket::readStatus(ogf="
250 << ogf
251 << ",ocf="
252 << ocf
253 << ",timeout="
254 << LastStatus
255 << ")"
256 << oendl;
257 return true;
258 }
259 }
260
261 owarn << "OTHCISocket::readStatus(ogf="
262 << ogf
263 << ",ocf="
264 << ocf
265 << ",timeout="
266 << LastStatus
267 << ") : timeout "
268 << oendl;
269 return false;
270}
271
272int OTHCISocket::socket() {
273 return HCISocket.socket();
274}