BlueTooth HID Profile Driver, SDP Submission faliure

I am Implementing a virtual BT Keyboard ( My Desktop is to be used as a BT Keyboard device ), For that, I have implemented a KMDF BT Profile Driver.

I am building the SDP in accordance with the HID SDP Spec and according to a BT Keyboard SDP Dump I have extracted using sdpverifier.exe

The generated SDP is successfully validated using SdpValidateStream.

The generated SDP is 90% Identical to the one sniffed through using sdpverifier.exe ( Comparing the binary stream )

However, SDP submission using IOCTL_BTH_SDP_SUBMIT_RECORD fails with STATUS_INVALID_PARAMETER

OPs suggest that registering a L2CAP channel with HID PSM ( 0x11 ) might not be possible, and indeed it is not, I want to try to register “HumanInterfaceDeviceServiceClassID_UUID16” with a PSM other than 0x11.

Having in mind that the PSM Id is referenced through the HID SDP, might “IOCTL_BTH_SDP_SUBMIT_RECORD” have a specialized HID verification implemented ( mandating the PSM referred through the SDP to be 0x11 ) ?

Having the above in mind, and, that SdpValidateStream SUCCEED, what may cause the SDP Submission failure ? Is there any way to get a more elaborate error code / log ?

Additional experimenting show that SDP with only a SDP_ATTRIB_CLASS_ID_LIST of HumanInterfaceDeviceServiceClassID_UUID16 is SUCCESSFULY Submitted, while when adding SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST Submission fail, following is a snap of the SDPs used ( reduced for experimenting )

SUCCESSFULY Submitted SDP:

SDP_BEGIN_RECORD()
SDP_ROOT_ATTRIBUTE_UINT(32, SDP_ATTRIB_RECORD_HANDLE, 0x10000)
SDP_START_LIST(SDP_ATTRIB_CLASS_ID_LIST)
SDP_DEFINE_NODE_UUID(16, HumanInterfaceDeviceServiceClassID_UUID16)
SDP_END_LIST()
SDP_END_RECORD()

FAILED SDP Submission:

SDP_BEGIN_RECORD()
SDP_ROOT_ATTRIBUTE_UINT(32, SDP_ATTRIB_RECORD_HANDLE, 0x10000)
SDP_START_LIST(SDP_ATTRIB_CLASS_ID_LIST)
SDP_DEFINE_NODE_UUID(16, HumanInterfaceDeviceServiceClassID_UUID16)
SDP_END_LIST()
// New Stuff added
SDP_START_LIST(SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST)
SDP_START_LIST(NULL)
SDP_DEFINE_NODE_UUID(16, L2CAP_PROTOCOL_UUID16)
SDP_DEFINE_NODE_UUID(16, m_Psm)// 0x11)
SDP_END_LIST()
SDP_START_LIST(NULL)
SDP_DEFINE_NODE_UUID(16, HID_PROTOCOL_UUID16)
//SDP_DEFINE_NODE_UUID(16, 0x13)
SDP_END_LIST()
SDP_END_LIST()
SDP_END_RECORD()

Nadav Rubinstein, See my Blog @ http://www.sophin.com

could you post your SDP.

I have added the following service record successfully using WSASetService api.

