First, you need to apt install bluez-tools obexpushd.
To send and receive files, you need to set up and pair the devices first.
SETUP
from Arch Wiki - bluetooth:
Bluetoothctl
Start the bluetoothctl interactive command. There one can input help to get a list of available commands.
- Turn the power to the controller on by entering
power on. It is off
by default.
- Enter
devices to get the MAC Address of the device with
which to pair.
- Enter device discovery mode with
scan on command if
device is not yet on the list.
- Turn the agent on with
agent on.
- Enter
pair MAC Address to do the pairing (tab completion works).
- If using a device without a PIN, one may need to manually trust the
device before it can reconnect successfully. Enter
trust MAC Address
to do so.
- Finally, use
connect MAC_address to establish a connection.
The last two bullet points are not necessary for the send part of a file transfer, but you need the connect later for the receive part.
An example session may look this way:
# bluetoothctl
[NEW] Controller 00:10:20:30:40:50 pi [default]
[bluetooth]# agent KeyboardOnly
Agent registered
[bluetooth]# default-agent
Default agent request successful
[bluetooth]# scan on
Discovery started
[CHG] Controller 00:10:20:30:40:50 Discovering: yes
[NEW] Device 00:12:34:56:78:90 myLino
[CHG] Device 00:12:34:56:78:90 LegacyPairing: yes
[bluetooth]# pair 00:12:34:56:78:90
Attempting to pair with 00:12:34:56:78:90
[CHG] Device 00:12:34:56:78:90 Connected: yes
[CHG] Device 00:12:34:56:78:90 Connected: no
[CHG] Device 00:12:34:56:78:90 Connected: yes
Request PIN code
[agent] Enter PIN code: 1234
[CHG] Device 00:12:34:56:78:90 Paired: yes
Pairing successful
[CHG] Device 00:12:34:56:78:90 Connected: no
[bluetooth]# connect 00:12:34:56:78:90
Attempting to connect to 00:12:34:56:78:90
[CHG] Device 00:12:34:56:78:90 Connected: yes
Connection successful
To make changes permanent and in order to have the device active after a reboot, a udev rule is needed:
/etc/udev/rules.d/10-local.rules
# Set bluetooth power up
ACTION=="add", KERNEL=="hci0", RUN+="/usr/bin/hciconfig %k up"
Tip: Replace KERNEL=="hci0" with KERNEL=="hci[0-9]*" to match all BT interfaces.
After a suspend/resume-cycle, the device can be powered on automatically using a custom systemd service:
/etc/systemd/system/bluetooth-auto-power@.service
[Unit]
Description=Bluetooth auto power on
After=bluetooth.service sys-subsystem-bluetooth-devices-%i.device suspend.target
[Service]
Type=oneshot
ExecStart=/usr/bin/hciconfig %i up
[Install]
WantedBy=suspend.target
Enable an instance of the unit using your bluetooth device name, for example bluetooth-auto-power@hci0.service.
Now your devices are paired. Check that you can see the other with bt-device -l.
SEND
Next, you have to send up your systemd infrastructure for the send to work, otherwise you get the following error:
Acquiring proxy failed: Error calling StartServiceByName for org.bluez.obex: GDBus.Error:org.freedesktop.systemd1.LoadFailed: Unit dbus-org.bluez.obex.service failed to load: No such file or directory.
Make the necessary systemd changes with
systemctl --user start obex
sudo systemctl --global enable obex
This makes sure you can send files. A sudo also in the first line will fail!
You can send files now by bluetooth-sendto --device=12:34:56:78:9A:BC filename filename2. If a transfer hangs at 100%, a ctrlc finalizes it (or aborts earlier).
To know your device name (12:34:56:78:9A:BC), you can issue bt-device -l.
RECEIVE
from Raspberry Pi forum:
We want to set up a OBEX push server, this is why obexpushd was needed.
The compatibility flag on the Bluetooth daemon is needed, you have to edit /etc/systemd/system/dbus-org.bluez.service with the editor of your choice by adding the -C flag to the end of the ExecStart= line. It should look like this:
ExecStart=/usr/lib/bluetooth/bluetoothd -C
Reboot or restart the service with sudo systemctl daemon-reload after editing. Choose a specific directory where received files are placed, for example by sudo mkdir /bluetooth.
Start the server with sudo obexpushd -B -o /bluetooth -n, it should respond with:
obexpushd 0.11.2 Copyright (C) 2006-2010 Hendrik Sattler
This software comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
Listening on bluetooth/[00:00:00:00:00:00]:9
If that's not working, and you get:
obexpushd 0.11.2 Copyright (C) 2006-2010 Hendrik Sattler
This software comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
BtOBEX_ServerRegister: Address already in use
net_init() failed
it could be because you have another daemon or program running which occupies the rfcomm channel 9 that obexpushd uses by default. In this case, change the channel to 23 like this:
sudo obexpushd -B23 -o /bluetooth -n
to use channel 23.
Once you get obexpushd running, open a second terminal window. You can verify that the OBEX service is registered with
sudo sdptool browse local
It should list (at channel 23 in this case), among others, this:
Service Name: OBEX Object Push
Service Description: a free OBEX server
Service Provider: obexpushd
Service RecHandle: 0x10005
Service Class ID List:
"OBEX Object Push" (0x1105)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 23
"OBEX" (0x0008)
Profile Descriptor List:
"OBEX Object Push" (0x1105)
Version: 0x0100
In that window, while obexpushd is still running, use bluetoothctl to set discoverable on. Now pair from your other device. Pairing MUST be done while obexpushd is running, or the other device wont recognize the service is available. If the phone is already paired, remove it from your other device, use bluetoothctl to remove it from the Ubuntu computer, and re-pair.
After you connect (the last bullet point from the above list), you should be able to receive files. They will appear in the /bluetooth directory. Notice that they will be owned by root, so you'll need sudo to access them. Or you can do a chmod 0777 /bluetooth for a public exchange directory, since the bluetooth authentification is device-based and not user-based anyway.
In order to automate the obexpushd command, create the file /etc/systemd/system/obexpush.service
[Unit]
Description=OBEX Push service
After=bluetooth.service
Requires=bluetooth.service
[Service]
ExecStart=/usr/bin/obexpushd -B23 -o /bluetooth -n
[Install]
WantedBy=multi-user.target
Then, set that to autostart with
sudo systemctl enable obexpush
After a reboot or restart of the service with sudo systemctl daemon-reload, you should be able to send and receive files in both directions now.
Don't forget to connect the devices when trying to receive files.