How to use the Bluetooth Driver Stack

After Windows loads and initializes the Bluetooth driver stack, the driver stack discovers active Bluetooth devices that have already been paired. The driver stack then generates device identifiers (device IDs) for all paired devices. Next, the driver stack uses standard Plug and Play (PnP) mechanisms to load the appropriate profile driver for each device. The profile driver to be loaded is selected based on the INF file that installs the profile driver and the device identifier, as generated by the Bluetooth driver stack and described in Installing a Bluetooth Device.

Profile drivers communicate with the Bluetooth driver stack through the standard I/O Request Packet (IRP)-based mechanism employed by all drivers based on the WDM architecture. A profile driver communicates with its device by allocating and sending IRPs down the Bluetooth driver stack to the Bluetooth port driver, Bthport.sys.

A profile driver allocates and initializes IRPs to be processed by Bthport.sys. Profile drivers then communicate with their devices by using IOCTL requests that are delivered to the device by means of an IRP_MJ_INTERNAL_DEVICE_CONTROL or IRP_MJ_DEVICE_CONTROL IRP. The profile driver specifies one of the I/O control codes in the following list in the IRP.

The Bluetooth driver stack supports the following IOCTLs for kernel-mode callers through IRP_MJ_DEVICE_CONTROL:

IOCTL_BTH_DISCONNECT_DEVICE

IOCTL_BTH_GET_DEVICE_INFO

IOCTL_BTH_GET_LOCAL_INFO

IOCTL_BTH_GET_RADIO_INFO

IOCTL_BTH_SDP_ATTRIBUTE_SEARCH

IOCTL_BTH_SDP_CONNECT

IOCTL_BTH_SDP_DISCONNECT

IOCTL_BTH_SDP_REMOVE_RECORD

IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH

IOCTL_BTH_SDP_SERVICE_SEARCH

IOCTL_BTH_SDP_SUBMIT_RECORD

IOCTL_BTH_SDP_SUBMIT_RECORD_WITH_INFO

The Bluetooth driver stack supports the following IOCTLs and BRBs kernel-mode callers (generally for driver-to-driver communication) through IRP_MJ_INTERNAL_DEVICE_CONTROL:

BRB_HCI_GET_LOCAL_BD_ADDR

BRB_L2CA_REGISTER_SERVER

BRB_L2CA_UNREGISTER_SERVER

BRB_L2CA_OPEN_CHANNEL

BRB_L2CA_OPEN_CHANNEL_RESPONSE

BRB_L2CA_CLOSE_CHANNEL

BRB_L2CA_ACL_TRANSFER

BRB_L2CA_UPDATE_CHANNEL

BRB_L2CA_PING

BRB_REGISTER_PSM

BRB_UNREGISTER_PSM

BRB_SCO_REGISTER_SERVER

BRB_SCO_UNREGISTER_SERVER

BRB_SCO_OPEN_CHANNEL

BRB_SCO_OPEN_CHANNEL_RESPONSE

BRB_SCO_CLOSE_CHANNEL

BRB_SCO_TRANSFER

BRB_SCO_GET_CHANNEL_INFO

BRB_SCO_GET_SYSTEM_INFO

BRB_SCO_FLUSH_CHANNEL

BRB_ACL_GET_MODE

BRB_ACL_ENTER_ACTIVE_MODE

BRB_GET_DEVICE_INTERFACE_STRING

IOCTL_INTERNAL_BTH_SUBMIT_BRB

IOCTL_INTERNAL_BTHENUM_GET_DEVINFO

IOCTL_INTERNAL_BTHENUM_GET_ENUMINFO

For more information about how to use the IOCTLs described in the previous lists, see Bluetooth IOCTLs.

