FreeBSD/usr.sbin/bluetooth/bthidcontrol/sdp.c
/*
 * seq len				2
 *	seq len				2
 *		uuid value		3
 *		uint16 value		3
 *		seq len			2
 *			uuid value	3
 */
seq len                              2
seq len                         2
uuid value              3
uint16 value            3
seq len                 2
uuid value      3
seq len 2 seq len 2 uuid value 3 uint16 value 3 seq len 2 uuid value 3
static int32_t
hid_sdp_parse_protocol_descriptor_list(sdp_attr_p a)
{
	uint8_t	*ptr = a->value;
	uint8_t	*end = a->value + a->vlen;
	int32_t	 type, len, uuid, psm;
	if (end - ptr < 15)
		return (-1);
	if (a->attr == SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS) {
		SDP_GET8(type, ptr);
		switch (type) {
		case SDP_DATA_SEQ8:
			SDP_GET8(len, ptr);
			break;
		case SDP_DATA_SEQ16:
			SDP_GET16(len, ptr);
			break;
		case SDP_DATA_SEQ32:
			SDP_GET32(len, ptr);
			break;
		default:
			return (-1);
		}
		if (ptr + len > end)
			return (-1);
	}
	SDP_GET8(type, ptr);
	switch (type) {
	case SDP_DATA_SEQ8:
		SDP_GET8(len, ptr);
		break;
	case SDP_DATA_SEQ16:
		SDP_GET16(len, ptr);
		break;
	case SDP_DATA_SEQ32:
		SDP_GET32(len, ptr);
		break;
	default:
		return (-1);
	}
	if (ptr + len > end)
		return (-1);
	SDP_GET8(type, ptr);
	switch (type) {
	case SDP_DATA_SEQ8:
		SDP_GET8(len, ptr);
		break;
	case SDP_DATA_SEQ16:
		SDP_GET16(len, ptr);
		break;
	case SDP_DATA_SEQ32:
		SDP_GET32(len, ptr);
		break;
	default:
		return (-1);
	}
	if (ptr + len > end)
		return (-1);
	if (ptr + 3 > end)
		return (-1);
	SDP_GET8(type, ptr);
	switch (type) {
	case SDP_DATA_UUID16:
		SDP_GET16(uuid, ptr);
		if (uuid != SDP_UUID_PROTOCOL_L2CAP)
			return (-1);
		break;
	case SDP_DATA_UUID32:  
	case SDP_DATA_UUID128: 
	default:
		return (-1);
	}
	if (ptr + 3 > end)
		return (-1);
	SDP_GET8(type, ptr);
	if (type != SDP_DATA_UINT16)
		return (-1);
	SDP_GET16(psm, ptr);
	return (psm);
}
static int32_t hid_sdp_parse_protocol_descriptor_list ( sdp_attr_p a ) { uint8_t * ptr = a -> value ; uint8_t * end = a -> value + a -> vlen ; int32_t type , len , uuid , psm ; if ( end - ptr < 15 ) return ( -1 ) ; if ( a -> attr == SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS ) { SDP_GET8 ( type , ptr ) ; switch ( type ) { case SDP_DATA_SEQ8 : SDP_GET8 ( len , ptr ) ; break ; case SDP_DATA_SEQ16 : SDP_GET16 ( len , ptr ) ; break ; case SDP_DATA_SEQ32 : SDP_GET32 ( len , ptr ) ; break ; default : return ( -1 ) ; } if ( ptr + len > end ) return ( -1 ) ; } SDP_GET8 ( type , ptr ) ; switch ( type ) { case SDP_DATA_SEQ8 : SDP_GET8 ( len , ptr ) ; break ; case SDP_DATA_SEQ16 : SDP_GET16 ( len , ptr ) ; break ; case SDP_DATA_SEQ32 : SDP_GET32 ( len , ptr ) ; break ; default : return ( -1 ) ; } if ( ptr + len > end ) return ( -1 ) ; SDP_GET8 ( type , ptr ) ; switch ( type ) { case SDP_DATA_SEQ8 : SDP_GET8 ( len , ptr ) ; break ; case SDP_DATA_SEQ16 : SDP_GET16 ( len , ptr ) ; break ; case SDP_DATA_SEQ32 : SDP_GET32 ( len , ptr ) ; break ; default : return ( -1 ) ; } if ( ptr + len > end ) return ( -1 ) ; if ( ptr + 3 > end ) return ( -1 ) ; SDP_GET8 ( type , ptr ) ; switch ( type ) { case SDP_DATA_UUID16 : SDP_GET16 ( uuid , ptr ) ; if ( uuid != SDP_UUID_PROTOCOL_L2CAP ) return ( -1 ) ; break ; case SDP_DATA_UUID32 : case SDP_DATA_UUID128 : default : return ( -1 ) ; } if ( ptr + 3 > end ) return ( -1 ) ; SDP_GET8 ( type , ptr ) ; if ( type != SDP_DATA_UINT16 ) return ( -1 ) ; SDP_GET16 ( psm , ptr ) ; return ( psm ) ; }
seq len                              2
      seq len                         2
              uuid value              3
              uint16 value            3
              seq len                 2
                      uuid value      3
seq len 2 seq len 2 uuid value 3 uint16 value 3 seq len 2 uuid value 3
/* Protocol */ /* UUID */ /* XXX FIXME can we have 32-bit UUID */ /* XXX FIXME can we have 128-bit UUID */ /* PSM */