mraa_gpio_context mraa_gpio_init(int pin) { mraa_board_t* board = plat; if (board == NULL) { syslog(LOG_ERR, "gpio%i: init: platform not initialised", pin); return NULL; } if (mraa_is_sub_platform_id(pin)) { syslog(LOG_NOTICE, "gpio%i: init: Using sub platform", pin); board = board->sub_platform; if (board == NULL) { syslog(LOG_ERR, "gpio%i: init: Sub platform not initialised", pin); return NULL; } pin = mraa_get_sub_platform_index(pin); } if (board->chardev_capable) { int pins[1] = { pin }; return mraa_gpio_init_multi(pins, 1); } if (pin < 0 || pin >= board->phy_pin_count) { syslog(LOG_ERR, "gpio: init: pin %i beyond platform pin count (%i)", pin, board->phy_pin_count); return NULL; } if (board->pins[pin].capabilities.gpio != 1) { syslog(LOG_ERR, "gpio: init: pin %i not capable of gpio", pin); return NULL; } if (board->pins[pin].gpio.mux_total > 0) { if (mraa_setup_mux_mapped(board->pins[pin].gpio) != MRAA_SUCCESS) { syslog(LOG_ERR, "gpio%i: init: unable to setup muxes", pin); return NULL; } } mraa_gpio_context r = mraa_gpio_init_internal(board->adv_func, board->pins[pin].gpio.pinmap); if (r == NULL) { return NULL; } if (r->phy_pin == -1) r->phy_pin = pin; if (IS_FUNC_DEFINED(r, gpio_init_post)) { mraa_result_t ret = r->advance_func->gpio_init_post(r); if (ret != MRAA_SUCCESS) { free(r); return NULL; } } return r; }
mraa_pwm_context mraa_pwm_init(int pin) { mraa_board_t* board = plat; if (board == NULL) { syslog(LOG_ERR, "pwm_init: Platform Not Initialised"); return NULL; } if (mraa_is_sub_platform_id(pin)) { syslog(LOG_NOTICE, "pwm_init: Using sub platform"); board = board->sub_platform; if (board == NULL) { syslog(LOG_ERR, "pwm_init: Sub platform Not Initialised"); return NULL; } pin = mraa_get_sub_platform_index(pin); } if (pin < 0 || pin > board->phy_pin_count) { syslog(LOG_ERR, "pwm_init: pin %i beyond platform definition", pin); return NULL; } if (board->pins[pin].capabilities.pwm != 1) { syslog(LOG_ERR, "pwm_init: pin %i not capable of pwm", pin); return NULL; } if (board->adv_func->pwm_init_replace != NULL) { return board->adv_func->pwm_init_replace(pin); } if (board->adv_func->pwm_init_internal_replace != NULL) { return board->adv_func->pwm_init_internal_replace(board->adv_func, pin); } if (board->adv_func->pwm_init_pre != NULL) { if (board->adv_func->pwm_init_pre(pin) != MRAA_SUCCESS) return NULL; } if (board->pins[pin].pwm.mux_total > 0) { if (mraa_setup_mux_mapped(board->pins[pin].pwm) != MRAA_SUCCESS) { syslog(LOG_ERR, "pwm_init: Failed to set-up pwm%i multiplexer", pin); return NULL; } } int chip = board->pins[pin].pwm.parent_id; int pinn = board->pins[pin].pwm.pinmap; if (board->adv_func->pwm_init_post != NULL) { mraa_pwm_context pret = mraa_pwm_init_raw(chip, pinn); mraa_result_t ret = board->adv_func->pwm_init_post(pret); if (ret != MRAA_SUCCESS) { free(pret); return NULL; } return pret; } return mraa_pwm_init_raw(chip, pinn); }
mraa_i2c_context mraa_i2c_init(int bus) { mraa_board_t* board = plat; if (board == NULL) { syslog(LOG_ERR, "i2c: Platform Not Initialised"); return NULL; } if (mraa_is_sub_platform_id(bus)) { syslog(LOG_NOTICE, "i2c: Using sub platform"); board = board->sub_platform; if (board == NULL) { syslog(LOG_ERR, "i2c: Sub platform Not Initialised"); return NULL; } bus = mraa_get_sub_platform_index(bus); } syslog(LOG_NOTICE, "i2c: Selected bus %d", bus); if (board->i2c_bus_count == 0) { syslog(LOG_ERR, "No i2c buses defined in platform"); return NULL; } if (bus >= board->i2c_bus_count) { syslog(LOG_ERR, "Above i2c bus count"); return NULL; } if (board->i2c_bus[bus].bus_id == -1) { syslog(LOG_ERR, "Invalid i2c bus, moving to default i2c bus"); bus = board->def_i2c_bus; } if (!board->no_bus_mux) { int pos = board->i2c_bus[bus].sda; if (board->pins[pos].i2c.mux_total > 0) { if (mraa_setup_mux_mapped(board->pins[pos].i2c) != MRAA_SUCCESS) { syslog(LOG_ERR, "i2c: Failed to set-up i2c sda multiplexer"); return NULL; } } pos = board->i2c_bus[bus].scl; if (board->pins[pos].i2c.mux_total > 0) { if (mraa_setup_mux_mapped(board->pins[pos].i2c) != MRAA_SUCCESS) { syslog(LOG_ERR, "i2c: Failed to set-up i2c scl multiplexer"); return NULL; } } } return mraa_i2c_init_internal(board->adv_func, (unsigned int) board->i2c_bus[bus].bus_id); }
mraa_gpio_context mraa_gpio_init(int pin) { mraa_board_t* board = plat; if (board == NULL) { syslog(LOG_ERR, "gpio: platform not initialised"); return NULL; } if (mraa_is_sub_platform_id(pin)) { syslog(LOG_NOTICE, "gpio: Using sub platform"); board = board->sub_platform; if (board == NULL) { syslog(LOG_ERR, "gpio: Sub platform Not Initialised"); return NULL; } pin = mraa_get_sub_platform_index(pin); } if (pin < 0 || pin > board->phy_pin_count) { syslog(LOG_ERR, "gpio: pin %i beyond platform definition", pin); return NULL; } if (board->pins[pin].capabilites.gpio != 1) { syslog(LOG_ERR, "gpio: pin %i not capable of gpio", pin); return NULL; } if (board->pins[pin].gpio.mux_total > 0) { if (mraa_setup_mux_mapped(board->pins[pin].gpio) != MRAA_SUCCESS) { syslog(LOG_ERR, "gpio: unable to setup muxes"); return NULL; } } mraa_gpio_context r = mraa_gpio_init_internal(board->adv_func, board->pins[pin].gpio.pinmap); if (r == NULL) { syslog(LOG_CRIT, "gpio: mraa_gpio_init_raw(%d) returned error", pin); return NULL; } if (r->phy_pin == -1) r->phy_pin = pin; if (IS_FUNC_DEFINED(r, gpio_init_post)) { mraa_result_t ret = r->advance_func->gpio_init_post(r); if (ret != MRAA_SUCCESS) { free(r); return NULL; } } return r; }
char* mraa_get_pin_name(int pin) { if (plat == NULL) return 0; mraa_board_t* current_plat = plat; if (mraa_is_sub_platform_id(pin)) { current_plat = plat->sub_platform; if (current_plat == NULL) { syslog(LOG_ERR, "mraa_get_pin_name: Sub platform Not Initialised"); return 0; } pin = mraa_get_sub_platform_index(pin); } if (pin > (current_plat->phy_pin_count - 1) || pin < 0) return NULL; return (char*) current_plat->pins[pin].name; }
mraa_boolean_t mraa_pin_mode_test(int pin, mraa_pinmodes_t mode) { if (plat == NULL) return 0; mraa_board_t* current_plat = plat; if (mraa_is_sub_platform_id(pin)) { current_plat = plat->sub_platform; if (current_plat == NULL) { syslog(LOG_ERR, "mraa_pin_mode_test: Sub platform Not Initialised"); return 0; } pin = mraa_get_sub_platform_index(pin); } if (current_plat == NULL || current_plat->platform_type == MRAA_UNKNOWN_PLATFORM || current_plat->platform_type == MRAA_NULL_PLATFORM) { return 0; } if (pin > (current_plat->phy_pin_count - 1) || pin < 0) return 0; switch (mode) { case MRAA_PIN_VALID: if (current_plat->pins[pin].capabilites.valid == 1) return 1; break; case MRAA_PIN_GPIO: if (current_plat->pins[pin].capabilites.gpio == 1) return 1; break; case MRAA_PIN_PWM: if (current_plat->pins[pin].capabilites.pwm == 1) return 1; break; case MRAA_PIN_FAST_GPIO: if (current_plat->pins[pin].capabilites.fast_gpio == 1) return 1; break; case MRAA_PIN_SPI: if (current_plat->pins[pin].capabilites.spi == 1) return 1; break; case MRAA_PIN_I2C: if (current_plat->pins[pin].capabilites.i2c == 1) return 1; break; case MRAA_PIN_AIO: if (current_plat->pins[pin].capabilites.aio == 1) return 1; break; case MRAA_PIN_UART: if (current_plat->pins[pin].capabilites.uart == 1) return 1; break; default: syslog(LOG_NOTICE, "requested pinmode invalid"); break; } return 0; }
mraa_pwm_context mraa_pwm_init(int pin) { mraa_board_t* board = plat; if (board == NULL) { syslog(LOG_ERR, "pwm_init: Platform Not Initialised"); return NULL; } if (mraa_is_sub_platform_id(pin)) { syslog(LOG_NOTICE, "pwm_init: Using sub platform"); board = board->sub_platform; if (board == NULL) { syslog(LOG_ERR, "pwm_init: Sub platform Not Initialised"); return NULL; } pin = mraa_get_sub_platform_index(pin); } if (pin < 0 || pin > board->phy_pin_count) { syslog(LOG_ERR, "pwm_init: pin %i beyond platform definition", pin); return NULL; } if (board->pins[pin].capabilites.pwm != 1) { syslog(LOG_ERR, "pwm_init: pin %i not capable of pwm", pin); return NULL; } if (board->adv_func->pwm_init_replace != NULL) { return board->adv_func->pwm_init_replace(pin); } if (board->adv_func->pwm_init_internal_replace != NULL) { return board->adv_func->pwm_init_internal_replace(board->adv_func, pin); } if (board->adv_func->pwm_init_pre != NULL) { if (board->adv_func->pwm_init_pre(pin) != MRAA_SUCCESS) return NULL; } if (board->pins[pin].capabilites.gpio == 1) { // This deserves more investigation mraa_gpio_context mux_i; mux_i = mraa_gpio_init_raw(board->pins[pin].gpio.pinmap); if (mux_i == NULL) { syslog(LOG_ERR, "pwm_init: error in gpio->pwm%i transition. gpio_init", pin); return NULL; } if (mraa_gpio_dir(mux_i, MRAA_GPIO_OUT) != MRAA_SUCCESS) { syslog(LOG_ERR, "pwm_init: error in gpio->pwm%i transition. gpio_dir", pin); return NULL; } if (mraa_gpio_write(mux_i, 1) != MRAA_SUCCESS) { syslog(LOG_ERR, "pwm_init: error in gpio->pwm%i transition. gpio_write", pin); return NULL; } if (mraa_gpio_close(mux_i) != MRAA_SUCCESS) { syslog(LOG_ERR, "pwm_init: error in gpio->pwm%i transition. gpio_close", pin); return NULL; } } if (board->pins[pin].pwm.mux_total > 0) { if (mraa_setup_mux_mapped(board->pins[pin].pwm) != MRAA_SUCCESS) { syslog(LOG_ERR, "pwm_init: Failed to set-up pwm%i multiplexer", pin); return NULL; } } int chip = board->pins[pin].pwm.parent_id; int pinn = board->pins[pin].pwm.pinmap; if (board->adv_func->pwm_init_post != NULL) { mraa_pwm_context pret = mraa_pwm_init_raw(chip, pinn); mraa_result_t ret = board->adv_func->pwm_init_post(pret); if (ret != MRAA_SUCCESS) { free(pret); return NULL; } return pret; } return mraa_pwm_init_raw(chip, pinn); }
mraa_aio_context mraa_aio_init(unsigned int aio) { mraa_board_t* board = plat; int pin; if (board == NULL) { syslog(LOG_ERR, "aio: Platform not initialised"); return NULL; } if (mraa_is_sub_platform_id(aio)) { syslog(LOG_NOTICE, "aio: Using sub platform"); board = board->sub_platform; if (board == NULL) { syslog(LOG_ERR, "aio: Sub platform Not Initialised"); return NULL; } aio = mraa_get_sub_platform_index(aio); } // aio are always past the gpio_count in the pin array pin = aio + board->gpio_count; if (pin < 0 || pin >= board->phy_pin_count) { syslog(LOG_ERR, "aio: pin %i beyond platform definition", pin); return NULL; } if (aio >= board->aio_count) { syslog(LOG_ERR, "aio: requested channel out of range"); return NULL; } if (board->pins[pin].capabilites.aio != 1) { syslog(LOG_ERR, "aio: pin %i not capable of aio", pin); return NULL; } if (board->pins[pin].aio.mux_total > 0) { if (mraa_setup_mux_mapped(board->pins[pin].aio) != MRAA_SUCCESS) { syslog(LOG_ERR, "aio: unable to setup multiplexers for pin"); return NULL; } } // Create ADC device connected to specified channel mraa_aio_context dev = mraa_aio_init_internal(board->adv_func, aio); if (dev == NULL) { syslog(LOG_ERR, "aio: Insufficient memory for specified input channel %d", aio); return NULL; } dev->channel = board->pins[pin].aio.pinmap; dev->value_bit = DEFAULT_BITS; if (IS_FUNC_DEFINED(dev, aio_init_pre)) { mraa_result_t pre_ret = (dev->advance_func->aio_init_pre(aio)); if (pre_ret != MRAA_SUCCESS) { free(dev); return NULL; } } if (IS_FUNC_DEFINED(dev, aio_init_post)) { mraa_result_t ret = dev->advance_func->aio_init_post(dev); if (ret != MRAA_SUCCESS) { free(dev); return NULL; } } raw_bits = mraa_adc_raw_bits(); return dev; }
mraa_aio_context mraa_aio_init(unsigned int aio) { mraa_board_t* board = plat; int pin; if (board == NULL) { syslog(LOG_ERR, "aio: Platform not initialised"); return NULL; } if (mraa_is_sub_platform_id(aio)) { syslog(LOG_NOTICE, "aio: Using sub platform"); board = board->sub_platform; if (board == NULL) { syslog(LOG_ERR, "aio: Sub platform Not Initialised"); return NULL; } aio = mraa_get_sub_platform_index(aio); } // Some boards, like the BBB, don't have sequential AIO pins // They will have their own specific mapping to map aio -> pin if((board->aio_non_seq) && (aio < board->aio_count)){ pin = board->aio_dev[aio].pin; } else { // aio are always past the gpio_count in the pin array pin = aio + board->gpio_count; } if (pin < 0 || pin >= board->phy_pin_count) { syslog(LOG_ERR, "aio: pin %i beyond platform definition", pin); return NULL; } if (aio >= board->aio_count) { syslog(LOG_ERR, "aio: requested channel out of range"); return NULL; } if (board->pins[pin].capabilities.aio != 1) { syslog(LOG_ERR, "aio: pin %i not capable of aio", pin); return NULL; } if (board->pins[pin].aio.mux_total > 0) { if (mraa_setup_mux_mapped(board->pins[pin].aio) != MRAA_SUCCESS) { syslog(LOG_ERR, "aio: unable to setup multiplexers for pin"); return NULL; } } // Create ADC device connected to specified channel mraa_aio_context dev = mraa_aio_init_internal(board->adv_func, aio, board->pins[pin].aio.pinmap); if (dev == NULL) { syslog(LOG_ERR, "aio: Insufficient memory for specified input channel %d", aio); return NULL; } dev->value_bit = DEFAULT_BITS; if (IS_FUNC_DEFINED(dev, aio_init_pre)) { mraa_result_t pre_ret = (dev->advance_func->aio_init_pre(aio)); if (pre_ret != MRAA_SUCCESS) { free(dev); return NULL; } } if (IS_FUNC_DEFINED(dev, aio_init_post)) { mraa_result_t ret = dev->advance_func->aio_init_post(dev); if (ret != MRAA_SUCCESS) { free(dev); return NULL; } } raw_bits = mraa_adc_raw_bits(); if (raw_bits < dev->value_bit) { shifter_value = dev->value_bit - raw_bits; max_analog_value = ((1 << raw_bits) - 1) << shifter_value; } else { shifter_value = raw_bits - dev->value_bit; max_analog_value = ((1 << raw_bits) - 1) >> shifter_value; } return dev; }
mraa_gpio_context mraa_gpio_chardev_init(int pins[], int num_pins) { int chip_id, line_offset; mraa_gpio_context dev; mraa_gpiod_group_t gpio_group; mraa_board_t* board = plat; dev = (mraa_gpio_context) calloc(1, sizeof(struct _gpio)); if (dev == NULL) { syslog(LOG_CRIT, "[GPIOD_INTERFACE]: Failed to allocate memory for context"); return NULL; } dev->pin_to_gpio_table = malloc(num_pins * sizeof(int)); if (dev->pin_to_gpio_table == NULL) { syslog(LOG_CRIT, "[GPIOD_INTERFACE]: Failed to allocate memory for internal member"); mraa_gpio_close(dev); return NULL; } dev->num_chips = mraa_get_number_of_gpio_chips(); if (dev->num_chips <= 0) { mraa_gpio_close(dev); return NULL; } dev->num_pins = num_pins; gpio_group = calloc(dev->num_chips, sizeof(struct _gpio_group)); if (gpio_group == NULL) { syslog(LOG_CRIT, "[GPIOD_INTERFACE]: Failed to allocate memory for internal member"); mraa_gpio_close(dev); return NULL; } for (int i = 0; i < dev->num_chips; ++i) { gpio_group[i].gpio_chip = i; /* Just to be sure realloc has the desired behaviour. */ gpio_group[i].gpio_lines = NULL; } for (int i = 0; i < num_pins; ++i) { if (mraa_is_sub_platform_id(pins[i])) { syslog(LOG_NOTICE, "[GPIOD_INTERFACE]: init: Using sub platform for %d", pins[i]); board = board->sub_platform; if (board == NULL) { syslog(LOG_ERR, "[GPIOD_INTERFACE]: init: Sub platform not initialised for pin %d", pins[i]); mraa_gpio_close(dev); return NULL; } pins[i] = mraa_get_sub_platform_index(pins[i]); } if (pins[i] < 0 || pins[i] >= board->phy_pin_count) { syslog(LOG_ERR, "[GPIOD_INTERFACE]: init: pin %d beyond platform pin count (%d)", pins[i], board->phy_pin_count); mraa_gpio_close(dev); return NULL; } if (board->pins[pins[i]].capabilities.gpio != 1) { syslog(LOG_ERR, "[GPIOD_INTERFACE]: init: pin %d not capable of gpio", pins[i]); mraa_gpio_close(dev); return NULL; } if (board->pins[pins[i]].gpio.mux_total > 0) { if (mraa_setup_mux_mapped(board->pins[pins[i]].gpio) != MRAA_SUCCESS) { syslog(LOG_ERR, "[GPIOD_INTERFACE]: init: unable to setup muxes for pin %d", pins[i]); mraa_gpio_close(dev); return NULL; } } chip_id = board->pins[pins[i]].gpio.gpio_chip; line_offset = board->pins[pins[i]].gpio.gpio_line; /* Map pin to _gpio_group structure. */ dev->pin_to_gpio_table[i] = chip_id; if (!gpio_group[chip_id].is_required) { mraa_gpiod_chip_info* cinfo = mraa_get_chip_info_by_number(chip_id); if (!cinfo) { syslog(LOG_ERR, "[GPIOD_INTERFACE]: error getting gpio_chip_info for chip %d", chip_id); mraa_gpio_close(dev); return NULL; } gpio_group[chip_id].dev_fd = cinfo->chip_fd; gpio_group[chip_id].is_required = 1; gpio_group[chip_id].gpiod_handle = -1; free(cinfo); } int line_in_group; line_in_group = gpio_group[chip_id].num_gpio_lines; gpio_group[chip_id].gpio_lines = realloc(gpio_group[chip_id].gpio_lines, (line_in_group + 1) * sizeof(unsigned int)); if (gpio_group[chip_id].gpio_lines == NULL) { syslog(LOG_CRIT, "[GPIOD_INTERFACE]: Failed to allocate memory for internal member"); mraa_gpio_close(dev); return NULL; } gpio_group[chip_id].gpio_lines[line_in_group] = line_offset; gpio_group[chip_id].num_gpio_lines++; } /* Initialize rw_values for read / write multiple functions. * Also, allocate memory for inverse map: */ for (int i = 0; i < dev->num_chips; ++i) { gpio_group[i].rw_values = calloc(gpio_group[i].num_gpio_lines, sizeof(unsigned char)); if (gpio_group[i].rw_values == NULL) { syslog(LOG_CRIT, "[GPIOD_INTERFACE]: Failed to allocate memory for internal member"); mraa_gpio_close(dev); return NULL; } gpio_group[i].gpio_group_to_pins_table = calloc(gpio_group[i].num_gpio_lines, sizeof(int)); if (gpio_group[i].gpio_group_to_pins_table == NULL) { syslog(LOG_CRIT, "[GPIOD_INTERFACE]: Failed to allocate memory for internal member"); mraa_gpio_close(dev); return NULL; } /* Set event handle arrays for all lines contained on a chip to NULL. */ gpio_group[i].event_handles = NULL; } /* Finally map the inverse relation between a gpio group and its original pin numbers * provided by user. */ int* counters = calloc(dev->num_chips, sizeof(int)); if (counters == NULL) { syslog(LOG_CRIT, "[GPIOD_INTERFACE]: Failed to allocate memory for local variable"); mraa_gpio_close(dev); return NULL; } for (int i = 0; i < num_pins; ++i) { int chip = dev->pin_to_gpio_table[i]; gpio_group[chip].gpio_group_to_pins_table[counters[chip]] = i; counters[chip]++; } free(counters); dev->gpio_group = gpio_group; /* Save the provided array from the user to our internal structure. */ dev->provided_pins = malloc(dev->num_pins * sizeof(int)); if (dev->provided_pins == NULL) { syslog(LOG_CRIT, "[GPIOD_INTERFACE]: Failed to allocate memory for internal member"); mraa_gpio_close(dev); return NULL; } memcpy(dev->provided_pins, pins, dev->num_pins * sizeof(int)); /* Initialize events array. */ dev->events = NULL; return dev; }