bluez input regression 4.96->master

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

While trying to work on the sixaxis plugin as external plugin, I found
that the same code
that works with 4.96 does not work with trunk.

In 4.96 the hidraw could have been read, in master the read is blocked
until device
disconnects, then it returns with i/o error.

I don't know how to produce more debug information, I appreciate if
someone can help.
I did not find any hint in git log... Maybe something should be
changed in plugin, not sure.

blocked code:
---
fd = open(hidraw_node, O_RDWR);
if (read(fd, &c, 1) != 1)
---

I also think that actually no hid events are gotten at all... cat
/dev/input/js0 produces nothing.

Attached is the same patch that is used for both.

Thanks,
Alon Bar-Lev.

---
bluez-4.96 - working
---
bluetoothd[4399]: Bluetooth daemon 4.96
bluetoothd[4399]: src/main.c:parse_config() parsing main.conf
bluetoothd[4399]: src/main.c:parse_config() discovto=0
bluetoothd[4399]: src/main.c:parse_config() pairto=0
bluetoothd[4399]: src/main.c:parse_config() pageto=8192
bluetoothd[4399]: src/main.c:parse_config() name=%h-%d
bluetoothd[4399]: src/main.c:parse_config() class=0x000100
bluetoothd[4399]: src/main.c:parse_config() discov_interval=30
bluetoothd[4399]: src/main.c:parse_config() Key file does not have key
'DeviceID'
bluetoothd[4399]: Starting SDP server
bluetoothd[4399]: src/plugin.c:plugin_init() Loading builtin plugins
bluetoothd[4399]: src/plugin.c:add_plugin() Loading audio plugin
bluetoothd[4399]: src/plugin.c:add_plugin() Loading input plugin
bluetoothd[4399]: src/plugin.c:add_plugin() Loading serial plugin
bluetoothd[4399]: src/plugin.c:add_plugin() Loading network plugin
bluetoothd[4399]: src/plugin.c:add_plugin() Loading service plugin
bluetoothd[4399]: src/plugin.c:add_plugin() Loading sixaxis plugin
bluetoothd[4399]: src/plugin.c:add_plugin() Loading hciops plugin
bluetoothd[4399]: src/plugin.c:add_plugin() Loading mgmtops plugin
bluetoothd[4399]: src/plugin.c:add_plugin() Loading formfactor plugin
bluetoothd[4399]: src/plugin.c:add_plugin() Loading storage plugin
bluetoothd[4399]: src/plugin.c:add_plugin() Loading adaptername plugin
bluetoothd[4399]: src/plugin.c:plugin_init() Loading plugins
/usr/lib64/bluetooth/plugins
bluetoothd[4399]: plugins/service.c:register_interface() path
/org/bluez/4399/any
bluetoothd[4399]: plugins/service.c:register_interface() Registered
interface org.bluez.Service on path /org/bluez/4399/any
bluetoothd[4399]: plugins/sixaxis.c:sixaxis_init() Setup Sixaxis cable plugin
bluetoothd[4399]: network/manager.c:read_config()
/etc/bluetooth/network.conf: Key file does not have key
'DisableSecurity'
bluetoothd[4399]: network/manager.c:read_config() Config options: Security=true
bluetoothd[4399]: input/manager.c:input_manager_init() input.conf: Key
file does not have key 'IdleTimeout'
bluetoothd[4399]: audio/manager.c:audio_manager_init() audio.conf: Key
file does not have key 'AutoConnect'
bluetoothd[4399]: audio/unix.c:unix_init() Unix socket created: 9
bluetoothd[4399]: Unable to start SCO server socket
bluetoothd[4399]: Failed to init audio plugin
bluetoothd[4399]: plugins/hciops.c:hciops_init()
bluetoothd[4399]: plugins/hciops.c:hciops_setup()
bluetoothd[4399]: src/main.c:main() Entering main loop
bluetoothd[4399]: src/rfkill.c:rfkill_event() RFKILL event idx 0 type
2 op 0 soft 0 hard 0
bluetoothd[4399]: src/rfkill.c:rfkill_event() RFKILL event idx 1 type
1 op 0 soft 0 hard 0
bluetoothd[4399]: src/rfkill.c:rfkill_event() RFKILL event idx 11 type
2 op 0 soft 0 hard 0
bluetoothd[4399]: plugins/hciops.c:init_known_adapters()
bluetoothd[4399]: plugins/hciops.c:init_device() hci0
bluetoothd[4399]: Listening for HCI events on hci0
bluetoothd[4399]: plugins/hciops.c:init_conn_list() hci0
bluetoothd[4399]: HCI dev 0 up
bluetoothd[4399]: plugins/hciops.c:device_devup_setup() hci0
bluetoothd[4399]: plugins/hciops.c:read_local_version_complete() Got
version for hci0
bluetoothd[4399]: src/adapter.c:btd_adapter_ref() 0x7f9eca360a10: ref=1
bluetoothd[4399]: plugins/hciops.c:hciops_read_bdaddr() hci0
bluetoothd[4399]: src/sdpd-database.c:sdp_init_services_list()
bluetoothd[4399]: plugins/hciops.c:hciops_add_uuid() hci0
bluetoothd[4399]: plugins/hciops.c:update_service_classes() hci0 value 0
bluetoothd[4399]: plugins/hciops.c:hciops_add_uuid() hci0
bluetoothd[4399]: plugins/hciops.c:update_service_classes() hci0 value 0
bluetoothd[4399]: plugins/service.c:register_interface() path
/org/bluez/4399/hci0
bluetoothd[4399]: plugins/service.c:register_interface() Registered
interface org.bluez.Service on path /org/bluez/4399/hci0
bluetoothd[4399]: network/manager.c:network_server_probe() path
/org/bluez/4399/hci0
bluetoothd[4399]: src/adapter.c:btd_adapter_ref() 0x7f9eca360a10: ref=2
bluetoothd[4399]: network/server.c:server_register() Registered
interface org.bluez.NetworkServer on path /org/bluez/4399/hci0
bluetoothd[4399]: serial/manager.c:proxy_probe() path /org/bluez/4399/hci0
bluetoothd[4399]: src/adapter.c:btd_adapter_ref() 0x7f9eca360a10: ref=3
bluetoothd[4399]: serial/proxy.c:proxy_register() Registered interface
org.bluez.SerialProxyManager on path /org/bluez/4399/hci0
bluetoothd[4399]: src/adapter.c:btd_adapter_ref() 0x7f9eca360a10: ref=4
bluetoothd[4399]: plugins/adaptername.c:adaptername_probe() Setting
name 'localhost-0' for device 'hci0'
bluetoothd[4399]: plugins/hciops.c:hciops_set_name() hci0, name localhost-0
bluetoothd[4399]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[4399]: Could not get the contents of DMI chassis type
bluetoothd[4399]: plugins/hciops.c:hciops_unblock_device() hci0 dba
00:00:00:00:00:00
bluetoothd[4399]: src/device.c:device_create() Creating device
/org/bluez/4399/hci0/dev_44_D8_32_A1_39_91
bluetoothd[4399]: src/device.c:btd_device_ref() 0x7f9eca362490: ref=1
bluetoothd[4399]: src/device.c:device_set_temporary() temporary 0
bluetoothd[4399]: src/device.c:device_probe_drivers() Probing drivers
for 44:D8:32:A1:39:91
bluetoothd[4399]: input/manager.c:hid_device_probe() path
/org/bluez/4399/hci0/dev_44_D8_32_A1_39_91
bluetoothd[4399]: src/device.c:btd_device_ref() 0x7f9eca362490: ref=2
bluetoothd[4399]: input/device.c:input_device_new() Registered
interface org.bluez.Input on path
/org/bluez/4399/hci0/dev_44_D8_32_A1_39_91
bluetoothd[4399]: plugins/hciops.c:hciops_load_keys() hci0 keys 0 debug_keys 0
bluetoothd[4399]: plugins/hciops.c:hciops_get_conn_list() hci0
bluetoothd[4399]: src/manager.c:btd_manager_register_adapter() Adapter
/org/bluez/4399/hci0 registered
bluetoothd[4399]: src/adapter.c:btd_adapter_ref() 0x7f9eca360a10: ref=5
bluetoothd[4399]: plugins/hciops.c:hciops_set_name() hci0, name localhost-0
bluetoothd[4399]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[4399]: plugins/hciops.c:hciops_set_dev_class() hci0 major 1 minor 0
bluetoothd[4399]: plugins/hciops.c:hciops_disable_cod_cache() hci0
cache_enable 1
bluetoothd[4399]: plugins/hciops.c:hciops_disable_cod_cache() hci0
current_cod 0x000000 wanted_cod 0x000100
bluetoothd[4399]: plugins/hciops.c:write_class() hci0 class 0x000100
bluetoothd[4399]: Adapter /org/bluez/4399/hci0 has been enabled
bluetoothd[4399]: plugins/hciops.c:hciops_set_discoverable() hci0 discoverable 0
bluetoothd[4399]: plugins/hciops.c:hciops_set_pairable() hci0 pairable 1
bluetoothd[4399]: plugins/hciops.c:hciops_stop_inquiry() hci0
bluetoothd[4399]: src/adapter.c:btd_adapter_unref() 0x7f9eca360a10: ref=4
bluetoothd[4399]: src/adapter.c:register_agent() Agent registered for
hci0 at :1.138:/blueDevil_agent
bluetoothd[4399]: plugins/hciops.c:read_tx_power_complete() hci0 status 0
bluetoothd[4399]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[4399]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[4399]: Inquiry Cancel Failed with status 0x12
bluetoothd[4399]: plugins/hciops.c:read_local_name_complete() hci0 status 0
bluetoothd[4399]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[4399]: plugins/hciops.c:read_simple_pairing_mode_complete()
hci0 status 0
bluetoothd[4399]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[4399]: plugins/hciops.c:read_local_name_complete() hci0 status 0
bluetoothd[4399]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[4399]: plugins/hciops.c:read_scan_complete() hci0 status 0
bluetoothd[4399]: src/adapter.c:adapter_mode_changed() old 0x00 new 0x02
bluetoothd[4399]: src/adapter.c:adapter_set_limited_discoverable() FALSE
bluetoothd[4399]: plugins/hciops.c:hciops_set_limited_discoverable()
hci0 limited 0
bluetoothd[4399]: src/adapter.c:set_mode_complete()
bluetoothd[4399]: plugins/hciops.c:conn_complete() status 0x00
bluetoothd[4399]: src/adapter.c:adapter_get_device() 44:D8:32:A1:39:91
bluetoothd[4399]: input/server.c:connect_event_cb() Incoming
connection from 44:D8:32:A1:39:91 on PSM 17
bluetoothd[4399]: plugins/hciops.c:remote_features_information() hci0 status 0
bluetoothd[4399]: input/server.c:connect_event_cb() Incoming
connection from 44:D8:32:A1:39:91 on PSM 19
bluetoothd[4399]: plugins/hciops.c:remote_name_information() hci0 status 0
bluetoothd[4399]: plugins/sixaxis.c:handle_device_plug() name:
PLAYSTATION(R)3 Controller
bluetoothd[4399]: plugins/sixaxis.c:handle_device_plug() Found a Sixaxis device
bluetoothd[4399]: plugins/sixaxis.c:handle_device_plug() joypad device_num: 1
bluetoothd[4399]: plugins/sixaxis.c:handle_device_plug() hidraw_node:
/dev/hidraw0
bluetoothd[4399]: plugins/sixaxis.c:handle_device_plug() driver: btusb
bluetoothd[4399]: plugins/sixaxis.c:handle_device_plug() opening hidraw
bluetoothd[4399]: plugins/sixaxis.c:handle_device_plug() waiting for events
bluetoothd[4399]: plugins/sixaxis.c:set_leds() Setting leds
bluetoothd[4399]: plugins/sixaxis.c:handle_device_plug() hidraw closed
---

