@@ -56,7 +56,21 @@ type AdvertisementOptions struct {
5656
5757 // ManufacturerData stores Advertising Data.
5858 // Keys are the Manufacturer ID to associate with the data.
59- ManufacturerData map [uint16 ]interface {}
59+ ManufacturerData []ManufacturerDataElement
60+ }
61+
62+ // Manufacturer data that's part of an advertisement packet.
63+ type ManufacturerDataElement struct {
64+ // The company ID, which must be one of the assigned company IDs.
65+ // The full list is in here:
66+ // https://www.bluetooth.com/specifications/assigned-numbers/
67+ // The list can also be viewed here:
68+ // https://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/company_identifiers/company_identifiers.yaml
69+ // The value 0xffff can also be used for testing.
70+ CompanyID uint16
71+
72+ // The value, which can be any value but can't be very large.
73+ Data []byte
6074}
6175
6276// Duration is the unit of time used in BLE, in 0.625µs units. This unit of time
@@ -112,7 +126,7 @@ type AdvertisementPayload interface {
112126
113127 // ManufacturerData returns a map with all the manufacturer data present in the
114128 //advertising. IT may be empty.
115- ManufacturerData () map [ uint16 ][] byte
129+ ManufacturerData () [] ManufacturerDataElement
116130}
117131
118132// AdvertisementFields contains advertisement fields in structured form.
@@ -127,7 +141,7 @@ type AdvertisementFields struct {
127141 ServiceUUIDs []UUID
128142
129143 // ManufacturerData is the manufacturer data of the advertisement.
130- ManufacturerData map [ uint16 ][] byte
144+ ManufacturerData [] ManufacturerDataElement
131145}
132146
133147// advertisementFields wraps AdvertisementFields to implement the
@@ -161,7 +175,7 @@ func (p *advertisementFields) Bytes() []byte {
161175}
162176
163177// ManufacturerData returns the underlying ManufacturerData field.
164- func (p * advertisementFields ) ManufacturerData () map [ uint16 ][] byte {
178+ func (p * advertisementFields ) ManufacturerData () [] ManufacturerDataElement {
165179 return p .AdvertisementFields .ManufacturerData
166180}
167181
@@ -254,22 +268,24 @@ func (buf *rawAdvertisementPayload) HasServiceUUID(uuid UUID) bool {
254268}
255269
256270// ManufacturerData returns the manufacturer data in the advertisement payload.
257- func (buf * rawAdvertisementPayload ) ManufacturerData () map [uint16 ][]byte {
258- mData := make (map [uint16 ][]byte )
259- data := buf .Bytes ()
260- for len (data ) >= 2 {
261- fieldLength := data [0 ]
262- if int (fieldLength )+ 1 > len (data ) {
263- // Invalid field length.
264- return nil
271+ func (buf * rawAdvertisementPayload ) ManufacturerData () []ManufacturerDataElement {
272+ var manufacturerData []ManufacturerDataElement
273+ for index := 0 ; index < int (buf .len )+ 4 ; index += int (buf .data [index ]) + 1 {
274+ fieldLength := int (buf .data [index + 0 ])
275+ if fieldLength < 3 {
276+ continue
265277 }
266- // If this is the manufacturer data
267- if byte ( 0xFF ) == data [ 1 ] {
268- mData [ uint16 ( data [ 2 ]) + ( uint16 ( data [ 3 ]) << 8 )] = data [ 4 : fieldLength + 1 ]
278+ fieldType := buf . data [ index + 1 ]
279+ if fieldType != 0xff {
280+ continue
269281 }
270- data = data [fieldLength + 1 :]
282+ key := uint16 (buf .data [index + 2 ]) | uint16 (buf .data [index + 3 ])<< 8
283+ manufacturerData = append (manufacturerData , ManufacturerDataElement {
284+ CompanyID : key ,
285+ Data : buf .data [index + 4 : index + fieldLength + 1 ],
286+ })
271287 }
272- return mData
288+ return manufacturerData
273289}
274290
275291// reset restores this buffer to the original state.
@@ -300,36 +316,31 @@ func (buf *rawAdvertisementPayload) addFromOptions(options AdvertisementOptions)
300316 }
301317 }
302318
303- if len (options .ManufacturerData ) > 0 {
304- buf .addManufacturerData (options .ManufacturerData )
319+ for _ , element := range options .ManufacturerData {
320+ if ! buf .addManufacturerData (element .CompanyID , element .Data ) {
321+ return false
322+ }
305323 }
306324
307325 return true
308326}
309327
310328// addManufacturerData adds manufacturer data ([]byte) entries to the advertisement payload.
311- func (buf * rawAdvertisementPayload ) addManufacturerData (manufacturerData map [uint16 ]interface {}) (ok bool ) {
312- payloadData := buf .Bytes ()
313- for manufacturerID , rawData := range manufacturerData {
314- data := rawData .([]byte )
315- // Check if the manufacturer ID is within the range of 16 bits (0-65535).
316- if manufacturerID > 0xFFFF {
317- // Invalid manufacturer ID.
318- return false
319- }
320-
321- fieldLength := len (data ) + 3
329+ func (buf * rawAdvertisementPayload ) addManufacturerData (key uint16 , value []byte ) (ok bool ) {
330+ // Check whether the field can fit this manufacturer data.
331+ fieldLength := len (value ) + 4
332+ if int (buf .len )+ fieldLength > len (buf .data ) {
333+ return false
334+ }
322335
323- // Build manufacturer ID parts
324- manufacturerDataBit := byte (0xFF )
325- manufacturerIDPart1 := byte (manufacturerID & 0xFF )
326- manufacturerIDPart2 := byte ((manufacturerID >> 8 ) & 0xFF )
336+ // Add the data.
337+ buf .data [buf .len + 0 ] = uint8 (fieldLength - 1 )
338+ buf .data [buf .len + 1 ] = 0xff
339+ buf .data [buf .len + 2 ] = uint8 (key )
340+ buf .data [buf .len + 3 ] = uint8 (key >> 8 )
341+ copy (buf .data [buf .len + 4 :], value )
342+ buf .len += uint8 (fieldLength )
327343
328- payloadData = append (payloadData , byte (fieldLength ), manufacturerDataBit , manufacturerIDPart1 , manufacturerIDPart2 )
329- payloadData = append (payloadData , data ... )
330- }
331- buf .len = uint8 (len (payloadData ))
332- copy (buf .data [:], payloadData )
333344 return true
334345}
335346
0 commit comments