Ejemplo n.º 1
0
static ssize_t decode_value(TALLOC_CTX *ctx, fr_cursor_t *cursor,
			    fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len)
{
	unsigned int	values, i;		/* How many values we need to decode */
	uint8_t const	*p = data;
	size_t		value_len;
	ssize_t		len;

	FR_PROTO_TRACE("%s called to parse %zu byte(s)", __FUNCTION__, data_len);
	FR_PROTO_HEX_DUMP(data, data_len, NULL);

	/*
	 *	TLVs can't be coalesced as they're variable length
	 */
	if (parent->type == FR_TYPE_TLV) return decode_tlv(ctx, cursor, parent, data, data_len);

	/*
	 *	Values with a fixed length may be coalesced into a single option
	 */
	values = fr_dhcpv4_array_members(&value_len, data_len, parent);
	if (values) {
		FR_PROTO_TRACE("found %u coalesced values (%zu bytes each)", values, value_len);

		if ((values * value_len) != data_len) {
			fr_strerror_printf("Option length not divisible by its fixed value "
					  "length (probably trailing garbage)");
			return -1;
		}
	}

	/*
	 *	Decode each of the (maybe) coalesced values as its own
	 *	attribute.
	 */
	for (i = 0, p = data; i < values; i++) {
		len = decode_value_internal(ctx, cursor, parent, p, value_len);
		if (len <= 0) return len;
		if (len != (ssize_t)value_len) {
			fr_strerror_printf("Failed decoding complete option value");
			return -1;
		}
		p += len;
	}

	return p - data;
}
Ejemplo n.º 2
0
static int show_control(const char *space, snd_hctl_elem_t *elem,
                        int level)
{
    int err;
    unsigned int item, idx, count, *tlv;
    snd_ctl_elem_type_t type;
    snd_ctl_elem_id_t *id;
    snd_ctl_elem_info_t *info;
    snd_ctl_elem_value_t *control;
    snd_aes_iec958_t iec958;
    snd_ctl_elem_id_alloca(&id);
    snd_ctl_elem_info_alloca(&info);
    snd_ctl_elem_value_alloca(&control);
    if ((err = snd_hctl_elem_info(elem, info)) < 0)
    {
        error("Control %s snd_hctl_elem_info error: %s\n", card, snd_strerror(err));
        return err;
    }
    if (level & LEVEL_ID)
    {
        snd_hctl_elem_get_id(elem, id);
        show_control_id(id);
        printf("\n");
    }
    count = snd_ctl_elem_info_get_count(info);
    type = snd_ctl_elem_info_get_type(info);
    printf("%s; type=%s,access=%s,values=%i", space, control_type(info), control_access(info), count);
    switch (type)
    {
    case SND_CTL_ELEM_TYPE_INTEGER:
        printf(",min=%li,max=%li,step=%li\n",
               snd_ctl_elem_info_get_min(info),
               snd_ctl_elem_info_get_max(info),
               snd_ctl_elem_info_get_step(info));
        break;
    case SND_CTL_ELEM_TYPE_INTEGER64:
        printf(",min=%Li,max=%Li,step=%Li\n",
               snd_ctl_elem_info_get_min64(info),
               snd_ctl_elem_info_get_max64(info),
               snd_ctl_elem_info_get_step64(info));
        break;
    case SND_CTL_ELEM_TYPE_ENUMERATED:
    {
        unsigned int items = snd_ctl_elem_info_get_items(info);
        printf(",items=%u\n", items);
        for (item = 0; item < items; item++)
        {
            snd_ctl_elem_info_set_item(info, item);
            if ((err = snd_hctl_elem_info(elem, info)) < 0)
            {
                error("Control %s element info error: %s\n", card, snd_strerror(err));
                return err;
            }
            printf("%s; Item #%u '%s'\n", space, item, snd_ctl_elem_info_get_item_name(info));
        }
        break;
    }
    default:
        printf("\n");
        break;
    }
    if (level & LEVEL_BASIC)
    {
        if (!snd_ctl_elem_info_is_readable(info))
            goto __skip_read;
        if ((err = snd_hctl_elem_read(elem, control)) < 0)
        {
            error("Control %s element read error: %s\n", card, snd_strerror(err));
            return err;
        }
        printf("%s: values=", space);
        for (idx = 0; idx < count; idx++)
        {
            if (idx > 0)
                printf(",");
            switch (type)
            {
            case SND_CTL_ELEM_TYPE_BOOLEAN:
                printf("%s", snd_ctl_elem_value_get_boolean(control, idx) ? "on" : "off");
                break;
            case SND_CTL_ELEM_TYPE_INTEGER:
                printf("%li", snd_ctl_elem_value_get_integer(control, idx));
                break;
            case SND_CTL_ELEM_TYPE_INTEGER64:
                printf("%Li", snd_ctl_elem_value_get_integer64(control, idx));
                break;
            case SND_CTL_ELEM_TYPE_ENUMERATED:
                printf("%u", snd_ctl_elem_value_get_enumerated(control, idx));
                break;
            case SND_CTL_ELEM_TYPE_BYTES:
                printf("0x%02x", snd_ctl_elem_value_get_byte(control, idx));
                break;
            case SND_CTL_ELEM_TYPE_IEC958:
                snd_ctl_elem_value_get_iec958(control, &iec958);
                printf("[AES0=0x%02x AES1=0x%02x AES2=0x%02x AES3=0x%02x]",
                       iec958.status[0], iec958.status[1],
                       iec958.status[2], iec958.status[3]);
                break;
            default:
                printf("?");
                break;
            }
        }
        printf("\n");
__skip_read:
        if (!snd_ctl_elem_info_is_tlv_readable(info))
            goto __skip_tlv;
        tlv = malloc(4096);
        if ((err = snd_hctl_elem_tlv_read(elem, tlv, 4096)) < 0)
        {
            error("Control %s element TLV read error: %s\n", card, snd_strerror(err));
            free(tlv);
            return err;
        }
        decode_tlv(strlen(space), tlv, 4096);
        free(tlv);
    }
__skip_tlv:
    return 0;
}
Ejemplo n.º 3
0
static void decode_tlv(unsigned int spaces, unsigned int *tlv, unsigned int tlv_size)
{
    unsigned int type = tlv[0];
    unsigned int size;
    unsigned int idx = 0;

    if (tlv_size < 2 * sizeof(unsigned int))
    {
        printf("TLV size error!\n");
        return;
    }
    print_spaces(spaces);
    printf("| ");
    type = tlv[idx++];
    size = tlv[idx++];
    tlv_size -= 2 * sizeof(unsigned int);
    if (size > tlv_size)
    {
        printf("TLV size error (%i, %i, %i)!\n", type, size, tlv_size);
        return;
    }
    switch (type)
    {
    case SND_CTL_TLVT_CONTAINER:
        size += sizeof(unsigned int) - 1;
        size /= sizeof(unsigned int);
        while (idx < size)
        {
            if (tlv[idx + 1] > (size - idx) * sizeof(unsigned int))
            {
                printf("TLV size error in compound!\n");
                return;
            }
            decode_tlv(spaces + 2, tlv + idx, tlv[idx + 1]);
            idx += 2 + (tlv[1] + sizeof(unsigned int) - 1) / sizeof(unsigned int);
        }
        break;
    case SND_CTL_TLVT_DB_SCALE:
        printf("dBscale-");
        if (size != 2 * sizeof(unsigned int))
        {
            while (size > 0)
            {
                printf("0x%08x,", tlv[idx++]);
                size -= sizeof(unsigned int);
            }
        }
        else
        {
            printf("min=");
            print_dB((int)tlv[2]);
            printf(",step=");
            print_dB(tlv[3] & 0xffff);
            printf(",mute=%i", (tlv[3] >> 16) & 1);
        }
        break;
#ifdef SND_CTL_TLVT_DB_LINEAR
    case SND_CTL_TLVT_DB_LINEAR:
        printf("dBlinear-");
        if (size != 2 * sizeof(unsigned int))
        {
            while (size > 0)
            {
                printf("0x%08x,", tlv[idx++]);
                size -= sizeof(unsigned int);
            }
        }
        else
        {
            printf("min=");
            print_dB(tlv[2]);
            printf(",max=");
            print_dB(tlv[3]);
        }
        break;
#endif
#ifdef SND_CTL_TLVT_DB_RANGE
    case SND_CTL_TLVT_DB_RANGE:
        printf("dBrange-\n");
        if ((size % (6 * sizeof(unsigned int))) != 0)
        {
            while (size > 0)
            {
                printf("0x%08x,", tlv[idx++]);
                size -= sizeof(unsigned int);
            }
            break;
        }
        while (size > 0)
        {
            print_spaces(spaces + 2);
            printf("rangemin=%i,", tlv[idx++]);
            printf(",rangemax=%i\n", tlv[idx++]);
            decode_tlv(spaces + 4, tlv + idx, 4 * sizeof(unsigned int));
            idx += 4;
            size -= 6 * sizeof(unsigned int);
        }
        break;
#endif
#ifdef SND_CTL_TLVT_DB_MINMAX
    case SND_CTL_TLVT_DB_MINMAX:
    case SND_CTL_TLVT_DB_MINMAX_MUTE:
        if (type == SND_CTL_TLVT_DB_MINMAX_MUTE)
            printf("dBminmaxmute-");
        else
            printf("dBminmax-");
        if (size != 2 * sizeof(unsigned int))
        {
            while (size > 0)
            {
                printf("0x%08x,", tlv[idx++]);
                size -= sizeof(unsigned int);
            }
        }
        else
        {
            printf("min=");
            print_dB(tlv[2]);
            printf(",max=");
            print_dB(tlv[3]);
        }
        break;
#endif
    default:
        printf("unk-%i-", type);
        while (size > 0)
        {
            printf("0x%08x,", tlv[idx++]);
            size -= sizeof(unsigned int);
        }
        break;
    }
    putc('\n', stdout);
}