Exemple #1
0
/**
 * \brief Convert card string to an integer value.
 * \param string String containing card identifier
 * \return zero if success, otherwise a negative error code
 *
 * The accepted format is an integer value in ASCII representation
 * or the card identifier (the id parameter for sound-card drivers).
 */
int snd_card_get_index(const char *string)
{
	int card;
	snd_ctl_t *handle;
	snd_ctl_card_info_t info;

	if (!string || *string == '\0')
		return -EINVAL;
	if ((isdigit(*string) && *(string + 1) == 0) ||
	    (isdigit(*string) && isdigit(*(string + 1)) && *(string + 2) == 0)) {
		if (sscanf(string, "%i", &card) != 1)
			return -EINVAL;
		if (card < 0 || card > 31)
			return -EINVAL;
		if (snd_card_load(card))
			return card;
		return -ENODEV;
	}
	for (card = 0; card < 32; card++) {
		if (! snd_card_load(card))
			continue;
		if (snd_ctl_hw_open(&handle, NULL, card, 0) < 0)
			continue;
		if (snd_ctl_card_info(handle, &info) < 0) {
			snd_ctl_close(handle);
			continue;
		}
		snd_ctl_close(handle);
		if (!strcmp((const char *)info.id, string))
			return card;
	}
	return -ENODEV;
}
Exemple #2
0
/**
 * \brief Obtain the card long name.
 * \param card Card number
 * \param name Result - card long name corresponding to card number
 * \result zero if success, otherwise a negative error code
 */
int snd_card_get_longname(int card, char **name)
{
	snd_ctl_t *handle;
	snd_ctl_card_info_t info;
	int err;
	
	if (name == NULL)
		return -EINVAL;
	if ((err = snd_ctl_hw_open(&handle, NULL, card, 0)) < 0)
		return err;
	if ((err = snd_ctl_card_info(handle, &info)) < 0) {
		snd_ctl_close(handle);
		return err;
	}
	snd_ctl_close(handle);
	*name = strdup((const char *)info.longname);
	if (*name == NULL)
		return -ENOMEM;
	return 0;
}
Exemple #3
0
int snd_rawmidi_hw_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
			const char *name, int card, int device, int subdevice,
			int mode)
{
	int fd, ver, ret;
	int attempt = 0;
	char filename[sizeof(SNDRV_FILE_RAWMIDI) + 20];
	snd_ctl_t *ctl;
	snd_rawmidi_t *rmidi;
	snd_rawmidi_hw_t *hw = NULL;
	snd_rawmidi_info_t info;
	int fmode;

	if (inputp)
		*inputp = NULL;
	if (outputp)
		*outputp = NULL;
	
	if ((ret = snd_ctl_hw_open(&ctl, NULL, card, 0)) < 0)
		return ret;
	sprintf(filename, SNDRV_FILE_RAWMIDI, card, device);

      __again:
      	if (attempt++ > 3) {
      		snd_ctl_close(ctl);
      		return -EBUSY;
      	}
      	ret = snd_ctl_rawmidi_prefer_subdevice(ctl, subdevice);
	if (ret < 0) {
		snd_ctl_close(ctl);
		return ret;
	}

	if (!inputp)
		fmode = O_WRONLY;
	else if (!outputp)
		fmode = O_RDONLY;
	else
		fmode = O_RDWR;

	if (mode & SND_RAWMIDI_APPEND) {
		assert(outputp);
		fmode |= O_APPEND;
	}

	if (mode & SND_RAWMIDI_NONBLOCK) {
		fmode |= O_NONBLOCK;
	}
	
	if (mode & SND_RAWMIDI_SYNC) {
		fmode |= O_SYNC;
	}

	assert(!(mode & ~(SND_RAWMIDI_APPEND|SND_RAWMIDI_NONBLOCK|SND_RAWMIDI_SYNC)));

	fd = snd_open_device(filename, fmode);
	if (fd < 0) {
		snd_card_load(card);
		fd = snd_open_device(filename, fmode);
		if (fd < 0) {
			snd_ctl_close(ctl);
			SYSERR("open %s failed", filename);
			return -errno;
		}
	}
#if 0
	/*
	 * this is bogus, an application have to care about open filedescriptors
	 */
	if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
		SYSERR("fcntl FD_CLOEXEC failed");
		ret = -errno;
		close(fd);
		return ret;
	}