---
master
---
bluetoothd[11731]: Bluetooth daemon 4.96
bluetoothd[11731]: src/main.c:parse_config() parsing main.conf
bluetoothd[11731]: src/main.c:parse_config() discovto=0
bluetoothd[11731]: src/main.c:parse_config() pairto=0
bluetoothd[11731]: src/main.c:parse_config() pageto=8192
bluetoothd[11731]: src/main.c:parse_config() auto_to=60
bluetoothd[11731]: src/main.c:parse_config() name=%h-%d
bluetoothd[11731]: src/main.c:parse_config() class=0x000100
bluetoothd[11731]: src/main.c:parse_config() discov_interval=30
bluetoothd[11731]: src/main.c:parse_config() Key file does not have
key 'DeviceID'
bluetoothd[11731]: Starting SDP server
bluetoothd[11731]: src/plugin.c:plugin_init() Loading builtin plugins
bluetoothd[11731]: src/plugin.c:add_plugin() Loading audio plugin
bluetoothd[11731]: src/plugin.c:add_plugin() Loading input plugin
bluetoothd[11731]: src/plugin.c:add_plugin() Loading serial plugin
bluetoothd[11731]: src/plugin.c:add_plugin() Loading network plugin
bluetoothd[11731]: src/plugin.c:add_plugin() Loading service plugin
bluetoothd[11731]: src/plugin.c:add_plugin() Loading sixaxis plugin
bluetoothd[11731]: src/plugin.c:add_plugin() Loading hciops plugin
bluetoothd[11731]: src/plugin.c:add_plugin() Loading mgmtops plugin
bluetoothd[11731]: src/plugin.c:add_plugin() Loading formfactor plugin
bluetoothd[11731]: src/plugin.c:add_plugin() Loading storage plugin
bluetoothd[11731]: src/plugin.c:add_plugin() Loading adaptername plugin
bluetoothd[11731]: src/plugin.c:plugin_init() Loading plugins
/usr/lib64/bluetooth/plugins
bluetoothd[11731]: plugins/service.c:register_interface() path
/org/bluez/11731/any
bluetoothd[11731]: plugins/service.c:register_interface() Registered
interface org.bluez.Service on path /org/bluez/11731/any
bluetoothd[11731]: plugins/sixaxis.c:sixaxis_init() Setup Sixaxis cable plugin
bluetoothd[11731]: network/manager.c:read_config()
/etc/bluetooth/network.conf: Key file does not have key
'DisableSecurity'
bluetoothd[11731]: network/manager.c:read_config() Config options: Security=true
bluetoothd[11731]: input/manager.c:input_manager_init() input.conf:
Key file does not have key 'IdleTimeout'
bluetoothd[11731]: audio/manager.c:audio_manager_init() audio.conf:
Key file does not have key 'AutoConnect'
bluetoothd[11731]: audio/unix.c:unix_init() Unix socket created: 10
bluetoothd[11731]: Unable to start SCO server socket
bluetoothd[11731]: Failed to init audio plugin
bluetoothd[11731]: plugins/hciops.c:hciops_init()
bluetoothd[11731]: plugins/hciops.c:hciops_setup()
bluetoothd[11731]: src/main.c:main() Entering main loop
bluetoothd[11731]: src/rfkill.c:rfkill_event() RFKILL event idx 0 type
2 op 0 soft 0 hard 0
bluetoothd[11731]: src/rfkill.c:rfkill_event() RFKILL event idx 1 type
1 op 0 soft 0 hard 0
bluetoothd[11731]: src/rfkill.c:rfkill_event() RFKILL event idx 11
type 2 op 0 soft 0 hard 0
bluetoothd[11731]: plugins/hciops.c:init_known_adapters()
bluetoothd[11731]: plugins/hciops.c:init_device() hci0
bluetoothd[11731]: Listening for HCI events on hci0
bluetoothd[11731]: plugins/hciops.c:init_conn_list() hci0
bluetoothd[11731]: HCI dev 0 up
bluetoothd[11731]: plugins/hciops.c:device_devup_setup() hci0
bluetoothd[11731]: plugins/hciops.c:read_local_version_complete() Got
version for hci0
bluetoothd[11731]: src/adapter.c:btd_adapter_ref() 0x7fc4b75d4cf0: ref=1
bluetoothd[11731]: plugins/hciops.c:hciops_read_bdaddr() hci0
bluetoothd[11731]: src/sdpd-database.c:sdp_init_services_list()
bluetoothd[11731]: plugins/hciops.c:hciops_add_uuid() hci0
bluetoothd[11731]: plugins/hciops.c:update_service_classes() hci0 value 0
bluetoothd[11731]: plugins/hciops.c:hciops_add_uuid() hci0
bluetoothd[11731]: plugins/hciops.c:update_service_classes() hci0 value 0
bluetoothd[11731]: plugins/service.c:register_interface() path
/org/bluez/11731/hci0
bluetoothd[11731]: plugins/service.c:register_interface() Registered
interface org.bluez.Service on path /org/bluez/11731/hci0
bluetoothd[11731]: network/manager.c:network_server_probe() path
/org/bluez/11731/hci0
bluetoothd[11731]: src/adapter.c:btd_adapter_ref() 0x7fc4b75d4cf0: ref=2
bluetoothd[11731]: network/server.c:server_register() Registered
interface org.bluez.NetworkServer on path /org/bluez/11731/hci0
bluetoothd[11731]: serial/manager.c:proxy_probe() path /org/bluez/11731/hci0
bluetoothd[11731]: src/adapter.c:btd_adapter_ref() 0x7fc4b75d4cf0: ref=3
bluetoothd[11731]: serial/proxy.c:proxy_register() Registered
interface org.bluez.SerialProxyManager on path /org/bluez/11731/hci0
bluetoothd[11731]: src/adapter.c:btd_adapter_ref() 0x7fc4b75d4cf0: ref=4
bluetoothd[11731]: plugins/adaptername.c:adaptername_probe() Setting
name 'localhost-0' for device 'hci0'
bluetoothd[11731]: plugins/hciops.c:hciops_set_name() hci0, name localhost-0
bluetoothd[11731]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[11731]: Could not get the contents of DMI chassis type
bluetoothd[11731]: plugins/hciops.c:hciops_unblock_device() hci0 dba
00:00:00:00:00:00
bluetoothd[11731]: src/device.c:device_create() Creating device
/org/bluez/11731/hci0/dev_44_D8_32_A1_39_91
bluetoothd[11731]: src/device.c:btd_device_ref() 0x7fc4b75d6510: ref=1
bluetoothd[11731]: src/device.c:device_set_temporary() temporary 0
bluetoothd[11731]: src/device.c:device_probe_drivers() Probing drivers
for 44:D8:32:A1:39:91
bluetoothd[11731]: input/manager.c:hid_device_probe() path
/org/bluez/11731/hci0/dev_44_D8_32_A1_39_91
bluetoothd[11731]: src/device.c:btd_device_ref() 0x7fc4b75d6510: ref=2
bluetoothd[11731]: input/device.c:input_device_new() Registered
interface org.bluez.Input on path
/org/bluez/11731/hci0/dev_44_D8_32_A1_39_91
bluetoothd[11731]: plugins/hciops.c:hciops_load_keys() hci0 keys 0 debug_keys 0
bluetoothd[11731]: plugins/hciops.c:hciops_get_conn_list() hci0
bluetoothd[11731]: src/manager.c:btd_manager_register_adapter()
Adapter /org/bluez/11731/hci0 registered
bluetoothd[11731]: src/adapter.c:btd_adapter_ref() 0x7fc4b75d4cf0: ref=5
bluetoothd[11731]: plugins/hciops.c:hciops_set_dev_class() hci0 major 1 minor 0
bluetoothd[11731]: plugins/hciops.c:hciops_disable_cod_cache() hci0
cache_enable 1
bluetoothd[11731]: plugins/hciops.c:hciops_disable_cod_cache() hci0
current_cod 0x000000 wanted_cod 0x000100
bluetoothd[11731]: plugins/hciops.c:write_class() hci0 class 0x000100
bluetoothd[11731]: Adapter /org/bluez/11731/hci0 has been enabled
bluetoothd[11731]: plugins/hciops.c:hciops_set_discoverable() hci0
discoverable 0
bluetoothd[11731]: plugins/hciops.c:hciops_set_pairable() hci0 pairable 1
bluetoothd[11731]: plugins/hciops.c:hciops_stop_inquiry() hci0
bluetoothd[11731]: src/adapter.c:btd_adapter_unref() 0x7fc4b75d4cf0: ref=4
bluetoothd[11731]: plugins/hciops.c:read_local_ext_features_complete()
hci0 status 0
bluetoothd[11731]: src/adapter.c:register_agent() Agent registered for
hci0 at :1.138:/blueDevil_agent
bluetoothd[11731]: plugins/hciops.c:read_tx_power_complete() hci0 status 0
bluetoothd[11731]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[11731]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[11731]: Inquiry Cancel Failed with status 0x12
bluetoothd[11731]: plugins/hciops.c:read_local_name_complete() hci0 status 0
bluetoothd[11731]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[11731]:
plugins/hciops.c:read_simple_pairing_mode_complete() hci0 status 0
bluetoothd[11731]: plugins/hciops.c:update_ext_inquiry_response() hci0
bluetoothd[11731]: plugins/hciops.c:read_scan_complete() hci0 status 0
bluetoothd[11731]: src/adapter.c:adapter_mode_changed() old 0x00 new 0x02
bluetoothd[11731]: src/adapter.c:adapter_set_limited_discoverable() FALSE
bluetoothd[11731]: plugins/hciops.c:hciops_set_limited_discoverable()
hci0 limited 0
bluetoothd[11731]: src/adapter.c:set_mode_complete()
bluetoothd[11731]: plugins/hciops.c:conn_complete() status 0x00
bluetoothd[11731]: src/adapter.c:adapter_get_device() 44:D8:32:A1:39:91
bluetoothd[11731]: input/server.c:connect_event_cb() Incoming
connection from 44:D8:32:A1:39:91 on PSM 17
bluetoothd[11731]: plugins/hciops.c:remote_features_information() hci0 status 0
bluetoothd[11731]: plugins/hciops.c:remote_name_information() hci0 status 0
bluetoothd[11731]: input/server.c:connect_event_cb() Incoming
connection from 44:D8:32:A1:39:91 on PSM 19
bluetoothd[11731]: plugins/sixaxis.c:handle_device_plug() name:
PLAYSTATION(R)3 Controller
bluetoothd[11731]: plugins/sixaxis.c:handle_device_plug() Found a Sixaxis device
bluetoothd[11731]: plugins/sixaxis.c:handle_device_plug() joypad device_num: 1
bluetoothd[11731]: plugins/sixaxis.c:handle_device_plug() hidraw_node:
/dev/hidraw0
bluetoothd[11731]: plugins/sixaxis.c:handle_device_plug() driver: btusb
bluetoothd[11731]: plugins/sixaxis.c:handle_device_plug() opening hidraw
bluetoothd[11731]: plugins/sixaxis.c:handle_device_plug() waiting for events
---
diff --git a/Makefile.am b/Makefile.am
index 283af4d..57f0848 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -249,6 +249,11 @@ builtin_sources += thermometer/main.c \
 			thermometer/thermometer.h thermometer/thermometer.c
 endif
 
