FreeBSD/usr.sbin/bluetooth/bthidcontrol/sdp.c
/*
 * seq len			2
 *	seq len			2
 *		uint8 value8	2
 * 		str value	3
 */
seq len                      2
seq len                 2
uint8 value8    2
str value       3
seq len 2 seq len 2 uint8 value8 2 str value 3
static int32_t
hid_sdp_parse_hid_descriptor(sdp_attr_p a)
{
	uint8_t	*ptr = a->value;
	uint8_t	*end = a->value + a->vlen;
	int32_t	 type, len, descriptor_type;
	if (end - ptr < 9)
		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);
	while (ptr < end) {
		SDP_GET8(type, ptr);
		switch (type) {
		case SDP_DATA_SEQ8:
			if (ptr + 1 > end)
				return (-1);
			SDP_GET8(len, ptr);
			break;
		case SDP_DATA_SEQ16:
			if (ptr + 2 > end)
				return (-1);
			SDP_GET16(len, ptr);
			break;
		case SDP_DATA_SEQ32:
			if (ptr + 4 > end)
				return (-1);
			SDP_GET32(len, ptr);
			break;
		default:
			return (-1);
		}
		if (ptr + 1 > end)
			return (-1);
		SDP_GET8(type, ptr);
		if (type != SDP_DATA_UINT8 || ptr + 1 > end)
			return (-1);
		SDP_GET8(descriptor_type, ptr);
		if (ptr + 1 > end)
			return (-1);
		SDP_GET8(type, ptr);
		switch (type) {
		case SDP_DATA_STR8:
			if (ptr + 1 > end)
				return (-1);
			SDP_GET8(len, ptr);
			break;
		case SDP_DATA_STR16:
			if (ptr + 2 > end)
				return (-1);
			SDP_GET16(len, ptr);
			break;
		case SDP_DATA_STR32:
			if (ptr + 4 > end)
				return (-1);
			SDP_GET32(len, ptr);
			break;
		default:
			return (-1);
		}
		if (ptr + len > end)
			return (-1);
		if (descriptor_type == UDESC_REPORT && len > 0) {
			a->value = ptr;
			a->vlen = len;
			return (0);
		}
		ptr += len;
	}
	return (-1);
}
static int32_t hid_sdp_parse_hid_descriptor ( sdp_attr_p a ) { uint8_t * ptr = a -> value ; uint8_t * end = a -> value + a -> vlen ; int32_t type , len , descriptor_type ; if ( end - ptr < 9 ) 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 ) ; while ( ptr < end ) { SDP_GET8 ( type , ptr ) ; switch ( type ) { case SDP_DATA_SEQ8 : if ( ptr + 1 > end ) return ( -1 ) ; SDP_GET8 ( len , ptr ) ; break ; case SDP_DATA_SEQ16 : if ( ptr + 2 > end ) return ( -1 ) ; SDP_GET16 ( len , ptr ) ; break ; case SDP_DATA_SEQ32 : if ( ptr + 4 > end ) return ( -1 ) ; SDP_GET32 ( len , ptr ) ; break ; default : return ( -1 ) ; } if ( ptr + 1 > end ) return ( -1 ) ; SDP_GET8 ( type , ptr ) ; if ( type != SDP_DATA_UINT8 || ptr + 1 > end ) return ( -1 ) ; SDP_GET8 ( descriptor_type , ptr ) ; if ( ptr + 1 > end ) return ( -1 ) ; SDP_GET8 ( type , ptr ) ; switch ( type ) { case SDP_DATA_STR8 : if ( ptr + 1 > end ) return ( -1 ) ; SDP_GET8 ( len , ptr ) ; break ; case SDP_DATA_STR16 : if ( ptr + 2 > end ) return ( -1 ) ; SDP_GET16 ( len , ptr ) ; break ; case SDP_DATA_STR32 : if ( ptr + 4 > end ) return ( -1 ) ; SDP_GET32 ( len , ptr ) ; break ; default : return ( -1 ) ; } if ( ptr + len > end ) return ( -1 ) ; if ( descriptor_type == UDESC_REPORT && len > 0 ) { a -> value = ptr ; a -> vlen = len ; return ( 0 ) ; } ptr += len ; } return ( -1 ) ; }
seq len                      2
      seq len                 2
              uint8 value8    2
              str value       3
seq len 2 seq len 2 uint8 value8 2 str value 3
/* Descriptor */ /* Descripor type */ /* Descriptor value */