#endif
	if (ioctl(fd, SNDRV_RAWMIDI_IOCTL_PVERSION, &ver) < 0) {
		ret = -errno;
		SYSERR("SNDRV_RAWMIDI_IOCTL_PVERSION failed");
		close(fd);
		snd_ctl_close(ctl);
		return ret;
	}
	if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_RAWMIDI_VERSION_MAX)) {
		close(fd);
		snd_ctl_close(ctl);
		return -SND_ERROR_INCOMPATIBLE_VERSION;
	}
	if (subdevice >= 0) {
		memset(&info, 0, sizeof(info));
		info.stream = outputp ? SNDRV_RAWMIDI_STREAM_OUTPUT : SNDRV_RAWMIDI_STREAM_INPUT;
		if (ioctl(fd, SNDRV_RAWMIDI_IOCTL_INFO, &info) < 0) {
			SYSERR("SNDRV_RAWMIDI_IOCTL_INFO failed");
			ret = -errno;
			close(fd);
			snd_ctl_close(ctl);
			return ret;
		}
		if (info.subdevice != (unsigned int) subdevice) {
			close(fd);
			goto __again;
		}
	}
	snd_ctl_close(ctl);

	hw = calloc(1, sizeof(snd_rawmidi_hw_t));
	if (hw == NULL)
		goto _nomem;
	hw->card = card;
	hw->device = device;
	hw->subdevice = subdevice;
	hw->fd = fd;

	if (inputp) {
		rmidi = calloc(1, sizeof(snd_rawmidi_t));
		if (rmidi == NULL)
			goto _nomem;
		if (name)
			rmidi->name = strdup(name);
		rmidi->type = SND_RAWMIDI_TYPE_HW;
		rmidi->stream = SND_RAWMIDI_STREAM_INPUT;
		rmidi->mode = mode;
		rmidi->poll_fd = fd;
		rmidi->ops = &snd_rawmidi_hw_ops;
		rmidi->private_data = hw;
		hw->open++;
		*inputp = rmidi;
	}
	if (outputp) {
		rmidi = calloc(1, sizeof(snd_rawmidi_t));
		if (rmidi == NULL)
			goto _nomem;
		if (name)
			rmidi->name = strdup(name);
		rmidi->type = SND_RAWMIDI_TYPE_HW;
		rmidi->stream = SND_RAWMIDI_STREAM_OUTPUT;
		rmidi->mode = mode;
		rmidi->poll_fd = fd;
		rmidi->ops = &snd_rawmidi_hw_ops;
		rmidi->private_data = hw;
		hw->open++;
		*outputp = rmidi;
	}
	return 0;

 _nomem:
	close(fd);
	free(hw);
	if (inputp)
		free(*inputp);
	if (outputp)
		free(*outputp);
	return -ENOMEM;
}
bool LegacyAmixerControl::accessHW(bool receive, string &error)
{
    CAutoLog autoLog(getConfigurableElement(), "ALSA", isDebugEnabled());

#ifdef SIMULATION
    if (receive) {

        memset(getBlackboardLocation(), 0, getSize());
    }
    log_info("%s ALSA Element Instance: %s\t\t(Control Element: %s)",
             receive ? "Reading" : "Writing",
             getConfigurableElement()->getPath().c_str(),
             getControlName().c_str());

    return true;
#endif

    int ret;
    // Mixer handle
    snd_ctl_t *sndCtrl;
    uint32_t value;
    uint32_t index;
    uint32_t elementCount;
    snd_ctl_elem_id_t *id;
    snd_ctl_elem_info_t *info;
    snd_ctl_elem_value_t *control;

    logControlInfo(receive);

    // Check parameter type is ok (deferred error, no exceptions available :-()
    if (!isTypeSupported()) {

        error = "Parameter type not supported.";

        return false;
    }

    int cardNumber = getCardNumber();

    if (cardNumber < 0) {

        error = "Card " + getCardName() + " not found. Error: " + strerror(cardNumber);

        return false;
    }
#ifdef ANDROID
    if ((ret = snd_ctl_hw_open(&sndCtrl, NULL, cardNumber, 0)) < 0) {

        error = snd_strerror(ret);

        return false;
    }
#else
    // Create device name
    ostringstream deviceName;

    deviceName << "hw:" << cardNumber;

    // Open sound control
    if ((ret = snd_ctl_open(&sndCtrl, deviceName.str().c_str(), 0)) < 0) {

        error = snd_strerror(ret);

        return false;
    }
#endif

    // Allocate in stack
    snd_ctl_elem_id_alloca(&id);
    snd_ctl_elem_info_alloca(&info);
    snd_ctl_elem_value_alloca(&control);

    // Set interface
    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);

    string controlName = getControlName();

    // Set name or id
    if (isdigit(controlName[0])) {

        snd_ctl_elem_id_set_numid(id, asInteger(controlName));
    } else {

        snd_ctl_elem_id_set_name(id, controlName.c_str());
    }
    // Init info id
    snd_ctl_elem_info_set_id(info, id);

    // Get info
    if ((ret = snd_ctl_elem_info(sndCtrl, info)) < 0) {

        error = "ALSA: Unable to get element info " + controlName +
                ": " + snd_strerror(ret);

        // Close sound control
        snd_ctl_close(sndCtrl);

        return false;
    }
    // Get type
    snd_ctl_elem_type_t eType = snd_ctl_elem_info_get_type(info);

    // Get element count
    elementCount = snd_ctl_elem_info_get_count(info);

    uint32_t scalarSize = getScalarSize();

    // If size defined in the PFW different from alsa mixer control size, return an error
    if (elementCount * scalarSize != getSize()) {

        error = "ALSA: Control element count (" + asString(elementCount) +
                ") and configurable scalar element count (" +
                asString(getSize() / scalarSize) + ") mismatch";

        // Close sound control
        snd_ctl_close(sndCtrl);

        return false;
    }
    // Set value id
    snd_ctl_elem_value_set_id(control, id);

    if (receive) {

        // Read element
        if ((ret = snd_ctl_elem_read(sndCtrl, control)) < 0) {

            error = "ALSA: Unable to read element " + controlName +
                    ": " + snd_strerror(ret);

            // Close sound control
            snd_ctl_close(sndCtrl);

            return false;
        }
        // Go through all indexes
        for (index = 0; index < elementCount; index++) {

            switch (eType) {
            case SND_CTL_ELEM_TYPE_BOOLEAN:
                value = snd_ctl_elem_value_get_boolean(control, index);
                break;
            case SND_CTL_ELEM_TYPE_INTEGER:
                value = snd_ctl_elem_value_get_integer(control, index);
                break;
            case SND_CTL_ELEM_TYPE_INTEGER64:
                value = snd_ctl_elem_value_get_integer64(control, index);
                break;
            case SND_CTL_ELEM_TYPE_ENUMERATED:
                value = snd_ctl_elem_value_get_enumerated(control, index);
                break;
            case SND_CTL_ELEM_TYPE_BYTES:
                value = snd_ctl_elem_value_get_byte(control, index);
                break;
            default:
                error = "ALSA: Unknown control element type while reading alsa element " +
                        controlName;
                return false;
            }

            if (isDebugEnabled()) {

                log_info("Reading alsa element %s, index %u with value %u",
                         controlName.c_str(), index, value);
            }

            // Write data to blackboard (beware this code is OK on Little Endian machines only)
            toBlackboard(value);
        }

    } else {

        // Go through all indexes
        for (index = 0; index < elementCount; index++) {

            // Read data from blackboard (beware this code is OK on Little Endian machines only)
            value = fromBlackboard();

            if (isDebugEnabled()) {

                log_info("Writing alsa element %s, index %u with value %u",
                         controlName.c_str(), index, value);
            }

            switch (eType) {
            case SND_CTL_ELEM_TYPE_BOOLEAN:
                snd_ctl_elem_value_set_boolean(control, index, value);
                break;
            case SND_CTL_ELEM_TYPE_INTEGER:
                snd_ctl_elem_value_set_integer(control, index, value);
                break;
            case SND_CTL_ELEM_TYPE_INTEGER64:
                snd_ctl_elem_value_set_integer64(control, index, value);
                break;
            case SND_CTL_ELEM_TYPE_ENUMERATED:
                snd_ctl_elem_value_set_enumerated(control, index, value);
                break;
            case SND_CTL_ELEM_TYPE_BYTES:
                snd_ctl_elem_value_set_byte(control, index, value);
                break;
            default:
                error = "ALSA: Unknown control element type while writing alsa element " +
                        controlName;
                return false;
            }
        }

        // Write element
        if ((ret = snd_ctl_elem_write(sndCtrl, control)) < 0) {

            error = "ALSA: Unable to write element " + controlName +
                    ": " + snd_strerror(ret);


            // Close sound control
            snd_ctl_close(sndCtrl);

            return false;
        }
    }
    // Close sound control
    snd_ctl_close(sndCtrl);

    return true;
}