+if SIXAXISPLUGIN
+builtin_modules += sixaxis
+builtin_sources += plugins/sixaxis.c
+endif
+
 builtin_modules += hciops mgmtops
 builtin_sources += plugins/hciops.c plugins/mgmtops.c
 
@@ -317,6 +322,9 @@ src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
 			src/oob.h src/oob.c src/eir.h src/eir.c
 src_bluetoothd_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@ @DBUS_LIBS@ \
 							@CAPNG_LIBS@ -ldl -lrt
+if SIXAXISPLUGIN
+src_bluetoothd_LDADD += @UDEV_LIBS@
+endif
 src_bluetoothd_LDFLAGS = -Wl,--export-dynamic \
 				-Wl,--version-script=$(srcdir)/src/bluetooth.ver
 
diff --git a/acinclude.m4 b/acinclude.m4
index 2097d77..7eae9b9 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -186,6 +186,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	sndfile_enable=${sndfile_found}
 	hal_enable=no
 	usb_enable=${usb_found}
+	sixaxis_enable=${udev_found}
 	alsa_enable=${alsa_found}
 	gstreamer_enable=${gstreamer_found}
 	audio_enable=yes
@@ -296,6 +297,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		usb_enable=${enableval}
 	])
 
+	AC_ARG_ENABLE(sixaxis, AC_HELP_STRING([--enable-sixaxis], [enable Sixaxis plugin]), [
+		sixaxis_enable=${enableval}
+	])
+
 	AC_ARG_ENABLE(tracer, AC_HELP_STRING([--enable-tracer], [install Tracing daemon]), [
 		tracer_enable=${enableval}
 	])
