Key Terms
One of Bluetooth’s earliest goals was simple: replace cables. Instead of plugging a serial RS-232 cable between two devices, just use Bluetooth. That is what RFCOMM does.
RFCOMM is based on the ETSI TS 07.10 standard — a multiplexer that runs multiple sessions over a single serial link. Bluetooth adopted it with some changes, so it is called an adopted protocol.
| Old World (Wired RS-232) | New World (RFCOMM over Bluetooth) |
|---|---|
| Physical RS-232 serial cable | Bluetooth RFCOMM wireless connection |
| Cable plug at each end | RFCOMM endpoint at each device |
| 1 cable = 1 connection | 1 Bluetooth link = up to 60 virtual connections |
| Physical COM port on PC | Virtual COM port — software behaves identically |
Common real-world uses of RFCOMM:
- Communication between two PCs
- Mobile phone connected to a Bluetooth headset
- Mobile phone tethered to a laptop
A real RS-232 port has 9 signal lines. RFCOMM emulates all 9 wirelessly. This makes RFCOMM a true drop-in replacement — terminal software like HyperTerminal or TeraTerm cannot tell the difference between a real cable and RFCOMM.
| Signal | Full Name | What It Does | Type |
|---|---|---|---|
| TD | Transmit Data | Carries outgoing data from the device | Data |
| RD | Receive Data | Carries incoming data to the device | Data |
| RTS | Request To Send | Device signals it wants to send data | Flow Control |
| CTS | Clear To Send | Other device confirms it can receive now | Flow Control |
| DSR | Data Set Ready | Modem signals it is powered and ready | HW Flow Control |
| DTR | Data Terminal Ready | Terminal signals it is ready to communicate | HW Flow Control |
| CD | Data Carrier Detect | Indicates modem is connected to telephone line | Status |
| RI | Ring Indicator | Signals an incoming call ring on telephone line | Status |
| GND | Signal Common | Common electrical ground reference for all signals | Ground |
RFCOMM recognises two kinds of communication devices:
| Type | Role in Communication | Real Example |
|---|---|---|
| Type 1 — Endpoint | Sits at the start or end of the path. Either produces or consumes data. Nothing passes further. | A laptop browsing the internet. It is the final consumer of data. |
| Type 2 — Relay | Sits in the middle. Takes data from one segment and passes it to another network. | A phone relaying laptop data (via Bluetooth) to the cellular network. This is Bluetooth tethering. |
RFCOMM is a multiplexer. One Bluetooth link can carry up to 60 separate virtual connections at the same time. Each is identified by a DLCI (Data Link Connection Identifier). Think of DLCIs as lanes on a motorway — all on the same road but carrying different traffic independently.
| DLCI Value | Purpose |
|---|---|
| 0 | Control channel — reserved for multiplexer setup commands before any other DLCIs are opened. |
| 2, 4, 6 … 60 | Server channels on the non-initiating side (device that did not start the session). |
| 3, 5, 7 … 61 | Server channels on the initiating side (device that started the session). |
Server applications register with RFCOMM and receive a Server Channel Number from 1 to 30. The final DLCI is calculated from this number and a direction bit (the lowest bit of DLCI) that identifies the initiator.
RFCOMM Multiplexing — Multiple apps sharing one Bluetooth link:
| Device A — Applications | RFCOMM Shared Layer | Device B — Applications |
|---|---|---|
|
File Transfer
Terminal Emulator
Hands-Free App
|
RFCOMM Multiplexer
DLCI 0 = Control
Up to 60 DLCIs total L2CAP — Single Bluetooth Link
|
File Transfer
Object Push
Hands-Free App
|
Multiple applications on both sides share one Bluetooth connection via RFCOMM DLCI multiplexing
This is one of RFCOMM’s key improvements over the base TS 07.10 standard, added after Bluetooth 1.0b. It solves this problem: what happens if the sender transmits faster than the receiver can process?
The answer: use credits as tokens. The receiver hands tokens to the sender. The sender spends one token per frame sent. When tokens run out, the sender stops and waits for more from the receiver.
| Sender | Direction | Receiver |
|---|---|---|
| DLCI opens. Waiting for credits. | ← | Grants 5 credits to sender. |
| Sends Frame 1 (credits left: 4) | → | Receives Frame 1. Processing. |
| Sends Frame 2 (credits left: 3) | → | Receives Frame 2. Processing. |
| Sends Frames 3, 4, 5 (credits = 0) | → | Buffer full. Still processing. |
| Credits = 0. STOP. Waiting. | Done processing. Grants 5 more credits. | |
| Credits restored. Resumes sending. | → | Ready to receive again. |
Credit-based flow control prevents buffer overflow and emulates the RTS/CTS handshaking of RS-232
# List all RFCOMM bindings on this machine
rfcomm
# Bind rfcomm0 to a remote device on channel 1
rfcomm bind /dev/rfcomm0 AA:BB:CC:DD:EE:FF 1
# Connect to a remote RFCOMM channel interactively
rfcomm connect /dev/rfcomm0 AA:BB:CC:DD:EE:FF 1
# Release a binding
rfcomm release /dev/rfcomm0
# Once bound, use like any serial port
minicom -D /dev/rfcomm0
# Find RFCOMM channels via SDP
sdptool browse AA:BB:CC:DD:EE:FF | grep -A5 "RFCOMM"
OBEX stands for Object Exchange Protocol. Bluetooth adopted it from the IrDA (Infrared Data Association) world, where it was called IrOBEX. Because it was borrowed rather than invented for Bluetooth, it is called an adopted specification.
The key benefit: since OBEX is identical whether it runs over Bluetooth or infrared, applications written for IrDA work on Bluetooth with no changes.
How the OBEX stack changed between versions:
| OBEX v1.1 | OBEX v2.0 (BT 3.0 + HS) | |||||||
|---|---|---|---|---|---|---|---|---|
OBEX sits on top of RFCOMM |
RFCOMM removed — less overhead, higher speed |
| Use Case | What It Does | Standard Formats |
|---|---|---|
| Synchronisation | Keeps contacts and calendar entries in sync between a phone and laptop. Changes on one device are pushed to the other. | vCard, vCalendar |
| File Transfer | Send and receive any file. Browse remote folders. Delete files remotely. Works like a wireless FTP client. | Any file type |
| Object Push | Push or pull small objects using standard formats so different brands of devices understand each other perfectly. | vCard (contacts), vCalendar (events), vMessage (messages), vNotes (notes) |
OBEX follows a strict client/server model — just like HTTP. The client always initiates. The server always responds. One request + one response = one operation. Operations are sequential — the client waits for a reply before sending the next request.
| Role | Typical Device | What It Can Do |
|---|---|---|
| Client only | PC sending files to a printer | Sends all operations: Connect, Put, Get, SetPath, Abort, Disconnect |
| Server only | Bluetooth printer — only receives jobs | Responds to operations. Cannot initiate anything. |
| Both roles | Mobile phone — can send and receive contacts | Acts as client or server depending on who starts the OBEX session. |
OBEX has exactly 6 operations. Each is a client request with a server response:
| Operation | Sent By | What It Does |
|---|---|---|
| Connect | Client | Opens the OBEX session. Negotiates OBEX version and max packet size. Always the first operation. |
| Disconnect | Client | Cleanly ends the OBEX session. Always the last operation. |
| Put | Client | Client pushes one object to the server. Example: sending a photo or vCard contact. |
| Get | Client requests, Server sends data | Client requests an object from the server. Server sends it back. Example: pulling a contact from another phone. |
| SetPath | Client | Sets the working folder on the server side. All following Put/Get operations work from that folder. Like cd in a terminal. |
| Abort | Client | Cancels an operation that was spread over multiple packets. Stops a large file transfer cleanly without corrupting the server. |
Here is what a typical OBEX contact-push looks like step by step between two phones:
| OBEX Client — Phone A | ↕ | OBEX Server — Phone B |
|---|---|---|
| 1. Connect Request Sends OBEX version + max packet size |
→ | 2. Connect Response — OK Agrees on negotiated parameters |
| 3. SetPath Request Navigate to /contacts folder on server |
→ | 4. SetPath Response — OK |
| 5. Put Request Sends John.vcf (vCard file) Large objects split across multiple packets |
→ | 6. Put Response — Continue / OK Acknowledges each incoming packet |
| 7. Disconnect Request | → | 8. Disconnect Response — OK |
| Session complete — contact delivered successfully | ||
Note on Abort: If the client wants to cancel step 5 midway through a large file, it sends an Abort operation. This stops the transfer cleanly without leaving corrupt data on the server side.
# Send a file using OBEX Object Push
obexftp --bluetooth AA:BB:CC:DD:EE:FF --channel 9 --put photo.jpg
# Send a vCard contact
obexftp --bluetooth AA:BB:CC:DD:EE:FF --channel 9 --put contact.vcf
# List files on remote device via OBEX FTP
obexftp --bluetooth AA:BB:CC:DD:EE:FF --channel 10 --list
# Pull a file from remote device
obexftp --bluetooth AA:BB:CC:DD:EE:FF --channel 10 --get notes.txt
# Using modern BlueZ obexctl (interactive session)
obexctl
[obexctl]# connect AA:BB:CC:DD:EE:FF
[NEW] Client /org/bluez/obex/client/session0
[obexctl]# send /home/user/contact.vcf
[obexctl]# disconnect
Emulates RS-232 over Bluetooth. Up to 60 virtual connections on one link. Apps see a normal COM port.
DLCI 0 is control. Even DLCIs belong to non-initiator. Odd to initiator. Maximum 60 total connections.
Receiver grants credits. Sender spends one per frame. Zero credits means stop. Receiver grants more when ready.
Adopted from IrDA. Handles file transfer, contact sync and object push using vCard, vCalendar formats.
Bypasses RFCOMM and goes directly over L2CAP. Less overhead and higher throughput for BT 3.0 + HS.
RFCOMM and OBEX both allow only one request at a time. Simple by design — easy to implement on small devices.