0x36, 0x01, 0x9B,
0x09, 0x00, 0x00, // TYPE:uint 16, ATTRIBUTE ID:ServiceRecordHandle
0x0A, 0x00, 0x01, 0x00, 0x00, // TYPE:uint 32, Parameter :service record handle
0x09, 0x00, 0x01, // TYPE:uint 16, ATTRIBUTE ID:ServiceClassIDList
0x35, 0x03, // TYPE:de.seq , 3 bytes
0x19, 0x11, 0x24, // TYPE:uuid 16, UUID :HumanInterfaceDeviceService
0x09, 0x00, 0x04, // TYPE:uint 16, ATTRIBUTE ID:ProtocolDescriptorList
0x35, 0x0D, // TYPE:de.seq , 13 bytes
0x35, 0x06, // TYPE:de.seq , 6 bytes
0x19, 0x01, 0x00, // TYPE:uuid 16, UUID :L2CAP
0x09, 0x00, 0x11, // TYPE:uint 16, Parameter :PSM
0x35, 0x03, // TYPE:de.seq , 3 bytes
0x19, 0x00, 0x11, // TYPE:uuid 16, UUID :HID
0x09, 0x00, 0x05, // TYPE:uint 16, ATTRIBUTE ID:BrowseGroupList
0x35, 0x03, // TYPE:de.seq , 3 bytes
0x19, 0x10, 0x02, // TYPE:uuid 16, UUID :PublicBrowseGroup
0x09, 0x00, 0x06, // TYPE:uint 16, ATTRIBUTE ID:LanguageBaseAttributeIDList
0x35, 0x09, // TYPE:de.seq , 9 bytes
0x09, 0x65, 0x6E, // TYPE:uint 16, Parameter :language ID"en"
0x09, 0x00, 0x6A, // TYPE:uint 16, Parameter :character encoding ID
0x09, 0x01, 0x00, // TYPE:uint 16, Parameter :base attribute ID
0x09, 0x00, 0x09, // TYPE:uint 16, ATTRIBUTE ID:BluetoothProfileDescriptorList
0x35, 0x08, // TYPE:de.seq , 8 bytes
0x35, 0x06, // TYPE:de.seq , 6 bytes
0x19, 0x11, 0x24, // TYPE:uuid 16, UUID :HumanInterfaceDeviceService
0x09, 0x01, 0x00, // TYPE:uint 16, Parameter :version number
0x09, 0x00, 0x0D, // TYPE:uint 16, ATTRIBUTE ID:AdditionalProtocolDescriptorLists
0x35, 0x0F, // TYPE:de.seq , 15 bytes
0x35, 0x0D, // TYPE:de.seq , 13 bytes
0x35, 0x06, // TYPE:de.seq , 6 bytes
0x19, 0x01, 0x00, // TYPE:uuid 16, UUID :L2CAP
0x09, 0x00, 0x13, // TYPE:uint 16, Parameter :
0x35, 0x03, // TYPE:de.seq , 3 bytes
0x19, 0x00, 0x11, // TYPE:uuid 16, UUID :HID
0x09, 0x01, 0x00, // TYPE:uint 16, ATTRIBUTE ID:ServiceName : Same as KB_MS till here
0x25, 0x23, // TYPE:text string, 35 bytes
0x4e, 0x61, 0x64, 0x61, 0x76, 0x27, 0x73, 0x20, 0x42, 0x6C, 0x75, 0x65,
0x74, 0x6F, 0x6F, 0x74, 0x68, 0x20, 0x57, 0x69, 0x72, 0x65, 0x6C, 0x65, 0x73, 0x73, 0x20, 0x4B,
0x65, 0x79, 0x62, 0x6F, 0x61, 0x72, 0x64,
0x09, 0x01, 0x01, // TYPE:uint 16, ATTRIBUTE ID:ServiceDescription
0x25, 0x08, // TYPE:text string, 8 bytes
0x4B, 0x65, 0x79, 0x62, 0x6F, 0x61, 0x72, 0x64,
// Keyboard
0x09, 0x01, 0x02, // TYPE:uint 16, ATTRIBUTE ID:ProviderName
0x25, 0x10, // TYPE:text string, 16 bytes
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
//
0x09, 0x02, 0x00, // TYPE:uint 16, ATTRIBUTE ID:VersionNumberList? or GroupID?
0x09, 0x01, 0x00, // TYPE:uint 16, Parameter :
0x09, 0x02, 0x01, // TYPE:uint 16, ATTRIBUTE ID:ServiceDatabaseState?
0x09, 0x01, 0x11, // TYPE:uint 16, Parameter :
0x09, 0x02, 0x02, // TYPE:uint 16, ATTRIBUTE ID:DeviceSubclass
0x08, 0x40, // TYPE:uint 8, Parameter :
0x09, 0x02, 0x03, // TYPE:uint 16, ATTRIBUTE ID:CountryCode
0x08, 0x00, // TYPE:uint 8, Parameter :
0x09, 0x02, 0x04, // TYPE:uint 16, ATTRIBUTE ID:VirtualCable
0x28, 0x01, // TYPE:bool 8, Parameter :
0x09, 0x02, 0x05, // TYPE:uint 16, ATTRIBUTE ID:ReconnectInitiate
0x28, 0x01, // TYPE:bool 8, Parameter :
0x09, 0x02, 0x06, // TYPE:uint 16, ATTRIBUTE ID:Descriptorlist
0x35, 0xAD, // TYPE:de.seq , 175 bytes
0x35, 0xAB, // TYPE:de.seq , 172 bytes
0x08, 0x22, // TYPE:uint 8, Parameter :
0x25, 0xA9, // TYPE:text string, 169 bytes
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xA1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xE0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xE7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x81, 0x01, // Input (Constant), ;Reserved byte
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x05, // REPORT_COUNT (5)
0x05, 0x08, // Usage Page (Page# for LEDs),
0x19, 0x01, // Usage Minimum (1),
0x29, 0x05, // Usage Maximum (5),
0x95, 0x03, // Report Count (3),
0x91, 0x01, // Report Size (1),
0x75, 0x08, // Report Size (8),
0x95, 0x06, // Report Count (6),
0x26, 0xFF, 0x00,
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0x00, // Usage Minimum (0),
0x2A, 0xFF, 0x00,
0x81, 0x00, // Input (Data, Array),
0xC0, // End Collection
0x05, 0x0C, // Usage Page (Consumer Page),
0x09, 0x01, // USAGE (Consumer Control Usage 0x01)
0xA1, 0x01, // COLLECTION (Application)
0x85, 0x10, // REPORT_ID (10)
0x19, 0x00, // Usage Minimum (0),
0x2A, 0xFF, 0x03,
0x75, 0x0C, // Report Size (12),
0x95, 0x01, // Report Count (1),
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xFF, 0x03,
0x81, 0x00, // Input (Data, Array),
0x75, 0x04, // Report Size (4),
0x95, 0x01, // Report Count (1),
0x81, 0x01, // Input (Constant), ;Reserved byte
0xC0, // End Collection
0x06, 0xFF, 0x00,
0x09, 0x01,
0xA1, 0x01, // COLLECTION (Application)
0x85, 0x11, // REPORT_ID (11)
0x19, 0x00, // Usage Minimum (0),
0x29, 0xFF, // Usage Maximum (255),
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xFF, 0x00,
0x75, 0x08,
0x95, 0x01, // Report Count (1),
0x81, 0x00, // Input (Data, Array),
0xC0, // End Collection
0x05, 0x01,
0x09, 0x80,
0xA1, 0x01, // COLLECTION (Application)
0x85, 0x12, // REPORT_ID (12)
0x19, 0x81, // Usage Minimum (129),
0x29, 0x93, // Usage Maximum (147),
0x15, 0x81, // LOGICAL_MINIMUM (129)
0x25, 0x93, // LOGICAL_MAXIMUM (147)
0x75, 0x08, // Report Size (8),
0x95, 0x01, // Report Count (1),
0x81, 0x40, //
0xC0, // End Collection
0x05, 0x0C, // Usage Page (Consumer Page),
0x09, 0x01, // USAGE (Consumer Control Usage 0x01)
0xA1, 0x01, // COLLECTION (Application)
0x05, 0x06,
0x85, 0x13, // REPORT_ID (13)
0x09, 0x20, // Usage Minimum (20),
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x64, // LOGICAL_MAXIMUM (100)
0x75, 0x08, // Report Size (8),
0x95, 0x01, // Report Count (1),
0x81, 0x42,
0x09, 0x01,
0x75, 0x08, // Report Size (8),
0x95, 0x07, // Report Count (7),
0xB1, 0x02,
0xC0, // End Collection
0x09, 0x02, 0x07, // TYPE:uint 16, ATTRIBUTE ID:LangIDBaseList
0x35, 0x08, // TYPE:de.seq , 8 bytes
0x35, 0x06, // TYPE:de.seq , 6 bytes
0x09, 0x04, 0x09, // TYPE:uint 16, Parameter :
0x09, 0x01, 0x00, // TYPE:uint 16, Parameter :
0x09, 0x02, 0x0B, // TYPE:uint 16, ATTRIBUTE ID:ProfileVersion
0x09, 0x01, 0x00, // TYPE:uint 16, Parameter :
0x09, 0x02, 0x0C, // TYPE:uint 16, ATTRIBUTE ID:SuperVisionTimeout
0x09, 0x25, 0x80, // TYPE:uint 16, Parameter :
0x09, 0x02, 0x0D, // TYPE:uint 16, ATTRIBUTE ID:NormallyConnectable
0x28, 0x00, // TYPE:bool 8, Parameter :
0x09, 0x02, 0x0E, // TYPE:uint 16, ATTRIBUTE ID:BootDevice
0x28, 0x01, // TYPE:bool 8, Parameter :