Profile drivers primarily use IOCTL_INTERNAL_BTH_SUBMIT_BRB to communicate and interact with the functionality provided in the Bluetooth driver stack. A profile driver uses IOCTL_INTERNAL_BTH_SUBMIT_BRB to deliver a variable-length data structure called a Bluetooth Request Block (BRB) to the device it manages. Profile drivers use BRBs to open and close connections to remote devices and to perform most input and output tasks. IOCTL_INTERNAL_BTH_SUBMIT_BRB contains a BRB that further describes the Bluetooth operation to perform. To learn more about how to build and send BRBs down the Bluetooth driver stack, see Building and Sending a BRB.

Each BRB begins with a standard header defined by the BRB_HEADER structure that specifies the type of BRB, which determines the structure of the rest of the BRB. The Type member, which must equal one of the values found in the BRB_TYPE enumeration, determines the type of Bluetooth operation that the profile driver requests. The BRB structure and size vary according to the type of BRB. The Length member of the BRB_HEADER structure specifies the size, in bytes, of the BRB. The BthAllocateBrb, BthInitializeBrb, and BthReuseBrb functions automatically set the Type and Length members.

For example, to open a connection to a remote device, specify either one of the function codes, BRB_L2CA_OPEN_CHANNEL or BRB_SCO_OPEN_CHANNEL, to indicate that the profile driver is attempting to open a L2CAP or a SCO connection channel to the remote device. The Bluetooth driver stack uses the Status member of the BRB structure to return a Bluetooth-specific status code.

For each BRB, the profile driver must allocate and initialize the appropriate corresponding structure with information about the Bluetooth operation to perform.

The following table describes the structures that correspond to specific BRBs that profile drivers can issue:

Bluetooth Request Block (BRB) Corresponding structure
BRB_HCI_GET_LOCAL_BD_ADDR _BRB_GET_LOCAL_BD_ADDR
BRB_L2CA_REGISTER_SERVER _BRB_L2CA_REGISTER_SERVER
BRB_L2CA_UNREGISTER_SERVER _BRB_L2CA_UNREGISTER_SERVER
BRB_L2CA_OPEN_CHANNEL _BRB_L2CA_OPEN_CHANNEL
BRB_L2CA_OPEN_CHANNEL_RESPONSE _BRB_L2CA_OPEN_CHANNEL
BRB_L2CA_CLOSE_CHANNEL _BRB_L2CA_CLOSE_CHANNEL
BRB_L2CA_ACL_TRANSFER _BRB_L2CA_ACL_TRANSFER
BRB_L2CA_UPDATE_CHANNEL _BRB_L2CA_UPDATE_CHANNEL
BRB_L2CA_PING _BRB_L2CA_PING
BRB_REGISTER_PSM _BRB_PSM
BRB_UNREGISTER_PSM _BRB_PSM
BRB_SCO_REGISTER_SERVER _BRB_SCO_REGISTER_SERVER
BRB_SCO_UNREGISTER_SERVER _BRB_SCO_UNREGISTER_SERVER
BRB_SCO_OPEN_CHANNEL _BRB_SCO_OPEN_CHANNEL
BRB_SCO_OPEN_CHANNEL_RESPONSE _BRB_SCO_OPEN_CHANNEL
BRB_SCO_CLOSE_CHANNEL _BRB_SCO_CLOSE_CHANNEL
BRB_SCO_TRANSFER _BRB_SCO_TRANSFER
BRB_SCO_GET_CHANNEL_INFO _BRB_SCO_GET_CHANNEL_INFO
BRB_SCO_GET_SYSTEM_INFO _BRB_SCO_GET_SYSTEM_INFO
BRB_SCO_FLUSH_CHANNEL _BRB_SCO_FLUSH_CHANNEL
BRB_ACL_GET_MODE _BRB_ACL_GET_MODE
BRB_ACL_ENTER_ACTIVE_MODE _BRB_ACL_ENTER_ACTIVE_MODE
BRB_GET_DEVICE_INTERFACE_STRING _BRB_GET_DEVICE_INTERFACE_STRING

For more information about using Bluetooth IOCTLs and BRBs, see Building and Sending a BRB.