38 #include "BTIoctl.hpp"
39 #include "HCIIoctl.hpp"
40 #include "L2CAPIoctl.hpp"
49 #include <sys/socket.h>
56 L2CAPEnv::L2CAPEnv() noexcept
57 : exploding(
jau::environment::getExplodingProperties("
direct_bt.l2cap") ),
58 L2CAP_READER_POLL_TIMEOUT(
jau::environment::getInt32Property("
direct_bt.l2cap.reader.timeout", 10000, 1500 , INT32_MAX ) ),
59 L2CAP_RESTART_COUNT_ON_ERROR(
jau::environment::getInt32Property("
direct_bt.l2cap.restart.count", 5, INT32_MIN , INT32_MAX ) ),
60 DEBUG_DATA(
jau::environment::getBooleanProperty("
direct_bt.debug.l2cap.data", false) )
69 fd = ::socket(AF_BLUETOOTH,
70 SOCK_SEQPACKET, BTPROTO_L2CAP);
73 ERR_PRINT(
"L2CAPComm::l2cap_open_dev: socket failed");
79 bzero((
void *)&a,
sizeof(a));
80 a.l2_family=AF_BLUETOOTH;
82 a.l2_bdaddr = adapterAddressAndType.
address;
85 if ( ::bind(fd, (
struct sockaddr *) &a,
sizeof(a)) < 0 ) {
86 ERR_PRINT(
"L2CAPComm::l2cap_open_dev: bind failed");
99 int L2CAPComm::l2cap_close_dev(
int dd)
111 adapterAddressAndType(adapterAddressAndType_),
112 psm(psm_), cid(cid_),
114 socket_descriptor(-1),
115 is_open(false), has_ioerror(false), interrupt_flag(false), tid_connect(0), tid_read(0)
128 #define SET_BT_SECURITY_POST_CONNECT 1
132 bool expOpen =
false;
133 if( !is_open.compare_exchange_strong(expOpen,
true) ) {
134 DBG_PRINT(
"L2CAPComm::open: Already open: %s, dd %d, %s, psm %s, cid %s",
139 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
161 int to_retry_count=0;
163 DBG_PRINT(
"L2CAPComm::open: Start Connect: %s, dd %d, %s, psm %s, cid %s",
167 socket_descriptor = l2cap_open_dev(adapterAddressAndType, psm, cid);
169 if( 0 > socket_descriptor ) {
173 #if !SET_BT_SECURITY_POST_CONNECT
174 #if USE_LINUX_BT_SECURITY
176 if( !setBTSecurityLevelImpl(sec_level) ) {
183 tid_connect = pthread_self();
186 bzero((
void *)&req,
sizeof(req));
187 req.l2_family = AF_BLUETOOTH;
189 req.l2_bdaddr = deviceAddressAndType.
address;
191 req.l2_bdaddr_type =
::number(deviceAddressAndType.
type);
193 while( !interrupt_flag ) {
195 res = ::connect(socket_descriptor, (
struct sockaddr*)&req,
sizeof(req));
197 DBG_PRINT(
"L2CAPComm::open: Connect Result %d, errno 0%X %s, %s", res, errno, strerror(errno), deviceAddressAndType.
toString().c_str());
203 }
else if( ETIMEDOUT == errno ) {
206 WORDY_PRINT(
"L2CAPComm::open: Connect timeout, retry %d", to_retry_count);
209 ERR_PRINT(
"L2CAPComm::open: Connect timeout, retried %d", to_retry_count);
215 ERR_PRINT(
"L2CAPComm::open: Connect failed");
222 #if SET_BT_SECURITY_POST_CONNECT
223 #if USE_LINUX_BT_SECURITY
225 if( !setBTSecurityLevelImpl(sec_level) ) {
235 const int err = errno;
243 if( !is_open.compare_exchange_strong(expOpen,
false) ) {
244 DBG_PRINT(
"L2CAPComm::close: Not connected: %s, dd %d, %s, psm %s, cid %s",
249 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
252 DBG_PRINT(
"L2CAPComm::close: Start: %s, dd %d, %s, psm %u, cid %u",
256 interrupt_flag =
true;
258 pthread_t tid_self = pthread_self();
259 pthread_t _tid_connect = tid_connect;
260 pthread_t _tid_read = tid_read;
265 if( 0 != _tid_read && tid_self != _tid_read ) {
267 if( 0 != ( kerr = pthread_kill(_tid_read, SIGALRM) ) ) {
268 ERR_PRINT(
"L2CAPComm::close: pthread_kill read %p FAILED: %d", (
void*)_tid_read, kerr);
272 interrupt_flag =
true;
273 if( 0 != _tid_connect && _tid_read != _tid_connect && tid_self != _tid_connect ) {
275 if( 0 != ( kerr = pthread_kill(_tid_connect, SIGALRM) ) ) {
276 ERR_PRINT(
"L2CAPComm::close: pthread_kill connect %p FAILED: %d", (
void*)_tid_connect, kerr);
281 l2cap_close_dev(socket_descriptor);
282 socket_descriptor = -1;
283 interrupt_flag =
false;
285 DBG_PRINT(
"L2CAPComm::close: End: dd %d", socket_descriptor.load());
291 DBG_PRINT(
"L2CAPComm::setBTSecurityLevel: Not connected: %s, dd %d, %s, psm %s, cid %s",
296 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
298 return setBTSecurityLevelImpl(sec_level);
301 bool L2CAPComm::setBTSecurityLevelImpl(
const BTSecurityLevel sec_level) {
303 DBG_PRINT(
"L2CAPComm::setBTSecurityLevel: sec_level %s, not set",
to_string(sec_level).c_str());
307 #if USE_LINUX_BT_SECURITY
308 struct bt_security bt_sec;
312 if( old_sec_level != sec_level ) {
313 bzero(&bt_sec,
sizeof(bt_sec));
315 result = setsockopt(socket_descriptor, SOL_BLUETOOTH, BT_SECURITY, &bt_sec,
sizeof(bt_sec));
317 DBG_PRINT(
"L2CAPComm::setBTSecurityLevel: sec_level %s -> %s, success",
321 ERR_PRINT(
"L2CAPComm::setBTSecurityLevel: sec_level %s -> %s, failed",
326 DBG_PRINT(
"L2CAPComm::setBTSecurityLevel: sec_level %s == %s, success (ignored)",
331 DBG_PRINT(
"L2CAPComm::setBTSecurityLevel: sec_level %s, not implemented",
to_string(sec_level).c_str());
338 DBG_PRINT(
"L2CAPComm::getBTSecurityLevel: Not connected: %s, dd %d, %s, psm %s, cid %s",
343 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
345 return getBTSecurityLevelImpl();
350 #if USE_LINUX_BT_SECURITY
351 struct bt_security bt_sec;
352 socklen_t optlen =
sizeof(bt_sec);
355 bzero(&bt_sec,
sizeof(bt_sec));
356 result = getsockopt(socket_descriptor, SOL_BLUETOOTH, BT_SECURITY, &bt_sec, &optlen);
358 if( optlen ==
sizeof(bt_sec) ) {
360 DBG_PRINT(
"L2CAPComm::getBTSecurityLevel: sec_level %s, success",
to_string(sec_level).c_str());
362 ERR_PRINT(
"L2CAPComm::getBTSecurityLevel: sec_level %s, failed. Returned size %zd != %zd ",
363 to_string(sec_level).c_str(), optlen,
sizeof(bt_sec));
366 ERR_PRINT(
"L2CAPComm::getBTSecurityLevel: sec_level %s, failed. Result %d",
to_string(sec_level).c_str(), result);
369 DBG_PRINT(
"L2CAPComm::setBTSecurityLevel: sec_level %s, not implemented",
to_string(sec_level).c_str());
379 tid_read = pthread_self();
381 if( 0 > socket_descriptor ) {
385 if( 0 == capacity ) {
393 p.fd = socket_descriptor; p.events = POLLIN;
394 while ( !interrupt_flag && (n = poll(&p, 1, timeoutMS)) < 0 ) {
395 if ( !interrupt_flag && ( errno == EAGAIN || errno == EINTR ) ) {
409 while ((len = ::
read(socket_descriptor, buffer, capacity)) < 0) {
410 if (errno == EAGAIN || errno == EINTR ) {
424 if( errno != ETIMEDOUT ) {
428 ABORT(
"L2CAPComm::read: Error res %d; %s, dd %d, %s, psm %s, cid %s",
432 IRQ_PRINT(
"L2CAPComm::read: Error res %d; %s, dd %d, %s, psm %s, cid %s",
442 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
446 if( 0 > socket_descriptor ) {
454 while( ( len = ::
write(socket_descriptor, buffer, length) ) < 0 ) {
455 if( EAGAIN == errno || EINTR == errno ) {
469 ABORT(
"L2CAPComm::write: Error res %d; %s, dd %d, %s, psm %s, cid %s",
473 IRQ_PRINT(
"L2CAPComm::write: Error res %d; %s, dd %d, %s, psm %s, cid %s",