@@ -395,6 +400,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		AC_DEFINE(HAVE_LIBUSB, 1, [Define to 1 if you have USB library.])
 	fi
 
+	if (test "${sixaxis_enable}" = "yes" && test "${udev_found}" = "yes"); then
+		AC_DEFINE(HAVE_SIXAXIS_PLUGIN, 1, [Define to 1 if you have sixaxis plugin.])
+	fi
+
 	AM_CONDITIONAL(SNDFILE, test "${sndfile_enable}" = "yes" && test "${sndfile_found}" = "yes")
 	AM_CONDITIONAL(USB, test "${usb_enable}" = "yes" && test "${usb_found}" = "yes")
 	AM_CONDITIONAL(SBC, test "${alsa_enable}" = "yes" || test "${gstreamer_enable}" = "yes" ||
@@ -433,4 +442,5 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	AM_CONDITIONAL(DBUSOOBPLUGIN, test "${dbusoob_enable}" = "yes")
 	AM_CONDITIONAL(WIIMOTEPLUGIN, test "${wiimote_enable}" = "yes")
 	AM_CONDITIONAL(THERMOMETERPLUGIN, test "${thermometer_enable}" = "yes")
+	AM_CONDITIONAL(SIXAXISPLUGIN, test "${sixaxis_enable}" = "yes" && test "${udev_found}" = "yes")
 ])
diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
new file mode 100644
index 0000000..a5d5876
--- /dev/null
+++ b/plugins/sixaxis.c
@@ -0,0 +1,633 @@
+/*
+ * sixaxis plugin: do cable association for Sixaxis controller
+ *
+ * Copyright (C) 2009  Bastien Nocera <hadess@xxxxxxxxxx>
+ * Copyright (C) 2011  Antonio Ospite <ospite@xxxxxxxxxxxxxxxxx>
+ *
+ *
+ * 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
+ *
+ */
+
+/*
+ * In the following this terminology is used:
+ *
+ *  - controller: a Sixaxis joypad.
+ *  - adapter: the bluetooth dongle on the host system.
+ *  - adapter_bdaddr: the bdaddr of the bluetooth adapter.
+ *  - device_bdaddr: the bdaddr of the Sixaxis controller.
+ *  - master_bdaddr: the bdaddr of the adapter to be configured into the
+ *    Sixaxis controller
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <glib.h>
+#include <linux/hidraw.h>
+
+#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE 1
+#include <libudev.h>
+
+#include "plugin.h"
+#include "log.h"
+#include "adapter.h"
+#include "device.h"
+#include "manager.h"
+#include "storage.h"
+#include "sdp_lib.h"
+
+/* Fallback definitions to compile with older headers */
+#ifndef HIDIOCGFEATURE
+#define HIDIOCGFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
+#endif
+
+#ifndef HIDIOCSFEATURE
+#define HIDIOCSFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
+#endif
+
+#define BDADDR_STR_SIZE 18 /* strlen("00:00:00:00:00:00") + 1 */
+
+struct sony_controller {
+	uint16_t vendor_id;
+	uint16_t product_id;
+	char *name;
+	char *pnp_record;
+	char *hid_uuid;
+
+	/* device specific callbacks to get master/device bdaddr and set
+	 * master bdaddr
+	 */
+	char * (*get_device_bdaddr)(int);
+	char * (*get_master_bdaddr)(int);
+	int (*set_master_bdaddr) (int, char *);
+};
+
+static char *sixaxis_get_device_bdaddr(int fd);
+static char *sixaxis_get_master_bdaddr(int fd);
+static int sixaxis_set_master_bdaddr(int fd, char *adapter_bdaddr);
+
+static struct sony_controller controllers[] = {
+	{
+		.vendor_id = 0x054c,
+		.product_id = 0x0268,
+		.name = "PLAYSTATION(R)3 Controller",
+		.pnp_record = "3601920900000A000100000900013503191124090004350D35061901000900113503190011090006350909656E09006A0901000900093508350619112409010009000D350F350D350619010009001335031900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E7465727461696E6D656E740902000901000902010901000902020800090203082109020428010902052801090206359A35980822259405010904A101A102850175089501150026FF00810375019513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A10075089504350046FF0009300931093209358102C0050175089527090181027508953009019102750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A10285EF750895300901B102C0C0090207350835060904090901000902082800090209280109020A280109020B09010009020C093E8009020D280009020E2800",
+		.hid_uuid = "00001124-0000-1000-8000-00805f9b34fb",
+		.get_device_bdaddr = sixaxis_get_device_bdaddr,
+		.get_master_bdaddr = sixaxis_get_master_bdaddr,
+		.set_master_bdaddr = sixaxis_set_master_bdaddr,
+	},
+};
+
+
+#define LED_1 (0x01 << 1)
+#define LED_2 (0x01 << 2)
+#define LED_3 (0x01 << 3)
+#define LED_4 (0x01 << 4)
+
+#define LED_STATUS_OFF 0
+#define LED_STATUS_ON  1
+
+static struct udev *ctx;
+static struct udev_monitor *monitor;
+static guint watch_id;
+
+
+static int create_controller_association(struct btd_adapter *adapter,
+					const char *address,
+					struct sony_controller *controller)
+{
+	DBusConnection *conn;
+	sdp_record_t *rec;
+	struct btd_device *device;
+	bdaddr_t src, dst;
+	char srcaddr[18];
+	int ret = 0;
+
+	DBG("association");
+
+	str2ba(address, &dst);
+	adapter_get_address(adapter, &src);
+	ba2str(&src, srcaddr);
+
+	write_device_name(&dst, &src, controller->name);
+
+	/* Store the device's SDP record */
+	rec = record_from_string(controller->pnp_record);
+	store_record(srcaddr, address, rec);
+	sdp_record_free(rec);
+
+	/* Set the device id */
+	store_device_id(srcaddr, address, 0xffff, controller->vendor_id,
+			controller->product_id, 0);
+	/* Don't write a profile here,
+	 * it will be updated when the device connects */
+
+	DBG("trust");
+	write_trust(srcaddr, address, "[all]", TRUE);
+
+	conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+	if (conn == NULL) {
+		DBG("Failed to get on the bus");
+		ret = -EPERM;
+		goto fail_dbus;
+	}
+
+	DBG("get_device");
+	device = adapter_get_device(conn, adapter, address);
+	if (device == NULL) {
+		DBG("Failed to get the device");
+		ret = -ENODEV;
+		goto fail_device;
+	}
+
+	DBG("set device");
+	device_set_temporary(device, FALSE);
+	device_set_name(device, controller->name);
+	btd_device_add_uuid(device, controller->hid_uuid);
+	DBG("finish");
+
+fail_device:
+	dbus_connection_unref(conn);
+fail_dbus:
+	return ret;
+}
+
+/* Usb cable pairing section */
+static unsigned char *get_feature_report(int fd, uint8_t report_number,
+						unsigned int len)
+{
+	unsigned char *buf;
+	int ret;
+
+	buf = calloc(len, sizeof(*buf));
+	if (buf == NULL) {
+		error("%s:%s() calloc failed", __FILE__, __func__);
+		return NULL;
+	}
+
+	buf[0] = report_number;
+
+	ret = ioctl(fd, HIDIOCGFEATURE(len), buf);
+	if (ret < 0) {
+		error("%s:%s() HIDIOCGFEATURE ret = %d",
+			__FILE__, __func__, ret);
+		free(buf);
+		return NULL;
+	}
+
+	return buf;
+}
+
+static int set_feature_report(int fd, uint8_t *report, int len)
+{
+	int ret;
+
+	ret = ioctl(fd, HIDIOCSFEATURE(len), report);
+	if (ret < 0)
+		error("%s:%s() HIDIOCSFEATURE failed, ret = %d",
+			__FILE__, __func__, ret);
+
+	return ret;
+}
+
+static char *sixaxis_get_device_bdaddr(int fd)
+{
+	unsigned char *buf;
+	char *address;
+
+	buf = get_feature_report(fd, 0xf2, 18);
+	if (buf == NULL) {
+		error("%s:%s() cannot get feature report", __FILE__, __func__);
+		return NULL;
+	}
+
+	address = calloc(BDADDR_STR_SIZE, sizeof(*address));
+	if (address == NULL) {
+		error("%s:%s() calloc failed", __FILE__, __func__);
+		free(buf);
+		return NULL;
+	}
+
+	snprintf(address, BDADDR_STR_SIZE,
+			"%02X:%02X:%02X:%02X:%02X:%02X",
+			buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]);
+
+	free(buf);
+	return address;
+}
+
+static char *sixaxis_get_master_bdaddr(int fd)
+{
+	unsigned char *buf;
+	char *address;
+
+	buf = get_feature_report(fd, 0xf5, 8);
+	if (buf == NULL) {
+		error("%s:%s() cannot get feature report", __FILE__, __func__);
+		return NULL;
+	}
+
+	address = calloc(BDADDR_STR_SIZE, sizeof(*address));
+	if (address == NULL) {
+		error("%s:%s() calloc failed", __FILE__, __func__);
+		free(buf);
+		return NULL;
+	}
+
+	snprintf(address, BDADDR_STR_SIZE,
+			"%02X:%02X:%02X:%02X:%02X:%02X",
+			buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+
+	free(buf);
+	return address;
+}
+
+static int sixaxis_set_master_bdaddr(int fd, char *adapter_bdaddr)
+{
+	uint8_t *report;
+	uint8_t addr[6];
+	int ret;
+
+	ret = sscanf(adapter_bdaddr,
+			"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+			&addr[0], &addr[1], &addr[2],
+			&addr[3], &addr[4], &addr[5]);
+	if (ret != 6) {
+
+		error("%s:%s() Parsing the bt address failed",
+			__FILE__, __func__);
+		return -EINVAL;
+	}
+
+	report = malloc(8);
+	if (report == NULL) {
+		error("%s:%s() malloc failed", __FILE__, __func__);
+		return -ENOMEM;
+	}
+
+	report[0] = 0xf5;
+	report[1] = 0x01;
+
+	report[2] = addr[0];
+	report[3] = addr[1];
+	report[4] = addr[2];
+	report[5] = addr[3];
+	report[6] = addr[4];
+	report[7] = addr[5];
+
+	ret = set_feature_report(fd, report, 8);
+	if (ret < 0) {
+		error("%s:%s() cannot set feature report",
+			__FILE__, __func__);
+		goto out;
+	}
+
+	DBG("New Master Bluetooth address: %s", adapter_bdaddr);
+
+out:
+	free(report);
+	return ret;
+}
+
+static int controller_pair(int fd, struct btd_adapter *adapter, struct sony_controller *controller)
+{
+	char *device_bdaddr;
+	char *master_bdaddr;
+	char adapter_bdaddr[18];
+	bdaddr_t dst;
+	int ret = 0;
+
+	adapter_get_address(adapter, &dst);
+	ba2str(&dst, adapter_bdaddr);
+	DBG("Adapter bdaddr %s", adapter_bdaddr);
+
+	master_bdaddr = controller->get_master_bdaddr(fd);
+	if (master_bdaddr == NULL) {
+		DBG("Failed to get the Old master Bluetooth address from the device");
+		return -EPERM;
+	}
+
+	/* Only set the master bdaddr when needed, this is how the PS3 does
+	 * it, perhaps to avoid unnecessary writes to some eeprom.
+	 */
+	if (g_strcmp0(master_bdaddr, adapter_bdaddr) != 0) {
+		DBG("Old master Bluetooth address was: %s", master_bdaddr);
+		ret = controller->set_master_bdaddr(fd, adapter_bdaddr);
+		if (ret < 0) {
+			DBG("Failed to set the master Bluetooth address");
+			free(master_bdaddr);
+			return ret;
+		}
+	}
+
+	device_bdaddr = controller->get_device_bdaddr(fd);
+	if (device_bdaddr == NULL) {
+		DBG("Failed to get the Bluetooth address from the device");
+		free(master_bdaddr);
+		return -EPERM;
+	}
+
+	DBG("Device bdaddr %s", device_bdaddr);
+
+	ret = create_controller_association(adapter, device_bdaddr, controller);
+	free(device_bdaddr);
+	free(master_bdaddr);
+	return ret;
+}
+
+/* Led setting section */
+static int set_leds(int fd, unsigned char leds_status[4])
+{
+	int ret;
+
+	/*
+	 * the total time the led is active (0xff means forever)
+	 * |     duty_length: how long a cycle is in deciseconds:
+	 * |     |                              (0 means "blink very fast")
+	 * |     |     ??? (Maybe a phase shift or duty_length multiplier?)
+	 * |     |     |     % of duty_length led is off (0xff means 100%)
+	 * |     |     |     |     % of duty_length led is on (0xff is 100%)
+	 * |     |     |     |     |
+	 * 0xff, 0x27, 0x10, 0x00, 0x32,
+	 */
+	unsigned char leds_report[] = {
+		0x01,
+		0x00, 0x00, 0x00, 0x00, 0x00, /* rumble values TBD */
+		0x00, 0x00, 0x00, 0x00, 0x1e, /* LED_1=0x02, LED_2=0x04 ... */
+		0xff, 0x27, 0x10, 0x00, 0x32, /* LED_4 */
+		0xff, 0x27, 0x10, 0x00, 0x32, /* LED_3 */
+		0xff, 0x27, 0x10, 0x00, 0x32, /* LED_2 */
+		0xff, 0x27, 0x10, 0x00, 0x32, /* LED_1 */
+		0x00, 0x00, 0x00, 0x00, 0x00,
+	};
+
+	int leds = 0;
+	if (leds_status[0])
+		leds |= LED_1;
+	if (leds_status[1])
+		leds |= LED_2;
+	if (leds_status[2])
+		leds |= LED_3;
+	if (leds_status[3])
+		leds |= LED_4;
+
+	leds_report[10] = leds;
+
+	DBG("Setting leds");
+	ret = write(fd, leds_report, sizeof(leds_report));
+	if (ret < (ssize_t) sizeof(leds_report))
+		error("%s:%s() Unable to write to hidraw device",
+			__FILE__, __func__);
+
+	return ret;
+}
+
+static int set_controller_number(int fd, unsigned int n)
+{
+	unsigned char leds_status[4] = {0, 0, 0, 0};
+
+	switch (n) {
+	case 0:
+		break;
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+		leds_status[n - 1] = LED_STATUS_ON;
+		break;
+	case 5:
+	case 6:
+	case 7:
+		leds_status[4 - 1] = LED_STATUS_ON;
+		leds_status[n - 4 - 1] = LED_STATUS_ON;
+		break;
+	default:
+		error("%s:%s() Only 7 controllers supported for now",
+			__FILE__, __func__);
+		return -1;
+	}
+
+	return set_leds(fd, leds_status);
+}
+
+
+static inline gboolean is_sixaxis(const char *hid_name)
+{
+	return g_str_has_suffix(hid_name, "PLAYSTATION(R)3 Controller") ||
+		g_str_has_suffix(hid_name,
+			"Sony Computer Entertainment Wireless Controller");
+}
+
+static void handle_device_plug(struct udev_device *udevice)
+{
+	struct udev_device *hid_parent;
+	struct udev_enumerate *enumerate;
+	struct udev_list_entry *devices, *dev_list_entry;
+	const char *hid_name;
+	const char *hid_phys;
+	const char *hidraw_node;
+	unsigned char is_usb = FALSE;
+	int js_num = 0;
+	int fd;
+	struct sony_controller *controller;
+
+	hid_parent = udev_device_get_parent_with_subsystem_devtype(udevice,
+								"hid", NULL);
+	if (!hid_parent) {
+		error("%s:%s() cannot get parent hid device",
+			__FILE__, __func__);
+		return;
+	}
+
+	hid_name = udev_device_get_property_value(hid_parent, "HID_NAME");
+	DBG("name: %s", hid_name);
+
+	if (!is_sixaxis(hid_name))
+		return;
+
+	controller = &controllers[0];
+
+	DBG("Found a Sixaxis device");
+
+	hidraw_node = udev_device_get_devnode(udevice);
+
+	hid_phys = udev_device_get_property_value(hid_parent, "HID_PHYS");
+
+	/* looking for joysticks */
+	enumerate = udev_enumerate_new(udev_device_get_udev(udevice));
+	udev_enumerate_add_match_sysname(enumerate, "js*");
+	udev_enumerate_scan_devices(enumerate);
+
+	devices = udev_enumerate_get_list_entry(enumerate);
+	udev_list_entry_foreach(dev_list_entry, devices) {
+		const char *devname;
+		struct udev_device *js_dev;
+		struct udev_device *input_parent;
+		const char *input_phys;
+
+		devname = udev_list_entry_get_name(dev_list_entry);
+		js_dev = udev_device_new_from_syspath(udev_device_get_udev(udevice),
+							devname);
+
+		input_parent = udev_device_get_parent_with_subsystem_devtype(js_dev,
+							"input", NULL);
+		if (!input_parent) {
+			error("%s:%s() cannot get parent input device.",
+				__FILE__, __func__);
+			continue;
+		}
+
+		/* check this is the joystick relative to
+		 * the hidraw device above */
+		input_phys = udev_device_get_sysattr_value(input_parent,
+								"phys");
+		if (g_strcmp0(input_phys, hid_phys) == 0) {
+			const char *usb_driver;
+
+			usb_driver = udev_device_get_property_value(js_dev,
+							"ID_USB_DRIVER");
+			js_num = atoi(udev_device_get_sysnum(js_dev)) + 1;
+			DBG("joypad device_num: %d", js_num);
+			DBG("hidraw_node: %s", hidraw_node);
+			DBG("driver: %s", usb_driver);
+
+			if (g_strcmp0(usb_driver, "usbhid") == 0)
+				is_usb = TRUE;
+		}
+
+		udev_device_unref(js_dev);
+	}
+
+	udev_enumerate_unref(enumerate);
+
+	DBG("opening hidraw");
+	fd = open(hidraw_node, O_RDWR);
+	if (fd < 0) {
+		error("%s:%s() hidraw open", __FILE__, __func__);
+		return;
+	}
+
+	if (is_usb) {
+		struct btd_adapter *adapter;
+
+		/* Look for the default adapter */
+		adapter = manager_get_default_adapter();
+		if (adapter == NULL) {
+			DBG("No adapters, exiting");
+			return;
+		}
+		controller_pair(fd, adapter, controller);
+	}
+
+	if (js_num > 0) {
+		char c;
+
+		/* wait for events before setting leds */
+		DBG("waiting for events");
+		if (read(fd, &c, 1) != 1)
+			perror("read error");
+		set_controller_number(fd, js_num);
+	}
+
+	close(fd);
+	DBG("hidraw closed");
+}
+
+static gboolean device_event_idle(struct udev_device *udevice)
+{
+	handle_device_plug(udevice);
+	udev_device_unref(udevice);
+	return FALSE;
+}
+
+static gboolean monitor_event(GIOChannel *source, GIOCondition condition,
+				gpointer data)
+{
+	struct udev_device *udevice;
+
+	udevice = udev_monitor_receive_device(monitor);
+	if (udevice == NULL)
+		goto out;
+	if (g_strcmp0(udev_device_get_action(udevice), "add") != 0) {
+		udev_device_unref(udevice);
+		goto out;
+	}
+
+	/* Give UDEV some time to load kernel modules */
+	g_timeout_add_seconds(1, (GSourceFunc) device_event_idle, udevice);
+
+out:
+	return TRUE;
+}
+
+static int sixaxis_init(void)
+{
+	GIOChannel *channel;
+
+	DBG("Setup Sixaxis cable plugin");
+
+	ctx = udev_new();
+	monitor = udev_monitor_new_from_netlink(ctx, "udev");
+	if (monitor == NULL) {
+		error("%s:%s() Could not get udev monitor",
+			__FILE__, __func__);
+		return -1;
+	}
+
+	/* Listen for newly connected hidraw interfaces */
+	udev_monitor_filter_add_match_subsystem_devtype(monitor,
+							"hidraw", NULL);
+	udev_monitor_enable_receiving(monitor);
+
+	channel = g_io_channel_unix_new(udev_monitor_get_fd(monitor));
+	watch_id = g_io_add_watch(channel, G_IO_IN, monitor_event, NULL);
+	g_io_channel_unref(channel);
+
+	return 0;
+}
+
+static void sixaxis_exit(void)
+{
+	DBG("Cleanup Sixaxis cable plugin");
+
+	if (watch_id != 0) {
+		g_source_remove(watch_id);
+		watch_id = 0;
+	}
+	if (monitor != NULL) {
+		udev_monitor_unref(monitor);
+		monitor = NULL;
+	}
+	if (ctx != NULL) {
+		udev_unref(ctx);
+		ctx = NULL;
+	}
+}
+
+BLUETOOTH_PLUGIN_DEFINE(sixaxis, VERSION,
+			BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+			sixaxis_init, sixaxis_exit)

[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux