BLUETOOTHCTL-GATT(1)

πŸ’… BLUETOOTHCTL-GATT β€” the generic attribute submenu, bestie

okay so this is bluetoothctl-gatt from the Linux System Administration manual, and it's literally the GATT girlie of the bluetoothctl family. Buckle up πŸŽ€


🌸 NAME 🌸

bluetoothctl-gatt β€” the Generic Attribute Submenu. that's her. that's the whole name. iconic, brief, no notes πŸ’…


✨ SYNOPSIS ✨

bluetoothctl [--options] [gatt.commands]

so like, this submenu is the one that talks to GATT services, characteristics, and descriptors β€” and it does it through the org.bluez.GattService(5), org.bluez.GattCharacteristic(5), org.bluez.GattDescriptor(5), and org.bluez.GattManager(5) interfaces. like those are the four besties she's always texting, ykwim? 🫢


πŸ‘‘ GENERIC ATTRIBUTE COMMANDS πŸ‘‘

πŸ” list-attributes

Lists the attributes of either the local device or a remote device, and it covers services, characteristics, and handles. basically a full read of the room β€” every Bluetooth attribute that's available, laid out so you can go poke at them with the other commands. main character energy for real ✨

Usage

> list-attributes [dev/local]

[dev/local] β€” device MAC address, object path, or "local" to list locally registered attributes (optional β€” omits = lists all of them, no cap)

Example: List attributes for specific service

> list-attributes /org/bluez/hci0/dev_00_11_22_33_44_55/service001a

Example: List attributes for specific characteristic

> list-attributes /org/bluez/hci0/dev_00_11_22_33_44_55/service001a/char001c

Example: List attributes for service on different device

> list-attributes /org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF/service0020

Example: List all Generic Access service attributes

> list-attributes 0x1800

Example: List all Battery Service attributes

> list-attributes 0x180F

Example: List all Device Name characteristic attributes

> list-attributes 0x2A00

Example: List attributes using full UUID

> list-attributes 00001801-0000-1000-8000-00805f9b34fb

Example: List attributes for custom service UUID

> list-attributes 12345678-1234-5678-9abc-123456789abc

🎯 select-attribute

Picks a specific attribute β€” local or remote β€” so everything you do next happens on that one. this is the whole vibe check of the workflow, because you literally cannot read or write to an attribute before you've selected it with this command. it sets the context for a bunch of other commands (read, write, notify, etc.) and tells them which attribute they're supposed to be operating on. no selection, no service πŸ’€

Usage

> select-attribute <attribute/UUID/local> [attribute/UUID]

<attribute/UUID/local> β€” GATT attribute path, UUID, or "local" to select from the local attributes

[attribute/UUID] β€” an extra attribute path or UUID for when you're using "local" (optional)

Example: Select specific characteristic

> select-attribute /org/bluez/hci0/dev_00_11_22_33_44_55/service001a/char001c

Example: Select specific descriptor

> select-attribute /org/bluez/hci0/dev_00_11_22_33_44_55/service0020/char0022/desc0024

Example: Select service on different device

> select-attribute /org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF/service001a

Example: Select Device Name characteristic

> select-attribute 0x2A00

Example: Select Battery Level characteristic

> select-attribute 0x2A19

Example: Select Client Characteristic Configuration descriptor

> select-attribute 0x2902

Example: Select Temperature characteristic using full UUID

> select-attribute 00002a6e-0000-1000-8000-00805f9b34fb

Example: Select custom characteristic

> select-attribute 12345678-1234-5678-9abc-123456789abc

πŸ“‹ attribute-info

Shows you the detailed tea on an attribute. if you don't hand it an attribute or UUID, it just spills about whatever attribute is currently selected. genuinely so useful for understanding an attribute's properties and capabilities β€” like reading their bio before you slide into their DMs 🫢

Usage

> attribute-info [attribute/UUID]

[attribute/UUID] β€” GATT attribute path or UUID to get info for (optional β€” uses the current one if you omit it)

Example: Show information for currently selected attribute

> attribute-info

Example: Show info for specific characteristic

> attribute-info /org/bluez/hci0/dev_00_11_22_33_44_55/service001a/char001c

Example: Show info for Battery Level characteristic

> attribute-info 0x2A19

Example: Show info for Device Name characteristic

> attribute-info 0x2A00

Example: Show info for Temperature characteristic

> attribute-info 00002a6e-0000-1000-8000-00805f9b34fb

πŸ“– read

Reads an attribute's value. ⚠️ heads up bestie: it requires that you selected an attribute beforehand with select-attribute, or it's giving nothing. the optional offset parameter is there for attributes that allow partial reads β€” so you can start reading from somewhere other than the very beginning, slay ✨

