diff --git a/device/adc.c b/device/adc.c index 8a354f9..67a06db 100644 --- a/device/adc.c +++ b/device/adc.c @@ -10,6 +10,45 @@ #ifdef MR_USING_ADC +static int adc_channel_set_state(struct mr_adc *adc, int channel, int state) +{ + struct mr_adc_ops *ops = (struct mr_adc_ops *)adc->dev.drv->ops; + + /* Check channel is valid */ + if (channel < 0 || channel >= 32) + { + return MR_EINVAL; + } + + /* Configure the channel */ + int ret = ops->channel_configure(adc, channel, state); + if (ret != MR_EOK) + { + return ret; + } + + /* Enable or disable the channel */ + if (state == MR_ADC_STATE_ENABLE) + { + mr_bits_set(adc->channel, (1 << channel)); + } else + { + mr_bits_clr(adc->channel, (1 << channel)); + } + return MR_EOK; +} + +static int adc_channel_get_state(struct mr_adc *adc, int channel) +{ + /* Check channel is valid */ + if (channel < 0 || channel >= 32) + { + return MR_EINVAL; + } + + return mr_bits_is_set(adc->channel, (1 << channel)); +} + static int mr_adc_open(struct mr_dev *dev) { struct mr_adc *adc = (struct mr_adc *)dev; @@ -66,52 +105,54 @@ static int mr_adc_ioctl(struct mr_dev *dev, int off, int cmd, void *args) switch (cmd) { + case MR_CTL_ADC_SET_CONFIG: + { + if (args != MR_NULL) + { + struct mr_adc_config config = *((struct mr_adc_config *)args); + + return adc_channel_set_state(adc, off, config.channel_state); + } + return MR_EINVAL; + } case MR_CTL_ADC_SET_CHANNEL_STATE: { if (args != MR_NULL) { int state = *((int *)args); - /* Check offset is valid */ - if (off < 0 || off >= 32) - { - return MR_EINVAL; - } - - /* Check if the channel is enabled */ - if (state != mr_bits_is_set(adc->channel, (1 << off))) - { - int ret = ops->channel_configure(adc, off, state); - if (ret == MR_EOK) - { - if (state == MR_ADC_STATE_ENABLE) - { - mr_bits_set(adc->channel, (1 << off)); - } else - { - mr_bits_clr(adc->channel, (1 << off)); - } - } - return ret; - } - return MR_EOK; + return adc_channel_set_state(adc, off, state); } return MR_EINVAL; } + case MR_CTL_ADC_GET_CONFIG: + { + if (args != MR_NULL) + { + struct mr_adc_config *config = (struct mr_adc_config *)args; + + int ret = adc_channel_get_state(adc, off); + if (ret < 0) + { + return ret; + } + config->channel_state = ret; + return MR_EOK; + } + } case MR_CTL_ADC_GET_CHANNEL_STATE: { if (args != MR_NULL) { int *state = (int *)args; - /* Check offset is valid */ - if (off < 0 || off >= 32) + int ret = adc_channel_get_state(adc, off); + if (ret < 0) { - return MR_EINVAL; + return ret; } - - *state = mr_bits_is_set(adc->channel, (1 << off)); + *state = ret; return MR_EOK; } return MR_EINVAL; diff --git a/device/dac.c b/device/dac.c index 0568a8d..c65081c 100644 --- a/device/dac.c +++ b/device/dac.c @@ -10,6 +10,45 @@ #ifdef MR_USING_DAC +static int dac_channel_set_state(struct mr_dac *dac, int channel, int state) +{ + struct mr_dac_ops *ops = (struct mr_dac_ops *)dac->dev.drv->ops; + + /* Check channel is valid */ + if (channel < 0 || channel >= 32) + { + return MR_EINVAL; + } + + /* Configure the channel */ + int ret = ops->channel_configure(dac, channel, state); + if (ret != MR_EOK) + { + return ret; + } + + /* Enable or disable the channel */ + if (state == MR_DAC_STATE_ENABLE) + { + mr_bits_set(dac->channel, (1 << channel)); + } else + { + mr_bits_clr(dac->channel, (1 << channel)); + } + return MR_EOK; +} + +static int dac_channel_get_state(struct mr_dac *dac, int channel) +{ + /* Check channel is valid */ + if (channel < 0 || channel >= 32) + { + return MR_EINVAL; + } + + return mr_bits_is_set(dac->channel, (1 << channel)); +} + static int mr_dac_open(struct mr_dev *dev) { struct mr_dac *dac = (struct mr_dac *)dev; @@ -66,47 +105,54 @@ static int mr_dac_ioctl(struct mr_dev *dev, int off, int cmd, void *args) switch (cmd) { + case MR_CTL_DAC_SET_CONFIG: + { + if (args != MR_NULL) + { + struct mr_dac_config config = *((struct mr_dac_config *)args); + + return dac_channel_set_state(dac, off, config.channel_state); + } + return MR_EINVAL; + } case MR_CTL_DAC_SET_CHANNEL_STATE: { if (args != MR_NULL) { int state = *((int *)args); - /* Check offset is valid */ - if (off < 0 || off >= 32) - { - return MR_EINVAL; - } - - int ret = ops->channel_configure(dac, off, state); - if (ret == MR_EOK) - { - if (state == MR_DAC_STATE_ENABLE) - { - mr_bits_set(dac->channel, (1 << off)); - } else - { - mr_bits_clr(dac->channel, (1 << off)); - } - } - return ret; + return dac_channel_set_state(dac, off, state); } return MR_EINVAL; } + case MR_CTL_DAC_GET_CONFIG: + { + if (args != MR_NULL) + { + struct mr_dac_config *config = (struct mr_dac_config *)args; + + int ret = dac_channel_get_state(dac, off); + if (ret < 0) + { + return ret; + } + config->channel_state = ret; + return MR_EOK; + } + } case MR_CTL_DAC_GET_CHANNEL_STATE: { if (args != MR_NULL) { int *state = (int *)args; - /* Check offset is valid */ - if (off < 0 || off >= 32) + int ret = dac_channel_get_state(dac, off); + if (ret < 0) { - return MR_EINVAL; + return ret; } - - *state = mr_bits_is_set(dac->channel, (1 << off)); + *state = ret; return MR_EOK; } return MR_EINVAL; diff --git a/device/pin.c b/device/pin.c index 4e5b473..d97fe54 100644 --- a/device/pin.c +++ b/device/pin.c @@ -18,6 +18,61 @@ struct pin_irq int (*call)(int desc, void *args); }; +static int pin_set_mode(struct mr_pin *pin, int number, int mode) +{ + struct mr_pin_ops *ops = (struct mr_pin_ops *)pin->dev.drv->ops; + + /* Check number is valid */ + if (number < 0) + { + return MR_EINVAL; + } + + /* Configure pin mode */ + int ret = ops->configure(pin, number, mode); + if (ret != MR_EOK) + { + return ret; + } + + /* If the irq exists, update it */ + struct mr_list *list = MR_NULL; + for (list = pin->irq_list.next; list != &pin->irq_list; list = list->next) + { + struct pin_irq *irq = (struct pin_irq *)mr_container_of(list, struct pin_irq, list); + if (irq->number == number) + { + if (mode < MR_PIN_MODE_IRQ_RISING) + { + /* Remove irq */ + mr_list_remove(list); + mr_free(irq); + } else + { + /* Update irq */ + irq->desc = pin->dev.rd_call.desc; + irq->call = pin->dev.rd_call.call; + } + return MR_EOK; + } + } + + /* If not exist, allocate new irq */ + if (mode >= MR_PIN_MODE_IRQ_RISING) + { + struct pin_irq *irq = (struct pin_irq *)mr_malloc(sizeof(struct pin_irq)); + if (irq != MR_NULL) + { + mr_list_init(&irq->list); + irq->number = number; + irq->desc = pin->dev.rd_call.desc; + irq->call = pin->dev.rd_call.call; + mr_list_insert_before(&pin->irq_list, &irq->list); + } + } + return MR_EOK; +} + static ssize_t mr_pin_read(struct mr_dev *dev, int off, void *buf, size_t size, int async) { struct mr_pin *pin = (struct mr_pin *)dev; @@ -67,61 +122,23 @@ static int mr_pin_ioctl(struct mr_dev *dev, int off, int cmd, void *args) switch (cmd) { + case MR_CTL_PIN_SET_CONFIG: + { + if (args != MR_NULL) + { + struct mr_pin_config config = *((struct mr_pin_config *)args); + + return pin_set_mode(pin, off, config.mode); + } + return MR_EINVAL; + } case MR_CTL_PIN_SET_MODE: { if (args != MR_NULL) { int mode = *((int *)args); - /* Check offset is valid */ - if (off < 0) - { - return MR_EINVAL; - } - - /* Configure pin mode */ - int ret = ops->configure(pin, off, mode); - if (ret != MR_EOK) - { - return ret; - } - - /* If the irq exists, update it */ - struct mr_list *list = MR_NULL; - for (list = pin->irq_list.next; list != &pin->irq_list; list = list->next) - { - struct pin_irq *irq = (struct pin_irq *)mr_container_of(list, struct pin_irq, list); - if (irq->number == off) - { - if (mode < MR_PIN_MODE_IRQ_RISING) - { - /* Remove irq */ - mr_list_remove(list); - mr_free(irq); - } else - { - /* Update irq */ - irq->desc = pin->dev.rd_call.desc; - irq->call = pin->dev.rd_call.call; - } - return MR_EOK; - } - } - - /* If not exist, allocate new irq */ - if (mode >= MR_PIN_MODE_IRQ_RISING) - { - struct pin_irq *irq = (struct pin_irq *)mr_malloc(sizeof(struct pin_irq)); - if (irq != MR_NULL) - { - mr_list_init(&irq->list); - irq->number = off; - irq->desc = dev->rd_call.desc; - irq->call = dev->rd_call.call; - mr_list_insert_before(&pin->irq_list, &irq->list); - } - } - return MR_EOK; + return pin_set_mode(pin, off, mode); } return MR_EINVAL; } diff --git a/include/device/adc.h b/include/device/adc.h index 39d7525..b081a8f 100644 --- a/include/device/adc.h +++ b/include/device/adc.h @@ -23,13 +23,24 @@ extern "C" { #define MR_ADC_STATE_DISABLE MR_DISABLE /**< ADC disabled */ #define MR_ADC_STATE_ENABLE MR_ENABLE /**< ADC enabled */ +/** + * @brief ADC configuration structure. + */ +struct mr_adc_config +{ + uint32_t channel_state: 1; /**< Channel state */ + uint32_t reserved: 31; /**< Reserved */ +}; + /** * @brief ADC control command. */ #define MR_CTL_ADC_SET_CHANNEL MR_CTL_SET_OFFSET /**< Set channel */ +#define MR_CTL_ADC_SET_CONFIG MR_CTL_SET_CONFIG /**< Set configuration */ #define MR_CTL_ADC_SET_CHANNEL_STATE (0x01 << 8) /**< Set channel state */ #define MR_CTL_ADC_GET_CHANNEL MR_CTL_GET_OFFSET /**< Get channel */ +#define MR_CTL_ADC_GET_CONFIG MR_CTL_GET_CONFIG /**< Get configuration */ #define MR_CTL_ADC_GET_CHANNEL_STATE (-(0x01 << 8)) /**< Get channel state */ /** diff --git a/include/device/dac.h b/include/device/dac.h index 6554d6a..03b88c4 100644 --- a/include/device/dac.h +++ b/include/device/dac.h @@ -23,13 +23,24 @@ extern "C" { #define MR_DAC_STATE_DISABLE MR_DISABLE /**< DAC disabled */ #define MR_DAC_STATE_ENABLE MR_ENABLE /**< DAC enabled */ +/** + * @brief DAC configuration structure. + */ +struct mr_dac_config +{ + uint32_t channel_state: 1; /**< Channel state */ + uint32_t reserved: 31; /**< Reserved */ +}; + /** * @brief DAC control command. */ #define MR_CTL_DAC_SET_CHANNEL MR_CTL_SET_OFFSET /**< Set channel */ +#define MR_CTL_DAC_SET_CONFIG MR_CTL_SET_CONFIG /**< Set configuration */ #define MR_CTL_DAC_SET_CHANNEL_STATE (0x01 << 8) /**< Set channel state */ #define MR_CTL_DAC_GET_CHANNEL MR_CTL_GET_OFFSET /**< Get channel */ +#define MR_CTL_DAC_GET_CONFIG MR_CTL_GET_CONFIG /**< Get configuration */ #define MR_CTL_DAC_GET_CHANNEL_STATE (-(0x01 << 8)) /**< Get channel state */ /** diff --git a/include/device/pin.h b/include/device/pin.h index 5352fa6..e65df97 100644 --- a/include/device/pin.h +++ b/include/device/pin.h @@ -42,10 +42,20 @@ extern "C" { #define MR_PIN_MODE_IRQ_LOW (9) /* Interrupt low level */ #define MR_PIN_MODE_IRQ_HIGH (10) /* Interrupt high level */ +/** + * @brief PIN configuration structure. + */ +struct mr_pin_config +{ + uint32_t mode: 1; /**< Mode */ + uint32_t reserved: 31; /**< Reserved */ +}; + /** * @brief PIN control command. */ #define MR_CTL_PIN_SET_NUMBER MR_CTL_SET_OFFSET /**< Set pin number */ +#define MR_CTL_PIN_SET_CONFIG MR_CTL_SET_CONFIG /**< Set pin configuration */ #define MR_CTL_PIN_SET_MODE (0x01 << 8) /**< Set pin mode */ #define MR_CTL_PIN_SET_EXTI_CALL MR_CTL_SET_RD_CALL /**< Set pin exti callback */