[meego-commits] 5880: Changes to Trunk/bluez
Anas Nashif
nashif at linux.intel.com
Tue Jul 20 22:43:08 UTC 2010
Hi,
I have made the following changes to bluez in project Trunk. Please review and accept ASAP.
Thank You,
Anas Nashif
[This message was auto-generated]
---
Request #5880:
submit: Trunk:Testing/bluez(r13) -> Trunk/bluez
Message:
Move to Trunk
State: new 2010-07-20T10:37:10 nashif
Comment: None
changes files:
--------------
--- bluez.changes
+++ bluez.changes
@@ -0,0 +1,3 @@
+* Mon Jul 19 2010 Zhu Yanhai <yanhai.zhu at linux.intel.com> 4.69
+- Upgrade to 4.69
+
old:
----
bluez-4.66.tar.gz
new:
----
bluez-4.69.tar.gz
spec files:
-----------
--- bluez.spec
+++ bluez.spec
@@ -1,13 +1,13 @@
#
-# Do NOT Edit the Auto-generated Part!
-# Generated by: spectacle version 0.19~pre
+# Do not Edit! Generated by:
+# spectacle version 0.17
#
# >> macros
# << macros
Name: bluez
Summary: Bluetooth utilities
-Version: 4.66
+Version: 4.69
Release: 1
Group: Applications/System
License: GPLv2+
other changes:
--------------
++++++ bluez-4.66.tar.gz -> bluez-4.69.tar.gz
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,25 @@
+ver 4.69:
+ Fix issue with calling g_option_context_free() twice.
+ Fix inconsistencies with initial LE commands and events.
+ Add support for telephony ClearLastNumber method.
+ Add support for network server interface.
+
+ver 4.68:
+ Fix initialization of adapters in RAW mode.
+ Fix signal strength for HFP in Maemo's telephony support.
+ Add support for following the radio state via Maemo's MCE.
+ Add initial set of LE commands and events definitions.
+ Add mode option for L2CAP sockets to the BtIO API.
+
+ver 4.67:
+ Fix issue with authentication reply when bonding already completed.
+ Fix issue with not canceling authentication when bonding fails.
+ Fix issue with changed combination keys and temporary storage.
+ Fix issue with sdp_get_supp_feat library function.
+ Fix issue with missing unblock on device removal.
+ Fix issue with not waiting for mode change completion.
+ Add ARMv6 optimized version of analysis filter for SBC encoder.
+
ver 4.66:
Fix regression with full debug enabling via SIGUSR2.
Fix redundant speaker/microphone gains being sent.
--- Makefile.am
+++ Makefile.am
@@ -53,7 +53,7 @@
lib_libbluetooth_la_SOURCES = $(lib_headers) \
lib/bluetooth.c lib/hci.c lib/sdp.c
-lib_libbluetooth_la_LDFLAGS = -version-info 11:0:8
+lib_libbluetooth_la_LDFLAGS = -version-info 12:0:9
lib_libbluetooth_la_DEPENDENCIES = $(local_headers)
CLEANFILES += $(local_headers)
@@ -65,7 +65,8 @@
sbc_libsbc_la_SOURCES = sbc/sbc.h sbc/sbc.c sbc/sbc_math.h sbc/sbc_tables.h \
sbc/sbc_primitives.h sbc/sbc_primitives.c \
sbc/sbc_primitives_mmx.h sbc/sbc_primitives_mmx.c \
- sbc/sbc_primitives_neon.h sbc/sbc_primitives_neon.c
+ sbc/sbc_primitives_neon.h sbc/sbc_primitives_neon.c \
+ sbc/sbc_primitives_armv6.h sbc/sbc_primitives_armv6.c
sbc_libsbc_la_CFLAGS = -finline-functions -fgcse-after-reload \
-funswitch-loops -funroll-loops
@@ -159,7 +160,6 @@
network/manager.h network/manager.c \
network/common.h network/common.c \
network/server.h network/server.c \
- network/bridge.h network/bridge.c \
network/connection.h network/connection.c
endif
@@ -177,6 +177,11 @@
builtin_modules += storage
builtin_sources += plugins/storage.c
+if MAEMO6PLUGIN
+builtin_modules += maemo6
+builtin_sources += plugins/maemo6.c
+endif
+
sbin_PROGRAMS += src/bluetoothd
src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
@@ -306,7 +311,7 @@
EXTRA_DIST += doc/manager-api.txt \
doc/adapter-api.txt doc/device-api.txt \
- doc/service-api.txt doc/agent-api.txt \
+ doc/service-api.txt doc/agent-api.txt doc/attribute-api.txt \
doc/serial-api.txt doc/network-api.txt \
doc/input-api.txt doc/audio-api.txt doc/control-api.txt
--- Makefile.in
+++ Makefile.in
@@ -88,11 +88,12 @@
@NETWORKPLUGIN_TRUE@ network/manager.h network/manager.c \
@NETWORKPLUGIN_TRUE@ network/common.h network/common.c \
@NETWORKPLUGIN_TRUE@ network/server.h network/server.c \
- at NETWORKPLUGIN_TRUE@ network/bridge.h network/bridge.c \
@NETWORKPLUGIN_TRUE@ network/connection.h network/connection.c
@SERVICEPLUGIN_TRUE at am__append_18 = service
@SERVICEPLUGIN_TRUE at am__append_19 = plugins/service.c
+ at MAEMO6PLUGIN_TRUE@am__append_20 = maemo6
+ at MAEMO6PLUGIN_TRUE@am__append_21 = plugins/maemo6.c
DIST_COMMON = README $(am__configure_deps) \
$(am__dist_udev_SCRIPTS_DIST) $(dist_man_MANS) \
$(include_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
@@ -104,57 +105,57 @@
ChangeLog INSTALL NEWS compile config.guess config.sub depcomp \
install-sh ltmain.sh missing tools/lexer.c tools/parser.c \
tools/parser.h ylwrap
- at CONFIGFILES_TRUE@@TOOLS_TRUE at am__append_20 = tools/rfcomm.conf
- at TOOLS_TRUE@am__append_21 = tools/rfcomm tools/l2ping \
+ at CONFIGFILES_TRUE@@TOOLS_TRUE at am__append_22 = tools/rfcomm.conf
+ at TOOLS_TRUE@am__append_23 = tools/rfcomm tools/l2ping \
@TOOLS_TRUE@ tools/hcitool tools/sdptool tools/ciptool
- at TOOLS_TRUE@am__append_22 = tools/hciattach tools/hciconfig
- at TOOLS_TRUE@am__append_23 = tools/avinfo tools/ppporc \
+ at TOOLS_TRUE@am__append_24 = tools/hciattach tools/hciconfig
+ at TOOLS_TRUE@am__append_25 = tools/avinfo tools/ppporc \
@TOOLS_TRUE@ tools/hcieventmask tools/hcisecfilter
- at TOOLS_TRUE@am__append_24 = tools/rfcomm.1 tools/l2ping.8 \
+ at TOOLS_TRUE@am__append_26 = tools/rfcomm.1 tools/l2ping.8 \
@TOOLS_TRUE@ tools/hciattach.8 tools/hciconfig.8 \
@TOOLS_TRUE@ tools/hcitool.1 tools/sdptool.1 tools/ciptool.1
- at TOOLS_FALSE@am__append_25 = tools/rfcomm.1 tools/l2ping.8 \
+ at TOOLS_FALSE@am__append_27 = tools/rfcomm.1 tools/l2ping.8 \
@TOOLS_FALSE@ tools/hciattach.8 tools/hciconfig.8 \
@TOOLS_FALSE@ tools/hcitool.1 tools/sdptool.1 tools/ciptool.1
- at TRACER_TRUE@am__append_26 = tracer/hcitrace
- at BCCMD_TRUE@am__append_27 = tools/bccmd
- at BCCMD_TRUE@@USB_TRUE at am__append_28 = tools/csr_usb.c
- at BCCMD_TRUE@@USB_TRUE at am__append_29 = @USB_LIBS@
- at BCCMD_TRUE@am__append_30 = tools/bccmd.8
- at BCCMD_FALSE@am__append_31 = tools/bccmd.8
- at HID2HCI_TRUE@am__append_32 = tools/hid2hci
- at HID2HCI_TRUE@am__append_33 = tools/hid2hci.8
- at HID2HCI_FALSE@am__append_34 = tools/hid2hci.8
- at DFUTOOL_TRUE@am__append_35 = tools/dfutool
- at DFUTOOL_TRUE@am__append_36 = tools/dfutool.1
- at DFUTOOL_FALSE@am__append_37 = tools/dfutool.1
- at USB_TRUE@am__append_38 = tools/dfubabel tools/avctrl
+ at TRACER_TRUE@am__append_28 = tracer/hcitrace
+ at BCCMD_TRUE@am__append_29 = tools/bccmd
+ at BCCMD_TRUE@@USB_TRUE at am__append_30 = tools/csr_usb.c
+ at BCCMD_TRUE@@USB_TRUE at am__append_31 = @USB_LIBS@
+ at BCCMD_TRUE@am__append_32 = tools/bccmd.8
+ at BCCMD_FALSE@am__append_33 = tools/bccmd.8
+ at HID2HCI_TRUE@am__append_34 = tools/hid2hci
+ at HID2HCI_TRUE@am__append_35 = tools/hid2hci.8
+ at HID2HCI_FALSE@am__append_36 = tools/hid2hci.8
+ at DFUTOOL_TRUE@am__append_37 = tools/dfutool
+ at DFUTOOL_TRUE@am__append_38 = tools/dfutool.1
+ at DFUTOOL_FALSE@am__append_39 = tools/dfutool.1
+ at USB_TRUE@am__append_40 = tools/dfubabel tools/avctrl
@CUPS_TRUE at cups_PROGRAMS = cups/bluetooth$(EXEEXT)
- at TEST_TRUE@am__append_39 = test/hciemu
- at TEST_TRUE@am__append_40 = test/l2test test/rctest
- at TEST_TRUE@am__append_41 = test/gaptest test/sdptest test/scotest \
+ at TEST_TRUE@am__append_41 = test/hciemu
+ at TEST_TRUE@am__append_42 = test/l2test test/rctest
+ at TEST_TRUE@am__append_43 = test/gaptest test/sdptest test/scotest \
@TEST_TRUE@ test/attest test/hstest test/avtest test/ipctest \
@TEST_TRUE@ test/lmptest test/bdaddr test/agent \
@TEST_TRUE@ test/btiotest test/test-textfile
- at TEST_TRUE@am__append_42 = test/rctest.1 test/hciemu.1
- at TEST_TRUE@am__append_43 = test/bdaddr.8
- at TEST_FALSE@am__append_44 = test/rctest.1 test/hciemu.1 test/bdaddr.8
- at HIDD_TRUE@am__append_45 = compat/hidd
- at HIDD_TRUE@am__append_46 = compat/hidd.1
- at HIDD_FALSE@am__append_47 = compat/hidd.1
- at PAND_TRUE@am__append_48 = compat/pand
- at PAND_TRUE@am__append_49 = compat/pand.1
- at PAND_FALSE@am__append_50 = compat/pand.1
- at DUND_TRUE@am__append_51 = compat/dund
- at DUND_TRUE@am__append_52 = compat/dund.1
- at DUND_FALSE@am__append_53 = compat/dund.1
- at HID2HCI_TRUE@@UDEVRULES_TRUE at am__append_54 = scripts/bluetooth-hid2hci.rules
- at PCMCIA_TRUE@@UDEVRULES_TRUE at am__append_55 = scripts/bluetooth-serial.rules
+ at TEST_TRUE@am__append_44 = test/rctest.1 test/hciemu.1
+ at TEST_TRUE@am__append_45 = test/bdaddr.8
+ at TEST_FALSE@am__append_46 = test/rctest.1 test/hciemu.1 test/bdaddr.8
+ at HIDD_TRUE@am__append_47 = compat/hidd
+ at HIDD_TRUE@am__append_48 = compat/hidd.1
+ at HIDD_FALSE@am__append_49 = compat/hidd.1
+ at PAND_TRUE@am__append_50 = compat/pand
+ at PAND_TRUE@am__append_51 = compat/pand.1
+ at PAND_FALSE@am__append_52 = compat/pand.1
+ at DUND_TRUE@am__append_53 = compat/dund
+ at DUND_TRUE@am__append_54 = compat/dund.1
+ at DUND_FALSE@am__append_55 = compat/dund.1
+ at HID2HCI_TRUE@@UDEVRULES_TRUE at am__append_56 = scripts/bluetooth-hid2hci.rules
+ at PCMCIA_TRUE@@UDEVRULES_TRUE at am__append_57 = scripts/bluetooth-serial.rules
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
@@ -301,11 +302,13 @@
am__sbc_libsbc_la_SOURCES_DIST = sbc/sbc.h sbc/sbc.c sbc/sbc_math.h \
sbc/sbc_tables.h sbc/sbc_primitives.h sbc/sbc_primitives.c \
sbc/sbc_primitives_mmx.h sbc/sbc_primitives_mmx.c \
- sbc/sbc_primitives_neon.h sbc/sbc_primitives_neon.c
+ sbc/sbc_primitives_neon.h sbc/sbc_primitives_neon.c \
+ sbc/sbc_primitives_armv6.h sbc/sbc_primitives_armv6.c
@SBC_TRUE at am_sbc_libsbc_la_OBJECTS = sbc/sbc_libsbc_la-sbc.lo \
@SBC_TRUE@ sbc/sbc_libsbc_la-sbc_primitives.lo \
@SBC_TRUE@ sbc/sbc_libsbc_la-sbc_primitives_mmx.lo \
- at SBC_TRUE@ sbc/sbc_libsbc_la-sbc_primitives_neon.lo
+ at SBC_TRUE@ sbc/sbc_libsbc_la-sbc_primitives_neon.lo \
+ at SBC_TRUE@ sbc/sbc_libsbc_la-sbc_primitives_armv6.lo
sbc_libsbc_la_OBJECTS = $(am_sbc_libsbc_la_OBJECTS)
sbc_libsbc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(sbc_libsbc_la_CFLAGS) \
@@ -403,20 +406,20 @@
serial/manager.c serial/proxy.h serial/proxy.c serial/port.h \
serial/port.c network/main.c network/manager.h \
network/manager.c network/common.h network/common.c \
- network/server.h network/server.c network/bridge.h \
- network/bridge.c network/connection.h network/connection.c \
- plugins/service.c plugins/hciops.c plugins/hal.c \
- plugins/storage.c src/main.c src/log.h src/log.c \
- src/security.c src/rfkill.c src/hcid.h src/sdpd.h \
- src/sdpd-server.c src/sdpd-request.c src/sdpd-service.c \
- src/sdpd-database.c src/sdp-xml.h src/sdp-xml.c src/btio.h \
- src/btio.c src/textfile.h src/textfile.c src/glib-helper.h \
- src/glib-helper.c src/oui.h src/oui.c src/uinput.h src/ppoll.h \
- src/plugin.h src/plugin.c src/storage.h src/storage.c \
- src/agent.h src/agent.c src/error.h src/error.c src/manager.h \
- src/manager.c src/adapter.h src/adapter.c src/device.h \
- src/device.c src/dbus-common.c src/dbus-common.h \
- src/dbus-hci.h src/dbus-hci.c
+ network/server.h network/server.c network/connection.h \
+ network/connection.c plugins/service.c plugins/hciops.c \
+ plugins/hal.c plugins/storage.c plugins/maemo6.c src/main.c \
+ src/log.h src/log.c src/security.c src/rfkill.c src/hcid.h \
+ src/sdpd.h src/sdpd-server.c src/sdpd-request.c \
+ src/sdpd-service.c src/sdpd-database.c src/sdp-xml.h \
+ src/sdp-xml.c src/btio.h src/btio.c src/textfile.h \
+ src/textfile.c src/glib-helper.h src/glib-helper.c src/oui.h \
+ src/oui.c src/uinput.h src/ppoll.h src/plugin.h src/plugin.c \
+ src/storage.h src/storage.c src/agent.h src/agent.c \
+ src/error.h src/error.c src/manager.h src/manager.c \
+ src/adapter.h src/adapter.c src/device.h src/device.c \
+ src/dbus-common.c src/dbus-common.h src/dbus-hci.h \
+ src/dbus-hci.c
@PNATPLUGIN_TRUE at am__objects_3 = plugins/pnat.$(OBJEXT)
@ECHOPLUGIN_TRUE at am__objects_4 = plugins/echo.$(OBJEXT)
@AUDIOPLUGIN_TRUE at am__objects_5 = audio/main.$(OBJEXT) \
@@ -441,14 +444,15 @@
@NETWORKPLUGIN_TRUE@ network/manager.$(OBJEXT) \
@NETWORKPLUGIN_TRUE@ network/common.$(OBJEXT) \
@NETWORKPLUGIN_TRUE@ network/server.$(OBJEXT) \
- at NETWORKPLUGIN_TRUE@ network/bridge.$(OBJEXT) \
@NETWORKPLUGIN_TRUE@ network/connection.$(OBJEXT)
@SERVICEPLUGIN_TRUE at am__objects_9 = plugins/service.$(OBJEXT)
-am__objects_10 = $(am__objects_3) $(am__objects_4) $(am__objects_5) \
+ at MAEMO6PLUGIN_TRUE@am__objects_10 = plugins/maemo6.$(OBJEXT)
+am__objects_11 = $(am__objects_3) $(am__objects_4) $(am__objects_5) \
$(am__objects_6) $(am__objects_7) $(am__objects_8) \
$(am__objects_9) plugins/hciops.$(OBJEXT) \
- plugins/hal.$(OBJEXT) plugins/storage.$(OBJEXT)
-am_src_bluetoothd_OBJECTS = $(am__objects_2) $(am__objects_10) \
+ plugins/hal.$(OBJEXT) plugins/storage.$(OBJEXT) \
+ $(am__objects_10)
+am_src_bluetoothd_OBJECTS = $(am__objects_2) $(am__objects_11) \
src/main.$(OBJEXT) src/log.$(OBJEXT) src/security.$(OBJEXT) \
src/rfkill.$(OBJEXT) src/sdpd-server.$(OBJEXT) \
src/sdpd-request.$(OBJEXT) src/sdpd-service.$(OBJEXT) \
@@ -459,10 +463,10 @@
src/error.$(OBJEXT) src/manager.$(OBJEXT) \
src/adapter.$(OBJEXT) src/device.$(OBJEXT) \
src/dbus-common.$(OBJEXT) src/dbus-hci.$(OBJEXT)
- at AUDIOPLUGIN_TRUE@am__objects_11 = audio/telephony.$(OBJEXT)
-am__objects_12 = $(am__objects_11)
+ at AUDIOPLUGIN_TRUE@am__objects_12 = audio/telephony.$(OBJEXT)
am__objects_13 = $(am__objects_12)
-nodist_src_bluetoothd_OBJECTS = $(am__objects_13)
+am__objects_14 = $(am__objects_13)
+nodist_src_bluetoothd_OBJECTS = $(am__objects_14)
src_bluetoothd_OBJECTS = $(am_src_bluetoothd_OBJECTS) \
$(nodist_src_bluetoothd_OBJECTS)
src_bluetoothd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
@@ -532,12 +536,12 @@
am__tools_bccmd_SOURCES_DIST = tools/bccmd.c tools/csr.h tools/csr.c \
tools/csr_hci.c tools/csr_h4.c tools/csr_3wire.c \
tools/csr_bcsp.c tools/ubcsp.h tools/ubcsp.c tools/csr_usb.c
- at BCCMD_TRUE@@USB_TRUE at am__objects_14 = tools/csr_usb.$(OBJEXT)
+ at BCCMD_TRUE@@USB_TRUE at am__objects_15 = tools/csr_usb.$(OBJEXT)
@BCCMD_TRUE at am_tools_bccmd_OBJECTS = tools/bccmd.$(OBJEXT) \
@BCCMD_TRUE@ tools/csr.$(OBJEXT) tools/csr_hci.$(OBJEXT) \
@BCCMD_TRUE@ tools/csr_h4.$(OBJEXT) tools/csr_3wire.$(OBJEXT) \
@BCCMD_TRUE@ tools/csr_bcsp.$(OBJEXT) tools/ubcsp.$(OBJEXT) \
- at BCCMD_TRUE@ $(am__objects_14)
+ at BCCMD_TRUE@ $(am__objects_15)
tools_bccmd_OBJECTS = $(am_tools_bccmd_OBJECTS)
am__DEPENDENCIES_1 =
@BCCMD_TRUE at tools_bccmd_DEPENDENCIES = lib/libbluetooth.la \
@@ -861,9 +865,9 @@
AM_MAKEFLAGS = --no-print-directory
lib_LTLIBRARIES = lib/libbluetooth.la
noinst_LTLIBRARIES = $(am__append_1)
-dist_man_MANS = $(am__append_24) $(am__append_30) $(am__append_33) \
- $(am__append_36) $(am__append_42) $(am__append_46) \
- $(am__append_49) $(am__append_52)
+dist_man_MANS = $(am__append_26) $(am__append_32) $(am__append_35) \
+ $(am__append_38) $(am__append_44) $(am__append_48) \
+ $(am__append_51) $(am__append_54)
dist_noinst_MANS =
CLEANFILES = $(local_headers) src/bluetooth.ver src/bluetooth.exp \
$(builtin_files) tools/lexer.c tools/parser.c tools/parser.h \
@@ -872,10 +876,10 @@
network/network.conf input/input.conf serial/serial.conf \
audio/audio.conf audio/telephony-dummy.c \
audio/telephony-maemo5.c audio/telephony-ofono.c \
- audio/telephony-maemo6.c audio/bluetooth.conf $(am__append_25) \
- tools/rfcomm.conf $(am__append_31) $(am__append_34) \
- $(am__append_37) tools/dfubabel.1 tools/avctrl.8 \
- $(am__append_43) $(am__append_44) test/apitest test/hsplay \
+ audio/telephony-maemo6.c audio/bluetooth.conf $(am__append_27) \
+ tools/rfcomm.conf $(am__append_33) $(am__append_36) \
+ $(am__append_39) tools/dfubabel.1 tools/avctrl.8 \
+ $(am__append_45) $(am__append_46) test/apitest test/hsplay \
test/hsmicro test/dbusdef.py test/monitor-bluetooth \
test/list-devices test/test-discovery test/test-manager \
test/test-adapter test/test-device test/test-service \
@@ -883,17 +887,18 @@
test/simple-agent test/simple-service test/test-audio \
test/test-input test/service-record.dtd test/service-did.xml \
test/service-spp.xml test/service-opp.xml test/service-ftp.xml \
- $(am__append_47) $(am__append_50) $(am__append_53) \
+ $(am__append_49) $(am__append_52) $(am__append_55) \
scripts/bluetooth.rules scripts/bluetooth-hid2hci.rules \
scripts/bluetooth-serial.rules doc/manager-api.txt \
doc/adapter-api.txt doc/device-api.txt doc/service-api.txt \
- doc/agent-api.txt doc/serial-api.txt doc/network-api.txt \
- doc/input-api.txt doc/audio-api.txt doc/control-api.txt
+ doc/agent-api.txt doc/attribute-api.txt doc/serial-api.txt \
+ doc/network-api.txt doc/input-api.txt doc/audio-api.txt \
+ doc/control-api.txt
include_HEADERS = $(lib_headers)
@CONFIGFILES_TRUE at dbusdir = $(sysconfdir)/dbus-1/system.d
@CONFIGFILES_TRUE at dbus_DATA = src/bluetooth.conf
@CONFIGFILES_TRUE at confdir = $(sysconfdir)/bluetooth
- at CONFIGFILES_TRUE@conf_DATA = src/main.conf $(am__append_20)
+ at CONFIGFILES_TRUE@conf_DATA = src/main.conf $(am__append_22)
@CONFIGFILES_TRUE at statedir = $(localstatedir)/lib/bluetooth
@CONFIGFILES_TRUE at state_DATA =
plugindir = $(libdir)/bluetooth/plugins
@@ -906,12 +911,13 @@
lib_libbluetooth_la_SOURCES = $(lib_headers) \
lib/bluetooth.c lib/hci.c lib/sdp.c
-lib_libbluetooth_la_LDFLAGS = -version-info 11:0:8
+lib_libbluetooth_la_LDFLAGS = -version-info 12:0:9
lib_libbluetooth_la_DEPENDENCIES = $(local_headers)
@SBC_TRUE at sbc_libsbc_la_SOURCES = sbc/sbc.h sbc/sbc.c sbc/sbc_math.h sbc/sbc_tables.h \
@SBC_TRUE@ sbc/sbc_primitives.h sbc/sbc_primitives.c \
@SBC_TRUE@ sbc/sbc_primitives_mmx.h sbc/sbc_primitives_mmx.c \
- at SBC_TRUE@ sbc/sbc_primitives_neon.h sbc/sbc_primitives_neon.c
+ at SBC_TRUE@ sbc/sbc_primitives_neon.h sbc/sbc_primitives_neon.c \
+ at SBC_TRUE@ sbc/sbc_primitives_armv6.h sbc/sbc_primitives_armv6.c
@SBC_TRUE at sbc_libsbc_la_CFLAGS = -finline-functions -fgcse-after-reload \
@SBC_TRUE@ -funswitch-loops -funroll-loops
@@ -930,11 +936,11 @@
gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/object.c gdbus/watch.c
builtin_modules = $(am__append_5) $(am__append_7) $(am__append_9) \
$(am__append_12) $(am__append_14) $(am__append_16) \
- $(am__append_18) hciops hal storage
+ $(am__append_18) hciops hal storage $(am__append_20)
builtin_sources = $(am__append_6) $(am__append_8) $(am__append_10) \
$(am__append_13) $(am__append_15) $(am__append_17) \
$(am__append_19) plugins/hciops.c plugins/hal.c \
- plugins/storage.c
+ plugins/storage.c $(am__append_21)
builtin_nodist = $(am__append_11)
@AUDIOPLUGIN_TRUE at noinst_LIBRARIES = audio/libtelephony.a
@AUDIOPLUGIN_TRUE at audio_libtelephony_a_SOURCES = audio/telephony.h audio/telephony-dummy.c \
@@ -1045,8 +1051,8 @@
@BCCMD_TRUE at tools_bccmd_SOURCES = tools/bccmd.c tools/csr.h \
@BCCMD_TRUE@ tools/csr.c tools/csr_hci.c tools/csr_h4.c \
@BCCMD_TRUE@ tools/csr_3wire.c tools/csr_bcsp.c tools/ubcsp.h \
- at BCCMD_TRUE@ tools/ubcsp.c $(am__append_28)
- at BCCMD_TRUE@tools_bccmd_LDADD = lib/libbluetooth.la $(am__append_29)
+ at BCCMD_TRUE@ tools/ubcsp.c $(am__append_30)
+ at BCCMD_TRUE@tools_bccmd_LDADD = lib/libbluetooth.la $(am__append_31)
@HID2HCI_TRUE at tools_hid2hci_LDADD = @USB_LIBS@
@DFUTOOL_TRUE at tools_dfutool_SOURCES = tools/dfutool.c tools/dfu.h tools/dfu.c
@DFUTOOL_TRUE at tools_dfutool_LDADD = @USB_LIBS@
@@ -1091,8 +1097,8 @@
@DUND_TRUE at compat_dund_LDADD = lib/libbluetooth.la
@UDEVRULES_TRUE at rulesdir = @UDEV_DATADIR@
- at UDEVRULES_TRUE@udev_files = scripts/bluetooth.rules $(am__append_54) \
- at UDEVRULES_TRUE@ $(am__append_55)
+ at UDEVRULES_TRUE@udev_files = scripts/bluetooth.rules $(am__append_56) \
+ at UDEVRULES_TRUE@ $(am__append_57)
@UDEVRULES_TRUE at rules_DATA = $(foreach file,$(udev_files), scripts/97-$(notdir $(file)))
@PCMCIA_TRUE at udevdir = $(libexecdir)/udev
@PCMCIA_TRUE at dist_udev_SCRIPTS = scripts/bluetooth_serial
@@ -1396,6 +1402,8 @@
sbc/$(DEPDIR)/$(am__dirstamp)
sbc/sbc_libsbc_la-sbc_primitives_neon.lo: sbc/$(am__dirstamp) \
sbc/$(DEPDIR)/$(am__dirstamp)
+sbc/sbc_libsbc_la-sbc_primitives_armv6.lo: sbc/$(am__dirstamp) \
+ sbc/$(DEPDIR)/$(am__dirstamp)
sbc/libsbc.la: $(sbc_libsbc_la_OBJECTS) $(sbc_libsbc_la_DEPENDENCIES) sbc/$(am__dirstamp)
$(AM_V_CCLD)$(sbc_libsbc_la_LINK) $(am_sbc_libsbc_la_rpath) $(sbc_libsbc_la_OBJECTS) $(sbc_libsbc_la_LIBADD) $(LIBS)
install-binPROGRAMS: $(bin_PROGRAMS)
@@ -1696,8 +1704,6 @@
network/$(DEPDIR)/$(am__dirstamp)
network/server.$(OBJEXT): network/$(am__dirstamp) \
network/$(DEPDIR)/$(am__dirstamp)
-network/bridge.$(OBJEXT): network/$(am__dirstamp) \
- network/$(DEPDIR)/$(am__dirstamp)
network/connection.$(OBJEXT): network/$(am__dirstamp) \
network/$(DEPDIR)/$(am__dirstamp)
plugins/service.$(OBJEXT): plugins/$(am__dirstamp) \
@@ -1708,6 +1714,8 @@
plugins/$(DEPDIR)/$(am__dirstamp)
plugins/storage.$(OBJEXT): plugins/$(am__dirstamp) \
plugins/$(DEPDIR)/$(am__dirstamp)
+plugins/maemo6.$(OBJEXT): plugins/$(am__dirstamp) \
+ plugins/$(DEPDIR)/$(am__dirstamp)
src/main.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/log.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/security.$(OBJEXT): src/$(am__dirstamp) \
@@ -2066,7 +2074,6 @@
-rm -f lib/hci.lo
-rm -f lib/sdp.$(OBJEXT)
-rm -f lib/sdp.lo
- -rm -f network/bridge.$(OBJEXT)
-rm -f network/common.$(OBJEXT)
-rm -f network/connection.$(OBJEXT)
-rm -f network/main.$(OBJEXT)
@@ -2075,6 +2082,7 @@
-rm -f plugins/echo.$(OBJEXT)
-rm -f plugins/hal.$(OBJEXT)
-rm -f plugins/hciops.$(OBJEXT)
+ -rm -f plugins/maemo6.$(OBJEXT)
-rm -f plugins/plugins_netlink_la-netlink.$(OBJEXT)
-rm -f plugins/plugins_netlink_la-netlink.lo
-rm -f plugins/pnat.$(OBJEXT)
@@ -2084,6 +2092,8 @@
-rm -f sbc/sbc_libsbc_la-sbc.lo
-rm -f sbc/sbc_libsbc_la-sbc_primitives.$(OBJEXT)
-rm -f sbc/sbc_libsbc_la-sbc_primitives.lo
+ -rm -f sbc/sbc_libsbc_la-sbc_primitives_armv6.$(OBJEXT)
+ -rm -f sbc/sbc_libsbc_la-sbc_primitives_armv6.lo
-rm -f sbc/sbc_libsbc_la-sbc_primitives_mmx.$(OBJEXT)
-rm -f sbc/sbc_libsbc_la-sbc_primitives_mmx.lo
-rm -f sbc/sbc_libsbc_la-sbc_primitives_neon.$(OBJEXT)
@@ -2221,7 +2231,6 @@
@AMDEP_TRUE@@am__include@ @am__quote at lib/$(DEPDIR)/bluetooth.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at lib/$(DEPDIR)/hci.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at lib/$(DEPDIR)/sdp.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at network/$(DEPDIR)/bridge.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at network/$(DEPDIR)/common.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at network/$(DEPDIR)/connection.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at network/$(DEPDIR)/main.Po at am__quote@
@@ -2230,12 +2239,14 @@
@AMDEP_TRUE@@am__include@ @am__quote at plugins/$(DEPDIR)/echo.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at plugins/$(DEPDIR)/hal.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at plugins/$(DEPDIR)/hciops.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at plugins/$(DEPDIR)/maemo6.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at plugins/$(DEPDIR)/plugins_netlink_la-netlink.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at plugins/$(DEPDIR)/pnat.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at plugins/$(DEPDIR)/service.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at plugins/$(DEPDIR)/storage.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at sbc/$(DEPDIR)/sbc_libsbc_la-sbc.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at sbc/$(DEPDIR)/sbc_libsbc_la-sbc_primitives.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at sbc/$(DEPDIR)/sbc_libsbc_la-sbc_primitives_armv6.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at sbc/$(DEPDIR)/sbc_libsbc_la-sbc_primitives_mmx.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at sbc/$(DEPDIR)/sbc_libsbc_la-sbc_primitives_neon.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at sbc/$(DEPDIR)/sbcdec.Po at am__quote@
@@ -2486,6 +2497,14 @@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sbc_libsbc_la_CFLAGS) $(CFLAGS) -c -o sbc/sbc_libsbc_la-sbc_primitives_neon.lo `test -f 'sbc/sbc_primitives_neon.c' || echo '$(srcdir)/'`sbc/sbc_primitives_neon.c
+sbc/sbc_libsbc_la-sbc_primitives_armv6.lo: sbc/sbc_primitives_armv6.c
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sbc_libsbc_la_CFLAGS) $(CFLAGS) -MT sbc/sbc_libsbc_la-sbc_primitives_armv6.lo -MD -MP -MF sbc/$(DEPDIR)/sbc_libsbc_la-sbc_primitives_armv6.Tpo -c -o sbc/sbc_libsbc_la-sbc_primitives_armv6.lo `test -f 'sbc/sbc_primitives_armv6.c' || echo '$(srcdir)/'`sbc/sbc_primitives_armv6.c
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbc/$(DEPDIR)/sbc_libsbc_la-sbc_primitives_armv6.Tpo sbc/$(DEPDIR)/sbc_libsbc_la-sbc_primitives_armv6.Plo
+ at am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sbc/sbc_primitives_armv6.c' object='sbc/sbc_libsbc_la-sbc_primitives_armv6.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sbc_libsbc_la_CFLAGS) $(CFLAGS) -c -o sbc/sbc_libsbc_la-sbc_primitives_armv6.lo `test -f 'sbc/sbc_primitives_armv6.c' || echo '$(srcdir)/'`sbc/sbc_primitives_armv6.c
+
.l.c:
$(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
--- acinclude.m4
+++ acinclude.m4
@@ -182,6 +182,7 @@
udevrules_enable=yes
configfiles_enable=yes
telephony_driver=dummy
+ maemo6_enable=no
AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable code optimization]), [
optimization_enable=${enableval}
@@ -293,6 +294,10 @@
AC_SUBST([TELEPHONY_DRIVER], [telephony-${telephony_driver}.c])
+ AC_ARG_ENABLE(maemo6, AC_HELP_STRING([--enable-maemo6], [compile with maemo6 plugin]), [
+ maemo6_enable=${enableval}
+ ])
+
if (test "${fortify_enable}" = "yes"); then
CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2"
fi
@@ -340,4 +345,5 @@
AM_CONDITIONAL(DFUTOOL, test "${dfutool_enable}" = "yes" && test "${usb_found}" = "yes")
AM_CONDITIONAL(UDEVRULES, test "${udevrules_enable}" = "yes")
AM_CONDITIONAL(CONFIGFILES, test "${configfiles_enable}" = "yes")
+ AM_CONDITIONAL(MAEMO6PLUGIN, test "${maemo6_enable}" = "yes")
])
--- audio/a2dp.c
+++ audio/a2dp.c
@@ -112,14 +112,14 @@
{
setup->ref++;
- DBG("setup_ref(%p): ref=%d", setup, setup->ref);
+ DBG("%p: ref=%d", setup, setup->ref);
return setup;
}
static void setup_free(struct a2dp_setup *s)
{
- DBG("setup_free(%p)", s);
+ DBG("%p", s);
setups = g_slist_remove(setups, s);
if (s->session)
avdtp_unref(s->session);
@@ -132,7 +132,7 @@
{
setup->ref--;
- DBG("setup_unref(%p): ref=%d", setup, setup->ref);
+ DBG("%p: ref=%d", setup, setup->ref);
if (setup->ref <= 0)
setup_free(setup);
--- audio/avdtp.c
+++ audio/avdtp.c
@@ -541,8 +541,7 @@
cont_fragments = (len - (session->omtu - sizeof(start))) /
(session->omtu - sizeof(cont)) + 1;
- DBG("avdtp_send: %zu bytes split into %d fragments", len,
- cont_fragments + 1);
+ DBG("%zu bytes split into %d fragments", len, cont_fragments + 1);
/* Send the start packet */
memset(&start, 0, sizeof(start));
@@ -559,8 +558,7 @@
if (!try_send(sock, session->buf, session->omtu))
return FALSE;
- DBG("avdtp_send: first packet with %zu bytes sent",
- session->omtu - sizeof(start));
+ DBG("first packet with %zu bytes sent", session->omtu - sizeof(start));
sent = session->omtu - sizeof(start);
@@ -572,13 +570,11 @@
if (left + sizeof(cont) > session->omtu) {
cont.packet_type = AVDTP_PKT_TYPE_CONTINUE;
to_copy = session->omtu - sizeof(cont);
- DBG("avdtp_send: sending continue with %d bytes",
- to_copy);
+ DBG("sending continue with %d bytes", to_copy);
} else {
cont.packet_type = AVDTP_PKT_TYPE_END;
to_copy = left;
- DBG("avdtp_send: sending end with %d bytes",
- to_copy);
+ DBG("sending end with %d bytes", to_copy);
}
cont.transaction = transaction;
@@ -804,7 +800,8 @@
struct avdtp_stream *stream = user_data;
struct avdtp *session = stream->session;
- avdtp_close(session, stream, FALSE);
+ if (avdtp_close(session, stream, FALSE) < 0)
+ error("stream_timeout: closing AVDTP stream failed");
stream->idle_timer = 0;
@@ -1119,7 +1116,7 @@
session->ref--;
- DBG("avdtp_unref(%p): ref=%d", session, session->ref);
+ DBG("%p: ref=%d", session, session->ref);
if (session->ref == 1) {
if (session->state == AVDTP_SESSION_STATE_CONNECTING &&
@@ -1146,8 +1143,7 @@
server = session->server;
- DBG("avdtp_unref(%p): freeing session and removing from list",
- session);
+ DBG("%p: freeing session and removing from list", session);
if (session->dc_timer)
remove_disconnect_timer(session);
@@ -1168,7 +1164,7 @@
struct avdtp *avdtp_ref(struct avdtp *session)
{
session->ref++;
- DBG("avdtp_ref(%p): ref=%d", session, session->ref);
+ DBG("%p: ref=%d", session, session->ref);
if (session->dc_timer)
remove_disconnect_timer(session);
return session;
@@ -1980,7 +1976,7 @@
struct avdtp_common_header *header;
gsize size;
- DBG("session_cb");
+ DBG("");
if (cond & G_IO_NVAL)
return FALSE;
@@ -2329,8 +2325,7 @@
* Abort the device's channel in favor of our own.
*/
if (session->state == AVDTP_SESSION_STATE_CONNECTING) {
- DBG("avdtp_confirm_cb: connect already in progress"
- " (XCASE connect:connect)");
+ DBG("connect already in progress (XCASE connect:connect)");
goto drop;
}
@@ -3345,8 +3340,8 @@
if (!(lsep && rsep))
return -EINVAL;
- DBG("avdtp_set_configuration(%p): int_seid=%u, acp_seid=%u",
- session, lsep->info.seid, rsep->seid);
+ DBG("%p: int_seid=%u, acp_seid=%u", session,
+ lsep->info.seid, rsep->seid);
new_stream = g_new0(struct avdtp_stream, 1);
new_stream->session = session;
--- audio/gstbluetooth.c
+++ audio/gstbluetooth.c
@@ -50,21 +50,24 @@
sbc_t sbc;
guint8 *data = gst_type_find_peek(tf, 0, 32);
- if (sbc_init(&sbc, 0) < 0)
+ if (data == NULL)
return;
- if (data == NULL || *data != 0x9c) /* SBC syncword */
+ if (sbc_init(&sbc, 0) < 0)
return;
aux = g_new(guint8, 32);
memcpy(aux, data, 32);
- sbc_parse(&sbc, aux, 32);
- g_free(aux);
- caps = gst_sbc_parse_caps_from_sbc(&sbc);
- sbc_finish(&sbc);
+ if (sbc_parse(&sbc, aux, 32) < 0)
+ goto done;
+ caps = gst_sbc_parse_caps_from_sbc(&sbc);
gst_type_find_suggest(tf, GST_TYPE_FIND_POSSIBLE, caps);
gst_caps_unref(caps);
+
+done:
+ g_free(aux);
+ sbc_finish(&sbc);
}
static gchar *sbc_exts[] = { "sbc", NULL };
--- audio/manager.c
+++ audio/manager.c
@@ -171,8 +171,7 @@
uuid16 = uuid.value.uuid16;
if (!server_is_enabled(&device->src, uuid16)) {
- DBG("audio handle_uuid: server not enabled for %s (0x%04x)",
- uuidstr, uuid16);
+ DBG("server not enabled for %s (0x%04x)", uuidstr, uuid16);
return;
}
@@ -351,12 +350,18 @@
sdp_data_t *channel, *features;
uint8_t netid = 0x01;
uint16_t sdpfeat;
- sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
+ sdp_data_t *network;
record = sdp_record_alloc();
if (!record)
return NULL;
+ network = sdp_data_alloc(SDP_UINT8, &netid);
+ if (!network) {
+ sdp_record_free(record);
+ return NULL;
+ }
+
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
root = sdp_list_append(0, &root_uuid);
sdp_set_browse_groups(record, root);
@@ -770,7 +775,7 @@
audio_dev = manager_get_device(&src, &dst, TRUE);
if (!audio_dev) {
- DBG("audio_probe: unable to get a device object");
+ DBG("unable to get a device object");
return -1;
}
@@ -800,7 +805,7 @@
{
adp->ref++;
- DBG("audio_adapter_ref(%p): ref=%d", adp, adp->ref);
+ DBG("%p: ref=%d", adp, adp->ref);
return adp;
}
@@ -809,7 +814,7 @@
{
adp->ref--;
- DBG("audio_adapter_unref(%p): ref=%d", adp, adp->ref);
+ DBG("%p: ref=%d", adp, adp->ref);
if (adp->ref > 0)
return;
--- audio/pcm_bluetooth.c
+++ audio/pcm_bluetooth.c
@@ -1007,7 +1007,7 @@
snd_pcm_sframes_t ret = 0;
unsigned int bytes_left;
int frame_size, encoded;
- size_t written;
+ ssize_t written;
uint8_t *buff;
DBG("areas->step=%u areas->first=%u offset=%lu size=%lu",
--- audio/telephony-maemo6.c
+++ audio/telephony-maemo6.c
@@ -134,11 +134,14 @@
static struct {
char *operator_name;
uint8_t status;
- int32_t signals_bar;
+ int32_t signal_bars;
} net = {
.operator_name = NULL,
.status = NETWORK_REG_STATUS_UNKOWN,
- .signals_bar = 0,
+ /* Init as 0 meaning inactive mode. In modem power off state
+ * can be be -1, but we treat all values as 0s regardless
+ * inactive or power off. */
+ .signal_bars = 0,
};
static int get_property(const char *iface, const char *prop);
@@ -181,6 +184,7 @@
static struct indicator maemo_indicators[] =
{
{ "battchg", "0-5", 5, TRUE },
+ /* signal strength in terms of bars */
{ "signal", "0-5", 0, TRUE },
{ "service", "0,1", 0, TRUE },
{ "call", "0,1", 0, TRUE },
@@ -1227,43 +1231,39 @@
update_registration_status(status);
}
-static void update_signal_strength(int32_t signals_bar)
+static void update_signal_strength(int32_t signal_bars)
{
- int signal;
-
- if (signals_bar < 0)
- signals_bar = 0;
- else if (signals_bar > 100) {
- DBG("signals_bar greater than expected: %u", signals_bar);
- signals_bar = 100;
+ if (signal_bars < 0) {
+ DBG("signal strength smaller than expected: %d < 0",
+ signal_bars);
+ signal_bars = 0;
+ } else if (signal_bars > 5) {
+ DBG("signal strength greater than expected: %d > 5",
+ signal_bars);
+ signal_bars = 5;
}
- if (net.signals_bar == signals_bar)
+ if (net.signal_bars == signal_bars)
return;
- /* A simple conversion from 0-100 to 0-5 (used by HFP) */
- signal = (signals_bar + 20) / 21;
-
- telephony_update_indicator(maemo_indicators, "signal", signal);
+ telephony_update_indicator(maemo_indicators, "signal", signal_bars);
- net.signals_bar = signals_bar;
-
- DBG("telephony-maemo6: signal strength updated: %u/100, %d/5", signals_bar, signal);
+ net.signal_bars = signal_bars;
+ DBG("telephony-maemo6: signal strength updated: %d/5", signal_bars);
}
-static void handle_signal_strength_changed(DBusMessage *msg)
+static void handle_signal_bars_changed(DBusMessage *msg)
{
- int32_t signals_bar, rssi_in_dbm;
+ int32_t signal_bars;
if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &signals_bar,
- DBUS_TYPE_INT32, &rssi_in_dbm,
+ DBUS_TYPE_INT32, &signal_bars,
DBUS_TYPE_INVALID)) {
- error("Unexpected parameters in SignalStrengthChanged");
+ error("Unexpected parameters in SignalBarsChanged");
return;
}
- update_signal_strength(signals_bar);
+ update_signal_strength(signal_bars);
}
static gboolean iter_get_basic_args(DBusMessageIter *iter,
@@ -1311,9 +1311,12 @@
goto done;
}
- dbus_message_get_args(reply, NULL,
+ if (!dbus_message_get_args(reply, NULL,
DBUS_TYPE_INT32, &level,
- DBUS_TYPE_INVALID);
+ DBUS_TYPE_INVALID)) {
+ error("Unexpected args in hald reply");
+ goto done;
+ }
*value = (int) level;
@@ -1527,7 +1530,7 @@
dbus_message_iter_get_basic(&sub, &name);
update_operator_name(name);
} else if (g_strcmp0(prop, "SignalBars") == 0) {
- uint32_t signal_bars;
+ int32_t signal_bars;
dbus_message_iter_get_basic(&sub, &signal_bars);
update_signal_strength(signal_bars);
@@ -1828,9 +1831,19 @@
return invalid_args(msg);
}
+static DBusMessage *clear_lastnumber(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ g_free(last_dialed_number);
+ last_dialed_number = NULL;
+
+ return dbus_message_new_method_return(msg);
+}
+
static GDBusMethodTable telephony_maemo_methods[] = {
- {"SetCallerId", "s", "", set_callerid,
- G_DBUS_METHOD_FLAG_ASYNC},
+ { "SetCallerId", "s", "", set_callerid,
+ G_DBUS_METHOD_FLAG_ASYNC },
+ { "ClearLastNumber", "", "", clear_lastnumber },
{ }
};
@@ -1896,8 +1909,8 @@
"OperatorNameChanged"))
handle_operator_name_changed(msg);
else if (dbus_message_is_signal(msg, CSD_CSNET_SIGNAL,
- "SignalStrengthChanged"))
- handle_signal_strength_changed(msg);
+ "SignalBarsChanged"))
+ handle_signal_bars_changed(msg);
else if (dbus_message_is_signal(msg, "org.freedesktop.Hal.Device",
"PropertyModified"))
handle_hal_property_modified(msg);
@@ -1978,6 +1991,12 @@
void telephony_exit(void)
{
+ g_free(net.operator_name);
+ net.operator_name = NULL;
+
+ g_free(last_dialed_number);
+ last_dialed_number = NULL;
+
g_slist_foreach(calls, (GFunc) csd_call_free, NULL);
g_slist_free(calls);
calls = NULL;
--- audio/telephony-ofono.c
+++ audio/telephony-ofono.c
@@ -598,8 +598,11 @@
dbus_message_iter_get_basic(&sub, &modem_obj_path_local);
modem_obj_path = g_strdup(modem_obj_path_local);
- DBG("modem_obj_path is %p, %s\n", modem_obj_path,
- modem_obj_path);
+ if (modem_obj_path != NULL) {
+ DBG("modem_obj_path is %p, %s\n", modem_obj_path,
+ modem_obj_path);
+ break;
+ }
dbus_message_iter_next(&sub);
}
--- configure
+++ configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.63 for bluez 4.66.
+# Generated by GNU Autoconf 2.63 for bluez 4.69.
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
@@ -743,8 +743,8 @@
# Identity of this package.
PACKAGE_NAME='bluez'
PACKAGE_TARNAME='bluez'
-PACKAGE_VERSION='4.66'
-PACKAGE_STRING='bluez 4.66'
+PACKAGE_VERSION='4.69'
+PACKAGE_STRING='bluez 4.69'
PACKAGE_BUGREPORT=''
ac_default_prefix=/usr/local
@@ -794,6 +794,8 @@
NETLINK_CFLAGS
CAPNG_LIBS
CAPNG_CFLAGS
+MAEMO6PLUGIN_FALSE
+MAEMO6PLUGIN_TRUE
CONFIGFILES_FALSE
CONFIGFILES_TRUE
UDEVRULES_FALSE
@@ -1015,6 +1017,7 @@
enable_configfiles
enable_debug
with_telephony
+enable_maemo6
enable_capng
enable_netlink
'
@@ -1598,7 +1601,7 @@
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures bluez 4.66 to adapt to many kinds of systems.
+\`configure' configures bluez 4.69 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1668,7 +1671,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of bluez 4.66:";;
+ short | recursive ) echo "Configuration of bluez 4.69:";;
esac
cat <<\_ACEOF
@@ -1713,6 +1716,7 @@
--enable-udevrules install Bluetooth udev rules
--enable-configfiles install Bluetooth configuration files
--enable-debug enable compiling with debugging information
+ --enable-maemo6 compile with maemo6 plugin
--enable-capng enable capabilities support
--enable-netlink enable netlink support
@@ -1828,7 +1832,7 @@
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-bluez configure 4.66
+bluez configure 4.69
generated by GNU Autoconf 2.63
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1842,7 +1846,7 @@
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by bluez $as_me 4.66, which was
+It was created by bluez $as_me 4.69, which was
generated by GNU Autoconf 2.63. Invocation command line was
$ $0 $@
@@ -2692,7 +2696,7 @@
# Define the identity of the package.
PACKAGE='bluez'
- VERSION='4.66'
+ VERSION='4.69'
cat >>confdefs.h <<_ACEOF
@@ -5350,13 +5354,13 @@
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:5353: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:5357: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:5356: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:5360: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:5359: output\"" >&5)
+ (eval echo "\"\$as_me:5363: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -6561,7 +6565,7 @@
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 6564 "configure"' > conftest.$ac_ext
+ echo '#line 6568 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -8384,11 +8388,11 @@
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8387: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8391: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:8391: \$? = $ac_status" >&5
+ echo "$as_me:8395: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -8723,11 +8727,11 @@
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8726: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8730: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:8730: \$? = $ac_status" >&5
+ echo "$as_me:8734: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -8828,11 +8832,11 @@
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8831: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8835: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:8835: \$? = $ac_status" >&5
+ echo "$as_me:8839: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -8883,11 +8887,11 @@
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8886: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8890: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:8890: \$? = $ac_status" >&5
+ echo "$as_me:8894: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -11686,7 +11690,7 @@
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11689 "configure"
+#line 11693 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11782,7 +11786,7 @@
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11785 "configure"
+#line 11789 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -13020,6 +13024,7 @@
udevrules_enable=yes
configfiles_enable=yes
telephony_driver=dummy
+ maemo6_enable=no
# Check whether --enable-optimization was given.
if test "${enable_optimization+set}" = set; then
@@ -13241,6 +13246,14 @@
TELEPHONY_DRIVER=telephony-${telephony_driver}.c
+ # Check whether --enable-maemo6 was given.
+if test "${enable_maemo6+set}" = set; then
+ enableval=$enable_maemo6;
+ maemo6_enable=${enableval}
+
+fi
+
+
if (test "${fortify_enable}" = "yes"); then
CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2"
fi
@@ -13467,6 +13480,14 @@
CONFIGFILES_FALSE=
fi
+ if test "${maemo6_enable}" = "yes"; then
+ MAEMO6PLUGIN_TRUE=
+ MAEMO6PLUGIN_FALSE='#'
+else
+ MAEMO6PLUGIN_TRUE='#'
+ MAEMO6PLUGIN_FALSE=
+fi
+
# Check whether --enable-capng was given.
@@ -13947,6 +13968,13 @@
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
+if test -z "${MAEMO6PLUGIN_TRUE}" && test -z "${MAEMO6PLUGIN_FALSE}"; then
+ { { $as_echo "$as_me:$LINENO: error: conditional \"MAEMO6PLUGIN\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"MAEMO6PLUGIN\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
if test -z "${NETLINK_TRUE}" && test -z "${NETLINK_FALSE}"; then
{ { $as_echo "$as_me:$LINENO: error: conditional \"NETLINK\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
@@ -14276,7 +14304,7 @@
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by bluez $as_me 4.66, which was
+This file was extended by bluez $as_me 4.69, which was
generated by GNU Autoconf 2.63. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14339,7 +14367,7 @@
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
-bluez config.status 4.66
+bluez config.status 4.69
configured by $0, generated by GNU Autoconf 2.63,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
--- configure.ac
+++ configure.ac
@@ -1,5 +1,5 @@
AC_PREREQ(2.60)
-AC_INIT(bluez, 4.66)
+AC_INIT(bluez, 4.69)
AM_INIT_AUTOMAKE([foreign subdir-objects])
AM_CONFIG_HEADER(config.h)
--- doc/attribute-api.txt
+++ doc/attribute-api.txt
+BlueZ D-Bus Attribute API description
+*************************************
+
+Copyright (C) 2004-2010 Marcel Holtmann <marcel at holtmann.org>
+
+
+Attribute hierarchy
+===================
+
+Service org.bluez
+Interface org.bluez.Service
+ org.bluez.Characteristic
+Object path [prefix]/{hci0}/{service0}
+ [prefix]/{hci0}/{device0}/{service0}/{characteristic0,...}
+ [prefix]/{hci0}/{device0}/{service1}/{characteristic0,...}
+
+Service details
+---------------
+
+One service object path for every remote SDP record or service in the
+attribute database. One service object path for every local SDP record
+or service from attribute database.
+
+Local services are children of the adapter object path. Remote services
+are children of the remote device object path. This doesn't solve the
+problem where local atttributes can have different instances based on
+the remote device.
+
+In general the idea is to also represent SDP records as services so that
+new style application can just use the service interfaces to retrieve the
+needed information. That way the usage of SDP and GATT would be mostly
+fully transparent and a differentiation becomes unimportant in the future.
+
+A service consists of some generic service information and a set of
+characteristics. All characteristic are presented as object path as well.
+
+Properties
+----------
+ string Name (mandatory)
+
+ General name of service
+
+ string Description (optional)
+
+ Description of service
+
+ string UUID (mandatory)
+
+ UUID of service. Service class value for SDP and GATT UUID
+ for attribute based services.
+
+ array{object} Characteristics
+
+ This list contains the characteristics owned by this specific
+ service and other characteristics from service includes. That
+ way no complicated service includes array is needed.
+
+ string UUID
+ string Name
+ string Description
+ struct Format (type, name, exponet etc.)
+
+ array{byte} Value
+ string Representation (of the binary Value)
+
+ object Service (the original service in case of includes)
+
+ At this point only GetProperties() method call should be
+ supported for simplicity. Changing characteristics is up
+ to future support.
+
+ The object path of the characteristics might be split
+ over multiple service objects, because of includes.
+
+ array[(object, dict)] GetCharacteristics()
+
+ Array of tuples with object path as identifier. An alternativ
+ is doing dict of dict since the object path is unique and the
+ order of characteristics is irrelevant. However it might be
+ good to actually present an order here.
+
+ See Characteristics properties for dictionary details.
+
+ RegisterCharacteristicsWatcher(object path)
+
+ Register a watcher for changes in specific characteristics
+ to monitor changes.
+
+ A watcher will be registered for this service and will
+ notifier about any changed characteristics in the service.
+ This also notifies about any included characteristics.
+
+ Method for the watch objects still need to be defined.
+
+ UnregisterCharacteristicsWatcher(object path)
+
+ Unregister a watcher.
--- doc/network-api.txt
+++ doc/network-api.txt
@@ -60,35 +60,29 @@
Indicates the connection role when available.
-Network Hub/Peer/Router hierarchy
-=================
+Network server hierarchy
+========================
Service org.bluez
-Interface org.bluez.network.{Hub, Peer, Router}
+Interface org.bluez.NetworkServer
Object path /org/bluez/{hci0,hci1,...}
-Methods dict GetProperties()
+Methods void Register(string uuid, string bridge)
- Returns all properties for the GN/PANU/NAP server. See the
- properties section for available properties.
+ Register server for the provided UUID. Every new
+ connection to this server will be added the bridge
+ interface.
- void SetProperty(string name, variant value)
+ Valid UUIDs are "gn", "panu" or "nap".
- Changes the value of the specified property. Only
- properties that are listed a read-write are changeable.
- On success this will emit a PropertyChanged signal.
+ Initially no network server SDP is provided. Only
+ after this method a SDP record will be available
+ and the BNEP server will be ready for incoming
+ connections.
- Possible Errors: org.bluez.Error.DoesNotExist
- org.bluez.Error.InvalidArguments
+ void Unregister(string uuid)
-Properties string Name[readwrite]
+ Unregister the server for provided UUID.
- The Bluetooth network server name.
-
- boolean Enable[readwrite]
-
- Indicates if the server is Enabled/Disabled.
-
- string Uuid[readonly]
-
- The Bluetooth network server UUID 128 identification.
+ All servers will be automatically unregistered when
+ the calling application terminates.
--- lib/bluetooth.c
+++ lib/bluetooth.c
@@ -474,6 +474,12 @@
return "Belkin International, Inc.";
case 93:
return "Realtek Semiconductor Corporation";
+ case 94:
+ return "Stonestreet One, LLC";
+ case 95:
+ return "Wicentric, Inc.";
+ case 96:
+ return "RivieraWaves S.A.S";
case 65535:
return "internal use";
default:
--- lib/hci.c
+++ lib/hci.c
@@ -1093,6 +1093,7 @@
hci_filter_set_ptype(HCI_EVENT_PKT, &nf);
hci_filter_set_event(EVT_CMD_STATUS, &nf);
hci_filter_set_event(EVT_CMD_COMPLETE, &nf);
+ hci_filter_set_event(EVT_LE_META_EVENT, &nf);
hci_filter_set_event(r->event, &nf);
hci_filter_set_opcode(opcode, &nf);
if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0)
@@ -1106,6 +1107,7 @@
evt_cmd_complete *cc;
evt_cmd_status *cs;
evt_remote_name_req_complete *rn;
+ evt_le_meta_event *me;
remote_name_req_cp *cp;
int len;
@@ -1186,6 +1188,17 @@
memcpy(r->rparam, ptr, r->rlen);
goto done;
+ case EVT_LE_META_EVENT:
+ me = (void *) ptr;
+
+ if (me->subevent != r->event)
+ continue;
+
+ len -= 1;
+ r->rlen = MIN(len, r->rlen);
+ memcpy(r->rparam, me->data, r->rlen);
+ goto done;
+
default:
if (hdr->evt != r->event)
break;
@@ -2591,3 +2604,143 @@
*accuracy = rp.accuracy;
return 0;
}
+
+int hci_le_set_scan_enable(int dd, uint8_t enable, uint8_t filter_dup)
+{
+ struct hci_request rq;
+ le_set_scan_enable_cp scan_cp;
+ uint8_t status;
+
+ memset(&scan_cp, 0, sizeof(scan_cp));
+ scan_cp.enable = enable;
+ scan_cp.filter_dup = filter_dup;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_SET_SCAN_ENABLE;
+ rq.cparam = &scan_cp;
+ rq.clen = LE_SET_SCAN_ENABLE_CP_SIZE;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ if (hci_send_req(dd, &rq, 100) < 0)
+ return -1;
+
+ if (status) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+int hci_le_set_scan_parameters(int dd, uint8_t type,
+ uint16_t interval, uint16_t window,
+ uint8_t own_type, uint8_t filter)
+{
+ struct hci_request rq;
+ le_set_scan_parameters_cp param_cp;
+ uint8_t status;
+
+ memset(¶m_cp, 0, sizeof(param_cp));
+ param_cp.type = type;
+ param_cp.interval = interval;
+ param_cp.window = window;
+ param_cp.own_bdaddr_type = own_type;
+ param_cp.filter = filter;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_SET_SCAN_PARAMETERS;
+ rq.cparam = ¶m_cp;
+ rq.clen = LE_SET_SCAN_PARAMETERS_CP_SIZE;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ if (hci_send_req(dd, &rq, 100) < 0)
+ return -1;
+
+ if (status) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+int hci_le_set_advertise_enable(int dd, uint8_t enable)
+{
+ struct hci_request rq;
+ le_set_advertise_enable_cp adv_cp;
+ uint8_t status;
+
+ memset(&adv_cp, 0, sizeof(adv_cp));
+ adv_cp.enable = enable;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE;
+ rq.cparam = &adv_cp;
+ rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ if (hci_send_req(dd, &rq, 100) < 0)
+ return -1;
+
+ if (status) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+int hci_le_create_conn(int dd, uint16_t interval, uint16_t window,
+ uint8_t initiator_filter, uint8_t peer_bdaddr_type,
+ bdaddr_t peer_bdaddr, uint8_t own_bdaddr_type,
+ uint16_t min_interval, uint16_t max_interval,
+ uint16_t latency, uint16_t supervision_timeout,
+ uint16_t min_ce_length, uint16_t max_ce_length,
+ uint16_t *handle, int to)
+{
+ struct hci_request rq;
+ le_create_connection_cp create_conn_cp;
+ evt_le_connection_complete conn_complete_rp;
+
+ memset(&create_conn_cp, 0, sizeof(create_conn_cp));
+ create_conn_cp.interval = interval;
+ create_conn_cp.window = window;
+ create_conn_cp.initiator_filter = initiator_filter;
+ create_conn_cp.peer_bdaddr_type = peer_bdaddr_type;
+ create_conn_cp.peer_bdaddr = peer_bdaddr;
+ create_conn_cp.own_bdaddr_type = own_bdaddr_type;
+ create_conn_cp.min_interval = min_interval;
+ create_conn_cp.max_interval = max_interval;
+ create_conn_cp.latency = latency;
+ create_conn_cp.supervision_timeout = supervision_timeout;
+ create_conn_cp.min_ce_length = min_ce_length;
+ create_conn_cp.max_ce_length = max_ce_length;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_CREATE_CONN;
+ rq.event = EVT_LE_CONN_COMPLETE;
+ rq.cparam = &create_conn_cp;
+ rq.clen = LE_CREATE_CONN_CP_SIZE;
+ rq.rparam = &conn_complete_rp;
+ rq.rlen = EVT_CONN_COMPLETE_SIZE;
+
+ if (hci_send_req(dd, &rq, to) < 0)
+ return -1;
+
+ if (conn_complete_rp.status) {
+ errno = EIO;
+ return -1;
+ }
+
+ if (handle)
+ *handle = conn_complete_rp.handle;
+
+ return 0;
+}
--- lib/hci.h
+++ lib/hci.h
@@ -1259,6 +1259,250 @@
} __attribute__ ((packed)) write_simple_pairing_debug_mode_rp;
#define WRITE_SIMPLE_PAIRING_DEBUG_MODE_RP_SIZE 1
+/* LE commands */
+#define OGF_LE_CTL 0x08
+
+#define OCF_LE_SET_EVENT_MASK 0x0001
+typedef struct {
+ uint8_t mask[8];
+} __attribute__ ((packed)) le_set_event_mask_cp;
+#define LE_SET_EVENT_MASK_CP_SIZE 8
+
+#define OCF_LE_READ_BUFFER_SIZE 0x0002
+typedef struct {
+ uint8_t status;
+ uint16_t pkt_len;
+ uint8_t max_pkt;
+} __attribute__ ((packed)) le_read_buffer_size_rp;
+#define LE_READ_BUFFER_SIZE_RP_SIZE 4
+
+#define OCF_LE_READ_LOCAL_SUPPORTED_FEATURES 0x0003
+typedef struct {
+ uint8_t status;
+ uint8_t features[8];
+} __attribute__ ((packed)) le_read_local_supported_features_rp;
+#define LE_READ_LOCAL_SUPPORTED_FEATURES_RP_SIZE 9
+
+#define OCF_LE_SET_RANDOM_ADDRESS 0x0005
+typedef struct {
+ bdaddr_t bdaddr;
+} __attribute__ ((packed)) le_set_random_address_cp;
+#define LE_SET_RANDOM_ADDRESS_CP_SIZE 6
+
+#define OCF_LE_SET_ADVERTISING_PARAMETERS 0x0006
+typedef struct {
+ uint16_t min_interval;
+ uint16_t max_interval;
+ uint8_t advtype;
+ uint8_t own_bdaddr_type;
+ uint8_t direct_bdaddr_type;
+ bdaddr_t direct_bdaddr;
+ uint8_t chan_map;
+ uint8_t filter;
+} __attribute__ ((packed)) le_set_advertising_parameters_cp;
+#define LE_SET_ADVERTISING_PARAMETERS_CP_SIZE 15
+
+#define OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER 0x0007
+typedef struct {
+ uint8_t status;
+ uint8_t level;
+} __attribute__ ((packed)) le_read_advertising_channel_tx_power_rp;
+#define LE_READ_ADVERTISING_CHANNEL_TX_POWER_RP_SIZE 2
+
+#define OCF_LE_SET_ADVERTISING_DATA 0x0008
+typedef struct {
+ uint8_t length;
+ uint8_t data[31];
+} __attribute__ ((packed)) le_set_advertising_data_cp;
+#define LE_SET_ADVERTISING_DATA_CP_SIZE 32
+
+#define OCF_LE_SET_SCAN_RESPONSE_DATA 0x0009
+typedef struct {
+ uint8_t length;
+ uint8_t data[31];
+} __attribute__ ((packed)) le_set_scan_response_data_cp;
+#define LE_SET_SCAN_RESPONSE_DATA_CP_SIZE 32
+
+#define OCF_LE_SET_ADVERTISE_ENABLE 0x000A
+typedef struct {
+ uint8_t enable;
+} __attribute__ ((packed)) le_set_advertise_enable_cp;
+#define LE_SET_ADVERTISE_ENABLE_CP_SIZE 1
+
+#define OCF_LE_SET_SCAN_PARAMETERS 0x000B
+typedef struct {
+ uint8_t type;
+ uint16_t interval;
+ uint16_t window;
+ uint8_t own_bdaddr_type;
+ uint8_t filter;
+} __attribute__ ((packed)) le_set_scan_parameters_cp;
+#define LE_SET_SCAN_PARAMETERS_CP_SIZE 7
+
+#define OCF_LE_SET_SCAN_ENABLE 0x000C
+typedef struct {
+ uint8_t enable;
+ uint8_t filter_dup;
+} __attribute__ ((packed)) le_set_scan_enable_cp;
+#define LE_SET_SCAN_ENABLE_CP_SIZE 2
+
+#define OCF_LE_CREATE_CONN 0x000D
+typedef struct {
+ uint16_t interval;
+ uint16_t window;
+ uint8_t initiator_filter;
+ uint8_t peer_bdaddr_type;
+ bdaddr_t peer_bdaddr;
+ uint8_t own_bdaddr_type;
+ uint16_t min_interval;
+ uint16_t max_interval;
+ uint16_t latency;
+ uint16_t supervision_timeout;
+ uint16_t min_ce_length;
+ uint16_t max_ce_length;
+} __attribute__ ((packed)) le_create_connection_cp;
+#define LE_CREATE_CONN_CP_SIZE 25
+
+#define OCF_LE_CREATE_CONN_CANCEL 0x000E
+
+#define OCF_LE_READ_WHITE_LIST_SIZE 0x000F
+typedef struct {
+ uint8_t status;
+ uint8_t size;
+} __attribute__ ((packed)) le_read_white_list_size_rp;
+#define LE_READ_WHITE_LIST_SIZE_RP_SIZE 2
+
+#define OCF_LE_CLEAR_WHITE_LIST 0x0010
+
+#define OCF_LE_ADD_DEVICE_TO_WHITE_LIST 0x0011
+typedef struct {
+ uint8_t bdaddr_type;
+ bdaddr_t bdaddr;
+} __attribute__ ((packed)) le_add_device_to_white_list_cp;
+#define LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE 7
+
+#define OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST 0x0012
+typedef struct {
+ uint8_t bdaddr_type;
+ bdaddr_t bdaddr;
+} __attribute__ ((packed)) le_remove_device_from_white_list_cp;
+#define LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE 7
+
+#define OCF_LE_CONN_UPDATE 0x0013
+typedef struct {
+ uint16_t handle;
+ uint16_t min_interval;
+ uint16_t max_interval;
+ uint16_t latency;
+ uint16_t supervision_timeout;
+ uint16_t min_ce_length;
+ uint16_t max_ce_length;
+} __attribute__ ((packed)) le_connection_update_cp;
+#define LE_CONN_UPDATE_CP_SIZE 14
+
+#define OCF_LE_SET_HOST_CHANNEL_CLASSIFICATION 0x0014
+typedef struct {
+ uint8_t map[5];
+} __attribute__ ((packed)) le_set_host_channel_classification_cp;
+#define LE_SET_HOST_CHANNEL_CLASSIFICATION_CP_SIZE 5
+
+#define OCF_LE_READ_CHANNEL_MAP 0x0015
+typedef struct {
+ uint16_t handle;
+} __attribute__ ((packed)) le_read_channel_map_cp;
+#define LE_READ_CHANNEL_MAP_CP_SIZE 2
+typedef struct {
+ uint8_t status;
+ uint16_t handle;
+ uint8_t map[5];
+} __attribute__ ((packed)) le_read_channel_map_rp;
+#define LE_READ_CHANNEL_MAP_RP_SIZE 8
+
+#define OCF_LE_READ_REMOTE_USED_FEATURES 0x0016
+typedef struct {
+ uint16_t handle;
+} __attribute__ ((packed)) le_read_remote_used_features_cp;
+#define LE_READ_REMOTE_USED_FEATURES_CP_SIZE 2
+
+#define OCF_LE_ENCRYPT 0x0017
+typedef struct {
+ uint8_t key[16];
+ uint8_t plaintext[16];
+} __attribute__ ((packed)) le_encrypt_cp;
+#define LE_ENCRYPT_CP_SIZE 32
+typedef struct {
+ uint8_t status;
+ uint8_t data[16];
+} __attribute__ ((packed)) le_encrypt_rp;
+#define LE_ENCRYPT_RP_SIZE 17
+
+#define OCF_LE_RAND 0x0018
+typedef struct {
+ uint8_t status;
+ uint64_t random;
+} __attribute__ ((packed)) le_rand_rp;
+#define LE_RAND_RP_SIZE 9
+
+#define OCF_LE_START_ENCRYPTION 0x0019
+typedef struct {
+ uint16_t handle;
+ uint64_t random;
+ uint16_t diversifier;
+ uint8_t key[16];
+} __attribute__ ((packed)) le_start_encryption_cp;
+#define LE_START_ENCRYPTION_CP_SIZE 28
+
+#define OCF_LE_LTK_REPLY 0x001A
+typedef struct {
+ uint16_t handle;
+ uint8_t key[16];
+} __attribute__ ((packed)) le_ltk_reply_cp;
+#define LE_LTK_REPLY_CP_SIZE 18
+typedef struct {
+ uint8_t status;
+ uint16_t handle;
+} __attribute__ ((packed)) le_ltk_reply_rp;
+#define LE_LTK_REPLY_RP_SIZE 3
+
+#define OCF_LE_LTK_NEG_REPLY 0x001B
+typedef struct {
+ uint16_t handle;
+} __attribute__ ((packed)) le_ltk_neg_reply_cp;
+#define LE_LTK_NEG_REPLY_CP_SIZE 2
+typedef struct {
+ uint8_t status;
+ uint16_t handle;
+} __attribute__ ((packed)) le_ltk_neg_reply_rp;
+#define LE_LTK_NEG_REPLY_RP_SIZE 3
+
+#define OCF_LE_READ_SUPPORTED_STATES 0x001C
+typedef struct {
+ uint8_t status;
+ uint64_t states;
+} __attribute__ ((packed)) le_read_supported_states_rp;
+#define LE_READ_SUPPORTED_STATES_RP_SIZE 9
+
+#define OCF_LE_RECEIVER_TEST 0x001D
+typedef struct {
+ uint8_t frequency;
+} __attribute__ ((packed)) le_receiver_test_cp;
+#define LE_RECEIVER_TEST_CP_SIZE 1
+
+#define OCF_LE_TRANSMITTER_TEST 0x001E
+typedef struct {
+ uint8_t frequency;
+ uint8_t length;
+ uint8_t payload;
+} __attribute__ ((packed)) le_transmitter_test_cp;
+#define LE_TRANSMITTER_TEST_CP_SIZE 3
+
+#define OCF_LE_TEST_END 0x001F
+typedef struct {
+ uint8_t status;
+ uint16_t num_pkts;
+} __attribute__ ((packed)) le_test_end_rp;
+#define LE_TEST_END_RP_SIZE 3
+
/* Vendor specific commands */
#define OGF_VENDOR_CMD 0x3f
@@ -1661,6 +1905,64 @@
} __attribute__ ((packed)) evt_remote_host_features_notify;
#define EVT_REMOTE_HOST_FEATURES_NOTIFY_SIZE 14
+#define EVT_LE_META_EVENT 0x3E
+typedef struct {
+ uint8_t subevent;
+ uint8_t data[0];
+} __attribute__ ((packed)) evt_le_meta_event;
+#define EVT_LE_META_EVENT_SIZE 1
+
+#define EVT_LE_CONN_COMPLETE 0x01
+typedef struct {
+ uint8_t status;
+ uint16_t handle;
+ uint8_t role;
+ uint8_t peer_bdaddr_type;
+ bdaddr_t peer_bdaddr;
+ uint16_t interval;
+ uint16_t latency;
+ uint16_t supervision_timeout;
+ uint8_t master_clock_accuracy;
+} __attribute__ ((packed)) evt_le_connection_complete;
+#define EVT_LE_CONN_COMPLETE_SIZE 18
+
+#define EVT_LE_ADVERTISING_REPORT 0x02
+typedef struct {
+ uint8_t evt_type;
+ uint8_t bdaddr_type;
+ bdaddr_t bdaddr;
+ uint8_t length;
+ uint8_t data[31];
+ uint8_t rssi;
+} __attribute__ ((packed)) le_advertising_info;
+#define LE_ADVERTISING_INFO_SIZE 41
+
+#define EVT_LE_CONN_UPDATE_COMPLETE 0x03
+typedef struct {
+ uint8_t status;
+ uint16_t handle;
+ uint16_t interval;
+ uint16_t latency;
+ uint16_t supervision_timeout;
+} __attribute__ ((packed)) evt_le_connection_update_complete;
+#define EVT_LE_CONN_UPDATE_COMPLETE_SIZE 9
+
+#define EVT_LE_READ_REMOTE_USED_FEATURES_COMPLETE 0x04
+typedef struct {
+ uint8_t status;
+ uint16_t handle;
+ uint8_t features[8];
+} __attribute__ ((packed)) evt_le_read_remote_used_features_complete;
+#define EVT_LE_READ_REMOTE_USED_FEATURES_COMPLETE_SIZE 11
+
+#define EVT_LE_LTK_REQUEST 0x05
+typedef struct {
+ uint16_t handle;
+ uint64_t random;
+ uint16_t diversifier;
+} __attribute__ ((packed)) evt_le_long_term_key_request;
+#define EVT_LE_LTK_REQUEST_SIZE 12
+
#define EVT_TESTING 0xFE
#define EVT_VENDOR 0xFF
--- lib/hci_lib.h
+++ lib/hci_lib.h
@@ -115,6 +115,19 @@
int hci_read_afh_map(int dd, uint16_t handle, uint8_t *mode, uint8_t *map, int to);
int hci_read_clock(int dd, uint16_t handle, uint8_t which, uint32_t *clock, uint16_t *accuracy, int to);
+int hci_le_set_scan_enable(int dev_id, uint8_t enable, uint8_t filter_dup);
+int hci_le_set_scan_parameters(int dev_id, uint8_t type, uint16_t interval,
+ uint16_t window, uint8_t own_type,
+ uint8_t filter);
+int hci_le_set_advertise_enable(int dev_id, uint8_t enable);
+int hci_le_create_conn(int dd, uint16_t interval, uint16_t window,
+ uint8_t initiator_filter, uint8_t peer_bdaddr_type,
+ bdaddr_t peer_bdaddr, uint8_t own_bdaddr_type,
+ uint16_t min_interval, uint16_t max_interval,
+ uint16_t latency, uint16_t supervision_timeout,
+ uint16_t min_ce_length, uint16_t max_ce_length,
+ uint16_t *handle, int to);
+
int hci_for_each_dev(int flag, int(*func)(int dd, int dev_id, long arg), long arg);
int hci_get_route(bdaddr_t *bdaddr);
--- lib/sdp.c
+++ lib/sdp.c
@@ -4769,13 +4769,32 @@
if (d->dtd < SDP_SEQ8 || d->dtd > SDP_SEQ32)
goto fail;
+
subseq = NULL;
+
for (dd = d->val.dataseq; dd; dd = dd->next) {
sdp_data_t *data;
- if (dd->dtd != SDP_UINT8 && dd->dtd != SDP_UINT16 &&
- dd->dtd != SDP_TEXT_STR8)
+ void *val;
+ int length;
+
+ switch (dd->dtd) {
+ case SDP_URL_STR8:
+ case SDP_URL_STR16:
+ case SDP_TEXT_STR8:
+ case SDP_TEXT_STR16:
+ val = dd->val.str;
+ length = dd->unitSize - sizeof(uint8_t);
+ break;
+ case SDP_UINT8:
+ case SDP_UINT16:
+ val = &dd->val;
+ length = 0;
+ break;
+ default:
goto fail;
- data = sdp_data_alloc(dd->dtd, &dd->val);
+ }
+
+ data = sdp_data_alloc_with_length(dd->dtd, val, length);
if (data)
subseq = sdp_list_append(subseq, data);
}
--- network/bridge.c
+++ network/bridge.c
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <marcel at holtmann.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <net/if.h>
-#include <linux/sockios.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/l2cap.h>
-#include <bluetooth/bnep.h>
-
-#include "log.h"
-#include "bridge.h"
-#include "common.h"
-
-static int bridge_socket = -1;
-static const char *gn_bridge = NULL;
-static const char *nap_bridge = NULL;
-
-int bridge_init(const char *gn_iface, const char *nap_iface)
-{
-#if 0
- struct stat st;
-
- if (stat("/sys/module/bridge", &st) < 0)
- return -EOPNOTSUPP;
-#endif
- bridge_socket = socket(AF_INET, SOCK_STREAM, 0);
- if (bridge_socket < 0) {
- error("Failed to open bridge socket: %s (%d)",
- strerror(errno), errno);
- return -errno;
- }
-
- gn_bridge = gn_iface;
- nap_bridge = nap_iface;
-
- return 0;
-}
-
-void bridge_cleanup(void)
-{
- close(bridge_socket);
-
- bridge_socket = -1;
-}
-
-int bridge_create(int id)
-{
- int err;
- const char *name = bridge_get_name(id);
-
- err = ioctl(bridge_socket, SIOCBRADDBR, name);
- if (err < 0)
- return -errno;
-
- info("bridge %s created", name);
-
- return 0;
-}
-
-int bridge_remove(int id)
-{
- int err;
- const char *name = bridge_get_name(id);
-
- err = bnep_if_down(name);
- if (err < 0)
- return err;
-
- err = ioctl(bridge_socket, SIOCBRDELBR, name);
- if (err < 0)
- return -errno;
-
- info("bridge %s removed", name);
-
- return 0;
-}
-
-int bridge_add_interface(int id, const char *dev)
-{
- struct ifreq ifr;
- int err;
- int ifindex = if_nametoindex(dev);
- const char *name = bridge_get_name(id);
-
- if (!name)
- return -EINVAL;
-
- if (ifindex == 0)
- return -ENODEV;
-
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, name, IFNAMSIZ - 1);
- ifr.ifr_ifindex = ifindex;
-
- err = ioctl(bridge_socket, SIOCBRADDIF, &ifr);
- if (err < 0)
- return err;
-
- info("bridge %s: interface %s added", name, dev);
-
- err = bnep_if_up(name, id);
- if (err < 0)
- return err;
-
- return 0;
-}
-
-const char *bridge_get_name(int id)
-{
- if (id == BNEP_SVC_GN)
- return gn_bridge;
-
- if (id == BNEP_SVC_NAP)
- return nap_bridge;
-
- return NULL;
-}
--- network/bridge.h
+++ network/bridge.h
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <marcel at holtmann.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int bridge_init(const char *gn_iface, const char *nap_iface);
-void bridge_cleanup(void);
-
-int bridge_create(int id);
-int bridge_remove(int id);
-int bridge_add_interface(int id, const char *dev);
-const char *bridge_get_name(int id);
--- network/common.c
+++ network/common.c
@@ -34,6 +34,7 @@
#include <sys/socket.h>
#include <sys/wait.h>
#include <net/if.h>
+#include <linux/sockios.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
@@ -45,7 +46,6 @@
#include "common.h"
static int ctl;
-static GSList *pids;
static struct {
const char *name; /* Friendly name */
@@ -58,34 +58,6 @@
{ NULL }
};
-static const char *panu = NULL;
-static const char *gn = NULL;
-static const char *nap = NULL;
-
-struct bnep_data {
- char *devname;
- char *script;
- int pid;
-};
-
-static gint find_devname(gconstpointer a, gconstpointer b)
-{
- struct bnep_data *data = (struct bnep_data *) a;
- const char *devname = b;
-
- return strcmp(data->devname, devname);
-}
-
-static void script_exited(GPid pid, gint status, gpointer data)
-{
- if (WIFEXITED(status))
- DBG("%d exited with status %d", pid, WEXITSTATUS(status));
- else
- DBG("%d was killed by signal %d", pid, WTERMSIG(status));
-
- g_spawn_close_pid(pid);
-}
-
uint16_t bnep_service_id(const char *svc)
{
int i;
@@ -131,8 +103,7 @@
return NULL;
}
-int bnep_init(const char *panu_script, const char *gn_script,
- const char *nap_script)
+int bnep_init(void)
{
ctl = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP);
@@ -143,9 +114,6 @@
return -err;
}
- panu = panu_script;
- gn = gn_script;
- nap = nap_script;
return 0;
}
@@ -219,155 +187,76 @@
return 0;
}
-static void bnep_setup(gpointer data)
-{
-}
-
-static int bnep_exec(const char **argv)
+int bnep_if_up(const char *devname)
{
- int pid;
- GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH;
-
- if (!g_spawn_async(NULL, (char **) argv, NULL, flags, bnep_setup, NULL,
- &pid, NULL)) {
- error("Unable to execute %s %s", argv[0], argv[1]);
- return -EINVAL;
- }
-
- return pid;
-}
-
-int bnep_if_up(const char *devname, uint16_t id)
-{
- int sd, err;
struct ifreq ifr;
- const char *argv[5];
- struct bnep_data *bnep = NULL;
- GSList *l;
-
- /* Check if a script is running */
- l = g_slist_find_custom(pids, devname, find_devname);
- if (l) {
- bnep = l->data;
-
- if (bnep->script && !strcmp(bnep->script, "avahi-autoipd")) {
- argv[0] = bnep->script;
- argv[1] = devname;
- argv[2] = "--refresh";
- argv[3] = NULL;
+ int sk, err;
- bnep->pid = bnep_exec(argv);
- }
- }
+ sk = socket(AF_INET, SOCK_DGRAM, 0);
- sd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, devname, IF_NAMESIZE - 1);
ifr.ifr_flags |= IFF_UP;
ifr.ifr_flags |= IFF_MULTICAST;
- if ((ioctl(sd, SIOCSIFFLAGS, (caddr_t) &ifr)) < 0) {
- err = errno;
- error("Could not bring up %s. %s(%d)", devname, strerror(err),
- err);
- return -err;
- }
-
- if (bnep)
- return bnep->pid;
-
- bnep = g_new0(struct bnep_data, 1);
- bnep->devname = g_strdup(devname);
-
- if (!id)
- goto done;
-
- if (id == BNEP_SVC_PANU)
- bnep->script = g_strdup(panu);
- else if (id == BNEP_SVC_GN)
- bnep->script = g_strdup(gn);
- else
- bnep->script = g_strdup(nap);
-
- if (!bnep->script)
- goto done;
-
- argv[0] = bnep->script;
- argv[1] = devname;
-
- if (!strcmp(bnep->script, "avahi-autoipd")) {
- argv[2] = "--no-drop-root";
- argv[3] = "--no-chroot";
- argv[4] = NULL;
- } else
- argv[2] = NULL;
+ err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr);
- bnep->pid = bnep_exec(argv);
- g_child_watch_add(bnep->pid, script_exited, bnep);
+ close(sk);
-done:
- pids = g_slist_append(pids, bnep);
+ if (err < 0) {
+ error("Could not bring up %s", devname);
+ return err;
+ }
- return bnep->pid;
+ return 0;
}
int bnep_if_down(const char *devname)
{
- int sd, err, pid;
struct ifreq ifr;
- struct bnep_data *bnep;
- GSList *l;
- GSpawnFlags flags;
- const char *argv[4];
+ int sk, err;
- l = g_slist_find_custom(pids, devname, find_devname);
- if (!l)
- return 0;
+ sk = socket(AF_INET, SOCK_DGRAM, 0);
- bnep = l->data;
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, devname, IF_NAMESIZE - 1);
- if (!bnep->pid)
- goto done;
+ ifr.ifr_flags &= ~IFF_UP;
- if (bnep->script && !strcmp(bnep->script, "avahi-autoipd")) {
- argv[0] = bnep->script;
- argv[1] = devname;
- argv[2] = "--kill";
- argv[3] = NULL;
-
- flags = G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH;
- g_spawn_async(NULL, (char **) argv, NULL, flags, bnep_setup,
- (gpointer) devname, &pid, NULL);
+ /* Bring down the interface */
+ err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr);
- goto done;
- }
+ close(sk);
- /* Kill script */
- err = kill(bnep->pid, SIGTERM);
- if (err < 0)
- error("kill(%d, SIGTERM): %s (%d)", bnep->pid,
- strerror(errno), errno);
+ return 0;
+}
-done:
- sd = socket(AF_INET, SOCK_DGRAM, 0);
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, devname, IF_NAMESIZE - 1);
+int bnep_add_to_bridge(const char *devname, const char *bridge)
+{
+ int ifindex = if_nametoindex(devname);
+ struct ifreq ifr;
+ int sk, err;
- ifr.ifr_flags &= ~IFF_UP;
+ if (!devname || !bridge)
+ return -EINVAL;
- /* Bring down the interface */
- ioctl(sd, SIOCSIFFLAGS, (caddr_t) &ifr);
+ sk = socket(AF_INET, SOCK_STREAM, 0);
+ if (sk < 0)
+ return -1;
- pids = g_slist_remove(pids, bnep);
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
+ ifr.ifr_ifindex = ifindex;
+
+ err = ioctl(sk, SIOCBRADDIF, &ifr);
- if (bnep->devname)
- g_free(bnep->devname);
+ close(sk);
- if (bnep->script)
- g_free(bnep->script);
+ if (err < 0)
+ return err;
- g_free(bnep);
+ info("bridge %s: interface %s added", bridge, devname);
return 0;
}
--- network/common.h
+++ network/common.h
@@ -26,8 +26,7 @@
#define GN_UUID "00001117-0000-1000-8000-00805f9b34fb"
#define BNEP_SVC_UUID "0000000f-0000-1000-8000-00805f9b34fb"
-int bnep_init(const char *panu_script, const char *gn_script,
- const char *nap_script);
+int bnep_init(void);
int bnep_cleanup(void);
uint16_t bnep_service_id(const char *svc);
@@ -38,5 +37,6 @@
int bnep_kill_all_connections(void);
int bnep_connadd(int sk, uint16_t role, char *dev);
-int bnep_if_up(const char *devname, uint16_t id);
+int bnep_if_up(const char *devname);
int bnep_if_down(const char *devname);
+int bnep_add_to_bridge(const char *devname, const char *bridge);
--- network/connection.c
+++ network/connection.c
@@ -82,7 +82,6 @@
} __attribute__ ((packed));
static DBusConnection *connection = NULL;
-static const char *prefix = NULL;
static GSList *peers = NULL;
static struct network_peer *find_peer(GSList *list, const char *path)
@@ -174,8 +173,8 @@
bnep_if_down(nc->dev);
nc->state = DISCONNECTED;
- memset(nc->dev, 0, 16);
- strncpy(nc->dev, prefix, sizeof(nc->dev) - 1);
+ memset(nc->dev, 0, sizeof(nc->dev));
+ strcpy(nc->dev, "bnep%d");
return FALSE;
}
@@ -289,7 +288,7 @@
goto failed;
}
- bnep_if_up(nc->dev, nc->id);
+ bnep_if_up(nc->dev);
pdev = nc->dev;
uuid = bnep_uuid(nc->id);
@@ -632,8 +631,8 @@
nc = g_new0(struct network_conn, 1);
nc->id = id;
- memset(nc->dev, 0, 16);
- strncpy(nc->dev, prefix, sizeof(nc->dev) - 1);
+ memset(nc->dev, 0, sizeof(nc->dev));
+ strcpy(nc->dev, "bnep%d");
nc->state = DISCONNECTED;
nc->peer = peer;
@@ -642,17 +641,15 @@
return 0;
}
-int connection_init(DBusConnection *conn, const char *iface_prefix)
+int connection_init(DBusConnection *conn)
{
connection = dbus_connection_ref(conn);
- prefix = iface_prefix;
return 0;
}
-void connection_exit()
+void connection_exit(void)
{
dbus_connection_unref(connection);
connection = NULL;
- prefix = NULL;
}
--- network/connection.h
+++ network/connection.h
@@ -21,8 +21,8 @@
*
*/
-int connection_init(DBusConnection *conn, const char *iface_prefix);
-void connection_exit();
+int connection_init(DBusConnection *conn);
+void connection_exit(void);
int connection_register(struct btd_device *device, const char *path,
bdaddr_t *src, bdaddr_t *dst, uint16_t id);
void connection_unregister(const char *path, uint16_t id);
--- network/manager.c
+++ network/manager.c
@@ -37,152 +37,39 @@
#include "adapter.h"
#include "device.h"
-#include "bridge.h"
#include "manager.h"
#include "common.h"
#include "connection.h"
#include "server.h"
-#define IFACE_PREFIX "bnep%d"
-#define GN_IFACE "pan0"
-#define NAP_IFACE "pan1"
-
-static struct btd_adapter_driver network_panu_server_driver;
-static struct btd_adapter_driver network_gn_server_driver;
-static struct btd_adapter_driver network_nap_server_driver;
-
static DBusConnection *connection = NULL;
-static struct network_conf {
- gboolean connection_enabled;
- gboolean server_enabled;
- gboolean security;
- char *iface_prefix;
- char *panu_script;
- char *gn_script;
- char *nap_script;
- char *gn_iface;
- char *nap_iface;
-} conf = {
- .connection_enabled = TRUE,
- .server_enabled = TRUE,
- .security = TRUE,
- .iface_prefix = NULL,
- .panu_script = NULL,
- .gn_script = NULL,
- .nap_script = NULL,
- .gn_iface = NULL,
- .nap_iface = NULL
-};
-
-static void conf_cleanup(void)
-{
- g_free(conf.iface_prefix);
- g_free(conf.panu_script);
- g_free(conf.gn_script);
- g_free(conf.nap_script);
- g_free(conf.gn_iface);
- g_free(conf.nap_iface);
-}
+static gboolean conf_security = TRUE;
static void read_config(const char *file)
{
GKeyFile *keyfile;
GError *err = NULL;
- char **disabled;
keyfile = g_key_file_new();
if (!g_key_file_load_from_file(keyfile, file, 0, &err)) {
- error("Parsing %s failed: %s", file, err->message);
g_clear_error(&err);
goto done;
}
- disabled = g_key_file_get_string_list(keyfile, "General",
- "Disable", NULL, &err);
- if (err) {
- DBG("%s: %s", file, err->message);
- g_clear_error(&err);
- } else {
- int i;
- for (i = 0; disabled[i] != NULL; i++) {
- if (g_str_equal(disabled[i], "Connection"))
- conf.connection_enabled = FALSE;
- else if (g_str_equal(disabled[i], "Server"))
- conf.server_enabled = FALSE;
- }
- g_strfreev(disabled);
- }
-
- conf.security = !g_key_file_get_boolean(keyfile, "General",
+ conf_security = !g_key_file_get_boolean(keyfile, "General",
"DisableSecurity", &err);
if (err) {
DBG("%s: %s", file, err->message);
g_clear_error(&err);
}
-#if 0
- conf.panu_script = g_key_file_get_string(keyfile, "PANU Role",
- "Script", &err);
- if (err) {
- DBG("%s: %s", file, err->message);
- g_clear_error(&err);
- }
-
- conf.gn_script = g_key_file_get_string(keyfile, "GN Role",
- "Script", &err);
- if (err) {
- DBG("%s: %s", file, err->message);
- g_clear_error(&err);
- }
-
- conf.nap_script = g_key_file_get_string(keyfile, "NAP Role",
- "Script", &err);
- if (err) {
- DBG("%s: %s", file, err->message);
- g_clear_error(&err);
- }
-#endif
-
- conf.iface_prefix = g_key_file_get_string(keyfile, "PANU Role",
- "Interface", &err);
- if (err) {
- DBG("%s: %s", file, err->message);
- g_clear_error(&err);
- }
-
- conf.gn_iface = g_key_file_get_string(keyfile, "GN Role",
- "Interface", &err);
- if (err) {
- DBG("%s: %s", file, err->message);
- g_clear_error(&err);
- }
-
- conf.nap_iface = g_key_file_get_string(keyfile, "NAP Role",
- "Interface", &err);
- if (err) {
- DBG("%s: %s", file, err->message);
- g_clear_error(&err);
- }
-
done:
g_key_file_free(keyfile);
- if (!conf.iface_prefix)
- conf.iface_prefix = g_strdup(IFACE_PREFIX);
-
- if (!conf.gn_iface)
- conf.gn_iface = g_strdup(GN_IFACE);
- if (!conf.nap_iface)
- conf.nap_iface = g_strdup(NAP_IFACE);
-
- DBG("Config options: InterfacePrefix=%s, PANU_Script=%s, "
- "GN_Script=%s, NAP_Script=%s, GN_Interface=%s, "
- "NAP_Interface=%s, Security=%s",
- conf.iface_prefix, conf.panu_script, conf.gn_script,
- conf.nap_script, conf.gn_iface, conf.nap_iface,
- conf.security ? "true" : "false");
+ DBG("Config options: Security=%s",
+ conf_security ? "true" : "false");
}
static int network_probe(struct btd_device *device, GSList *uuids, uint16_t id)
@@ -238,55 +125,22 @@
network_remove(device, BNEP_SVC_NAP);
}
-static int network_server_probe(struct btd_adapter *adapter, uint16_t id)
+static int network_server_probe(struct btd_adapter *adapter)
{
const gchar *path = adapter_get_path(adapter);
DBG("path %s", path);
- if (!conf.server_enabled)
- return 0;
-
- return server_register(adapter, id);
+ return server_register(adapter);
}
-static void network_server_remove(struct btd_adapter *adapter, uint16_t id)
+static void network_server_remove(struct btd_adapter *adapter)
{
const gchar *path = adapter_get_path(adapter);
DBG("path %s", path);
- server_unregister(adapter, id);
-}
-
-static int panu_server_probe(struct btd_adapter *adapter)
-{
- return network_server_probe(adapter, BNEP_SVC_PANU);
-}
-
-static int gn_server_probe(struct btd_adapter *adapter)
-{
- return network_server_probe(adapter, BNEP_SVC_GN);
-}
-
-static int nap_server_probe(struct btd_adapter *adapter)
-{
- return network_server_probe(adapter, BNEP_SVC_NAP);
-}
-
-static void panu_server_remove(struct btd_adapter *adapter)
-{
- network_server_remove(adapter, BNEP_SVC_PANU);
-}
-
-static void gn_server_remove(struct btd_adapter *adapter)
-{
- network_server_remove(adapter, BNEP_SVC_GN);
-}
-
-static void nap_server_remove(struct btd_adapter *adapter)
-{
- network_server_remove(adapter, BNEP_SVC_NAP);
+ server_unregister(adapter);
}
static struct btd_device_driver network_panu_driver = {
@@ -310,29 +164,17 @@
.remove = nap_remove,
};
-static struct btd_adapter_driver network_panu_server_driver = {
- .name = "network-panu-server",
- .probe = panu_server_probe,
- .remove = panu_server_remove,
-};
-
-static struct btd_adapter_driver network_gn_server_driver = {
- .name = "network-gn-server",
- .probe = gn_server_probe,
- .remove = gn_server_remove,
-};
-
-static struct btd_adapter_driver network_nap_server_driver = {
- .name = "network-nap-server",
- .probe = nap_server_probe,
- .remove = nap_server_remove,
+static struct btd_adapter_driver network_server_driver = {
+ .name = "network-server",
+ .probe = network_server_probe,
+ .remove = network_server_remove,
};
int network_manager_init(DBusConnection *conn)
{
read_config(CONFIGDIR "/network.conf");
- if (bnep_init(conf.panu_script, conf.gn_script, conf.nap_script)) {
+ if (bnep_init()) {
error("Can't init bnep module");
return -1;
}
@@ -343,20 +185,14 @@
* (setup connection request) contains the destination service
* field that defines which service the source is connecting to.
*/
- if (bridge_init(conf.gn_iface, conf.nap_iface) < 0) {
- error("Can't init bridge module");
- return -1;
- }
- if (server_init(conn, conf.iface_prefix, conf.security) < 0)
+ if (server_init(conn, conf_security) < 0)
return -1;
- /* Register PANU, GN and NAP servers if they don't exist */
- btd_register_adapter_driver(&network_panu_server_driver);
- btd_register_adapter_driver(&network_gn_server_driver);
- btd_register_adapter_driver(&network_nap_server_driver);
+ /* Register network server if it doesn't exist */
+ btd_register_adapter_driver(&network_server_driver);
- if (connection_init(conn, conf.iface_prefix) < 0)
+ if (connection_init(conn) < 0)
return -1;
btd_register_device_driver(&network_panu_driver);
@@ -370,24 +206,18 @@
void network_manager_exit(void)
{
- if (conf.server_enabled)
- server_exit();
+ server_exit();
- if (conf.connection_enabled) {
- btd_unregister_device_driver(&network_panu_driver);
- btd_unregister_device_driver(&network_gn_driver);
- btd_unregister_device_driver(&network_nap_driver);
- connection_exit();
- }
+ btd_unregister_device_driver(&network_panu_driver);
+ btd_unregister_device_driver(&network_gn_driver);
+ btd_unregister_device_driver(&network_nap_driver);
+
+ connection_exit();
- btd_unregister_adapter_driver(&network_panu_server_driver);
- btd_unregister_adapter_driver(&network_gn_server_driver);
- btd_unregister_adapter_driver(&network_nap_server_driver);
+ btd_unregister_adapter_driver(&network_server_driver);
dbus_connection_unref(connection);
connection = NULL;
bnep_cleanup();
- bridge_cleanup();
- conf_cleanup();
}
--- network/network.conf
+++ network/network.conf
@@ -1,33 +1,6 @@
# Configuration file for the network service
-# This section contains options which are not specific to any
-# particular interface
[General]
# Disable link encryption: default=false
#DisableSecurity=true
-
-[PANU Role]
-
-# Network interface name for PANU for connections. default:bnep%d
-# (up to 16 characters)
-#Interface=
-
-# PAN user connection interface up script. default:none
-Script=avahi-autoipd
-
-[GN Role]
-
-# Network Interface name for Group Network server. default:pan0
-#Interface=
-
-# Group Network connection interface up script. default:none
-Script=avahi-autoipd
-
-[NAP Role]
-
-# Network Interface name for Network Access Point server. default:pan1
-#Interface=
-
-# Network Access Point connection interface up script. default:none
-Script=dhclient
--- network/server.c
+++ network/server.c
@@ -50,13 +50,10 @@
#include "btio.h"
#include "glib-helper.h"
-#include "bridge.h"
#include "common.h"
#include "server.h"
-#define NETWORK_PEER_INTERFACE "org.bluez.NetworkPeer"
-#define NETWORK_HUB_INTERFACE "org.bluez.NetworkHub"
-#define NETWORK_ROUTER_INTERFACE "org.bluez.NetworkRouter"
+#define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer"
#define SETUP_TIMEOUT 1
/* Pending Authorization */
@@ -78,17 +75,16 @@
bdaddr_t src; /* Bluetooth Local Address */
char *iface; /* DBus interface */
char *name; /* Server service name */
- char *range; /* IP Address range */
- gboolean enable; /* Enable flag */
+ char *bridge; /* Bridge name */
uint32_t record_id; /* Service record id */
uint16_t id; /* Service class identifier */
GSList *sessions; /* Active connections */
struct network_adapter *na; /* Adapter reference */
+ guint watch_id; /* Client service watch */
};
static DBusConnection *connection = NULL;
static GSList *adapters = NULL;
-static const char *prefix = NULL;
static gboolean security = TRUE;
static struct network_adapter *find_adapter(GSList *list,
@@ -145,7 +141,7 @@
uint16_t security_desc = (security ? 0x0001 : 0x0000);
uint16_t net_access_type = 0xfffe;
uint32_t max_net_access_rate = 0;
- const char *desc = "BlueZ PAN service";
+ const char *desc = "Network service";
sdp_record_t *record;
record = sdp_record_alloc();
@@ -276,15 +272,10 @@
uint16_t dst_role)
{
char devname[16];
- const char *bridge;
int err, nsk;
- /* Server can be disabled in the meantime */
- if (ns->enable == FALSE)
- return -EPERM;
-
- memset(devname, 0, 16);
- strncpy(devname, prefix, sizeof(devname) - 1);
+ memset(devname, 0, sizeof(devname));
+ strcpy(devname, "bnep%d");
nsk = g_io_channel_unix_get_fd(session->io);
err = bnep_connadd(nsk, dst_role, devname);
@@ -293,18 +284,13 @@
info("Added new connection: %s", devname);
- bridge = bridge_get_name(ns->id);
- if (bridge) {
- if (bridge_add_interface(ns->id, devname) < 0) {
- error("Can't add %s to the bridge %s: %s(%d)",
- devname, bridge, strerror(errno),
- errno);
- return -EPERM;
- }
+ if (bnep_add_to_bridge(devname, ns->bridge) < 0) {
+ error("Can't add %s to the bridge %s: %s(%d)",
+ devname, ns->bridge, strerror(errno), errno);
+ return -EPERM;
+ }
- bnep_if_up(devname, 0);
- } else
- bnep_if_up(devname, ns->id);
+ bnep_if_up(devname);
ns->sessions = g_slist_append(ns->sessions, session);
@@ -322,8 +308,8 @@
return BNEP_CONN_INVALID_SRC;
case BNEP_SVC_PANU:
if (src_role == BNEP_SVC_PANU ||
- src_role == BNEP_SVC_GN ||
- src_role == BNEP_SVC_NAP)
+ src_role == BNEP_SVC_GN ||
+ src_role == BNEP_SVC_NAP)
return 0;
return BNEP_CONN_INVALID_SRC;
@@ -422,11 +408,21 @@
goto reply;
ns = find_server(na->servers, dst_role);
- if (!ns || ns->enable == FALSE) {
+ if (!ns) {
error("Server unavailable: (0x%x)", dst_role);
goto reply;
}
+ if (!ns->record_id) {
+ error("Service record not available");
+ goto reply;
+ }
+
+ if (!ns->bridge) {
+ error("Bridge interface not configured");
+ goto reply;
+ }
+
if (server_connadd(ns, na->setup, dst_role) < 0)
goto reply;
@@ -484,6 +480,7 @@
static void confirm_event(GIOChannel *chan, gpointer user_data)
{
struct network_adapter *na = user_data;
+ struct network_server *ns;
int perr;
bdaddr_t src, dst;
char address[18];
@@ -507,6 +504,16 @@
goto drop;
}
+ ns = find_server(na->servers, BNEP_SVC_NAP);
+ if (!ns)
+ goto drop;
+
+ if (!ns->record_id)
+ goto drop;
+
+ if (!ns->bridge)
+ goto drop;
+
na->setup = g_new0(struct network_session, 1);
bacpy(&na->setup->dst, &dst);
na->setup->io = g_io_channel_ref(chan);
@@ -526,24 +533,16 @@
g_io_channel_shutdown(chan, TRUE, NULL);
}
-int server_init(DBusConnection *conn, const char *iface_prefix,
- gboolean secure)
+int server_init(DBusConnection *conn, gboolean secure)
{
security = secure;
connection = dbus_connection_ref(conn);
- prefix = iface_prefix;
-
- if (bridge_create(BNEP_SVC_GN) < 0)
- error("Can't create GN bridge");
return 0;
}
-void server_exit()
+void server_exit(void)
{
- if (bridge_remove(BNEP_SVC_GN) < 0)
- error("Can't remove GN bridge");
-
dbus_connection_unref(connection);
connection = NULL;
}
@@ -564,7 +563,7 @@
return 0;
}
- DBG("register_server_record: got record id 0x%x", record->handle);
+ DBG("got record id 0x%x", record->handle);
return record->handle;
}
@@ -583,166 +582,81 @@
description);
}
-static DBusMessage *enable(DBusConnection *conn,
- DBusMessage *msg, void *data)
+static void server_disconnect(DBusConnection *conn, void *user_data)
{
- struct network_server *ns = data;
- DBusMessage *reply;
+ struct network_server *ns = user_data;
- if (ns->enable)
- return g_dbus_create_error(msg, ERROR_INTERFACE
- ".AlreadyExist",
- "Server already enabled");
+ ns->watch_id = 0;
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- /* Add the service record */
- ns->record_id = register_server_record(ns);
- if (!ns->record_id) {
- dbus_message_unref(reply);
- return failed(msg, "Service record registration failed");
+ if (ns->record_id) {
+ remove_record_from_server(ns->record_id);
+ ns->record_id = 0;
}
- ns->enable = TRUE;
-
- return reply;
+ g_free(ns->bridge);
+ ns->bridge = NULL;
}
-static DBusMessage *disable(DBusConnection *conn,
+static DBusMessage *register_server(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct network_server *ns = data;
DBusMessage *reply;
+ const char *uuid, *bridge;
- reply = dbus_message_new_method_return(msg);
- if (!reply)
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid,
+ DBUS_TYPE_STRING, &bridge, DBUS_TYPE_INVALID))
return NULL;
- if (!ns->enable)
- return failed(msg, "Not enabled");
-
- /* Remove the service record */
- if (ns->record_id) {
- remove_record_from_server(ns->record_id);
- ns->record_id = 0;
- }
-
- ns->enable = FALSE;
-
- g_slist_foreach(ns->sessions, (GFunc) session_free, NULL);
- g_slist_free(ns->sessions);
-
- return reply;
-}
+ if (g_strcmp0(uuid, "nap"))
+ return failed(msg, "Invalid UUID");
-static DBusMessage *set_name(DBusConnection *conn, DBusMessage *msg,
- const char *name, void *data)
-{
- struct network_server *ns = data;
- DBusMessage *reply;
+ if (ns->record_id)
+ return failed(msg, "Already registered");
reply = dbus_message_new_method_return(msg);
if (!reply)
return NULL;
- if (!name || (strlen(name) == 0))
- return invalid_arguments(msg, "Invalid name");
+ ns->record_id = register_server_record(ns);
+ if (!ns->record_id)
+ return failed(msg, "SDP record registration failed");
- if (ns->name)
- g_free(ns->name);
- ns->name = g_strdup(name);
-
- if (ns->enable && ns->record_id) {
- uint32_t handle = register_server_record(ns);
- if (!handle) {
- dbus_message_unref(reply);
- return failed(msg,
- "Service record attribute update failed");
- }
+ g_free(ns->bridge);
+ ns->bridge = g_strdup(bridge);
- remove_record_from_server(ns->record_id);
- ns->record_id = handle;
- }
+ ns->watch_id = g_dbus_add_disconnect_watch(conn,
+ dbus_message_get_sender(msg),
+ server_disconnect, ns, NULL);
return reply;
}
-static DBusMessage *get_properties(DBusConnection *conn,
- DBusMessage *msg, void *data)
+static DBusMessage *unregister_server(DBusConnection *conn,
+ DBusMessage *msg, void *data)
{
struct network_server *ns = data;
DBusMessage *reply;
- DBusMessageIter iter;
- DBusMessageIter dict;
const char *uuid;
- reply = dbus_message_new_method_return(msg);
- if (!reply)
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid,
+ DBUS_TYPE_INVALID))
return NULL;
- dbus_message_iter_init_append(reply, &iter);
+ if (g_strcmp0(uuid, "nap"))
+ return failed(msg, "Invalid UUID");
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
- dict_append_entry(&dict, "Name", DBUS_TYPE_STRING, &ns->name);
-
- uuid = bnep_uuid(ns->id);
- dict_append_entry(&dict, "Uuid", DBUS_TYPE_STRING, &uuid);
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
- dict_append_entry(&dict, "Enabled", DBUS_TYPE_BOOLEAN, &ns->enable);
+ g_dbus_remove_watch(conn, ns->watch_id);
- dbus_message_iter_close_container(&iter, &dict);
+ server_disconnect(conn, ns);
return reply;
}
-static DBusMessage *set_property(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- DBusMessageIter iter;
- DBusMessageIter sub;
- const char *property;
-
- if (!dbus_message_iter_init(msg, &iter))
- return invalid_arguments(msg, "Not a dict");
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return invalid_arguments(msg, "Key not a string");
-
- dbus_message_iter_get_basic(&iter, &property);
- dbus_message_iter_next(&iter);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
- return invalid_arguments(msg, "Value not a variant");
- dbus_message_iter_recurse(&iter, &sub);
-
- if (g_str_equal("Name", property)) {
- const char *name;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)
- return invalid_arguments(msg, "Value not string");
- dbus_message_iter_get_basic(&sub, &name);
-
- return set_name(conn, msg, name, data);
- } else if (g_str_equal("Enabled", property)) {
- gboolean enabled;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
- return invalid_arguments(msg, "Value not boolean");
- dbus_message_iter_get_basic(&sub, &enabled);
-
- return enabled ? enable(conn, msg, data) :
- disable(conn, msg, data);
- }
-
- return invalid_arguments(msg, "Property does not exist");
-}
-
static void adapter_free(struct network_adapter *na)
{
if (na->io != NULL) {
@@ -764,14 +678,9 @@
if (ns->record_id)
remove_record_from_server(ns->record_id);
- if (ns->iface)
- g_free(ns->iface);
-
- if (ns->name)
- g_free(ns->name);
-
- if (ns->range)
- g_free(ns->range);
+ g_free(ns->iface);
+ g_free(ns->name);
+ g_free(ns->bridge);
if (ns->sessions) {
g_slist_foreach(ns->sessions, (GFunc) session_free, NULL);
@@ -800,13 +709,8 @@
}
static GDBusMethodTable server_methods[] = {
- { "SetProperty", "sv", "", set_property },
- { "GetProperties", "", "a{sv}",get_properties },
- { }
-};
-
-static GDBusSignalTable server_signals[] = {
- { "PropertyChanged", "sv" },
+ { "Register", "ss", "", register_server },
+ { "Unregister", "s", "", unregister_server },
{ }
};
@@ -840,7 +744,7 @@
return na;
}
-int server_register(struct btd_adapter *adapter, uint16_t id)
+int server_register(struct btd_adapter *adapter)
{
struct network_adapter *na;
struct network_server *ns;
@@ -854,31 +758,19 @@
adapters = g_slist_append(adapters, na);
}
- ns = find_server(na->servers, id);
+ ns = find_server(na->servers, BNEP_SVC_NAP);
if (ns)
return 0;
ns = g_new0(struct network_server, 1);
- switch (id) {
- case BNEP_SVC_PANU:
- ns->iface = g_strdup(NETWORK_PEER_INTERFACE);
- ns->name = g_strdup("BlueZ PANU service");
- break;
- case BNEP_SVC_GN:
- ns->iface = g_strdup(NETWORK_HUB_INTERFACE);
- ns->name = g_strdup("BlueZ GN service");
- break;
- case BNEP_SVC_NAP:
- ns->iface = g_strdup(NETWORK_ROUTER_INTERFACE);
- ns->name = g_strdup("BlueZ NAP service");
- break;
- }
+ ns->iface = g_strdup(NETWORK_SERVER_INTERFACE);
+ ns->name = g_strdup("Network service");
path = adapter_get_path(adapter);
if (!g_dbus_register_interface(connection, path, ns->iface,
- server_methods, server_signals, NULL,
+ server_methods, NULL, NULL,
ns, path_unregister)) {
error("D-Bus failed to register %s interface",
ns->iface);
@@ -887,10 +779,9 @@
}
adapter_get_address(adapter, &ns->src);
- ns->id = id;
+ ns->id = BNEP_SVC_NAP;
ns->na = na;
- ns->record_id = register_server_record(ns);
- ns->enable = TRUE;
+ ns->record_id = 0;
na->servers = g_slist_append(na->servers, ns);
DBG("Registered interface %s on path %s", ns->iface, path);
@@ -898,10 +789,11 @@
return 0;
}
-int server_unregister(struct btd_adapter *adapter, uint16_t id)
+int server_unregister(struct btd_adapter *adapter)
{
struct network_adapter *na;
struct network_server *ns;
+ uint16_t id = BNEP_SVC_NAP;
na = find_adapter(adapters, adapter);
if (!na)
--- network/server.h
+++ network/server.h
@@ -21,14 +21,9 @@
*
*/
-int server_init(DBusConnection *conn, const char *iface_prefix,
- gboolean secure);
-void server_exit();
-int server_register(struct btd_adapter *adapter, uint16_t id);
-int server_unregister(struct btd_adapter *adapter, uint16_t id);
-int server_register_from_file(const char *path, const bdaddr_t *src,
- uint16_t id, const char *filename);
-
-int server_store(const char *path);
+int server_init(DBusConnection *conn, gboolean secure);
+void server_exit(void);
+int server_register(struct btd_adapter *adapter);
+int server_unregister(struct btd_adapter *adapter);
int server_find_data(const char *path, const char *pattern);
--- plugins/hciops.c
+++ plugins/hciops.c
@@ -76,7 +76,7 @@
error("unable to write to child pipe");
}
-static void configure_device(int index)
+static void device_devup_setup(int index)
{
struct hci_dev_info di;
uint16_t policy;
@@ -111,6 +111,12 @@
OCF_WRITE_DEFAULT_LINK_POLICY, 2, &policy);
hci_close_dev(dd);
+
+ start_security_manager(index);
+
+ /* Return value 1 means ioctl(DEVDOWN) was performed */
+ if (manager_start_adapter(index) == 1)
+ stop_security_manager(index);
}
static void init_device(int index)
@@ -202,17 +208,6 @@
manager_register_adapter(index, devup);
}
-static void device_devup_setup(int index)
-{
- configure_device(index);
-
- start_security_manager(index);
-
- /* Return value 1 means ioctl(DEVDOWN) was performed */
- if (manager_start_adapter(index) == 1)
- stop_security_manager(index);
-}
-
static void device_event(int event, int index)
{
switch (event) {
@@ -456,7 +451,7 @@
static int hciops_powered(int index, gboolean powered)
{
- int dd;
+ int dd, err;
uint8_t mode = SCAN_DISABLED;
if (powered)
@@ -466,8 +461,13 @@
if (dd < 0)
return -EIO;
- hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE,
+ err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE,
1, &mode);
+ if (err < 0) {
+ err = -errno;
+ hci_close_dev(dd);
+ return err;
+ }
hci_close_dev(dd);
@@ -476,36 +476,40 @@
static int hciops_connectable(int index)
{
- int dd;
+ int dd, err;
uint8_t mode = SCAN_PAGE;
dd = hci_open_dev(index);
if (dd < 0)
return -EIO;
- hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE,
+ err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE,
1, &mode);
+ if (err < 0)
+ err = -errno;
hci_close_dev(dd);
- return 0;
+ return err;
}
static int hciops_discoverable(int index)
{
- int dd;
+ int dd, err;
uint8_t mode = (SCAN_PAGE | SCAN_INQUIRY);
dd = hci_open_dev(index);
if (dd < 0)
return -EIO;
- hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE,
+ err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE,
1, &mode);
+ if (err < 0)
+ err = -errno;
hci_close_dev(dd);
- return 0;
+ return err;
}
static int hciops_set_class(int index, uint32_t class)
@@ -533,7 +537,7 @@
static int hciops_set_limited_discoverable(int index, uint32_t class,
gboolean limited)
{
- int dd;
+ int dd, err;
int num = (limited ? 2 : 1);
uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e };
write_current_iac_lap_cp cp;
@@ -550,8 +554,13 @@
cp.num_current_iac = num;
memcpy(&cp.lap, lap, num * 3);
- hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_CURRENT_IAC_LAP,
+ err = hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_CURRENT_IAC_LAP,
(num * 3 + 1), &cp);
+ if (err < 0) {
+ err = -errno;
+ hci_close_dev(dd);
+ return err;
+ }
hci_close_dev(dd);
--- plugins/maemo6.c
+++ plugins/maemo6.c
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2006-2010 Nokia Corporation
+ * Copyright (C) 2004-2010 Marcel Holtmann <marcel at holtmann.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <dbus/dbus.h>
+
+#include "adapter.h"
+#include "plugin.h"
+#include "log.h"
+#include "gdbus.h"
+
+/* from mce/mode-names.h */
+#define MCE_RADIO_STATE_BLUETOOTH (1 << 3)
+
+/* from mce/dbus-names.h */
+#define MCE_SERVICE "com.nokia.mce"
+#define MCE_REQUEST_IF "com.nokia.mce.request"
+#define MCE_SIGNAL_IF "com.nokia.mce.signal"
+#define MCE_REQUEST_PATH "/com/nokia/mce/request"
+#define MCE_SIGNAL_PATH "/com/nokia/mce/signal"
+#define MCE_RADIO_STATES_GET "get_radio_states"
+#define MCE_RADIO_STATES_SIG "radio_states_ind"
+
+static guint watch_id;
+static DBusConnection *conn = NULL;
+
+static gboolean mce_signal_callback(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ DBusMessageIter args;
+ uint32_t sigvalue;
+ struct btd_adapter *adapter = user_data;
+
+ DBG("received mce signal");
+
+ if (!dbus_message_iter_init(message, &args))
+ error("message has no arguments");
+ else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
+ error("argument is not uint32");
+ else {
+ dbus_message_iter_get_basic(&args, &sigvalue);
+ DBG("got signal with value %u", sigvalue);
+
+ if (sigvalue & MCE_RADIO_STATE_BLUETOOTH)
+ btd_adapter_switch_online(adapter);
+ else
+ btd_adapter_switch_offline(adapter);
+ }
+
+ return TRUE;
+}
+
+static void read_radio_states_cb(DBusPendingCall *call, void *user_data)
+{
+ DBusError err;
+ DBusMessage *reply;
+ dbus_uint32_t radio_states;
+ struct btd_adapter *adapter = user_data;
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&err);
+ if (dbus_set_error_from_message(&err, reply)) {
+ error("mce replied with an error: %s, %s",
+ err.name, err.message);
+ dbus_error_free(&err);
+ goto done;
+ }
+
+ dbus_error_init(&err);
+ if (dbus_message_get_args(reply, &err,
+ DBUS_TYPE_UINT32, &radio_states,
+ DBUS_TYPE_INVALID) == FALSE) {
+ error("unable to parse get_radio_states reply: %s, %s",
+ err.name, err.message);
+ dbus_error_free(&err);
+ goto done;
+ }
+
+ if (radio_states & MCE_RADIO_STATE_BLUETOOTH)
+ btd_adapter_switch_online(adapter);
+
+done:
+ dbus_message_unref(reply);
+}
+
+static int mce_probe(struct btd_adapter *adapter)
+{
+ DBusMessage *msg;
+ DBusPendingCall *call;
+
+ DBG("path %s", adapter_get_path(adapter));
+
+ msg = dbus_message_new_method_call(MCE_SERVICE, MCE_REQUEST_PATH,
+ MCE_REQUEST_IF, MCE_RADIO_STATES_GET);
+
+ if (!dbus_connection_send_with_reply(conn, msg, &call, -1)) {
+ error("calling %s failed", MCE_RADIO_STATES_GET);
+ dbus_message_unref(msg);
+ return -1;
+ }
+
+ dbus_pending_call_set_notify(call, read_radio_states_cb, adapter, NULL);
+ dbus_pending_call_unref(call);
+ dbus_message_unref(msg);
+
+ watch_id = g_dbus_add_signal_watch(conn, NULL, MCE_SIGNAL_PATH,
+ MCE_SIGNAL_IF, MCE_RADIO_STATES_SIG,
+ mce_signal_callback, adapter, NULL);
+ return 0;
+}
+
+static void mce_remove(struct btd_adapter *adapter)
+{
+ DBG("path %s", adapter_get_path(adapter));
+
+ if (watch_id > 0)
+ g_dbus_remove_watch(conn, watch_id);
+}
+
+static struct btd_adapter_driver mce_driver = {
+ .name = "mce",
+ .probe = mce_probe,
+ .remove = mce_remove,
+};
+
+static int maemo6_init(void)
+{
+ DBG("init maemo6 plugin");
+
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+ if (conn == NULL) {
+ error("Unable to connect to D-Bus");
+ return -1;
+ }
+
+ return btd_register_adapter_driver(&mce_driver);
+}
+
+static void maemo6_exit(void)
+{
+ DBG("exit maemo6 plugin");
+
+ if (conn != NULL)
+ dbus_connection_unref(conn);
+
+ btd_unregister_adapter_driver(&mce_driver);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(maemo6, VERSION,
+ BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, maemo6_init, maemo6_exit)
--- sbc/sbc.c
+++ sbc/sbc.c
@@ -78,7 +78,7 @@
uint8_t joint;
/* only the lower 4 bits of every element are to be used */
- uint32_t scale_factor[2][8];
+ uint32_t SBC_ALIGNED scale_factor[2][8];
/* raw integer subband samples in the frame */
int32_t SBC_ALIGNED sb_sample_f[16][2][8];
@@ -160,7 +160,8 @@
* Takes a pointer to the frame in question, a pointer to the bits array and
* the sampling frequency (as 2 bit integer)
*/
-static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8])
+static SBC_ALWAYS_INLINE void sbc_calculate_bits_internal(
+ const struct sbc_frame *frame, int (*bits)[8], int subbands)
{
uint8_t sf = frame->frequency;
@@ -171,17 +172,17 @@
for (ch = 0; ch < frame->channels; ch++) {
max_bitneed = 0;
if (frame->allocation == SNR) {
- for (sb = 0; sb < frame->subbands; sb++) {
+ for (sb = 0; sb < subbands; sb++) {
bitneed[ch][sb] = frame->scale_factor[ch][sb];
if (bitneed[ch][sb] > max_bitneed)
max_bitneed = bitneed[ch][sb];
}
} else {
- for (sb = 0; sb < frame->subbands; sb++) {
+ for (sb = 0; sb < subbands; sb++) {
if (frame->scale_factor[ch][sb] == 0)
bitneed[ch][sb] = -5;
else {
- if (frame->subbands == 4)
+ if (subbands == 4)
loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb];
else
loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb];
@@ -202,7 +203,7 @@
bitslice--;
bitcount += slicecount;
slicecount = 0;
- for (sb = 0; sb < frame->subbands; sb++) {
+ for (sb = 0; sb < subbands; sb++) {
if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16))
slicecount++;
else if (bitneed[ch][sb] == bitslice + 1)
@@ -215,7 +216,7 @@
bitslice--;
}
- for (sb = 0; sb < frame->subbands; sb++) {
+ for (sb = 0; sb < subbands; sb++) {
if (bitneed[ch][sb] < bitslice + 2)
bits[ch][sb] = 0;
else {
@@ -225,7 +226,8 @@
}
}
- for (sb = 0; bitcount < frame->bitpool && sb < frame->subbands; sb++) {
+ for (sb = 0; bitcount < frame->bitpool &&
+ sb < subbands; sb++) {
if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) {
bits[ch][sb]++;
bitcount++;
@@ -235,7 +237,8 @@
}
}
- for (sb = 0; bitcount < frame->bitpool && sb < frame->subbands; sb++) {
+ for (sb = 0; bitcount < frame->bitpool &&
+ sb < subbands; sb++) {
if (bits[ch][sb] < 16) {
bits[ch][sb]++;
bitcount++;
@@ -251,7 +254,7 @@
max_bitneed = 0;
if (frame->allocation == SNR) {
for (ch = 0; ch < 2; ch++) {
- for (sb = 0; sb < frame->subbands; sb++) {
+ for (sb = 0; sb < subbands; sb++) {
bitneed[ch][sb] = frame->scale_factor[ch][sb];
if (bitneed[ch][sb] > max_bitneed)
max_bitneed = bitneed[ch][sb];
@@ -259,11 +262,11 @@
}
} else {
for (ch = 0; ch < 2; ch++) {
- for (sb = 0; sb < frame->subbands; sb++) {
+ for (sb = 0; sb < subbands; sb++) {
if (frame->scale_factor[ch][sb] == 0)
bitneed[ch][sb] = -5;
else {
- if (frame->subbands == 4)
+ if (subbands == 4)
loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb];
else
loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb];
@@ -286,7 +289,7 @@
bitcount += slicecount;
slicecount = 0;
for (ch = 0; ch < 2; ch++) {
- for (sb = 0; sb < frame->subbands; sb++) {
+ for (sb = 0; sb < subbands; sb++) {
if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16))
slicecount++;
else if (bitneed[ch][sb] == bitslice + 1)
@@ -301,7 +304,7 @@
}
for (ch = 0; ch < 2; ch++) {
- for (sb = 0; sb < frame->subbands; sb++) {
+ for (sb = 0; sb < subbands; sb++) {
if (bitneed[ch][sb] < bitslice + 2) {
bits[ch][sb] = 0;
} else {
@@ -325,7 +328,8 @@
if (ch == 1) {
ch = 0;
sb++;
- if (sb >= frame->subbands) break;
+ if (sb >= subbands)
+ break;
} else
ch = 1;
}
@@ -340,7 +344,8 @@
if (ch == 1) {
ch = 0;
sb++;
- if (sb >= frame->subbands) break;
+ if (sb >= subbands)
+ break;
} else
ch = 1;
}
@@ -349,6 +354,14 @@
}
+static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8])
+{
+ if (frame->subbands == 4)
+ sbc_calculate_bits_internal(frame, bits, 4);
+ else
+ sbc_calculate_bits_internal(frame, bits, 8);
+}
+
/*
* Unpacks a SBC frame at the beginning of the stream in data,
* which has at most len bytes into frame.
@@ -743,9 +756,10 @@
* -99 not implemented
*/
-static SBC_ALWAYS_INLINE int sbc_pack_frame_internal(uint8_t *data,
+static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(uint8_t *data,
struct sbc_frame *frame, size_t len,
- int frame_subbands, int frame_channels)
+ int frame_subbands, int frame_channels,
+ int joint)
{
/* Bitstream writer starts from the fourth byte */
uint8_t *data_ptr = data + 4;
@@ -802,63 +816,6 @@
crc_pos = 16;
if (frame->mode == JOINT_STEREO) {
- /* like frame->sb_sample but joint stereo */
- int32_t sb_sample_j[16][2];
- /* scalefactor and scale_factor in joint case */
- uint32_t scalefactor_j[2];
- uint8_t scale_factor_j[2];
-
- uint8_t joint = 0;
- frame->joint = 0;
-
- for (sb = 0; sb < frame_subbands - 1; sb++) {
- scale_factor_j[0] = 0;
- scalefactor_j[0] = 2 << SCALE_OUT_BITS;
- scale_factor_j[1] = 0;
- scalefactor_j[1] = 2 << SCALE_OUT_BITS;
-
- for (blk = 0; blk < frame->blocks; blk++) {
- uint32_t tmp;
- /* Calculate joint stereo signal */
- sb_sample_j[blk][0] =
- ASR(frame->sb_sample_f[blk][0][sb], 1) +
- ASR(frame->sb_sample_f[blk][1][sb], 1);
- sb_sample_j[blk][1] =
- ASR(frame->sb_sample_f[blk][0][sb], 1) -
- ASR(frame->sb_sample_f[blk][1][sb], 1);
-
- /* calculate scale_factor_j and scalefactor_j for joint case */
- tmp = fabs(sb_sample_j[blk][0]);
- while (scalefactor_j[0] < tmp) {
- scale_factor_j[0]++;
- scalefactor_j[0] *= 2;
- }
- tmp = fabs(sb_sample_j[blk][1]);
- while (scalefactor_j[1] < tmp) {
- scale_factor_j[1]++;
- scalefactor_j[1] *= 2;
- }
- }
-
- /* decide whether to join this subband */
- if ((frame->scale_factor[0][sb] +
- frame->scale_factor[1][sb]) >
- (scale_factor_j[0] +
- scale_factor_j[1])) {
- /* use joint stereo for this subband */
- joint |= 1 << (frame_subbands - 1 - sb);
- frame->joint |= 1 << sb;
- frame->scale_factor[0][sb] = scale_factor_j[0];
- frame->scale_factor[1][sb] = scale_factor_j[1];
- for (blk = 0; blk < frame->blocks; blk++) {
- frame->sb_sample_f[blk][0][sb] =
- sb_sample_j[blk][0];
- frame->sb_sample_f[blk][1][sb] =
- sb_sample_j[blk][1];
- }
- }
- }
-
PUT_BITS(data_ptr, bits_cache, bits_count,
joint, frame_subbands);
crc_header[crc_pos >> 3] = joint;
@@ -916,18 +873,23 @@
return data_ptr - data;
}
-static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len)
+static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len,
+ int joint)
{
if (frame->subbands == 4) {
if (frame->channels == 1)
- return sbc_pack_frame_internal(data, frame, len, 4, 1);
+ return sbc_pack_frame_internal(
+ data, frame, len, 4, 1, joint);
else
- return sbc_pack_frame_internal(data, frame, len, 4, 2);
+ return sbc_pack_frame_internal(
+ data, frame, len, 4, 2, joint);
} else {
if (frame->channels == 1)
- return sbc_pack_frame_internal(data, frame, len, 8, 1);
+ return sbc_pack_frame_internal(
+ data, frame, len, 8, 1, joint);
else
- return sbc_pack_frame_internal(data, frame, len, 8, 2);
+ return sbc_pack_frame_internal(
+ data, frame, len, 8, 2, joint);
}
}
@@ -1056,10 +1018,11 @@
}
ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
- void *output, size_t output_len, size_t *written)
+ void *output, size_t output_len, ssize_t *written)
{
struct sbc_priv *priv;
- int framelen, samples;
+ int samples;
+ ssize_t framelen;
int (*sbc_enc_process_input)(int position,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels);
@@ -1121,11 +1084,18 @@
samples = sbc_analyze_audio(&priv->enc_state, &priv->frame);
- priv->enc_state.sbc_calc_scalefactors(
- priv->frame.sb_sample_f, priv->frame.scale_factor,
- priv->frame.blocks, priv->frame.channels, priv->frame.subbands);
-
- framelen = sbc_pack_frame(output, &priv->frame, output_len);
+ if (priv->frame.mode == JOINT_STEREO) {
+ int j = priv->enc_state.sbc_calc_scalefactors_j(
+ priv->frame.sb_sample_f, priv->frame.scale_factor,
+ priv->frame.blocks, priv->frame.subbands);
+ framelen = sbc_pack_frame(output, &priv->frame, output_len, j);
+ } else {
+ priv->enc_state.sbc_calc_scalefactors(
+ priv->frame.sb_sample_f, priv->frame.scale_factor,
+ priv->frame.blocks, priv->frame.channels,
+ priv->frame.subbands);
+ framelen = sbc_pack_frame(output, &priv->frame, output_len, 0);
+ }
if (written)
*written = framelen;
--- sbc/sbc.h
+++ sbc/sbc.h
@@ -92,7 +92,7 @@
/* Encodes ONE input block into ONE output block */
ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
- void *output, size_t output_len, size_t *written);
+ void *output, size_t output_len, ssize_t *written);
/* Returns the output block size in bytes */
size_t sbc_get_frame_length(sbc_t *sbc);
--- sbc/sbc_primitives.c
+++ sbc/sbc_primitives.c
@@ -34,6 +34,7 @@
#include "sbc_primitives.h"
#include "sbc_primitives_mmx.h"
#include "sbc_primitives_neon.h"
+#include "sbc_primitives_armv6.h"
/*
* A reference C code of analysis filter with SIMD-friendly tables
@@ -440,6 +441,80 @@
}
}
+static int sbc_calc_scalefactors_j(
+ int32_t sb_sample_f[16][2][8],
+ uint32_t scale_factor[2][8],
+ int blocks, int subbands)
+{
+ int blk, joint = 0;
+ int32_t tmp0, tmp1;
+ uint32_t x, y;
+
+ /* last subband does not use joint stereo */
+ int sb = subbands - 1;
+ x = 1 << SCALE_OUT_BITS;
+ y = 1 << SCALE_OUT_BITS;
+ for (blk = 0; blk < blocks; blk++) {
+ tmp0 = fabs(sb_sample_f[blk][0][sb]);
+ tmp1 = fabs(sb_sample_f[blk][1][sb]);
+ if (tmp0 != 0)
+ x |= tmp0 - 1;
+ if (tmp1 != 0)
+ y |= tmp1 - 1;
+ }
+ scale_factor[0][sb] = (31 - SCALE_OUT_BITS) - sbc_clz(x);
+ scale_factor[1][sb] = (31 - SCALE_OUT_BITS) - sbc_clz(y);
+
+ /* the rest of subbands can use joint stereo */
+ while (--sb >= 0) {
+ int32_t sb_sample_j[16][2];
+ x = 1 << SCALE_OUT_BITS;
+ y = 1 << SCALE_OUT_BITS;
+ for (blk = 0; blk < blocks; blk++) {
+ tmp0 = sb_sample_f[blk][0][sb];
+ tmp1 = sb_sample_f[blk][1][sb];
+ sb_sample_j[blk][0] = ASR(tmp0, 1) + ASR(tmp1, 1);
+ sb_sample_j[blk][1] = ASR(tmp0, 1) - ASR(tmp1, 1);
+ tmp0 = fabs(tmp0);
+ tmp1 = fabs(tmp1);
+ if (tmp0 != 0)
+ x |= tmp0 - 1;
+ if (tmp1 != 0)
+ y |= tmp1 - 1;
+ }
+ scale_factor[0][sb] = (31 - SCALE_OUT_BITS) -
+ sbc_clz(x);
+ scale_factor[1][sb] = (31 - SCALE_OUT_BITS) -
+ sbc_clz(y);
+ x = 1 << SCALE_OUT_BITS;
+ y = 1 << SCALE_OUT_BITS;
+ for (blk = 0; blk < blocks; blk++) {
+ tmp0 = fabs(sb_sample_j[blk][0]);
+ tmp1 = fabs(sb_sample_j[blk][1]);
+ if (tmp0 != 0)
+ x |= tmp0 - 1;
+ if (tmp1 != 0)
+ y |= tmp1 - 1;
+ }
+ x = (31 - SCALE_OUT_BITS) - sbc_clz(x);
+ y = (31 - SCALE_OUT_BITS) - sbc_clz(y);
+
+ /* decide whether to use joint stereo for this subband */
+ if ((scale_factor[0][sb] + scale_factor[1][sb]) > x + y) {
+ joint |= 1 << (subbands - 1 - sb);
+ scale_factor[0][sb] = x;
+ scale_factor[1][sb] = y;
+ for (blk = 0; blk < blocks; blk++) {
+ sb_sample_f[blk][0][sb] = sb_sample_j[blk][0];
+ sb_sample_f[blk][1][sb] = sb_sample_j[blk][1];
+ }
+ }
+ }
+
+ /* bitmask with the information about subbands using joint stereo */
+ return joint;
+}
+
/*
* Detect CPU features and setup function pointers
*/
@@ -457,6 +532,7 @@
/* Default implementation for scale factors calculation */
state->sbc_calc_scalefactors = sbc_calc_scalefactors;
+ state->sbc_calc_scalefactors_j = sbc_calc_scalefactors_j;
state->implementation_info = "Generic C";
/* X86/AMD64 optimizations */
@@ -465,6 +541,9 @@
#endif
/* ARM optimizations */
+#ifdef SBC_BUILD_WITH_ARMV6_SUPPORT
+ sbc_init_primitives_armv6(state);
+#endif
#ifdef SBC_BUILD_WITH_NEON_SUPPORT
sbc_init_primitives_neon(state);
#endif
--- sbc/sbc_primitives.h
+++ sbc/sbc_primitives.h
@@ -63,6 +63,10 @@
void (*sbc_calc_scalefactors)(int32_t sb_sample_f[16][2][8],
uint32_t scale_factor[2][8],
int blocks, int channels, int subbands);
+ /* Scale factors calculation with joint stereo support */
+ int (*sbc_calc_scalefactors_j)(int32_t sb_sample_f[16][2][8],
+ uint32_t scale_factor[2][8],
+ int blocks, int subbands);
const char *implementation_info;
};
--- sbc/sbc_primitives_armv6.c
+++ sbc/sbc_primitives_armv6.c
+/*
+ *
+ * Bluetooth low-complexity, subband codec (SBC) library
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2004-2010 Marcel Holtmann <marcel at holtmann.org>
+ * Copyright (C) 2004-2005 Henryk Ploetz <henryk at ploetzli.ch>
+ * Copyright (C) 2005-2006 Brad Midgley <bmidgley at xmission.com>
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdint.h>
+#include <limits.h>
+#include "sbc.h"
+#include "sbc_math.h"
+#include "sbc_tables.h"
+
+#include "sbc_primitives_armv6.h"
+
+/*
+ * ARMv6 optimizations. The instructions are scheduled for ARM11 pipeline.
+ */
+
+#ifdef SBC_BUILD_WITH_ARMV6_SUPPORT
+
+static void __attribute__((naked)) sbc_analyze_four_armv6()
+{
+ /* r0 = in, r1 = out, r2 = consts */
+ asm volatile (
+ "push {r1, r4-r7, lr}\n"
+ "push {r8-r11}\n"
+ "ldrd r4, r5, [r0, #0]\n"
+ "ldrd r6, r7, [r2, #0]\n"
+ "ldrd r8, r9, [r0, #16]\n"
+ "ldrd r10, r11, [r2, #16]\n"
+ "mov r14, #0x8000\n"
+ "smlad r3, r4, r6, r14\n"
+ "smlad r12, r5, r7, r14\n"
+ "ldrd r4, r5, [r0, #32]\n"
+ "ldrd r6, r7, [r2, #32]\n"
+ "smlad r3, r8, r10, r3\n"
+ "smlad r12, r9, r11, r12\n"
+ "ldrd r8, r9, [r0, #48]\n"
+ "ldrd r10, r11, [r2, #48]\n"
+ "smlad r3, r4, r6, r3\n"
+ "smlad r12, r5, r7, r12\n"
+ "ldrd r4, r5, [r0, #64]\n"
+ "ldrd r6, r7, [r2, #64]\n"
+ "smlad r3, r8, r10, r3\n"
+ "smlad r12, r9, r11, r12\n"
+ "ldrd r8, r9, [r0, #8]\n"
+ "ldrd r10, r11, [r2, #8]\n"
+ "smlad r3, r4, r6, r3\n" /* t1[0] is done */
+ "smlad r12, r5, r7, r12\n" /* t1[1] is done */
+ "ldrd r4, r5, [r0, #24]\n"
+ "ldrd r6, r7, [r2, #24]\n"
+ "pkhtb r3, r12, r3, asr #16\n" /* combine t1[0] and t1[1] */
+ "smlad r12, r8, r10, r14\n"
+ "smlad r14, r9, r11, r14\n"
+ "ldrd r8, r9, [r0, #40]\n"
+ "ldrd r10, r11, [r2, #40]\n"
+ "smlad r12, r4, r6, r12\n"
+ "smlad r14, r5, r7, r14\n"
+ "ldrd r4, r5, [r0, #56]\n"
+ "ldrd r6, r7, [r2, #56]\n"
+ "smlad r12, r8, r10, r12\n"
+ "smlad r14, r9, r11, r14\n"
+ "ldrd r8, r9, [r0, #72]\n"
+ "ldrd r10, r11, [r2, #72]\n"
+ "smlad r12, r4, r6, r12\n"
+ "smlad r14, r5, r7, r14\n"
+ "ldrd r4, r5, [r2, #80]\n" /* start loading cos table */
+ "smlad r12, r8, r10, r12\n" /* t1[2] is done */
+ "smlad r14, r9, r11, r14\n" /* t1[3] is done */
+ "ldrd r6, r7, [r2, #88]\n"
+ "ldrd r8, r9, [r2, #96]\n"
+ "ldrd r10, r11, [r2, #104]\n" /* cos table fully loaded */
+ "pkhtb r12, r14, r12, asr #16\n" /* combine t1[2] and t1[3] */
+ "smuad r4, r3, r4\n"
+ "smuad r5, r3, r5\n"
+ "smlad r4, r12, r8, r4\n"
+ "smlad r5, r12, r9, r5\n"
+ "smuad r6, r3, r6\n"
+ "smuad r7, r3, r7\n"
+ "smlad r6, r12, r10, r6\n"
+ "smlad r7, r12, r11, r7\n"
+ "pop {r8-r11}\n"
+ "stmia r1, {r4, r5, r6, r7}\n"
+ "pop {r1, r4-r7, pc}\n"
+ );
+}
+
+#define sbc_analyze_four(in, out, consts) \
+ ((void (*)(int16_t *, int32_t *, const FIXED_T*)) \
+ sbc_analyze_four_armv6)((in), (out), (consts))
+
+static void __attribute__((naked)) sbc_analyze_eight_armv6()
+{
+ /* r0 = in, r1 = out, r2 = consts */
+ asm volatile (
+ "push {r1, r4-r7, lr}\n"
+ "push {r8-r11}\n"
+ "ldrd r4, r5, [r0, #24]\n"
+ "ldrd r6, r7, [r2, #24]\n"
+ "ldrd r8, r9, [r0, #56]\n"
+ "ldrd r10, r11, [r2, #56]\n"
+ "mov r14, #0x8000\n"
+ "smlad r3, r4, r6, r14\n"
+ "smlad r12, r5, r7, r14\n"
+ "ldrd r4, r5, [r0, #88]\n"
+ "ldrd r6, r7, [r2, #88]\n"
+ "smlad r3, r8, r10, r3\n"
+ "smlad r12, r9, r11, r12\n"
+ "ldrd r8, r9, [r0, #120]\n"
+ "ldrd r10, r11, [r2, #120]\n"
+ "smlad r3, r4, r6, r3\n"
+ "smlad r12, r5, r7, r12\n"
+ "ldrd r4, r5, [r0, #152]\n"
+ "ldrd r6, r7, [r2, #152]\n"
+ "smlad r3, r8, r10, r3\n"
+ "smlad r12, r9, r11, r12\n"
+ "ldrd r8, r9, [r0, #16]\n"
+ "ldrd r10, r11, [r2, #16]\n"
+ "smlad r3, r4, r6, r3\n" /* t1[6] is done */
+ "smlad r12, r5, r7, r12\n" /* t1[7] is done */
+ "ldrd r4, r5, [r0, #48]\n"
+ "ldrd r6, r7, [r2, #48]\n"
+ "pkhtb r3, r12, r3, asr #16\n" /* combine t1[6] and t1[7] */
+ "str r3, [sp, #-4]!\n" /* save to stack */
+ "smlad r3, r8, r10, r14\n"
+ "smlad r12, r9, r11, r14\n"
+ "ldrd r8, r9, [r0, #80]\n"
+ "ldrd r10, r11, [r2, #80]\n"
+ "smlad r3, r4, r6, r3\n"
+ "smlad r12, r5, r7, r12\n"
+ "ldrd r4, r5, [r0, #112]\n"
+ "ldrd r6, r7, [r2, #112]\n"
+ "smlad r3, r8, r10, r3\n"
+ "smlad r12, r9, r11, r12\n"
+ "ldrd r8, r9, [r0, #144]\n"
+ "ldrd r10, r11, [r2, #144]\n"
+ "smlad r3, r4, r6, r3\n"
+ "smlad r12, r5, r7, r12\n"
+ "ldrd r4, r5, [r0, #0]\n"
+ "ldrd r6, r7, [r2, #0]\n"
+ "smlad r3, r8, r10, r3\n" /* t1[4] is done */
+ "smlad r12, r9, r11, r12\n" /* t1[5] is done */
+ "ldrd r8, r9, [r0, #32]\n"
+ "ldrd r10, r11, [r2, #32]\n"
+ "pkhtb r3, r12, r3, asr #16\n" /* combine t1[4] and t1[5] */
+ "str r3, [sp, #-4]!\n" /* save to stack */
+ "smlad r3, r4, r6, r14\n"
+ "smlad r12, r5, r7, r14\n"
+ "ldrd r4, r5, [r0, #64]\n"
+ "ldrd r6, r7, [r2, #64]\n"
+ "smlad r3, r8, r10, r3\n"
+ "smlad r12, r9, r11, r12\n"
+ "ldrd r8, r9, [r0, #96]\n"
+ "ldrd r10, r11, [r2, #96]\n"
+ "smlad r3, r4, r6, r3\n"
+ "smlad r12, r5, r7, r12\n"
+ "ldrd r4, r5, [r0, #128]\n"
+ "ldrd r6, r7, [r2, #128]\n"
+ "smlad r3, r8, r10, r3\n"
+ "smlad r12, r9, r11, r12\n"
+ "ldrd r8, r9, [r0, #8]\n"
+ "ldrd r10, r11, [r2, #8]\n"
+ "smlad r3, r4, r6, r3\n" /* t1[0] is done */
+ "smlad r12, r5, r7, r12\n" /* t1[1] is done */
+ "ldrd r4, r5, [r0, #40]\n"
+ "ldrd r6, r7, [r2, #40]\n"
+ "pkhtb r3, r12, r3, asr #16\n" /* combine t1[0] and t1[1] */
+ "smlad r12, r8, r10, r14\n"
+ "smlad r14, r9, r11, r14\n"
+ "ldrd r8, r9, [r0, #72]\n"
+ "ldrd r10, r11, [r2, #72]\n"
+ "smlad r12, r4, r6, r12\n"
+ "smlad r14, r5, r7, r14\n"
+ "ldrd r4, r5, [r0, #104]\n"
+ "ldrd r6, r7, [r2, #104]\n"
+ "smlad r12, r8, r10, r12\n"
+ "smlad r14, r9, r11, r14\n"
+ "ldrd r8, r9, [r0, #136]\n"
+ "ldrd r10, r11, [r2, #136]!\n"
+ "smlad r12, r4, r6, r12\n"
+ "smlad r14, r5, r7, r14\n"
+ "ldrd r4, r5, [r2, #(160 - 136 + 0)]\n"
+ "smlad r12, r8, r10, r12\n" /* t1[2] is done */
+ "smlad r14, r9, r11, r14\n" /* t1[3] is done */
+ "ldrd r6, r7, [r2, #(160 - 136 + 8)]\n"
+ "smuad r4, r3, r4\n"
+ "smuad r5, r3, r5\n"
+ "pkhtb r12, r14, r12, asr #16\n" /* combine t1[2] and t1[3] */
+ /* r3 = t2[0:1] */
+ /* r12 = t2[2:3] */
+ "pop {r0, r14}\n" /* t2[4:5], t2[6:7] */
+ "ldrd r8, r9, [r2, #(160 - 136 + 32)]\n"
+ "smuad r6, r3, r6\n"
+ "smuad r7, r3, r7\n"
+ "ldrd r10, r11, [r2, #(160 - 136 + 40)]\n"
+ "smlad r4, r12, r8, r4\n"
+ "smlad r5, r12, r9, r5\n"
+ "ldrd r8, r9, [r2, #(160 - 136 + 64)]\n"
+ "smlad r6, r12, r10, r6\n"
+ "smlad r7, r12, r11, r7\n"
+ "ldrd r10, r11, [r2, #(160 - 136 + 72)]\n"
+ "smlad r4, r0, r8, r4\n"
+ "smlad r5, r0, r9, r5\n"
+ "ldrd r8, r9, [r2, #(160 - 136 + 96)]\n"
+ "smlad r6, r0, r10, r6\n"
+ "smlad r7, r0, r11, r7\n"
+ "ldrd r10, r11, [r2, #(160 - 136 + 104)]\n"
+ "smlad r4, r14, r8, r4\n"
+ "smlad r5, r14, r9, r5\n"
+ "ldrd r8, r9, [r2, #(160 - 136 + 16 + 0)]\n"
+ "smlad r6, r14, r10, r6\n"
+ "smlad r7, r14, r11, r7\n"
+ "ldrd r10, r11, [r2, #(160 - 136 + 16 + 8)]\n"
+ "stmia r1!, {r4, r5}\n"
+ "smuad r4, r3, r8\n"
+ "smuad r5, r3, r9\n"
+ "ldrd r8, r9, [r2, #(160 - 136 + 16 + 32)]\n"
+ "stmia r1!, {r6, r7}\n"
+ "smuad r6, r3, r10\n"
+ "smuad r7, r3, r11\n"
+ "ldrd r10, r11, [r2, #(160 - 136 + 16 + 40)]\n"
+ "smlad r4, r12, r8, r4\n"
+ "smlad r5, r12, r9, r5\n"
+ "ldrd r8, r9, [r2, #(160 - 136 + 16 + 64)]\n"
+ "smlad r6, r12, r10, r6\n"
+ "smlad r7, r12, r11, r7\n"
+ "ldrd r10, r11, [r2, #(160 - 136 + 16 + 72)]\n"
+ "smlad r4, r0, r8, r4\n"
+ "smlad r5, r0, r9, r5\n"
+ "ldrd r8, r9, [r2, #(160 - 136 + 16 + 96)]\n"
+ "smlad r6, r0, r10, r6\n"
+ "smlad r7, r0, r11, r7\n"
+ "ldrd r10, r11, [r2, #(160 - 136 + 16 + 104)]\n"
+ "smlad r4, r14, r8, r4\n"
+ "smlad r5, r14, r9, r5\n"
+ "smlad r6, r14, r10, r6\n"
+ "smlad r7, r14, r11, r7\n"
+ "pop {r8-r11}\n"
+ "stmia r1!, {r4, r5, r6, r7}\n"
+ "pop {r1, r4-r7, pc}\n"
+ );
+}
+
+#define sbc_analyze_eight(in, out, consts) \
+ ((void (*)(int16_t *, int32_t *, const FIXED_T*)) \
+ sbc_analyze_eight_armv6)((in), (out), (consts))
+
+static void sbc_analyze_4b_4s_armv6(int16_t *x, int32_t *out, int out_stride)
+{
+ /* Analyze blocks */
+ sbc_analyze_four(x + 12, out, analysis_consts_fixed4_simd_odd);
+ out += out_stride;
+ sbc_analyze_four(x + 8, out, analysis_consts_fixed4_simd_even);
+ out += out_stride;
+ sbc_analyze_four(x + 4, out, analysis_consts_fixed4_simd_odd);
+ out += out_stride;
+ sbc_analyze_four(x + 0, out, analysis_consts_fixed4_simd_even);
+}
+
+static void sbc_analyze_4b_8s_armv6(int16_t *x, int32_t *out, int out_stride)
+{
+ /* Analyze blocks */
+ sbc_analyze_eight(x + 24, out, analysis_consts_fixed8_simd_odd);
+ out += out_stride;
+ sbc_analyze_eight(x + 16, out, analysis_consts_fixed8_simd_even);
+ out += out_stride;
+ sbc_analyze_eight(x + 8, out, analysis_consts_fixed8_simd_odd);
+ out += out_stride;
+ sbc_analyze_eight(x + 0, out, analysis_consts_fixed8_simd_even);
+}
+
+void sbc_init_primitives_armv6(struct sbc_encoder_state *state)
+{
+ state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_armv6;
+ state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_armv6;
+ state->implementation_info = "ARMv6 SIMD";
+}
+
+#endif
--- sbc/sbc_primitives_armv6.h
+++ sbc/sbc_primitives_armv6.h
+/*
+ *
+ * Bluetooth low-complexity, subband codec (SBC) library
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2004-2010 Marcel Holtmann <marcel at holtmann.org>
+ * Copyright (C) 2004-2005 Henryk Ploetz <henryk at ploetzli.ch>
+ * Copyright (C) 2005-2006 Brad Midgley <bmidgley at xmission.com>
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __SBC_PRIMITIVES_ARMV6_H
+#define __SBC_PRIMITIVES_ARMV6_H
+
+#include "sbc_primitives.h"
+
+#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
+ defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
+ defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) || \
+ defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7__) || \
+ defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || \
+ defined(__ARM_ARCH_7M__)
+#define SBC_HAVE_ARMV6 1
+#endif
+
+#if !defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15) && \
+ defined(__GNUC__) && defined(SBC_HAVE_ARMV6) && \
+ defined(__ARM_EABI__) && !defined(__thumb__) && \
+ !defined(__ARM_NEON__)
+
+#define SBC_BUILD_WITH_ARMV6_SUPPORT
+
+void sbc_init_primitives_armv6(struct sbc_encoder_state *encoder_state);
+
+#endif
+
+#endif
--- sbc/sbc_primitives_mmx.c
+++ sbc/sbc_primitives_mmx.c
@@ -276,6 +276,59 @@
asm volatile ("emms\n");
}
+static void sbc_calc_scalefactors_mmx(
+ int32_t sb_sample_f[16][2][8],
+ uint32_t scale_factor[2][8],
+ int blocks, int channels, int subbands)
+{
+ static const SBC_ALIGNED int32_t consts[2] = {
+ 1 << SCALE_OUT_BITS,
+ 1 << SCALE_OUT_BITS,
+ };
+ int ch, sb;
+ intptr_t blk;
+ for (ch = 0; ch < channels; ch++) {
+ for (sb = 0; sb < subbands; sb += 2) {
+ blk = (blocks - 1) * (((char *) &sb_sample_f[1][0][0] -
+ (char *) &sb_sample_f[0][0][0]));
+ asm volatile (
+ "movq (%4), %%mm0\n"
+ "1:\n"
+ "movq (%1, %0), %%mm1\n"
+ "pxor %%mm2, %%mm2\n"
+ "pcmpgtd %%mm2, %%mm1\n"
+ "paddd (%1, %0), %%mm1\n"
+ "pcmpgtd %%mm1, %%mm2\n"
+ "pxor %%mm2, %%mm1\n"
+
+ "por %%mm1, %%mm0\n"
+
+ "sub %2, %0\n"
+ "jns 1b\n"
+
+ "movd %%mm0, %k0\n"
+ "psrlq $32, %%mm0\n"
+ "bsrl %k0, %k0\n"
+ "subl %5, %k0\n"
+ "movl %k0, (%3)\n"
+
+ "movd %%mm0, %k0\n"
+ "bsrl %k0, %k0\n"
+ "subl %5, %k0\n"
+ "movl %k0, 4(%3)\n"
+ : "+r" (blk)
+ : "r" (&sb_sample_f[0][ch][sb]),
+ "i" ((char *) &sb_sample_f[1][0][0] -
+ (char *) &sb_sample_f[0][0][0]),
+ "r" (&scale_factor[ch][sb]),
+ "r" (&consts),
+ "i" (SCALE_OUT_BITS)
+ : "memory");
+ }
+ }
+ asm volatile ("emms\n");
+}
+
static int check_mmx_support(void)
{
#ifdef __amd64__
@@ -314,6 +367,7 @@
if (check_mmx_support()) {
state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_mmx;
state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_mmx;
+ state->sbc_calc_scalefactors = sbc_calc_scalefactors_mmx;
state->implementation_info = "MMX";
}
}
--- sbc/sbc_primitives_neon.c
+++ sbc/sbc_primitives_neon.c
@@ -237,10 +237,656 @@
_sbc_analyze_eight_neon(x + 0, out, analysis_consts_fixed8_simd_even);
}
+static void sbc_calc_scalefactors_neon(
+ int32_t sb_sample_f[16][2][8],
+ uint32_t scale_factor[2][8],
+ int blocks, int channels, int subbands)
+{
+ int ch, sb;
+ for (ch = 0; ch < channels; ch++) {
+ for (sb = 0; sb < subbands; sb += 4) {
+ int blk = blocks;
+ int32_t *in = &sb_sample_f[0][ch][sb];
+ asm volatile (
+ "vmov.s32 q0, #0\n"
+ "vmov.s32 q1, %[c1]\n"
+ "vmov.s32 q14, #1\n"
+ "vmov.s32 q15, %[c2]\n"
+ "vadd.s32 q1, q1, q14\n"
+ "1:\n"
+ "vld1.32 {d16, d17}, [%[in], :128], %[inc]\n"
+ "vabs.s32 q8, q8\n"
+ "vld1.32 {d18, d19}, [%[in], :128], %[inc]\n"
+ "vabs.s32 q9, q9\n"
+ "vld1.32 {d20, d21}, [%[in], :128], %[inc]\n"
+ "vabs.s32 q10, q10\n"
+ "vld1.32 {d22, d23}, [%[in], :128], %[inc]\n"
+ "vabs.s32 q11, q11\n"
+ "vmax.s32 q0, q0, q8\n"
+ "vmax.s32 q1, q1, q9\n"
+ "vmax.s32 q0, q0, q10\n"
+ "vmax.s32 q1, q1, q11\n"
+ "subs %[blk], %[blk], #4\n"
+ "bgt 1b\n"
+ "vmax.s32 q0, q0, q1\n"
+ "vsub.s32 q0, q0, q14\n"
+ "vclz.s32 q0, q0\n"
+ "vsub.s32 q0, q15, q0\n"
+ "vst1.32 {d0, d1}, [%[out], :128]\n"
+ :
+ [blk] "+r" (blk),
+ [in] "+r" (in)
+ :
+ [inc] "r" ((char *) &sb_sample_f[1][0][0] -
+ (char *) &sb_sample_f[0][0][0]),
+ [out] "r" (&scale_factor[ch][sb]),
+ [c1] "i" (1 << SCALE_OUT_BITS),
+ [c2] "i" (31 - SCALE_OUT_BITS)
+ : "d0", "d1", "d2", "d3", "d16", "d17", "d18", "d19",
+ "d20", "d21", "d22", "d23", "d24", "d25", "d26",
+ "d27", "d28", "d29", "d30", "d31", "cc", "memory");
+ }
+ }
+}
+
+int sbc_calc_scalefactors_j_neon(
+ int32_t sb_sample_f[16][2][8],
+ uint32_t scale_factor[2][8],
+ int blocks, int subbands)
+{
+ static SBC_ALIGNED int32_t joint_bits_mask[8] = {
+ 8, 4, 2, 1, 128, 64, 32, 16
+ };
+ int joint, i;
+ int32_t *in0, *in1;
+ int32_t *in = &sb_sample_f[0][0][0];
+ uint32_t *out0, *out1;
+ uint32_t *out = &scale_factor[0][0];
+ int32_t *consts = joint_bits_mask;
+
+ i = subbands;
+
+ asm volatile (
+ /*
+ * constants: q13 = (31 - SCALE_OUT_BITS), q14 = 1
+ * input: q0 = ((1 << SCALE_OUT_BITS) + 1)
+ * %[in0] - samples for channel 0
+ * %[in1] - samples for shannel 1
+ * output: q0, q1 - scale factors without joint stereo
+ * q2, q3 - scale factors with joint stereo
+ * q15 - joint stereo selection mask
+ */
+ ".macro calc_scalefactors\n"
+ "vmov.s32 q1, q0\n"
+ "vmov.s32 q2, q0\n"
+ "vmov.s32 q3, q0\n"
+ "mov %[i], %[blocks]\n"
+ "1:\n"
+ "vld1.32 {d18, d19}, [%[in1], :128], %[inc]\n"
+ "vbic.s32 q11, q9, q14\n"
+ "vld1.32 {d16, d17}, [%[in0], :128], %[inc]\n"
+ "vhadd.s32 q10, q8, q11\n"
+ "vhsub.s32 q11, q8, q11\n"
+ "vabs.s32 q8, q8\n"
+ "vabs.s32 q9, q9\n"
+ "vabs.s32 q10, q10\n"
+ "vabs.s32 q11, q11\n"
+ "vmax.s32 q0, q0, q8\n"
+ "vmax.s32 q1, q1, q9\n"
+ "vmax.s32 q2, q2, q10\n"
+ "vmax.s32 q3, q3, q11\n"
+ "subs %[i], %[i], #1\n"
+ "bgt 1b\n"
+ "vsub.s32 q0, q0, q14\n"
+ "vsub.s32 q1, q1, q14\n"
+ "vsub.s32 q2, q2, q14\n"
+ "vsub.s32 q3, q3, q14\n"
+ "vclz.s32 q0, q0\n"
+ "vclz.s32 q1, q1\n"
+ "vclz.s32 q2, q2\n"
+ "vclz.s32 q3, q3\n"
+ "vsub.s32 q0, q13, q0\n"
+ "vsub.s32 q1, q13, q1\n"
+ "vsub.s32 q2, q13, q2\n"
+ "vsub.s32 q3, q13, q3\n"
+ ".endm\n"
+ /*
+ * constants: q14 = 1
+ * input: q15 - joint stereo selection mask
+ * %[in0] - value set by calc_scalefactors macro
+ * %[in1] - value set by calc_scalefactors macro
+ */
+ ".macro update_joint_stereo_samples\n"
+ "sub %[out1], %[in1], %[inc]\n"
+ "sub %[out0], %[in0], %[inc]\n"
+ "sub %[in1], %[in1], %[inc], asl #1\n"
+ "sub %[in0], %[in0], %[inc], asl #1\n"
+ "vld1.32 {d18, d19}, [%[in1], :128]\n"
+ "vbic.s32 q11, q9, q14\n"
+ "vld1.32 {d16, d17}, [%[in0], :128]\n"
+ "vld1.32 {d2, d3}, [%[out1], :128]\n"
+ "vbic.s32 q3, q1, q14\n"
+ "vld1.32 {d0, d1}, [%[out0], :128]\n"
+ "vhsub.s32 q10, q8, q11\n"
+ "vhadd.s32 q11, q8, q11\n"
+ "vhsub.s32 q2, q0, q3\n"
+ "vhadd.s32 q3, q0, q3\n"
+ "vbif.s32 q10, q9, q15\n"
+ "vbif.s32 d22, d16, d30\n"
+ "sub %[inc], %[zero], %[inc], asl #1\n"
+ "sub %[i], %[blocks], #2\n"
+ "2:\n"
+ "vbif.s32 d23, d17, d31\n"
+ "vst1.32 {d20, d21}, [%[in1], :128], %[inc]\n"
+ "vbif.s32 d4, d2, d30\n"
+ "vld1.32 {d18, d19}, [%[in1], :128]\n"
+ "vbif.s32 d5, d3, d31\n"
+ "vst1.32 {d22, d23}, [%[in0], :128], %[inc]\n"
+ "vbif.s32 d6, d0, d30\n"
+ "vld1.32 {d16, d17}, [%[in0], :128]\n"
+ "vbif.s32 d7, d1, d31\n"
+ "vst1.32 {d4, d5}, [%[out1], :128], %[inc]\n"
+ "vbic.s32 q11, q9, q14\n"
+ "vld1.32 {d2, d3}, [%[out1], :128]\n"
+ "vst1.32 {d6, d7}, [%[out0], :128], %[inc]\n"
+ "vbic.s32 q3, q1, q14\n"
+ "vld1.32 {d0, d1}, [%[out0], :128]\n"
+ "vhsub.s32 q10, q8, q11\n"
+ "vhadd.s32 q11, q8, q11\n"
+ "vhsub.s32 q2, q0, q3\n"
+ "vhadd.s32 q3, q0, q3\n"
+ "vbif.s32 q10, q9, q15\n"
+ "vbif.s32 d22, d16, d30\n"
+ "subs %[i], %[i], #2\n"
+ "bgt 2b\n"
+ "sub %[inc], %[zero], %[inc], asr #1\n"
+ "vbif.s32 d23, d17, d31\n"
+ "vst1.32 {d20, d21}, [%[in1], :128]\n"
+ "vbif.s32 q2, q1, q15\n"
+ "vst1.32 {d22, d23}, [%[in0], :128]\n"
+ "vbif.s32 q3, q0, q15\n"
+ "vst1.32 {d4, d5}, [%[out1], :128]\n"
+ "vst1.32 {d6, d7}, [%[out0], :128]\n"
+ ".endm\n"
+
+ "vmov.s32 q14, #1\n"
+ "vmov.s32 q13, %[c2]\n"
+
+ "cmp %[i], #4\n"
+ "bne 8f\n"
+
+ "4:\n" /* 4 subbands */
+ "add %[in0], %[in], #0\n"
+ "add %[in1], %[in], #32\n"
+ "add %[out0], %[out], #0\n"
+ "add %[out1], %[out], #32\n"
+ "vmov.s32 q0, %[c1]\n"
+ "vadd.s32 q0, q0, q14\n"
+
+ "calc_scalefactors\n"
+
+ /* check whether to use joint stereo for subbands 0, 1, 2 */
+ "vadd.s32 q15, q0, q1\n"
+ "vadd.s32 q9, q2, q3\n"
+ "vmov.s32 d31[1], %[zero]\n" /* last subband -> no joint */
+ "vld1.32 {d16, d17}, [%[consts], :128]!\n"
+ "vcgt.s32 q15, q15, q9\n"
+
+ /* calculate and save to memory 'joint' variable */
+ /* update and save scale factors to memory */
+ " vand.s32 q8, q8, q15\n"
+ "vbit.s32 q0, q2, q15\n"
+ " vpadd.s32 d16, d16, d17\n"
+ "vbit.s32 q1, q3, q15\n"
+ " vpadd.s32 d16, d16, d16\n"
+ "vst1.32 {d0, d1}, [%[out0], :128]\n"
+ "vst1.32 {d2, d3}, [%[out1], :128]\n"
+ " vst1.32 {d16[0]}, [%[joint]]\n"
+
+ "update_joint_stereo_samples\n"
+ "b 9f\n"
+
+ "8:\n" /* 8 subbands */
+ "add %[in0], %[in], #16\n\n"
+ "add %[in1], %[in], #48\n"
+ "add %[out0], %[out], #16\n\n"
+ "add %[out1], %[out], #48\n"
+ "vmov.s32 q0, %[c1]\n"
+ "vadd.s32 q0, q0, q14\n"
+
+ "calc_scalefactors\n"
+
+ /* check whether to use joint stereo for subbands 4, 5, 6 */
+ "vadd.s32 q15, q0, q1\n"
+ "vadd.s32 q9, q2, q3\n"
+ "vmov.s32 d31[1], %[zero]\n" /* last subband -> no joint */
+ "vld1.32 {d16, d17}, [%[consts], :128]!\n"
+ "vcgt.s32 q15, q15, q9\n"
+
+ /* calculate part of 'joint' variable and save it to d24 */
+ /* update and save scale factors to memory */
+ " vand.s32 q8, q8, q15\n"
+ "vbit.s32 q0, q2, q15\n"
+ " vpadd.s32 d16, d16, d17\n"
+ "vbit.s32 q1, q3, q15\n"
+ "vst1.32 {d0, d1}, [%[out0], :128]\n"
+ "vst1.32 {d2, d3}, [%[out1], :128]\n"
+ " vpadd.s32 d24, d16, d16\n"
+
+ "update_joint_stereo_samples\n"
+
+ "add %[in0], %[in], #0\n"
+ "add %[in1], %[in], #32\n"
+ "add %[out0], %[out], #0\n\n"
+ "add %[out1], %[out], #32\n"
+ "vmov.s32 q0, %[c1]\n"
+ "vadd.s32 q0, q0, q14\n"
+
+ "calc_scalefactors\n"
+
+ /* check whether to use joint stereo for subbands 0, 1, 2, 3 */
+ "vadd.s32 q15, q0, q1\n"
+ "vadd.s32 q9, q2, q3\n"
+ "vld1.32 {d16, d17}, [%[consts], :128]!\n"
+ "vcgt.s32 q15, q15, q9\n"
+
+ /* combine last part of 'joint' with d24 and save to memory */
+ /* update and save scale factors to memory */
+ " vand.s32 q8, q8, q15\n"
+ "vbit.s32 q0, q2, q15\n"
+ " vpadd.s32 d16, d16, d17\n"
+ "vbit.s32 q1, q3, q15\n"
+ " vpadd.s32 d16, d16, d16\n"
+ "vst1.32 {d0, d1}, [%[out0], :128]\n"
+ " vadd.s32 d16, d16, d24\n"
+ "vst1.32 {d2, d3}, [%[out1], :128]\n"
+ " vst1.32 {d16[0]}, [%[joint]]\n"
+
+ "update_joint_stereo_samples\n"
+ "9:\n"
+ ".purgem calc_scalefactors\n"
+ ".purgem update_joint_stereo_samples\n"
+ :
+ [i] "+&r" (i),
+ [in] "+&r" (in),
+ [in0] "=&r" (in0),
+ [in1] "=&r" (in1),
+ [out] "+&r" (out),
+ [out0] "=&r" (out0),
+ [out1] "=&r" (out1),
+ [consts] "+&r" (consts)
+ :
+ [inc] "r" ((char *) &sb_sample_f[1][0][0] -
+ (char *) &sb_sample_f[0][0][0]),
+ [blocks] "r" (blocks),
+ [joint] "r" (&joint),
+ [c1] "i" (1 << SCALE_OUT_BITS),
+ [c2] "i" (31 - SCALE_OUT_BITS),
+ [zero] "r" (0)
+ : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "d16", "d17", "d18", "d19", "d20", "d21", "d22",
+ "d23", "d24", "d25", "d26", "d27", "d28", "d29",
+ "d30", "d31", "cc", "memory");
+
+ return joint;
+}
+
+#define PERM_BE(a, b, c, d) { \
+ (a * 2) + 1, (a * 2) + 0, \
+ (b * 2) + 1, (b * 2) + 0, \
+ (c * 2) + 1, (c * 2) + 0, \
+ (d * 2) + 1, (d * 2) + 0 \
+ }
+#define PERM_LE(a, b, c, d) { \
+ (a * 2) + 0, (a * 2) + 1, \
+ (b * 2) + 0, (b * 2) + 1, \
+ (c * 2) + 0, (c * 2) + 1, \
+ (d * 2) + 0, (d * 2) + 1 \
+ }
+
+static SBC_ALWAYS_INLINE int sbc_enc_process_input_4s_neon_internal(
+ int position,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels, int big_endian)
+{
+ static SBC_ALIGNED uint8_t perm_be[2][8] = {
+ PERM_BE(7, 3, 6, 4),
+ PERM_BE(0, 2, 1, 5)
+ };
+ static SBC_ALIGNED uint8_t perm_le[2][8] = {
+ PERM_LE(7, 3, 6, 4),
+ PERM_LE(0, 2, 1, 5)
+ };
+ /* handle X buffer wraparound */
+ if (position < nsamples) {
+ int16_t *dst = &X[0][SBC_X_BUFFER_SIZE - 40];
+ int16_t *src = &X[0][position];
+ asm volatile (
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0}, [%[src], :64]!\n"
+ "vst1.16 {d0}, [%[dst], :64]!\n"
+ :
+ [dst] "+r" (dst),
+ [src] "+r" (src)
+ : : "memory", "d0", "d1", "d2", "d3");
+ if (nchannels > 1) {
+ dst = &X[1][SBC_X_BUFFER_SIZE - 40];
+ src = &X[1][position];
+ asm volatile (
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0}, [%[src], :64]!\n"
+ "vst1.16 {d0}, [%[dst], :64]!\n"
+ :
+ [dst] "+r" (dst),
+ [src] "+r" (src)
+ : : "memory", "d0", "d1", "d2", "d3");
+ }
+ position = SBC_X_BUFFER_SIZE - 40;
+ }
+
+ if ((nchannels > 1) && ((uintptr_t)pcm & 1)) {
+ /* poor 'pcm' alignment */
+ int16_t *x = &X[0][position];
+ int16_t *y = &X[1][position];
+ asm volatile (
+ "vld1.8 {d0, d1}, [%[perm], :128]\n"
+ "1:\n"
+ "sub %[x], %[x], #16\n"
+ "sub %[y], %[y], #16\n"
+ "sub %[position], %[position], #8\n"
+ "vld1.8 {d4, d5}, [%[pcm]]!\n"
+ "vuzp.16 d4, d5\n"
+ "vld1.8 {d20, d21}, [%[pcm]]!\n"
+ "vuzp.16 d20, d21\n"
+ "vswp d5, d20\n"
+ "vtbl.8 d16, {d4, d5}, d0\n"
+ "vtbl.8 d17, {d4, d5}, d1\n"
+ "vtbl.8 d18, {d20, d21}, d0\n"
+ "vtbl.8 d19, {d20, d21}, d1\n"
+ "vst1.16 {d16, d17}, [%[x], :128]\n"
+ "vst1.16 {d18, d19}, [%[y], :128]\n"
+ "subs %[nsamples], %[nsamples], #8\n"
+ "bgt 1b\n"
+ :
+ [x] "+r" (x),
+ [y] "+r" (y),
+ [pcm] "+r" (pcm),
+ [nsamples] "+r" (nsamples),
+ [position] "+r" (position)
+ :
+ [perm] "r" (big_endian ? perm_be : perm_le)
+ : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+ "d5", "d6", "d7", "d16", "d17", "d18", "d19",
+ "d20", "d21", "d22", "d23");
+ } else if (nchannels > 1) {
+ /* proper 'pcm' alignment */
+ int16_t *x = &X[0][position];
+ int16_t *y = &X[1][position];
+ asm volatile (
+ "vld1.8 {d0, d1}, [%[perm], :128]\n"
+ "1:\n"
+ "sub %[x], %[x], #16\n"
+ "sub %[y], %[y], #16\n"
+ "sub %[position], %[position], #8\n"
+ "vld2.16 {d4, d5}, [%[pcm]]!\n"
+ "vld2.16 {d20, d21}, [%[pcm]]!\n"
+ "vswp d5, d20\n"
+ "vtbl.8 d16, {d4, d5}, d0\n"
+ "vtbl.8 d17, {d4, d5}, d1\n"
+ "vtbl.8 d18, {d20, d21}, d0\n"
+ "vtbl.8 d19, {d20, d21}, d1\n"
+ "vst1.16 {d16, d17}, [%[x], :128]\n"
+ "vst1.16 {d18, d19}, [%[y], :128]\n"
+ "subs %[nsamples], %[nsamples], #8\n"
+ "bgt 1b\n"
+ :
+ [x] "+r" (x),
+ [y] "+r" (y),
+ [pcm] "+r" (pcm),
+ [nsamples] "+r" (nsamples),
+ [position] "+r" (position)
+ :
+ [perm] "r" (big_endian ? perm_be : perm_le)
+ : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+ "d5", "d6", "d7", "d16", "d17", "d18", "d19",
+ "d20", "d21", "d22", "d23");
+ } else {
+ int16_t *x = &X[0][position];
+ asm volatile (
+ "vld1.8 {d0, d1}, [%[perm], :128]\n"
+ "1:\n"
+ "sub %[x], %[x], #16\n"
+ "sub %[position], %[position], #8\n"
+ "vld1.8 {d4, d5}, [%[pcm]]!\n"
+ "vtbl.8 d16, {d4, d5}, d0\n"
+ "vtbl.8 d17, {d4, d5}, d1\n"
+ "vst1.16 {d16, d17}, [%[x], :128]\n"
+ "subs %[nsamples], %[nsamples], #8\n"
+ "bgt 1b\n"
+ :
+ [x] "+r" (x),
+ [pcm] "+r" (pcm),
+ [nsamples] "+r" (nsamples),
+ [position] "+r" (position)
+ :
+ [perm] "r" (big_endian ? perm_be : perm_le)
+ : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+ "d5", "d6", "d7", "d16", "d17", "d18", "d19");
+ }
+ return position;
+}
+
+static SBC_ALWAYS_INLINE int sbc_enc_process_input_8s_neon_internal(
+ int position,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels, int big_endian)
+{
+ static SBC_ALIGNED uint8_t perm_be[4][8] = {
+ PERM_BE(15, 7, 14, 8),
+ PERM_BE(13, 9, 12, 10),
+ PERM_BE(11, 3, 6, 0),
+ PERM_BE(5, 1, 4, 2)
+ };
+ static SBC_ALIGNED uint8_t perm_le[4][8] = {
+ PERM_LE(15, 7, 14, 8),
+ PERM_LE(13, 9, 12, 10),
+ PERM_LE(11, 3, 6, 0),
+ PERM_LE(5, 1, 4, 2)
+ };
+ /* handle X buffer wraparound */
+ if (position < nsamples) {
+ int16_t *dst = &X[0][SBC_X_BUFFER_SIZE - 72];
+ int16_t *src = &X[0][position];
+ asm volatile (
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0, d1}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1}, [%[dst], :128]!\n"
+ :
+ [dst] "+r" (dst),
+ [src] "+r" (src)
+ : : "memory", "d0", "d1", "d2", "d3");
+ if (nchannels > 1) {
+ dst = &X[1][SBC_X_BUFFER_SIZE - 72];
+ src = &X[1][position];
+ asm volatile (
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+ "vld1.16 {d0, d1}, [%[src], :128]!\n"
+ "vst1.16 {d0, d1}, [%[dst], :128]!\n"
+ :
+ [dst] "+r" (dst),
+ [src] "+r" (src)
+ : : "memory", "d0", "d1", "d2", "d3");
+ }
+ position = SBC_X_BUFFER_SIZE - 72;
+ }
+
+ if ((nchannels > 1) && ((uintptr_t)pcm & 1)) {
+ /* poor 'pcm' alignment */
+ int16_t *x = &X[0][position];
+ int16_t *y = &X[1][position];
+ asm volatile (
+ "vld1.8 {d0, d1, d2, d3}, [%[perm], :128]\n"
+ "1:\n"
+ "sub %[x], %[x], #32\n"
+ "sub %[y], %[y], #32\n"
+ "sub %[position], %[position], #16\n"
+ "vld1.8 {d4, d5, d6, d7}, [%[pcm]]!\n"
+ "vuzp.16 q2, q3\n"
+ "vld1.8 {d20, d21, d22, d23}, [%[pcm]]!\n"
+ "vuzp.16 q10, q11\n"
+ "vswp q3, q10\n"
+ "vtbl.8 d16, {d4, d5, d6, d7}, d0\n"
+ "vtbl.8 d17, {d4, d5, d6, d7}, d1\n"
+ "vtbl.8 d18, {d4, d5, d6, d7}, d2\n"
+ "vtbl.8 d19, {d4, d5, d6, d7}, d3\n"
+ "vst1.16 {d16, d17, d18, d19}, [%[x], :128]\n"
+ "vtbl.8 d16, {d20, d21, d22, d23}, d0\n"
+ "vtbl.8 d17, {d20, d21, d22, d23}, d1\n"
+ "vtbl.8 d18, {d20, d21, d22, d23}, d2\n"
+ "vtbl.8 d19, {d20, d21, d22, d23}, d3\n"
+ "vst1.16 {d16, d17, d18, d19}, [%[y], :128]\n"
+ "subs %[nsamples], %[nsamples], #16\n"
+ "bgt 1b\n"
+ :
+ [x] "+r" (x),
+ [y] "+r" (y),
+ [pcm] "+r" (pcm),
+ [nsamples] "+r" (nsamples),
+ [position] "+r" (position)
+ :
+ [perm] "r" (big_endian ? perm_be : perm_le)
+ : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+ "d5", "d6", "d7", "d16", "d17", "d18", "d19",
+ "d20", "d21", "d22", "d23");
+ } else if (nchannels > 1) {
+ /* proper 'pcm' alignment */
+ int16_t *x = &X[0][position];
+ int16_t *y = &X[1][position];
+ asm volatile (
+ "vld1.8 {d0, d1, d2, d3}, [%[perm], :128]\n"
+ "1:\n"
+ "sub %[x], %[x], #32\n"
+ "sub %[y], %[y], #32\n"
+ "sub %[position], %[position], #16\n"
+ "vld2.16 {d4, d5, d6, d7}, [%[pcm]]!\n"
+ "vld2.16 {d20, d21, d22, d23}, [%[pcm]]!\n"
+ "vswp q3, q10\n"
+ "vtbl.8 d16, {d4, d5, d6, d7}, d0\n"
+ "vtbl.8 d17, {d4, d5, d6, d7}, d1\n"
+ "vtbl.8 d18, {d4, d5, d6, d7}, d2\n"
+ "vtbl.8 d19, {d4, d5, d6, d7}, d3\n"
+ "vst1.16 {d16, d17, d18, d19}, [%[x], :128]\n"
+ "vtbl.8 d16, {d20, d21, d22, d23}, d0\n"
+ "vtbl.8 d17, {d20, d21, d22, d23}, d1\n"
+ "vtbl.8 d18, {d20, d21, d22, d23}, d2\n"
+ "vtbl.8 d19, {d20, d21, d22, d23}, d3\n"
+ "vst1.16 {d16, d17, d18, d19}, [%[y], :128]\n"
+ "subs %[nsamples], %[nsamples], #16\n"
+ "bgt 1b\n"
+ :
+ [x] "+r" (x),
+ [y] "+r" (y),
+ [pcm] "+r" (pcm),
+ [nsamples] "+r" (nsamples),
+ [position] "+r" (position)
+ :
+ [perm] "r" (big_endian ? perm_be : perm_le)
+ : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+ "d5", "d6", "d7", "d16", "d17", "d18", "d19",
+ "d20", "d21", "d22", "d23");
+ } else {
+ int16_t *x = &X[0][position];
+ asm volatile (
+ "vld1.8 {d0, d1, d2, d3}, [%[perm], :128]\n"
+ "1:\n"
+ "sub %[x], %[x], #32\n"
+ "sub %[position], %[position], #16\n"
+ "vld1.8 {d4, d5, d6, d7}, [%[pcm]]!\n"
+ "vtbl.8 d16, {d4, d5, d6, d7}, d0\n"
+ "vtbl.8 d17, {d4, d5, d6, d7}, d1\n"
+ "vtbl.8 d18, {d4, d5, d6, d7}, d2\n"
+ "vtbl.8 d19, {d4, d5, d6, d7}, d3\n"
+ "vst1.16 {d16, d17, d18, d19}, [%[x], :128]\n"
+ "subs %[nsamples], %[nsamples], #16\n"
+ "bgt 1b\n"
+ :
+ [x] "+r" (x),
+ [pcm] "+r" (pcm),
+ [nsamples] "+r" (nsamples),
+ [position] "+r" (position)
+ :
+ [perm] "r" (big_endian ? perm_be : perm_le)
+ : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+ "d5", "d6", "d7", "d16", "d17", "d18", "d19");
+ }
+ return position;
+}
+
+#undef PERM_BE
+#undef PERM_LE
+
+static int sbc_enc_process_input_4s_be_neon(int position, const uint8_t *pcm,
+ int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
+{
+ return sbc_enc_process_input_4s_neon_internal(
+ position, pcm, X, nsamples, nchannels, 1);
+}
+
+static int sbc_enc_process_input_4s_le_neon(int position, const uint8_t *pcm,
+ int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
+{
+ return sbc_enc_process_input_4s_neon_internal(
+ position, pcm, X, nsamples, nchannels, 0);
+}
+
+static int sbc_enc_process_input_8s_be_neon(int position, const uint8_t *pcm,
+ int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
+{
+ return sbc_enc_process_input_8s_neon_internal(
+ position, pcm, X, nsamples, nchannels, 1);
+}
+
+static int sbc_enc_process_input_8s_le_neon(int position, const uint8_t *pcm,
+ int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
+{
+ return sbc_enc_process_input_8s_neon_internal(
+ position, pcm, X, nsamples, nchannels, 0);
+}
+
void sbc_init_primitives_neon(struct sbc_encoder_state *state)
{
state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_neon;
state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_neon;
+ state->sbc_calc_scalefactors = sbc_calc_scalefactors_neon;
+ state->sbc_calc_scalefactors_j = sbc_calc_scalefactors_j_neon;
+ state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le_neon;
+ state->sbc_enc_process_input_4s_be = sbc_enc_process_input_4s_be_neon;
+ state->sbc_enc_process_input_8s_le = sbc_enc_process_input_8s_le_neon;
+ state->sbc_enc_process_input_8s_be = sbc_enc_process_input_8s_be_neon;
state->implementation_info = "NEON";
}
--- sbc/sbcenc.c
+++ sbc/sbcenc.c
@@ -50,7 +50,7 @@
struct au_header au_hdr;
sbc_t sbc;
int fd, size, srate, codesize, nframes;
- size_t encoded;
+ ssize_t encoded;
ssize_t len;
if (sizeof(au_hdr) != 24) {
--- src/adapter.c
+++ src/adapter.c
@@ -105,6 +105,7 @@
uint8_t mode; /* off, connectable, discoverable,
* limited */
uint8_t global_mode; /* last valid global mode */
+ struct session_req *pending_mode;
int state; /* standard inq, periodic inq, name
* resloving */
GSList *found_devices;
@@ -412,10 +413,47 @@
adapter->pending_cod = adapter->wanted_cod;
}
-static int set_mode(struct btd_adapter *adapter, uint8_t new_mode)
+static struct session_req *session_ref(struct session_req *req)
+{
+ req->refcount++;
+
+ DBG("%p: ref=%d", req, req->refcount);
+
+ return req;
+}
+
+static struct session_req *create_session(struct btd_adapter *adapter,
+ DBusConnection *conn, DBusMessage *msg,
+ uint8_t mode, GDBusWatchFunction cb)
+{
+ const char *sender = dbus_message_get_sender(msg);
+ struct session_req *req;
+
+ req = g_new0(struct session_req, 1);
+ req->adapter = adapter;
+ req->conn = dbus_connection_ref(conn);
+ req->msg = dbus_message_ref(msg);
+ req->mode = mode;
+
+ if (cb == NULL)
+ return session_ref(req);
+
+ req->owner = g_strdup(sender);
+ req->id = g_dbus_add_disconnect_watch(conn, sender, cb, req, NULL);
+
+ info("%s session %p with %s activated",
+ req->mode ? "Mode" : "Discovery", req, sender);
+
+ return session_ref(req);
+}
+
+static int set_mode(struct btd_adapter *adapter, uint8_t new_mode,
+ DBusMessage *msg)
{
int err;
- const char *modestr;
+
+ if (adapter->pending_mode != NULL)
+ return -EALREADY;
if (!adapter->up && new_mode != MODE_OFF) {
err = adapter_ops->set_powered(adapter->dev_id, TRUE);
@@ -456,11 +494,18 @@
}
done:
- modestr = mode2str(new_mode);
+ DBG("%s", mode2str(new_mode));
- write_device_mode(&adapter->bdaddr, modestr);
-
- adapter->mode = new_mode;
+ if (msg != NULL)
+ /* Wait for mode change to reply */
+ adapter->pending_mode = create_session(adapter, connection,
+ msg, new_mode, NULL);
+ else {
+ /* Nothing to reply just write the new mode */
+ const char *modestr = mode2str(new_mode);
+ adapter->mode = new_mode;
+ write_device_mode(&adapter->bdaddr, modestr);
+ }
return 0;
}
@@ -477,7 +522,7 @@
if (mode == adapter->mode)
return dbus_message_new_method_return(msg);
- err = set_mode(adapter, mode);
+ err = set_mode(adapter, mode, NULL);
if (err < 0)
return failed_strerror(msg, -err);
@@ -501,11 +546,11 @@
if (mode == adapter->mode)
return dbus_message_new_method_return(msg);
- err = set_mode(adapter, mode);
+ err = set_mode(adapter, mode, msg);
if (err < 0)
return failed_strerror(msg, -err);
- return dbus_message_new_method_return(msg);
+ return 0;
}
static DBusMessage *set_pairable(DBusConnection *conn, DBusMessage *msg,
@@ -521,6 +566,19 @@
if (pairable == adapter->pairable)
goto done;
+ if (!(adapter->scan_mode & SCAN_INQUIRY))
+ goto store;
+
+ mode = (pairable && adapter->discov_timeout > 0 &&
+ adapter->discov_timeout <= 60) ?
+ MODE_LIMITED : MODE_DISCOVERABLE;
+
+ err = set_mode(adapter, mode, NULL);
+ if (err < 0 && msg)
+ return failed_strerror(msg, -err);
+
+store:
+
adapter->pairable = pairable;
write_device_pairable(&adapter->bdaddr, pairable);
@@ -533,17 +591,6 @@
adapter_set_pairable_timeout(adapter,
adapter->pairable_timeout);
- if (!(adapter->scan_mode & SCAN_INQUIRY))
- goto done;
-
- mode = (pairable && adapter->discov_timeout > 0 &&
- adapter->discov_timeout <= 60) ?
- MODE_LIMITED : MODE_DISCOVERABLE;
-
- err = set_mode(adapter, mode);
- if (err < 0 && msg)
- return failed_strerror(msg, -err);
-
done:
return msg ? dbus_message_new_method_return(msg) : NULL;
}
@@ -606,6 +653,13 @@
{
struct btd_adapter *adapter = req->adapter;
+ /* Ignore set_mode session */
+ if (req->owner == NULL)
+ return;
+
+ DBG("%s session %p with %s deactivated",
+ req->mode ? "Mode" : "Discovery", req, req->owner);
+
if (req->mode) {
uint8_t mode;
@@ -619,7 +673,7 @@
DBG("Switching to '%s' mode", mode2str(mode));
- set_mode(adapter, mode);
+ set_mode(adapter, mode, NULL);
} else {
adapter->disc_sessions = g_slist_remove(adapter->disc_sessions,
req);
@@ -647,9 +701,6 @@
static void session_free(struct session_req *req)
{
- DBG("%s session %p with %s deactivated",
- req->mode ? "Mode" : "Discovery", req, req->owner);
-
if (req->id)
g_dbus_remove_watch(req->conn, req->id);
@@ -672,20 +723,11 @@
session_free(req);
}
-static struct session_req *session_ref(struct session_req *req)
-{
- req->refcount++;
-
- DBG("session_ref(%p): ref=%d", req, req->refcount);
-
- return req;
-}
-
static void session_unref(struct session_req *req)
{
req->refcount--;
- DBG("session_unref(%p): ref=%d", req, req->refcount);
+ DBG("%p: ref=%d", req, req->refcount);
if (req->refcount)
return;
@@ -693,30 +735,6 @@
session_free(req);
}
-static struct session_req *create_session(struct btd_adapter *adapter,
- DBusConnection *conn, DBusMessage *msg,
- uint8_t mode, GDBusWatchFunction cb)
-{
- struct session_req *req;
- const char *sender = dbus_message_get_sender(msg);
-
- req = g_new0(struct session_req, 1);
- req->adapter = adapter;
- req->conn = dbus_connection_ref(conn);
- req->msg = dbus_message_ref(msg);
- req->owner = g_strdup(dbus_message_get_sender(msg));
- req->mode = mode;
-
- if (cb)
- req->id = g_dbus_add_disconnect_watch(conn, sender, cb, req,
- NULL);
-
- info("%s session %p with %s activated",
- req->mode ? "Mode" : "Discovery", req, sender);
-
- return session_ref(req);
-}
-
static void confirm_mode_cb(struct agent *agent, DBusError *derr, void *data)
{
struct session_req *req = data;
@@ -731,7 +749,7 @@
return;
}
- err = set_mode(req->adapter, req->mode);
+ err = set_mode(req->adapter, req->mode, NULL);
if (err < 0)
reply = failed_strerror(req->msg, -err);
else
@@ -1118,7 +1136,7 @@
struct btd_device *device;
const char *path;
- DBG("adapter_create_device(%s)", address);
+ DBG("%s", address);
device = device_create(conn, adapter, address);
if (!device)
@@ -1170,7 +1188,7 @@
{
struct btd_device *device;
- DBG("adapter_get_device(%s)", address);
+ DBG("%s", address);
if (!adapter)
return NULL;
@@ -1586,7 +1604,7 @@
ERROR_INTERFACE ".AlreadyExists",
"Device already exists");
- DBG("create_device(%s)", address);
+ DBG("%s", address);
device = adapter_create_device(conn, adapter, address);
if (!device)
@@ -2498,7 +2516,7 @@
agent_free(adapter->agent);
adapter->agent = NULL;
- DBG("adapter_free(%p)", adapter);
+ DBG("%p", adapter);
if (adapter->auth_idle_id)
g_source_remove(adapter->auth_idle_id);
@@ -2511,7 +2529,7 @@
{
adapter->ref++;
- DBG("btd_adapter_ref(%p): ref=%d", adapter, adapter->ref);
+ DBG("%p: ref=%d", adapter, adapter->ref);
return adapter;
}
@@ -2522,7 +2540,7 @@
adapter->ref--;
- DBG("btd_adapter_unref(%p): ref=%d", adapter, adapter->ref);
+ DBG("%p: ref=%d", adapter, adapter->ref);
if (adapter->ref > 0)
return;
@@ -2848,6 +2866,45 @@
adapter->oor_devices = g_slist_copy(adapter->found_devices);
}
+static void set_mode_complete(struct btd_adapter *adapter)
+{
+ struct session_req *pending;
+ const char *modestr;
+ int err;
+
+ if (adapter->pending_mode == NULL)
+ return;
+
+ pending = adapter->pending_mode;
+ adapter->pending_mode = NULL;
+
+ err = (pending->mode != adapter->mode) ? -EINVAL : 0;
+
+ if (pending->msg != NULL) {
+ DBusMessage *msg = pending->msg;
+ DBusMessage *reply;
+
+ if (err < 0)
+ reply = failed_strerror(msg, -err);
+ else
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+
+ g_dbus_send_message(connection, reply);
+ }
+
+ modestr = mode2str(adapter->mode);
+
+ DBG("%s", modestr);
+
+ /* Only store if the mode matches the pending */
+ if (err == 0)
+ write_device_mode(&adapter->bdaddr, modestr);
+ else
+ error("unable to set mode: %s", mode2str(pending->mode));
+
+ session_unref(pending);
+}
+
void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode)
{
const gchar *path = adapter_get_path(adapter);
@@ -2907,6 +2964,8 @@
DBUS_TYPE_BOOLEAN, &discoverable);
adapter->scan_mode = scan_mode;
+
+ set_mode_complete(adapter);
}
struct agent *adapter_get_agent(struct btd_adapter *adapter)
@@ -3198,6 +3257,17 @@
return 0;
return adapter_ops->set_powered(adapter->dev_id, TRUE);
+}
+
+int btd_adapter_switch_online(struct btd_adapter *adapter)
+{
+ if (!adapter_ops)
+ return -EINVAL;
+
+ if (adapter->up)
+ return 0;
+
+ return adapter_ops->set_powered(adapter->dev_id, TRUE);
}
int btd_adapter_switch_offline(struct btd_adapter *adapter)
--- src/adapter.h
+++ src/adapter.h
@@ -163,6 +163,7 @@
gboolean adapter_powering_down(struct btd_adapter *adapter);
int btd_adapter_restore_powered(struct btd_adapter *adapter);
+int btd_adapter_switch_online(struct btd_adapter *adapter);
int btd_adapter_switch_offline(struct btd_adapter *adapter);
struct btd_adapter_ops {
--- src/btio.c
+++ src/btio.c
@@ -57,6 +57,7 @@
uint16_t imtu;
uint16_t omtu;
int master;
+ uint8_t mode;
};
struct connect {
@@ -474,10 +475,10 @@
return TRUE;
}
-static gboolean l2cap_set(int sock, int sec_level, uint16_t imtu,
- uint16_t omtu, int master, GError **err)
+static gboolean l2cap_set(int sock, int sec_level, uint16_t imtu, uint16_t omtu,
+ uint8_t mode, int master, GError **err)
{
- if (imtu || omtu) {
+ if (imtu || omtu || mode) {
struct l2cap_options l2o;
socklen_t len;
@@ -493,6 +494,8 @@
l2o.imtu = imtu;
if (omtu)
l2o.omtu = omtu;
+ if (mode)
+ l2o.mode = mode;
if (setsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o,
sizeof(l2o)) < 0) {
@@ -629,6 +632,7 @@
opts->defer = DEFAULT_DEFER_TIMEOUT;
opts->master = -1;
opts->sec_level = BT_IO_SEC_MEDIUM;
+ opts->mode = L2CAP_MODE_BASIC;
while (opt != BT_IO_OPT_INVALID) {
switch (opt) {
@@ -678,6 +682,9 @@
case BT_IO_OPT_MASTER:
opts->master = va_arg(args, gboolean);
break;
+ case BT_IO_OPT_MODE:
+ opts->mode = va_arg(args, int);
+ break;
default:
g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
"Unknown option %d", opt);
@@ -1088,7 +1095,7 @@
case BT_IO_L2RAW:
case BT_IO_L2CAP:
return l2cap_set(sock, opts.sec_level, opts.imtu, opts.omtu,
- opts.master, err);
+ opts.mode, opts.master, err);
case BT_IO_RFCOMM:
return rfcomm_set(sock, opts.sec_level, opts.master, err);
case BT_IO_SCO:
@@ -1129,7 +1136,7 @@
if (l2cap_bind(sock, &opts->src,
server ? opts->psm : 0, err) < 0)
goto failed;
- if (!l2cap_set(sock, opts->sec_level, 0, 0, -1, err))
+ if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, err))
goto failed;
break;
case BT_IO_L2CAP:
@@ -1142,7 +1149,7 @@
server ? opts->psm : 0, err) < 0)
goto failed;
if (!l2cap_set(sock, opts->sec_level, opts->imtu, opts->omtu,
- opts->master, err))
+ opts->mode, opts->master, err))
goto failed;
break;
case BT_IO_RFCOMM:
--- src/btio.h
+++ src/btio.h
@@ -60,6 +60,7 @@
BT_IO_OPT_MASTER,
BT_IO_OPT_HANDLE,
BT_IO_OPT_CLASS,
+ BT_IO_OPT_MODE,
} BtIOOption;
typedef enum {
--- src/dbus-hci.c
+++ src/dbus-hci.c
@@ -418,7 +418,7 @@
struct btd_adapter *adapter;
struct btd_device *device;
- DBG("hcid_dbus_bonding_process_complete: status=%02x", status);
+ DBG("status=%02x", status);
if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
return;
@@ -427,7 +427,7 @@
/* This means that there was no pending PIN or SSP token
* request from the controller, i.e. this is not a new
* pairing */
- DBG("hcid_dbus_bonding_process_complete: no pending auth request");
+ DBG("no pending auth request");
return;
}
@@ -442,7 +442,7 @@
struct btd_adapter *adapter;
struct btd_device *device;
- DBG("hcid_dbus_simple_pairing_complete: status=%02x", status);
+ DBG("status=%02x", status);
if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
return;
@@ -681,12 +681,19 @@
old_key_type = 0x03;
if (old_key_type != 0xff)
new_key_type = old_key_type;
+ else
+ /* This is Changed Combination Link Key for
+ * a temporary link key.*/
+ return 0;
}
get_auth_requirements(local, peer, &local_auth);
remote_auth = device_get_auth(device);
bonding = device_is_bonding(device, NULL);
+ DBG("key type 0x%02x old key type 0x%02x new key type 0x%02x",
+ key_type, old_key_type, new_key_type);
+
DBG("local auth 0x%02x and remote auth 0x%02x",
local_auth, remote_auth);
--- src/dbus-hci.h
+++ src/dbus-hci.h
@@ -50,8 +50,6 @@
struct btd_device **device,
gboolean create);
-DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status);
-
const char *class_to_icon(uint32_t class);
void set_dbus_connection(DBusConnection *conn);
--- src/device.c
+++ src/device.c
@@ -81,7 +81,6 @@
DBusConnection *conn;
DBusMessage *msg;
GIOChannel *io;
- guint io_id;
guint listener_id;
struct btd_device *device;
};
@@ -157,14 +156,6 @@
static GSList *device_drivers = NULL;
-static DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn,
- DBusMessage *msg, int err)
-{
- return error_common_reply(conn, msg,
- ERROR_INTERFACE ".ConnectionAttemptFailed",
- err > 0 ? strerror(err) : "Connection attempt failed");
-}
-
static DBusHandlerResult error_failed(DBusConnection *conn,
DBusMessage *msg, const char * desc)
{
@@ -251,7 +242,7 @@
if (device->discov_timer)
g_source_remove(device->discov_timer);
- DBG("device_free(%p)", device);
+ DBG("%p", device);
g_free(device->authr);
g_free(device->path);
@@ -513,7 +504,8 @@
return 0;
}
-static int device_unblock(DBusConnection *conn, struct btd_device *device)
+static int device_unblock(DBusConnection *conn, struct btd_device *device,
+ gboolean silent)
{
int dev_id, dd, err;
bdaddr_t src;
@@ -543,10 +535,12 @@
if (err < 0)
error("write_blocked(): %s (%d)", strerror(-err), -err);
- emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Blocked",
+ if (!silent) {
+ emit_property_changed(conn, device->path,
+ DEVICE_INTERFACE, "Blocked",
DBUS_TYPE_BOOLEAN, &device->blocked);
-
- device_probe_drivers(device, device->uuids);
+ device_probe_drivers(device, device->uuids);
+ }
return 0;
}
@@ -560,7 +554,7 @@
if (value)
err = device_block(conn, device);
else
- err = device_unblock(conn, device);
+ err = device_unblock(conn, device, FALSE);
switch (-err) {
case 0:
@@ -794,11 +788,6 @@
if (!bonding->io)
return;
- if (bonding->io_id) {
- g_source_remove(bonding->io_id);
- bonding->io_id = 0;
- }
-
g_io_channel_shutdown(bonding->io, TRUE, NULL);
g_io_channel_unref(bonding->io);
bonding->io = NULL;
@@ -1100,6 +1089,7 @@
{
bdaddr_t src;
char addr[18];
+ DBusConnection *conn = get_dbus_connection();
adapter_get_address(device->adapter, &src);
ba2str(&device->bdaddr, addr);
@@ -1109,6 +1099,9 @@
delete_entry(&src, "profiles", addr);
delete_entry(&src, "trusts", addr);
delete_all_records(&src, &device->bdaddr);
+
+ if (device->blocked)
+ device_unblock(conn, device, TRUE);
}
void device_remove(struct btd_device *device, gboolean remove_stored)
@@ -1737,7 +1730,7 @@
return FALSE;
}
-DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status)
+static DBusMessage *new_authentication_return(DBusMessage *msg, int status)
{
switch (status) {
case 0x00: /* success */
@@ -1808,9 +1801,6 @@
if (bonding->conn)
dbus_connection_unref(bonding->conn);
- if (bonding->io_id)
- g_source_remove(bonding->io_id);
-
if (bonding->io)
g_io_channel_unref(bonding->io);
@@ -1891,63 +1881,19 @@
return bonding;
}
-static gboolean bonding_io_cb(GIOChannel *io, GIOCondition cond,
- gpointer user_data)
-{
- struct btd_device *device = user_data;
- DBusMessage *reply;
-
- if (!device->bonding)
- return FALSE;
-
- reply = new_authentication_return(device->bonding->msg,
- HCI_CONNECTION_TERMINATED);
- g_dbus_send_message(device->bonding->conn, reply);
-
- bonding_request_free(device->bonding);
-
- return FALSE;
-}
-
-static void bonding_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+static int device_authentication_requested(struct btd_device *device,
+ int handle)
{
- struct btd_device *device = user_data;
struct hci_request rq;
auth_requested_cp cp;
evt_cmd_status rp;
int dd;
- uint16_t handle;
-
- if (!device->bonding) {
- if (!err)
- g_io_channel_shutdown(io, TRUE, NULL);
- return;
- }
-
- if (err) {
- error("%s", err->message);
- error_connection_attempt_failed(device->bonding->conn,
- device->bonding->msg,
- ENETDOWN);
- goto cleanup;
- }
-
- if (!bt_io_get(io, BT_IO_L2RAW, &err,
- BT_IO_OPT_HANDLE, &handle,
- BT_IO_OPT_INVALID)) {
- error("Unable to get connection handle: %s", err->message);
- error_connection_attempt_failed(device->bonding->conn,
- device->bonding->msg,
- ENETDOWN);
- g_error_free(err);
- goto failed;
- }
dd = hci_open_dev(adapter_get_dev_id(device->adapter));
if (dd < 0) {
- DBusMessage *reply = no_such_adapter(device->bonding->msg);
- g_dbus_send_message(device->bonding->conn, reply);
- goto failed;
+ int err = -errno;
+ error("Unable to open adapter: %s(%d)", strerror(-err), -err);
+ return err;
}
memset(&rp, 0, sizeof(rp));
@@ -1965,37 +1911,60 @@
rq.event = EVT_CMD_STATUS;
if (hci_send_req(dd, &rq, HCI_REQ_TIMEOUT) < 0) {
+ int err = -errno;
error("Unable to send HCI request: %s (%d)",
- strerror(errno), errno);
- error_failed_errno(device->bonding->conn, device->bonding->msg,
- errno);
+ strerror(-err), -err);
hci_close_dev(dd);
- goto failed;
+ return err;
}
if (rp.status) {
error("HCI_Authentication_Requested failed with status 0x%02x",
rp.status);
- error_failed_errno(device->bonding->conn, device->bonding->msg,
- bt_error(rp.status));
hci_close_dev(dd);
- goto failed;
+ return rp.status;
}
+ info("Authentication requested");
+
hci_close_dev(dd);
+ return 0;
+}
+
+static void bonding_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+{
+ struct btd_device *device = user_data;
+ uint16_t handle;
+ int status;
+
+ if (!device->bonding) {
+ if (!err)
+ g_io_channel_shutdown(io, TRUE, NULL);
+ return;
+ }
+
+ if (err)
+ /* Wait proper error to be propagated by bonding complete */
+ return;
+
+ if (!bt_io_get(io, BT_IO_L2RAW, &err,
+ BT_IO_OPT_HANDLE, &handle,
+ BT_IO_OPT_INVALID)) {
+ error("Unable to get connection handle: %s", err->message);
+ g_error_free(err);
+ status = -errno;
+ goto failed;
+ }
- device->bonding->io_id = g_io_add_watch(io,
- G_IO_NVAL | G_IO_HUP | G_IO_ERR,
- bonding_io_cb, device);
+ status = device_authentication_requested(device, handle);
+ if (status != 0)
+ goto failed;
return;
failed:
g_io_channel_shutdown(io, TRUE, NULL);
-
-cleanup:
- device->bonding->io_id = 0;
- bonding_request_free(device->bonding);
+ device_cancel_bonding(device, status);
}
static void create_bond_req_exit(DBusConnection *conn, void *user_data)
@@ -2108,6 +2077,7 @@
agent_cancel(auth->agent);
if (status) {
+ device_cancel_authentication(device, TRUE);
device_cancel_bonding(device, status);
return;
}
@@ -2267,11 +2237,7 @@
DBG("%s: requesting agent authentication", device->path);
- agent = device->agent;
-
- if (!agent)
- agent = adapter_get_agent(device->adapter);
-
+ agent = device_get_agent(device);
if (!agent) {
error("No agent available for %u request", type);
return -EPERM;
@@ -2473,7 +2439,7 @@
{
device->ref++;
- DBG("btd_device_ref(%p): ref=%d", device, device->ref);
+ DBG("%p: ref=%d", device, device->ref);
return device;
}
@@ -2485,7 +2451,7 @@
device->ref--;
- DBG("btd_device_unref(%p): ref=%d", device, device->ref);
+ DBG("%p: ref=%d", device, device->ref);
if (device->ref > 0)
return;
--- src/log.c
+++ src/log.c
@@ -73,21 +73,21 @@
static gboolean is_enabled(struct btd_debug_desc *desc)
{
- int i;
+ int i;
- if (enabled == NULL)
- return 0;
+ if (enabled == NULL)
+ return 0;
- for (i = 0; enabled[i] != NULL; i++) {
- if (desc->name != NULL && g_pattern_match_simple(enabled[i],
- desc->name) == TRUE)
- return 1;
- if (desc->file != NULL && g_pattern_match_simple(enabled[i],
- desc->file) == TRUE)
- return 1;
- }
+ for (i = 0; enabled[i] != NULL; i++) {
+ if (desc->name != NULL && g_pattern_match_simple(enabled[i],
+ desc->name) == TRUE)
+ return 1;
+ if (desc->file != NULL && g_pattern_match_simple(enabled[i],
+ desc->file) == TRUE)
+ return 1;
+ }
- return 0;
+ return 0;
}
void __btd_toggle_debug()
--- src/log.h
+++ src/log.h
@@ -31,11 +31,11 @@
void __btd_toggle_debug();
struct btd_debug_desc {
- const char *name;
- const char *file;
+ const char *name;
+ const char *file;
#define BTD_DEBUG_FLAG_DEFAULT (0)
#define BTD_DEBUG_FLAG_PRINT (1 << 0)
- unsigned int flags;
+ unsigned int flags;
} __attribute__((aligned(8)));
/**
@@ -47,12 +47,11 @@
* name it is called in.
*/
#define DBG(fmt, arg...) do { \
- static struct btd_debug_desc __btd_debug_desc \
- __attribute__((used, section("__debug"), aligned(8))) = { \
- .file = __FILE__, .flags = BTD_DEBUG_FLAG_DEFAULT, \
- }; \
- if (__btd_debug_desc.flags & BTD_DEBUG_FLAG_PRINT) \
- btd_debug("%s:%s() " fmt, \
- __FILE__, __FUNCTION__ , ## arg); \
+ static struct btd_debug_desc __btd_debug_desc \
+ __attribute__((used, section("__debug"), aligned(8))) = { \
+ .file = __FILE__, .flags = BTD_DEBUG_FLAG_DEFAULT, \
+ }; \
+ if (__btd_debug_desc.flags & BTD_DEBUG_FLAG_PRINT) \
+ btd_debug("%s:%s() " fmt, __FILE__, __FUNCTION__ , ## arg); \
} while (0)
--- src/main.c
+++ src/main.c
@@ -302,6 +302,7 @@
static gchar *option_debug = NULL;
static gboolean option_detach = TRUE;
+static gboolean option_version = FALSE;
static gboolean option_udev = FALSE;
static guint last_adapter_timeout = 0;
@@ -334,7 +335,8 @@
last_adapter_timeout = 0;
}
-static gboolean parse_debug(const char *key, const char *value, gpointer user_data, GError **error)
+static gboolean parse_debug(const char *key, const char *value,
+ gpointer user_data, GError **error)
{
if (value)
option_debug = g_strdup(value);
@@ -345,12 +347,14 @@
}
static GOptionEntry options[] = {
- { "nodaemon", 'n', G_OPTION_FLAG_REVERSE,
- G_OPTION_ARG_NONE, &option_detach,
- "Don't run as daemon in background" },
{ "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
G_OPTION_ARG_CALLBACK, parse_debug,
- "Enable debug information output", "DEBUG" },
+ "Specify debug options to enable", "DEBUG" },
+ { "nodetach", 'n', G_OPTION_FLAG_REVERSE,
+ G_OPTION_ARG_NONE, &option_detach,
+ "Don't run as daemon in background" },
+ { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
+ "Show version information and exit" },
{ "udev", 'u', 0, G_OPTION_ARG_NONE, &option_udev,
"Run from udev mode of operation" },
{ NULL },
@@ -387,6 +391,13 @@
exit(1);
}
+ g_option_context_free(context);
+
+ if (option_version == TRUE) {
+ printf("%s\n", VERSION);
+ exit(0);
+ }
+
if (option_udev == TRUE) {
int err;
@@ -399,8 +410,6 @@
}
}
- g_option_context_free(context);
-
if (option_detach == TRUE && option_udev == FALSE) {
if (daemon(0, 0)) {
perror("Can't start daemon");
--- src/manager.c
+++ src/manager.c
@@ -337,7 +337,7 @@
adapter_get_address(adapter, &bdaddr);
ba2str(&bdaddr, addr);
- return strcmp(addr, address);
+ return strcasecmp(addr, address);
}
struct btd_adapter *manager_find_adapter(const bdaddr_t *sba)
--- src/security.c
+++ src/security.c
@@ -377,11 +377,14 @@
dev_id = hci_devid(sa);
if (dev_id < 0)
err = -errno;
- else
+ else {
err = hcid_dbus_link_key_notify(sba, dba, evt->link_key,
evt->key_type,
io_data[dev_id].pin_length,
old_key_type);
+ io_data[dev_id].pin_length = -1;
+ }
+
if (err < 0) {
uint16_t handle;
@@ -403,8 +406,6 @@
DISCONNECT_CP_SIZE, &cp);
}
}
-
- io_data[dev_id].pin_length = -1;
}
static void return_link_keys(int dev, bdaddr_t *sba, void *ptr)
--- src/storage.c
+++ src/storage.c
@@ -73,7 +73,7 @@
free(tmp);
- return err;
+ return err < 0 ? -EIO : 0;
}
int write_device_alias(const char *src, const char *dst, const char *alias)
--- test/test-adapter
+++ test/test-adapter
@@ -3,15 +3,29 @@
import sys
import dbus
import time
+from optparse import OptionParser, make_option
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.bluez.Manager")
-adapter = dbus.Interface(bus.get_object("org.bluez", manager.DefaultAdapter()),
+option_list = [
+ make_option("-i", "--device", action="store",
+ type="string", dest="dev_id"),
+ ]
+parser = OptionParser(option_list=option_list)
+
+(options, args) = parser.parse_args()
+
+if options.dev_id:
+ adapter_path = manager.FindAdapter(options.dev_id)
+else:
+ adapter_path = manager.DefaultAdapter()
+
+adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
"org.bluez.Adapter")
-if (len(sys.argv) < 2):
+if (len(args) < 1):
print "Usage: %s <command>" % (sys.argv[0])
print ""
print " address"
@@ -24,80 +38,80 @@
print " discovering"
sys.exit(1)
-if (sys.argv[1] == "address"):
+if (args[0] == "address"):
properties = adapter.GetProperties()
print properties["Address"]
sys.exit(0)
-if (sys.argv[1] == "name"):
- if (len(sys.argv) < 3):
+if (args[0] == "name"):
+ if (len(args) < 2):
properties = adapter.GetProperties()
print properties["Name"]
else:
- adapter.SetProperty("Name", sys.argv[2])
+ adapter.SetProperty("Name", args[1])
sys.exit(0)
-if (sys.argv[1] == "powered"):
- if (len(sys.argv) < 3):
+if (args[0] == "powered"):
+ if (len(args) < 2):
properties = adapter.GetProperties()
print properties["Powered"]
else:
- if (sys.argv[2] == "on"):
+ if (args[1] == "on"):
value = dbus.Boolean(1)
- elif (sys.argv[2] == "off"):
+ elif (args[1] == "off"):
value = dbus.Boolean(0)
else:
- value = dbus.Boolean(sys.argv[2])
+ value = dbus.Boolean(args[1])
adapter.SetProperty("Powered", value)
sys.exit(0)
-if (sys.argv[1] == "pairable"):
- if (len(sys.argv) < 3):
+if (args[0] == "pairable"):
+ if (len(args) < 2):
properties = adapter.GetProperties()
print properties["Pairable"]
else:
- if (sys.argv[2] == "on"):
+ if (args[1] == "on"):
value = dbus.Boolean(1)
- elif (sys.argv[2] == "off"):
+ elif (args[1] == "off"):
value = dbus.Boolean(0)
else:
- value = dbus.Boolean(sys.argv[2])
+ value = dbus.Boolean(args[1])
adapter.SetProperty("Pairable", value)
sys.exit(0)
-if (sys.argv[1] == "pairabletimeout"):
- if (len(sys.argv) < 3):
+if (args[0] == "pairabletimeout"):
+ if (len(args) < 2):
properties = adapter.GetProperties()
print properties["PairableTimeout"]
else:
- timeout = dbus.UInt32(sys.argv[2])
+ timeout = dbus.UInt32(args[1])
adapter.SetProperty("PairableTimeout", timeout)
sys.exit(0)
-if (sys.argv[1] == "discoverable"):
- if (len(sys.argv) < 3):
+if (args[0] == "discoverable"):
+ if (len(args) < 2):
properties = adapter.GetProperties()
print properties["Discoverable"]
else:
- if (sys.argv[2] == "on"):
+ if (args[1] == "on"):
value = dbus.Boolean(1)
- elif (sys.argv[2] == "off"):
+ elif (args[1] == "off"):
value = dbus.Boolean(0)
else:
- value = dbus.Boolean(sys.argv[2])
+ value = dbus.Boolean(args[1])
adapter.SetProperty("Discoverable", value)
sys.exit(0)
-if (sys.argv[1] == "discoverabletimeout"):
- if (len(sys.argv) < 3):
+if (args[0] == "discoverabletimeout"):
+ if (len(args) < 2):
properties = adapter.GetProperties()
print properties["DiscoverableTimeout"]
else:
- timeout = dbus.UInt32(sys.argv[2])
+ timeout = dbus.UInt32(args[1])
adapter.SetProperty("DiscoverableTimeout", timeout)
sys.exit(0)
-if (sys.argv[1] == "discovering"):
+if (args[0] == "discovering"):
properties = adapter.GetProperties()
print properties["Discovering"]
sys.exit(0)
--- test/test-audio
+++ test/test-audio
@@ -2,14 +2,29 @@
import sys
import dbus
+from optparse import OptionParser, make_option
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.bluez.Manager")
-adapter = dbus.Interface(bus.get_object("org.bluez", manager.DefaultAdapter()),
- "org.bluez.Adapter")
-if len(sys.argv) < 3:
+option_list = [
+ make_option("-i", "--device", action="store",
+ type="string", dest="dev_id"),
+ ]
+parser = OptionParser(option_list=option_list)
+
+(options, args) = parser.parse_args()
+
+if options.dev_id:
+ adapter_path = manager.FindAdapter(options.dev_id)
+else:
+ adapter_path = manager.DefaultAdapter()
+
+adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
+ "org.bluez.Adapter")
+
+if len(args) < 2:
print """Usage: %s <command>
connect <bdaddr>
@@ -17,13 +32,13 @@
""" % sys.argv[0]
sys.exit(1)
-device = adapter.FindDevice(sys.argv[2])
+device = adapter.FindDevice(args[1])
audio = dbus.Interface(bus.get_object("org.bluez", device),
"org.bluez.Audio")
-if sys.argv[1] == "connect":
+if args[0] == "connect":
audio.Connect()
-elif sys.argv[1] == "disconnect":
+elif args[0] == "disconnect":
audio.Disconnect()
else:
print "Unknown command"
--- test/test-device
+++ test/test-device
@@ -3,15 +3,29 @@
import sys
import dbus
import re
+from optparse import OptionParser, make_option
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.bluez.Manager")
-adapter = dbus.Interface(bus.get_object("org.bluez", manager.DefaultAdapter()),
+option_list = [
+ make_option("-i", "--device", action="store",
+ type="string", dest="dev_id"),
+ ]
+parser = OptionParser(option_list=option_list)
+
+(options, args) = parser.parse_args()
+
+if options.dev_id:
+ adapter_path = manager.FindAdapter(options.dev_id)
+else:
+ adapter_path = manager.DefaultAdapter()
+
+adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
"org.bluez.Adapter")
-if (len(sys.argv) < 2):
+if (len(args) < 1):
print "Usage: %s <command>" % (sys.argv[0])
print ""
print " list"
@@ -25,41 +39,45 @@
print " blocked <address> [yes/no]"
sys.exit(1)
-if (sys.argv[1] == "list"):
- list = adapter.ListDevices()
- print list
+if (args[0] == "list"):
+ for path in adapter.ListDevices():
+ device = dbus.Interface(bus.get_object("org.bluez", path),
+ "org.bluez.Device")
+ properties = device.GetProperties()
+ print "%s %s" % (properties["Address"], properties["Alias"])
+
sys.exit(0)
-if (sys.argv[1] == "create"):
- if (len(sys.argv) < 3):
+if (args[0] == "create"):
+ if (len(args) < 2):
print "Need address parameter"
else:
- device = adapter.CreateDevice(sys.argv[2])
+ device = adapter.CreateDevice(args[1])
print device
sys.exit(0)
-if (sys.argv[1] == "remove"):
- if (len(sys.argv) < 3):
+if (args[0] == "remove"):
+ if (len(args) < 2):
print "Need address or object path parameter"
else:
try:
- path = adapter.FindDevice(sys.argv[2])
+ path = adapter.FindDevice(args[1])
except:
- path = sys.argv[2]
+ path = args[1]
adapter.RemoveDevice(path)
sys.exit(0)
-if (sys.argv[1] == "discover"):
- if (len(sys.argv) < 3):
+if (args[0] == "discover"):
+ if (len(args) < 2):
print "Need address parameter"
else:
- path = adapter.FindDevice(sys.argv[2])
+ path = adapter.FindDevice(args[1])
device = dbus.Interface(bus.get_object("org.bluez", path),
"org.bluez.Device")
- if (len(sys.argv) < 4):
+ if (len(args) < 3):
pattern = ""
else:
- pattern = sys.argv[3]
+ pattern = args[2]
services = device.DiscoverServices(pattern);
for key in services.keys():
p = re.compile(">.*?<")
@@ -69,79 +87,79 @@
print
sys.exit(0)
-if (sys.argv[1] == "class"):
- if (len(sys.argv) < 3):
+if (args[0] == "class"):
+ if (len(args) < 2):
print "Need address parameter"
else:
- path = adapter.FindDevice(sys.argv[2])
+ path = adapter.FindDevice(args[1])
device = dbus.Interface(bus.get_object("org.bluez", path),
"org.bluez.Device")
properties = device.GetProperties()
print "0x%06x" % (properties["Class"])
sys.exit(0)
-if (sys.argv[1] == "name"):
- if (len(sys.argv) < 3):
+if (args[0] == "name"):
+ if (len(args) < 2):
print "Need address parameter"
else:
- path = adapter.FindDevice(sys.argv[2])
+ path = adapter.FindDevice(args[1])
device = dbus.Interface(bus.get_object("org.bluez", path),
"org.bluez.Device")
properties = device.GetProperties()
print properties["Name"]
sys.exit(0)
-if (sys.argv[1] == "alias"):
- if (len(sys.argv) < 3):
+if (args[0] == "alias"):
+ if (len(args) < 2):
print "Need address parameter"
else:
- path = adapter.FindDevice(sys.argv[2])
+ path = adapter.FindDevice(args[1])
device = dbus.Interface(bus.get_object("org.bluez", path),
"org.bluez.Device")
- if (len(sys.argv) < 4):
+ if (len(args) < 3):
properties = device.GetProperties()
print properties["Alias"]
else:
- device.SetProperty("Alias", sys.argv[3])
+ device.SetProperty("Alias", args[2])
sys.exit(0)
-if (sys.argv[1] == "trusted"):
- if (len(sys.argv) < 3):
+if (args[0] == "trusted"):
+ if (len(args) < 2):
print "Need address parameter"
else:
- path = adapter.FindDevice(sys.argv[2])
+ path = adapter.FindDevice(args[1])
device = dbus.Interface(bus.get_object("org.bluez", path),
"org.bluez.Device")
- if (len(sys.argv) < 4):
+ if (len(args) < 3):
properties = device.GetProperties()
print properties["Trusted"]
else:
- if (sys.argv[3] == "yes"):
+ if (args[2] == "yes"):
value = dbus.Boolean(1)
- elif (sys.argv[3] == "no"):
+ elif (args[2] == "no"):
value = dbus.Boolean(0)
else:
- value = dbus.Boolean(sys.argv[3])
+ value = dbus.Boolean(args[2])
device.SetProperty("Trusted", value)
sys.exit(0)
-if (sys.argv[1] == "blocked"):
- if (len(sys.argv) < 3):
+if (args[0] == "blocked"):
+ if (len(args) < 2):
print "Need address parameter"
else:
- path = adapter.FindDevice(sys.argv[2])
+ path = adapter.FindDevice(args[1])
device = dbus.Interface(bus.get_object("org.bluez", path),
"org.bluez.Device")
- if (len(sys.argv) < 4):
+ if (len(args) < 3):
properties = device.GetProperties()
print properties["Blocked"]
else:
- if (sys.argv[3] == "yes"):
+ if (args[2] == "yes"):
value = dbus.Boolean(1)
- elif (sys.argv[3] == "no"):
+ elif (args[2] == "no"):
value = dbus.Boolean(0)
else:
- value = dbus.Boolean(sys.argv[3])
+ value = dbus.Boolean(args[2])
device.SetProperty("Blocked", value)
sys.exit(0)
--- test/test-discovery
+++ test/test-discovery
@@ -4,6 +4,7 @@
import dbus
import dbus.mainloop.glib
+from optparse import OptionParser, make_option
def device_found(address, properties):
print "[ " + address + " ]"
@@ -26,8 +27,20 @@
manager = dbus.Interface(bus.get_object("org.bluez", "/"),
"org.bluez.Manager")
- path = manager.DefaultAdapter()
- adapter = dbus.Interface(bus.get_object("org.bluez", path),
+ option_list = [
+ make_option("-i", "--device", action="store",
+ type="string", dest="dev_id"),
+ ]
+ parser = OptionParser(option_list=option_list)
+
+ (options, args) = parser.parse_args()
+
+ if options.dev_id:
+ adapter_path = manager.FindAdapter(options.dev_id)
+ else:
+ adapter_path = manager.DefaultAdapter()
+
+ adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
"org.bluez.Adapter")
bus.add_signal_receiver(device_found,
--- test/test-input
+++ test/test-input
@@ -2,14 +2,29 @@
import sys
import dbus
+from optparse import OptionParser, make_option
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.bluez.Manager")
-adapter = dbus.Interface(bus.get_object("org.bluez", manager.DefaultAdapter()),
- "org.bluez.Adapter")
-if len(sys.argv) < 3:
+option_list = [
+ make_option("-i", "--device", action="store",
+ type="string", dest="dev_id"),
+ ]
+parser = OptionParser(option_list=option_list)
+
+(options, args) = parser.parse_args()
+
+if options.dev_id:
+ adapter_path = manager.FindAdapter(options.dev_id)
+else:
+ adapter_path = manager.DefaultAdapter()
+
+adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
+ "org.bluez.Adapter")
+
+if len(args) < 2:
print """Usage: %s <command>
connect <bdaddr>
@@ -17,13 +32,13 @@
""" % sys.argv[0]
sys.exit(1)
-device = adapter.FindDevice(sys.argv[2])
+device = adapter.FindDevice(args[1])
input = dbus.Interface(bus.get_object("org.bluez", device),
"org.bluez.Input")
-if sys.argv[1] == "connect":
+if args[0] == "connect":
input.Connect()
-elif sys.argv[1] == "disconnect":
+elif args[0] == "disconnect":
input.Disconnect()
else:
print "Unknown command"
--- test/test-network
+++ test/test-network
@@ -3,25 +3,39 @@
import sys
import time
import dbus
+from optparse import OptionParser, make_option
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.bluez", "/"),
"org.bluez.Manager")
-adapter = dbus.Interface(bus.get_object("org.bluez", manager.DefaultAdapter()),
+option_list = [
+ make_option("-i", "--device", action="store",
+ type="string", dest="dev_id"),
+ ]
+parser = OptionParser(option_list=option_list)
+
+(options, args) = parser.parse_args()
+
+if options.dev_id:
+ adapter_path = manager.FindAdapter(options.dev_id)
+else:
+ adapter_path = manager.DefaultAdapter()
+
+adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
"org.bluez.Adapter")
-if (len(sys.argv) < 2):
+if (len(args) < 1):
print "Usage: %s <address> [service]" % (sys.argv[0])
sys.exit(1)
-address = sys.argv[1]
+address = args[0]
-if (len(sys.argv) < 3):
+if (len(args) < 2):
service = "panu"
else:
- service = sys.argv[2]
+ service = args[1]
device = adapter.FindDevice(address)
--- test/test-serial
+++ test/test-serial
@@ -3,25 +3,38 @@
import sys
import time
import dbus
+from optparse import OptionParser, make_option
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.bluez", "/"),
"org.bluez.Manager")
+option_list = [
+ make_option("-i", "--device", action="store",
+ type="string", dest="dev_id"),
+ ]
+parser = OptionParser(option_list=option_list)
-adapter = dbus.Interface(bus.get_object("org.bluez", manager.DefaultAdapter()),
+(options, args) = parser.parse_args()
+
+if options.dev_id:
+ adapter_path = manager.FindAdapter(options.dev_id)
+else:
+ adapter_path = manager.DefaultAdapter()
+
+adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
"org.bluez.Adapter")
-if (len(sys.argv) < 2):
+if (len(args) < 1):
print "Usage: %s <address> [service]" % (sys.argv[0])
sys.exit(1)
-address = sys.argv[1]
+address = sys.argv[0]
-if (len(sys.argv) < 3):
+if (len(args) < 2):
service = "spp"
else:
- service = sys.argv[2]
+ service = args[1]
path = adapter.FindDevice(address)
--- test/test-service
+++ test/test-service
@@ -3,25 +3,39 @@
import sys
import dbus
import time
+from optparse import OptionParser, make_option
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.bluez.Manager")
-adapter = dbus.Interface(bus.get_object("org.bluez", manager.FindAdapter("any")),
- "org.bluez.Service")
+option_list = [
+ make_option("-i", "--device", action="store",
+ type="string", dest="dev_id"),
+ ]
+parser = OptionParser(option_list=option_list)
-if (len(sys.argv) < 2):
+(options, args) = parser.parse_args()
+
+if options.dev_id:
+ adapter_path = manager.FindAdapter(options.dev_id)
+else:
+ adapter_path = manager.DefaultAdapter()
+
+adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
+ "org.bluez.Adapter")
+
+if (len(args) < 1):
print "Usage: %s <command>" % (sys.argv[0])
print ""
print " addrecord <file>"
sys.exit(1)
-if (sys.argv[1] == "addrecord"):
- if (len(sys.argv) < 3):
+if (args[0] == "addrecord"):
+ if (len(args) < 2):
print "Need file parameter"
else:
- f = open(sys.argv[2])
+ f = open(args[1])
record = f.read()
f.close()
handle = adapter.AddRecord(record)
--- test/test-telephony
+++ test/test-telephony
@@ -2,16 +2,32 @@
import sys
import dbus
+from optparse import OptionParser, make_option
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.bluez.Manager")
-adapter = dbus.Interface(bus.get_object("org.bluez", manager.DefaultAdapter()),
- "org.bluez.Adapter")
+
+option_list = [
+ make_option("-i", "--device", action="store",
+ type="string", dest="dev_id"),
+ ]
+parser = OptionParser(option_list=option_list)
+
+(options, args) = parser.parse_args()
+
+if options.dev_id:
+ adapter_path = manager.FindAdapter(options.dev_id)
+else:
+ adapter_path = manager.DefaultAdapter()
+
+adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
+ "org.bluez.Adapter")
+
test = dbus.Interface(bus.get_object("org.bluez", "/org/bluez/test"),
"org.bluez.TelephonyTest")
-if len(sys.argv) < 2:
+if len(args) < 1:
print """Usage: %s <command>
connect <bdaddr>
@@ -31,127 +47,127 @@
""" % sys.argv[0]
sys.exit(1)
-if sys.argv[1] == "connect":
- if len(sys.argv) < 3:
+if args[0] == "connect":
+ if len(args) < 2:
print "Need device address parameter"
sys.exit(1)
- device = adapter.FindDevice(sys.argv[2])
+ device = adapter.FindDevice(args[1])
headset = dbus.Interface(bus.get_object("org.bluez", device),
"org.bluez.Headset")
headset.Connect()
sys.exit(0)
-if sys.argv[1] == "disconnect":
- if len(sys.argv) < 3:
+if args[0] == "disconnect":
+ if len(args) < 2:
print "Need device address parameter"
sys.exit(1)
- device = adapter.FindDevice(sys.argv[2])
+ device = adapter.FindDevice(args[1])
headset = dbus.Interface(bus.get_object("org.bluez", device),
"org.bluez.Headset")
headset.Disconnect()
sys.exit(0)
-if sys.argv[1] == "speakergain":
- if len(sys.argv) < 3:
+if args[0] == "speakergain":
+ if len(args) < 2:
print "Need device address parameter"
sys.exit(1)
- device = adapter.FindDevice(sys.argv[2])
+ device = adapter.FindDevice(args[1])
headset = dbus.Interface(bus.get_object("org.bluez", device),
"org.bluez.Headset")
- if len(sys.argv) > 3:
- headset.SetProperty('SpeakerGain', dbus.UInt16(sys.argv[3]))
+ if len(args) > 2:
+ headset.SetProperty('SpeakerGain', dbus.UInt16(args[2]))
else:
props = headset.GetProperties()
print props['SpeakerGain']
sys.exit(0)
-if sys.argv[1] == "microphonegain":
- if len(sys.argv) < 3:
+if args[0] == "microphonegain":
+ if len(args) < 2:
print "Need device address parameter"
sys.exit(1)
- device = adapter.FindDevice(sys.argv[2])
+ device = adapter.FindDevice(args[1])
headset = dbus.Interface(bus.get_object("org.bluez", device),
"org.bluez.Headset")
- if len(sys.argv) > 3:
- headset.SetProperty('MicrophoneGain', dbus.UInt16(sys.argv[3]))
+ if len(args) > 2:
+ headset.SetProperty('MicrophoneGain', dbus.UInt16(args[2]))
else:
props = headset.GetProperties()
print props['MicrophoneGain']
sys.exit(0)
-if sys.argv[1] == "play":
- if len(sys.argv) < 3:
+if args[0] == "play":
+ if len(args) < 2:
print "Need device address parameter"
sys.exit(1)
- device = adapter.FindDevice(sys.argv[2])
+ device = adapter.FindDevice(args[1])
headset = dbus.Interface(bus.get_object("org.bluez", device),
"org.bluez.Headset")
headset.Play()
sys.exit(0)
-if sys.argv[1] == "stop":
- if len(sys.argv) < 3:
+if args[0] == "stop":
+ if len(args) < 2:
print "Need device address parameter"
sys.exit(1)
- device = adapter.FindDevice(sys.argv[2])
+ device = adapter.FindDevice(args[1])
headset = dbus.Interface(bus.get_object("org.bluez", device),
"org.bluez.Headset")
headset.Stop()
sys.exit(0)
-if sys.argv[1] == "outgoing":
- if len(sys.argv) > 2:
- test.OutgoingCall(sys.argv[2])
+if args[0] == "outgoing":
+ if len(args) > 1:
+ test.OutgoingCall(args[1])
else:
print "Need number parameter"
sys.exit(0)
-if sys.argv[1] == "incoming":
- if len(sys.argv) > 2:
- test.IncomingCall(sys.argv[2])
+if args[0] == "incoming":
+ if len(args) > 1:
+ test.IncomingCall(args[1])
else:
print "Need number parameter"
sys.exit(0)
-if sys.argv[1] == "cancel":
+if args[0] == "cancel":
test.CancelCall()
sys.exit(0)
-if sys.argv[1] == "signal":
- if len(sys.argv) > 2:
- test.SignalStrength(sys.argv[2])
+if args[0] == "signal":
+ if len(args) > 1:
+ test.SignalStrength(args[1])
else:
print "Need signal strength parameter"
sys.exit(0)
-if sys.argv[1] == "battery":
- if len(sys.argv) > 2:
- test.BatteryLevel(sys.argv[2])
+if args[0] == "battery":
+ if len(args) > 1:
+ test.BatteryLevel(args[1])
else:
print "Need battery level parameter"
sys.exit(0)
-if sys.argv[1] == "roaming":
- if len(sys.argv) > 2:
- test.RoamingStatus(sys.argv[2] == "yes" or False)
+if args[0] == "roaming":
+ if len(args) > 1:
+ test.RoamingStatus(args[1] == "yes" or False)
else:
print "Need yes/no parameter"
sys.exit(0)
-if sys.argv[1] == "registration":
- if len(sys.argv) > 2:
- test.RegistrationStatus(sys.argv[2] == "yes" or False)
+if args[0] == "registration":
+ if len(args) > 1:
+ test.RegistrationStatus(args[1] == "yes" or False)
else:
print "Need yes/no parameter"
sys.exit(0)
-if sys.argv[1] == "subscriber":
- if len(sys.argv) > 2:
- test.SetSubscriberNumber(sys.argv[2])
+if args[0] == "subscriber":
+ if len(args) > 1:
+ test.SetSubscriberNumber(args[1])
else:
print "Need number parameter"
sys.exit(0)
--- tools/hciattach.8
+++ tools/hciattach.8
@@ -3,10 +3,15 @@
hciattach \- attach serial devices via UART HCI to BlueZ stack
.SH SYNOPSIS
.B hciattach
+.RB [\| \-b \|]
.RB [\| \-n \|]
.RB [\| \-p \|]
.RB [\| \-t
.IR timeout \|]
+.RB [\| \-s
+.IR speed \|]
+.RB [\| \-l \|]
+.RB [\| \-r \|]
.I tty
.IR type \||\| id
.I speed
@@ -18,6 +23,9 @@
transport interface.
.SH OPTIONS
.TP
+.B \-b
+Send break.
+.TP
.B \-n
Don't detach from controlling terminal.
.TP
@@ -27,6 +35,15 @@
.BI \-t " timeout"
Specify an initialization timeout. (Default is 5 seconds.)
.TP
+.BI \-s " speed"
+Specify an initial speed instead of the hardware default.
+.TP
+.B \-l
+List all available configurations.
+.TP
+.B \-r
+Set the HCI device into raw mode (the kernel and bluetoothd will ignore it).
+.TP
.I tty
This specifies the serial device to attach. A leading
.B /dev
--- tools/hciattach.c
+++ tools/hciattach.c
@@ -326,7 +326,8 @@
static void bcsp_tshy_sig_alarm(int sig)
{
unsigned char bcsp_sync_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xda,0xdc,0xed,0xed,0xc0};
- int len, retries = 0;
+ int len;
+ static int retries = 0;
if (retries < bcsp_max_retries) {
retries++;
@@ -343,7 +344,8 @@
static void bcsp_tconf_sig_alarm(int sig)
{
unsigned char bcsp_conf_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xad,0xef,0xac,0xed,0xc0};
- int len, retries = 0;
+ int len;
+ static int retries = 0;
if (retries < bcsp_max_retries){
retries++;
@@ -1095,10 +1097,14 @@
}
/* Initialize UART driver */
-static int init_uart(char *dev, struct uart_t *u, int send_break)
+static int init_uart(char *dev, struct uart_t *u, int send_break, int raw)
{
struct termios ti;
int fd, i;
+ unsigned long flags = 0;
+
+ if (raw)
+ flags |= 1 << HCI_UART_RAW_DEVICE;
fd = open(dev, O_RDWR | O_NOCTTY);
if (fd < 0) {
@@ -1157,6 +1163,11 @@
return -1;
}
+ if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) {
+ perror("Can't set UART flags");
+ return -1;
+ }
+
if (ioctl(fd, HCIUARTSETPROTO, u->proto) < 0) {
perror("Can't set device");
return -1;
@@ -1172,14 +1183,14 @@
{
printf("hciattach - HCI UART driver initialization utility\n");
printf("Usage:\n");
- printf("\thciattach [-n] [-p] [-b] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow|noflow] [bdaddr]\n");
+ printf("\thciattach [-n] [-p] [-b] [-r] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow|noflow] [bdaddr]\n");
printf("\thciattach -l\n");
}
int main(int argc, char *argv[])
{
struct uart_t *u = NULL;
- int detach, printpid, opt, i, n, ld, err;
+ int detach, printpid, raw, opt, i, n, ld, err;
int to = 10;
int init_speed = 0;
int send_break = 0;
@@ -1191,8 +1202,9 @@
detach = 1;
printpid = 0;
+ raw = 0;
- while ((opt=getopt(argc, argv, "bnpt:s:l")) != EOF) {
+ while ((opt=getopt(argc, argv, "bnpt:s:lr")) != EOF) {
switch(opt) {
case 'b':
send_break = 1;
@@ -1221,6 +1233,10 @@
}
exit(0);
+ case 'r':
+ raw = 1;
+ break;
+
default:
usage();
exit(1);
@@ -1298,7 +1314,7 @@
alarm(to);
bcsp_max_retries = to;
- n = init_uart(dev, u, send_break);
+ n = init_uart(dev, u, send_break, raw);
if (n < 0) {
perror("Can't initialize device");
exit(1);
--- tools/hciattach.h
+++ tools/hciattach.h
@@ -30,6 +30,8 @@
#define HCIUARTSETPROTO _IOW('U', 200, int)
#define HCIUARTGETPROTO _IOR('U', 201, int)
#define HCIUARTGETDEVICE _IOR('U', 202, int)
+#define HCIUARTSETFLAGS _IOW('U', 203, int)
+#define HCIUARTGETFLAGS _IOR('U', 204, int)
#define HCI_UART_H4 0
#define HCI_UART_BCSP 1
@@ -37,6 +39,8 @@
#define HCI_UART_H4DS 3
#define HCI_UART_LL 4
+#define HCI_UART_RAW_DEVICE 0
+
int read_hci_event(int fd, unsigned char* buf, int size);
int set_speed(int fd, struct termios *ti, int speed);
--- tools/hciconfig.8
+++ tools/hciconfig.8
@@ -10,6 +10,7 @@
.br
.B hciconfig
.RB [\| \-a \|]
+.B hciX
.RI [\| command
.RI [\| "command parameters" \|]\|]
--- tools/hcitool.c
+++ tools/hcitool.c
@@ -2354,6 +2354,240 @@
hci_close_dev(dd);
}
+static int print_advertising_devices(int dd)
+{
+ unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr;
+ struct hci_filter nf, of;
+ socklen_t olen;
+ hci_event_hdr *hdr;
+ int num, len;
+
+ olen = sizeof(of);
+ if (getsockopt(dd, SOL_HCI, HCI_FILTER, &of, &olen) < 0) {
+ printf("Could not get socket options\n");
+ return -1;
+ }
+
+ hci_filter_clear(&nf);
+ hci_filter_set_ptype(HCI_EVENT_PKT, &nf);
+ hci_filter_set_event(EVT_LE_META_EVENT, &nf);
+
+ if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) {
+ printf("Could not set socket options\n");
+ return -1;
+ }
+
+ /* Wait for 10 report events */
+ num = 10;
+ while (num--) {
+ evt_le_meta_event *meta;
+ le_advertising_info *info;
+ char addr[18];
+
+ while ((len = read(dd, buf, sizeof(buf))) < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ goto done;
+ }
+
+ hdr = (void *) (buf + 1);
+ ptr = buf + (1 + HCI_EVENT_HDR_SIZE);
+ len -= (1 + HCI_EVENT_HDR_SIZE);
+
+ meta = (void *) ptr;
+
+ if (meta->subevent != 0x02)
+ goto done;
+
+ /* Ignoring multiple reports */
+ info = (le_advertising_info *) (meta->data + 1);
+ ba2str(&info->bdaddr, addr);
+ printf("%s\n", addr);
+ }
+
+done:
+ setsockopt(dd, SOL_HCI, HCI_FILTER, &of, sizeof(of));
+
+ if (len < 0)
+ return -1;
+
+ return 0;
+}
+
+static struct option lescan_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *lescan_help =
+ "Usage:\n"
+ "\tlescan\n";
+
+static void cmd_lescan(int dev_id, int argc, char **argv)
+{
+ int err, opt, dd;
+
+ for_each_opt(opt, lescan_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", lescan_help);
+ return;
+ }
+ }
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("Could not open device");
+ exit(1);
+ }
+
+ err = hci_le_set_scan_parameters(dd, 0x01, htobs(0x0010), htobs(0x0010),
+ 0x00, 0x00);
+ if (err < 0) {
+ perror("Set scan parameters failed");
+ exit(1);
+ }
+
+ err = hci_le_set_scan_enable(dd, 0x01, 0x00);
+ if (err < 0) {
+ perror("Enable scan failed");
+ exit(1);
+ }
+
+ printf("LE Scan ...\n");
+
+ err = print_advertising_devices(dd);
+ if (err < 0) {
+ perror("Could not receive advertising events");
+ exit(1);
+ }
+
+ err = hci_le_set_scan_enable(dd, 0x00, 0x00);
+ if (err < 0) {
+ perror("Disable scan failed");
+ exit(1);
+ }
+
+ hci_close_dev(dd);
+}
+
+static struct option lecc_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *lecc_help =
+ "Usage:\n"
+ "\tlecc <bdaddr>\n";
+
+static void cmd_lecc(int dev_id, int argc, char **argv)
+{
+ int err, opt, dd;
+ bdaddr_t bdaddr;
+ uint16_t interval, latency, max_ce_length, max_interval, min_ce_length;
+ uint16_t min_interval, supervision_timeout, window, handle;
+ uint8_t initiator_filter, own_bdaddr_type, peer_bdaddr_type;
+
+ for_each_opt(opt, lecc_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", lecc_help);
+ return;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ printf("%s", lecc_help);
+ return;
+ }
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("Could not open device");
+ exit(1);
+ }
+
+ str2ba(argv[0], &bdaddr);
+
+ interval = htobs(0x0004);
+ window = htobs(0x0004);
+ initiator_filter = 0x00;
+ peer_bdaddr_type = 0x00;
+ own_bdaddr_type = 0x00;
+ min_interval = htobs(0x000F);
+ max_interval = htobs(0x000F);
+ latency = htobs(0x0000);
+ supervision_timeout = htobs(0x0C80);
+ min_ce_length = htobs(0x0001);
+ max_ce_length = htobs(0x0001);
+
+ err = hci_le_create_conn(dd, interval, window, initiator_filter,
+ peer_bdaddr_type, bdaddr, own_bdaddr_type, min_interval,
+ max_interval, latency, supervision_timeout,
+ min_ce_length, max_ce_length, &handle, 25000);
+ if (err < 0) {
+ perror("Could not create connection");
+ exit(1);
+ }
+
+ printf("Connection handle %d\n", handle);
+
+ hci_close_dev(dd);
+}
+
+static struct option ledc_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *ledc_help =
+ "Usage:\n"
+ "\tledc <handle> [reason]\n";
+
+static void cmd_ledc(int dev_id, int argc, char **argv)
+{
+ int err, opt, dd;
+ uint16_t handle;
+ uint8_t reason;
+
+ for_each_opt(opt, ledc_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", ledc_help);
+ return;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ printf("%s", ledc_help);
+ return;
+ }
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("Could not open device");
+ exit(1);
+ }
+
+ handle = atoi(argv[0]);
+
+ reason = (argc > 1) ? atoi(argv[1]) : HCI_OE_USER_ENDED_CONNECTION;
+
+ err = hci_disconnect(dd, handle, reason, 10000);
+ if (err < 0) {
+ perror("Could not disconnect");
+ exit(1);
+ }
+
+ hci_close_dev(dd);
+}
+
static struct {
char *cmd;
void (*func)(int dev_id, int argc, char **argv);
@@ -2383,6 +2617,9 @@
{ "key", cmd_key, "Change connection link key" },
{ "clkoff", cmd_clkoff, "Read clock offset" },
{ "clock", cmd_clock, "Read local or remote clock" },
+ { "lescan", cmd_lescan, "Start LE scan" },
+ { "lecc", cmd_lecc, "Create a LE Connection", },
+ { "ledc", cmd_ledc, "Disconnect a LE Connection", },
{ NULL, NULL, 0 }
};
++++++ bluez.yaml
--- bluez.yaml
+++ bluez.yaml
@@ -1,6 +1,6 @@
Name: bluez
Summary: Bluetooth utilities
-Version: 4.66
+Version: 4.69
Release: 1
Group: Applications/System
License: GPLv2+
More information about the MeeGo-commits
mailing list