summaryrefslogtreecommitdiff
path: root/libhfp
diff options
context:
space:
mode:
authorsamr7 <samr7@126591fb-c623-4b62-a76d-97a8e4f34109>2008-10-29 05:51:15 +0000
committersamr7 <samr7@126591fb-c623-4b62-a76d-97a8e4f34109>2008-10-29 05:51:15 +0000
commit87398b95137013cb6fa3062e10a98a2d5efe72d2 (patch)
tree1761a1bb78b8e389b48c94b0c060eec6c2c254c3 /libhfp
parentb9670bec58a5fd321c9ea4570049959bcaebc71d (diff)
downloadnohands-87398b95137013cb6fa3062e10a98a2d5efe72d2.tar.gz
Enhance reporting of RFCOMM/SCO EPROTONOSUPPORT failures.
Test SCO MTUs when starting HfpService. Make hfconsole fail to start with an error if: - Bluetooth service is unavailable - Attempting to start it fails due to lack of RFCOMM/SCO support or bad SCO MTU Add a 'Version' property to net.sf.nohands.hfpd Make hfconsole fail to start if there is a version mismatch. Fix a miscellaneous bug in hfpdtext net.cpp git-svn-id: http://nohands.svn.sourceforge.net/svnroot/nohands/trunk@18 126591fb-c623-4b62-a76d-97a8e4f34109
Diffstat (limited to 'libhfp')
-rw-r--r--libhfp/bt.cpp45
-rw-r--r--libhfp/hfp.cpp44
-rw-r--r--libhfp/rfcomm.cpp9
3 files changed, 91 insertions, 7 deletions
diff --git a/libhfp/bt.cpp b/libhfp/bt.cpp
index 0b2c42d..3b1ee29 100644
--- a/libhfp/bt.cpp
+++ b/libhfp/bt.cpp
@@ -801,12 +801,46 @@ HciCancel(HciTask *taskp)
}
}
+int HciAsyncTaskHandler::
+HciGetScoMtu(uint16_t &mtu, uint16_t &pkts)
+{
+ hci_dev_info di;
+
+ if (m_hci_fh < 0)
+ return -ESHUTDOWN;
+
+ di.dev_id = m_hci_id;
+ if (ioctl(m_hci_fh, HCIGETDEVINFO, (void *) &di) < 0)
+ return -errno;
+
+ mtu = di.sco_mtu;
+ pkts = di.sco_pkts;
+ return 0;
+}
+
+/* This only works as superuser */
+int HciAsyncTaskHandler::
+HciSetScoMtu(uint16_t mtu, uint16_t pkts)
+{
+ hci_dev_req dr;
+
+ if (m_hci_fh < 0)
+ return -ESHUTDOWN;
+
+ dr.dev_id = m_hci_id;
+ ((uint16_t *) &dr.dev_opt)[0] = htobs(mtu);
+ ((uint16_t *) &dr.dev_opt)[1] = htobs(pkts);
+ if (ioctl(m_hci_fh, HCISETSCOMTU, (void *) &dr) < 0)
+ return -errno;
+
+ return 0;
+}
int HciAsyncTaskHandler::
HciInit(void)
{
struct hci_filter flt;
- int did, fh;
+ int did, fh, err;
assert(m_hci_fh == -1);
assert(!m_hci_not);
@@ -817,9 +851,9 @@ HciInit(void)
return -ENODEV;
fh = hci_open_dev(did);
if (fh < 0) {
- did = -errno;
+ err = -errno;
m_ei->LogWarn("Could not open HCI: %s\n", strerror(errno));
- return did;
+ return err;
}
hci_filter_clear(&flt);
@@ -831,11 +865,11 @@ HciInit(void)
hci_filter_set_event(EVT_REMOTE_NAME_REQ_COMPLETE, &flt);
if (setsockopt(fh, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
- did = -errno;
+ err = -errno;
m_ei->LogWarn("Could not set filter on HCI: %s\n",
strerror(errno));
close(fh);
- return did;
+ return err;
}
m_hci_not = m_ei->NewSocket(fh, false);
@@ -855,6 +889,7 @@ HciInit(void)
m_resubmit->Register(this, &HciAsyncTaskHandler::HciResubmit);
m_hci_not->Register(this, &HciAsyncTaskHandler::HciDataReadyNot);
+ m_hci_id = did;
m_hci_fh = fh;
return 0;
}
diff --git a/libhfp/hfp.cpp b/libhfp/hfp.cpp
index 83d2a75..d75385b 100644
--- a/libhfp/hfp.cpp
+++ b/libhfp/hfp.cpp
@@ -127,17 +127,59 @@ bool HfpService::
ScoListen(void)
{
struct sockaddr_sco saddr;
- int sock = -1;
+ int sock = -1, res;
+ uint16_t mtu, pkts;
assert(m_sco_listen == -1);
+ /*
+ * I'm not sure what the whole story is with this, but some
+ * Broadcom dongles cause the kernel to set its SCO MTU
+ * values to 16:0. This is unsuitable for us, we need bigger
+ * packets and more buffering, and we will refuse to listen
+ * if it is not available.
+ */
+ res = GetHub()->HciGetScoMtu(mtu, pkts);
+ if (res) {
+ GetDi()->LogWarn("Get SCO MTU: %s\n",
+ strerror(-res));
+ return false;
+ }
+
+ if ((mtu < 48) || (pkts < 8)) {
+ if (GetHub()->HciSetScoMtu(64, 8) < 0) {
+ GetDi()->LogError("Unsuitable SCO MTU values %u:%u "
+ "detected\n", mtu, pkts);
+ GetDi()->LogError("To fix this, run, as superuser, "
+ "\"hciconfig hci0 scomtu 64:8\"\n");
+ GetHub()->SetAutoRestart(false);
+ return false;
+ }
+
+ mtu = 64;
+ pkts = 8;
+ }
+
+ /*
+ * Somebody may have also forgotten to enable SCO support
+ * in the kernel, or the sco.ko module got lost.
+ */
sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
if (sock < 0) {
+ sock = errno;
+ if (sock == EPROTONOSUPPORT) {
+ GetDi()->LogError("Your kernel is not configured with "
+ "support for SCO sockets.\n");
+ GetHub()->SetAutoRestart(false);
+ return false;
+ }
GetDi()->LogWarn("Create SCO socket: %s\n",
strerror(errno));
return false;
}
+ GetDi()->LogDebug("SCO MTU: %u:%u\n", mtu, pkts);
+
memset(&saddr, 0, sizeof(saddr));
saddr.sco_family = AF_BLUETOOTH;
bacpy(&saddr.sco_bdaddr, BDADDR_ANY);
diff --git a/libhfp/rfcomm.cpp b/libhfp/rfcomm.cpp
index 30c7e76..8740734 100644
--- a/libhfp/rfcomm.cpp
+++ b/libhfp/rfcomm.cpp
@@ -164,7 +164,14 @@ RfcommListen(uint8_t channel)
rsock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if (rsock < 0) {
- GetDi()->LogWarn("Create RFCOMM socket");
+ rsock = errno;
+ if (rsock == EPROTONOSUPPORT) {
+ GetDi()->LogError("Your kernel is not configured with "
+ "support for RFCOMM sockets.\n");
+ GetHub()->SetAutoRestart(false);
+ return false;
+ }
+ GetDi()->LogWarn("Create RFCOMM socket: %s", strerror(errno));
return false;
}