Usage

> read [offset]

Uses org.bluez.GattCharacteristic(5) method ReadValue

[offset] β€” byte offset to start reading from (optional, defaults to 0)

Example: Read attribute value from offset 0

> read

Example: Read attribute value from offset 0 (explicit)

> read 0

Example: Read attribute value starting from offset 4

> read 4

Example: Read attribute value starting from offset 10

> read 10

Example: Read attribute value starting from offset 16

> read 16

✍️ write

Writes a value into an attribute. ⚠️ same rule as read: you must have selected an attribute in advance with select-attribute. data has to come in hexadecimal format β€” no vibes-based input, sorry 😭. the optional offset and type parameters are there for when your write has specific requirements.

Usage

> write <data="xx xx ..."> [offset] [type]

Uses org.bluez.GattCharacteristic(5) method WriteValue

<xx xx ...> β€” hexadecimal data bytes to write to the attribute

[offset] β€” byte offset to start writing at (optional, defaults to 0)

[type] β€” write type: request, command, or reliable (optional, defaults to request)

Example: Write Hello to attribute (ASCII bytes)

> write "48 65 6C 6C 6F"

Example: Write binary data to attribute

> write "01 02 03 04"

Example: Write single byte value

> write "FF"

Example: Write 2 bytes starting at offset 4

> write "01 02" 4

Example: Write with write request (default)

> write "48 65 6C 6C 6F" 0 request

Example: Write with write command (no response)

> write "01 02 03" 0 command

Example: Write with reliable write

> write "FF EE DD" 0 reliable

πŸ”‘ acquire-write

Grabs a Write file descriptor for the attribute you already selected. super handy for apps that need a file descriptor to do their write operations. it's giving "hold my spot" πŸ’…

Usage

> acquire-write

Uses org.bluez.GattCharacteristic(5) method AcquireWrite

Example: Acquire write file descriptor for current attribute

> acquire-write

🧹 release-write

Releases the Write file descriptor you got from acquire-write. this is the cleanup step β€” you literally need it to free up resources once you're done writing. don't ghost your file descriptors, bestie, that's not the vibe 🫢

Usage

> release-write

Example: Release write file descriptor for current attribute

> release-write

πŸ”” acquire-notify

Grabs a Notify file descriptor for the attribute you selected earlier. this is what lets applications listen for notifications when an attribute's value changes. lowkey the most useful thing ever πŸ‘‘

Usage

> acquire-notify

Uses org.bluez.GattCharacteristic(5) method AcquireNotify

Example: Acquire notify file descriptor for current attribute

> acquire-notify

🧼 release-notify

Releases the Notify file descriptor you got with acquire-notify. frees the resources once you're done listening for notifications. closure is healthy ✨

Usage

> release-notify

Example: Release notify file descriptor for current attribute

> release-notify

πŸ”• notify

Turns notifications for attribute value changes on or off. ⚠️ the relevant attribute has to be selected before you can use this one. it means apps can get told about attribute changes without polling β€” no more refreshing like a feral person, we love to see it πŸ’–

Usage

> notify <on/off>

Uses org.bluez.GattCharacteristic(5) methods StartNotify, StopNotify

<on/off> β€” enable or disable notifications for the current attribute

Example: Enable notifications for current attribute

> notify on

Example: Disable notifications for current attribute

> notify off

πŸ‘― clone

Makes a clone of a device or attribute. useful for creating a backup, or for working with a copy when you're testing stuff. girlie said "I'll just duplicate myself" πŸ’…

Usage

> clone [dev/attribute/UUID]

[dev/attribute/UUID] β€” device MAC address, attribute path, or UUID to clone (optional β€” clones the current one if omitted)

Example: Clone entire device GATT database

> clone 00:11:22:33:44:55

Example: Clone another device

> clone AA:BB:CC:DD:EE:FF

Example: Clone specific service

> clone /org/bluez/hci0/dev_00_11_22_33_44_55/service001a

Example: Clone specific characteristic

> clone /org/bluez/hci0/dev_00_11_22_33_44_55/service001a/char001c

Example: Clone Generic Access service

> clone 0x1800

Example: Clone Battery Service

> clone 0x180F

Example: Clone Battery Level characteristic

> clone 0x2A19

πŸ“ register-application

Registers a new application with the Bluetooth system, so you can manage services, characteristics, and descriptors under that application. it's giving "signing the lease on your own little GATT apartment" 🏠✨

Usage

> register-application [UUID ...]

Uses org.bluez.GattManager(5) method RegisterApplication

[UUID ...] β€” optional list of service UUIDs to register with the application

Example: Register GATT application without specific UUIDs

> register-application

Example: Register application with Battery Service

> register-application 0x180F

Example: Register with Generic Access and Battery Service

> register-application 0x1800 0x180F

Example: Register application with custom service UUID

> register-application 12345678-1234-5678-9abc-123456789abc

Example: Register with multiple standard services

> register-application 0x1800 0x180F 0x180A

πŸ—‘οΈ unregister-application

Removes an application you previously registered from the Bluetooth system. bye bestie πŸ‘‹ no hard feelings, just cleanup.

Usage

> unregister-application

Uses org.bluez.GattManager(5) method UnregisterApplication

Example: Unregister current GATT application

> unregister-application

πŸ†• register-service

Adds a new service under a registered application. genuinely crucial if you're defining new services that devices can offer β€” this is the "here's what I bring to the table" command πŸ”₯

Usage

> register-service <UUID> [handle]

<UUID> β€” service UUID to register (16-bit, 32-bit, or 128-bit format)

[handle] β€” specific attribute handle to assign (optional β€” auto-assigned if you omit it)

Example: Register Generic Access service (auto handle)

> register-service 0x1800

Example: Register Battery Service (auto handle)

> register-service 0x180F

Example: Register Device Information service (auto handle)

> register-service 0x180A

Example: Register Generic Access service at handle 1

> register-service 0x1800 0x0001

Example: Register Battery Service at handle 16

> register-service 0x180F 0x0010

okay so, the rest of the register-service examples are serving exact-handle realness, and you already know the vibe:

  • Register Device Info service at handle 32 β€” > register-service 0x180A 0x0020
  • Register custom service (auto handle) β€” > register-service 12345678-1234-5678-9abc-123456789abc
  • Register custom service at specific handle β€” > register-service 12345678-1234-5678-9abc-123456789abc 0x0050

πŸ’– unregister-service πŸ’–

This one yanks a service out of a registered application, so it stops being available. It’s giving β€œavailability revoked, periodt.”

Usage

> unregister-service <UUID/object>
  • <UUID/object> β€” the service UUID or object path of the service you’re unregistering, bestie.

Examples

  • Unregister Generic Access service β€” > unregister-service 0x1800
  • Unregister Battery Service β€” > unregister-service 0x180F
  • Unregister custom service β€” > unregister-service 12345678-1234-5678-9abc-123456789abc
  • Unregister service by object path β€” > unregister-service /org/bluez/example/service0
  • Unregister another service β€” > unregister-service /org/bluez/example/service1

🧚 register-includes 🧚

Marks a service as included within another service, so you can build service hierarchies and complex service structures. It’s lowkey giving nesting-doll energy.

Usage

> register-includes <UUID> [handle]
  • <UUID> β€” service UUID to register as an included service.
  • [handle] β€” specific attribute handle to assign; it’s optional and auto-assigned if you omit it.

Examples

  • Register Generic Access as included service β€” > register-includes 0x1800
  • Register Battery Service as included at handle 21 β€” > register-includes 0x180F 0x0015
  • Register custom service as included β€” > register-includes 12345678-1234-5678-9abc-123456789abc

πŸ¦‹ unregister-includes πŸ¦‹

Removes an included service relationship, simplifying the service structure. It’s the β€œokay we’re untangling this now” command.

Usage

> unregister-includes <Service-UUID> <Inc-UUID>
  • <Service-UUID> β€” parent service UUID that contains the included service.
  • <Inc-UUID> β€” included service UUID to remove from the parent service.

Examples

  • Unregister Battery Service inclusion from Generic Access β€” > unregister-includes 0x1800 0x180F
  • Unregister Device Info inclusion from custom service β€” > unregister-includes 12345678-1234-5678-9abc-123456789abc 0x180A

✨ register-characteristic ✨

Introduces a new characteristic under a service, specifying its properties and access permissions with flags. This is where the GATT girlies really start customizing, no cap.

Usage

> register-characteristic <UUID> <Flags=read,write,notify...> [handle]
  • <UUID> β€” characteristic UUID to register; it can be 16-bit, 32-bit, or 128-bit format.
  • <Flags=read,write,notify...> β€” comma-separated list of characteristic properties and permissions.
  • [handle] β€” specific attribute handle to assign; optional, and auto-assigned if omitted.

