SOL_API struct sol_i2c *
sol_i2c_open_raw(uint8_t bus, enum sol_i2c_speed speed)
{
    struct sol_i2c *i2c;
    qm_i2c_config_t cfg;
    qm_i2c_speed_t bus_speed;
    qm_rc_t ret;

    if (bus >= QM_I2C_NUM) {
        SOL_WRN("I2C bus #%" PRIu8 " doesn't exist.", bus);
        return NULL;
    }

    if ((i2c = buses[bus]) != NULL)
        return i2c;

    switch (speed) {
    case SOL_I2C_SPEED_10KBIT:
    case SOL_I2C_SPEED_100KBIT:
        bus_speed = QM_I2C_SPEED_STD;
        break;
    case SOL_I2C_SPEED_400KBIT:
        bus_speed = QM_I2C_SPEED_FAST;
        break;
    case SOL_I2C_SPEED_1MBIT:
    case SOL_I2C_SPEED_3MBIT_400KBIT:
        bus_speed = QM_I2C_SPEED_FAST_PLUS;
        break;
    default:
        SOL_WRN("Unsupported speed value: %d", speed);
        return NULL;
    };

    switch (bus) {
    case QM_I2C_0:
        qm_irq_request(QM_IRQ_I2C_0, qm_i2c_0_isr);
        clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_I2C_M0_REGISTER);
        break;
#if QUARK_SE
    case QM_I2C_1:
        qm_irq_request(QM_IRQ_I2C_1, qm_i2c_1_isr);
        clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_I2C_M1_REGISTER);
        break;
#endif
    case QM_I2C_NUM:
        /* We checked if we were passed the limit before, so we should never
         * hit this point. Using all the enum values and no default, however,
         * allows us to rely on the compiler to know if there are values
         * we are not considering (depending on warning levels) */
        break;
    }

    i2c = calloc(1, sizeof(*i2c));
    SOL_NULL_CHECK(i2c, NULL);

    i2c->bus = bus;

    ret = qm_i2c_get_config(i2c->bus, &cfg);
    SOL_EXP_CHECK_GOTO(ret != QM_RC_OK, error);

    cfg.speed = bus_speed;
    cfg.address_mode = QM_I2C_7_BIT;
    cfg.mode = QM_I2C_MASTER;
    cfg.slave_addr = 0;

    ret = qm_i2c_set_config(i2c->bus, &cfg);
    SOL_EXP_CHECK_GOTO(ret != QM_RC_OK, error);

    if (!i2c_irq_event) {
        bool r;

        i2c_irq_event = process_alloc_event();
        r = sol_mainloop_contiki_event_handler_add(&i2c_irq_event, NULL,
            i2c_cb_dispatch, NULL);
        SOL_EXP_CHECK_GOTO(!r, error);
    }

    buses[i2c->bus] = i2c;

    return i2c;

