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; }
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; }