Examples

  • Register Device Name (read-only) β€” > register-characteristic 0x2A00 read
  • Register Battery Level (read + notifications) β€” > register-characteristic 0x2A19 read,notify
  • Register Heart Rate Measurement (notify-only) β€” > register-characteristic 0x2A37 notify
  • Register Device Name (read + write) β€” > register-characteristic 0x2A00 read,write
  • Register Battery Level (read + write + notify) β€” > register-characteristic 0x2A19 read,write,notify
  • Register Temperature (read + indications) β€” > register-characteristic 0x2A6E read,indicate
  • Register Device Name at handle 3 β€” > register-characteristic 0x2A00 read 0x0003
  • Register Battery Level at handle 19 β€” > register-characteristic 0x2A19 read,notify 0x0013
  • Register custom characteristic with full capabilities β€” > register-characteristic 12345678-1234-5678-9abc-123456789abc read,write,notify
  • Register custom write-only characteristic β€” > register-characteristic ABCD1234-ABCD-1234-ABCD-123456789ABC write-without-response
  • Register with all flags β€” > register-characteristic 0x2A00 read,write,write-without-response,notify,indicate

πŸŽ€ unregister-characteristic πŸŽ€

Eliminates a characteristic from a service, removing its functionality. It’s the clean-girl removal arc.

Usage

> unregister-characteristic <UUID/object>
  • <UUID/object> β€” characteristic UUID or object path of the characteristic to unregister.

Examples

  • Unregister Device Name characteristic β€” > unregister-characteristic 0x2A00
  • Unregister Battery Level characteristic β€” > unregister-characteristic 0x2A19
  • Unregister custom characteristic β€” > unregister-characteristic 12345678-1234-5678-9abc-123456789abc
  • Unregister characteristic by object path β€” > unregister-characteristic /org/bluez/example/service0/char0
  • Unregister another characteristic β€” > unregister-characteristic /org/bluez/example/service1/char1

🌸 register-descriptor 🌸

Adds a descriptor to a characteristic, further defining its behavior and access controls. Descriptors are literally the little accessories that finish the outfit.

Usage

> register-descriptor <UUID> <Flags=read,write...> [handle]
  • <UUID> β€” descriptor UUID to register; it can be 16-bit, 32-bit, or 128-bit format.
  • <Flags=read,write...> β€” comma-separated list of descriptor properties and permissions.
  • [handle] β€” specific attribute handle to assign; optional, and auto-assigned if omitted.

Examples

  • Register Client Characteristic Configuration β€” > register-descriptor 0x2902 read,write
  • Register Characteristic User Description β€” > register-descriptor 0x2901 read
  • Register Characteristic Presentation Format β€” > register-descriptor 0x2904 read
  • Register CCCD at handle 5 β€” > register-descriptor 0x2902 read,write 0x0005
  • Register User Description at handle 21 β€” > register-descriptor 0x2901 read 0x0015
  • Register custom descriptor β€” > register-descriptor 12345678-1234-5678-9abc-123456789abc read,write
  • Register custom read-only descriptor β€” > register-descriptor ABCD1234-ABCD-1234-ABCD-123456789ABC read
  • Register Valid Range descriptor β€” > register-descriptor 0x2906 read
  • Register External Report Reference β€” > register-descriptor 0x2907 read
  • Register Report Reference β€” > register-descriptor 0x2908 read

πŸ’… unregister-descriptor πŸ’…

Removes a descriptor from a characteristic, simplifying its behavior. It’s giving β€œwe don’t need that accessory anymore, bestie.”

Usage

> unregister-descriptor <UUID/object>
  • <UUID/object> β€” descriptor UUID or object path of the descriptor to unregister.

Examples

  • Unregister Client Characteristic Configuration β€” > unregister-descriptor 0x2902
  • Unregister Characteristic User Description β€” > unregister-descriptor 0x2901
  • Unregister custom descriptor β€” > unregister-descriptor 12345678-1234-5678-9abc-123456789abc
  • Unregister descriptor by object path β€” > unregister-descriptor /org/bluez/example/service0/char0/desc0
  • Unregister another descriptor β€” > unregister-descriptor /org/bluez/example/service1/char1/desc1

🌐 RESOURCES 🌐

The official BlueZ website is right here: http://www.bluez.org β€” iconic, honestly.

πŸ› REPORTING BUGS πŸ›

Bug reports go to linux-bluetooth@vger.kernel.org. Tell them what happened, bestie.

Legal tea, served fresh: Free use of this software is granted under the terms of the GNU Lesser General Public Licenses (LGPL).


okay signing off β€” source/version is BlueZ, date is November 2022, and the manual is BLUETOOTHCTL-GATT(1). mwah πŸ’‹βœ¨πŸ«Ά

πŸ“¦ where this page comes from