error:
    free(i2c);
    return NULL;
}
Example #2
0
SOL_API struct sol_lwm2m_bootstrap_server *
sol_lwm2m_bootstrap_server_new(uint16_t port, const char **known_clients,
    uint16_t num_sec_modes, ...)
{
    struct sol_lwm2m_bootstrap_server *server;
    struct sol_network_link_addr servaddr = { .family = SOL_NETWORK_FAMILY_INET6,
                                              .port = port };
    int r;
    struct sol_lwm2m_security_psk **known_psks = NULL, *cli_psk;
    struct sol_lwm2m_security_rpk *my_rpk = NULL;
    struct sol_blob **known_pub_keys = NULL, *cli_pub_key;
    enum sol_lwm2m_security_mode *sec_modes;
    enum sol_socket_dtls_cipher *cipher_suites;
    uint16_t i, j;
    va_list ap;

    SOL_LOG_INTERNAL_INIT_ONCE;

    SOL_NULL_CHECK(known_clients, NULL);
    SOL_INT_CHECK(num_sec_modes, == 0, NULL);

    va_start(ap, num_sec_modes);

    cipher_suites = calloc(num_sec_modes, sizeof(enum sol_socket_dtls_cipher));
    SOL_NULL_CHECK_GOTO(cipher_suites, err_va_list);

    sec_modes = calloc(num_sec_modes, sizeof(enum sol_lwm2m_security_mode));
    SOL_NULL_CHECK_GOTO(sec_modes, err_cipher_suites);

    for (i = 0; i < num_sec_modes; i++) {
        sec_modes[i] = va_arg(ap, enum sol_lwm2m_security_mode);
        SOL_EXP_CHECK_GOTO(sec_mode_is_repeated(sec_modes[i], sec_modes, i), err_sec_modes);

        switch (sec_modes[i]) {
        case SOL_LWM2M_SECURITY_MODE_PRE_SHARED_KEY:
            known_psks = va_arg(ap, struct sol_lwm2m_security_psk **);
            SOL_NULL_CHECK_GOTO(known_psks, err_sec_modes);

            cipher_suites[i] = SOL_SOCKET_DTLS_CIPHER_PSK_AES128_CCM8;
            break;
        case SOL_LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY:
            my_rpk = va_arg(ap, struct sol_lwm2m_security_rpk *);
            SOL_NULL_CHECK_GOTO(my_rpk, err_sec_modes);
            known_pub_keys = va_arg(ap, struct sol_blob **);
            SOL_NULL_CHECK_GOTO(known_pub_keys, err_sec_modes);

            cipher_suites[i] = SOL_SOCKET_DTLS_CIPHER_ECDHE_ECDSA_AES128_CCM8;
            break;
        case SOL_LWM2M_SECURITY_MODE_CERTIFICATE:
            SOL_WRN("Certificate security mode is not supported yet.");
            goto err_sec_modes;
        case SOL_LWM2M_SECURITY_MODE_NO_SEC:
            SOL_WRN("Bootstrap Server MUST use DTLS.");
            goto err_sec_modes;
        default:
            SOL_WRN("Unknown DTLS Security Mode: %d", sec_modes[i]);
            goto err_sec_modes;
        }
    }

    server = calloc(1, sizeof(struct sol_lwm2m_bootstrap_server));
    SOL_NULL_CHECK_GOTO(server, err_sec_modes);

    //LWM2M Bootstrap Server MUST always use DTLS
    for (i = 0; i < num_sec_modes; i++) {
        if (sec_modes[i] == SOL_LWM2M_SECURITY_MODE_PRE_SHARED_KEY) {
            sol_vector_init(&server->known_psks, sizeof(sol_lwm2m_security_psk));

            for (j = 0; known_psks[j]; j++) {
                cli_psk = sol_vector_append(&server->known_psks);
                SOL_NULL_CHECK_GOTO(cli_psk, err_copy_keys);
                cli_psk->id = sol_blob_ref(known_psks[j]->id);
                cli_psk->key = sol_blob_ref(known_psks[j]->key);
            }
        } else if (sec_modes[i] == SOL_LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY) {
            sol_ptr_vector_init(&server->known_pub_keys);

            for (j = 0; known_pub_keys[j]; j++) {
                r = sol_ptr_vector_append(&server->known_pub_keys,
                    sol_blob_ref(known_pub_keys[j]));
                SOL_INT_CHECK_GOTO(r, < 0, err_copy_keys);
            }

            server->rpk_pair.private_key = sol_blob_ref(my_rpk->private_key);
            server->rpk_pair.public_key = sol_blob_ref(my_rpk->public_key);
        }
    }
SOL_API struct sol_spi *
sol_spi_open(unsigned int bus, const struct sol_spi_config *config)
{
    struct sol_spi *spi;
    qm_spi_t max_bus_available;
    int ret;

    SOL_LOG_INTERNAL_INIT_ONCE;

    /* QM_SPI_NUM is always considering that both master and the slave
     * exist, so we can't use it to check the valid buses to use */
#if QUARK_SE
    max_bus_available = QM_SPI_MST_1;
#else
    max_bus_available = QM_SPI_MST_0;
#endif

    SOL_EXP_CHECK(bus >= max_bus_available, NULL);
    SOL_NULL_CHECK(config, NULL);

#ifndef SOL_NO_API_VERSION
    if (unlikely(config->api_version != SOL_SPI_CONFIG_API_VERSION)) {
        SOL_WRN("Couldn't open SPI that has unsupported version '%u', "
            "expected version is '%u'",
            config->api_version, SOL_SPI_CONFIG_API_VERSION);
        return NULL;
    }
#endif

    if (config->chip_select > 3) {
        SOL_WRN("Invalid chip_select value '%u'. Value must be between 0 and 3.",
            config->chip_select);
        return NULL;
    }

    if ((config->bits_per_word < 4) || (config->bits_per_word > 32)) {
        SOL_WRN("Invalid bits_per_word value '%" PRIu8 "'. Value must be "
            "between 4 and 32.", config->bits_per_word);
        return NULL;
    }

    spi = calloc(1, sizeof(*spi));
    SOL_NULL_CHECK(spi, NULL);

    if (!spi_irq_event) {
        bool r;

        spi_irq_event = process_alloc_event();
        r = sol_mainloop_contiki_event_handler_add(&spi_irq_event, NULL,
            spi_cb_dispatch, NULL);
        SOL_EXP_CHECK_GOTO(!r, error);
    }

    spi->bus = bus;
    spi->slave = BIT(config->chip_select);
    spi->config.frame_size = config->bits_per_word - 1;
    spi->config.transfer_mode = QM_SPI_TMOD_TX_RX;
    spi->config.bus_mode = config->mode;
    spi->config.clk_divider = 32000000 / config->frequency;

    switch (spi->bus) {
    case QM_SPI_MST_0:
        clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_SPI_M0_REGISTER);
        qm_irq_request(QM_IRQ_SPI_MASTER_0, qm_spi_master_0_isr);
        break;
#if QUARK_SE
    case QM_SPI_MST_1:
        qm_irq_request(QM_IRQ_SPI_MASTER_1, qm_spi_master_1_isr);
        break;
#endif
    case QM_SPI_SLV_0:
    case QM_SPI_NUM:
        /* We checked if we were passed the limit before, so we should never
         * hit this point. Using all the enum values and no default, however,
         * allows us to rely on the compiler to know if there are values
         * we are not considering (depending on warning levels) */
        break;
    }

    ret = spi_set_gpio_ss(spi);
    SOL_INT_CHECK_GOTO(ret, < 0, error);

    return spi;

error:
    free(spi);
    return NULL;
}