void
sol_interrupt_scheduler_process(msg_t *msg)
{
    unsigned int state;

    switch (msg->type) {
#ifdef USE_GPIO
    case GPIO: {
        struct gpio_interrupt_data *int_data = (void *)msg->content.ptr;

        state = irq_disable();
        int_data->base.pending = false;
        irq_restore(state);

        if (int_data->base.deleted)
            interrupt_scheduler_handler_free(int_data);
        else
            int_data->cb((void *)int_data->data);
        break;
    }
#endif
#ifdef USE_UART
    case UART_RX: {
        struct uart_interrupt_data *int_data = (void *)msg->content.ptr;
        uint16_t start, end, len;

        state = irq_disable();
        start = int_data->buf_next_read;
        end = int_data->buf_next_write;
        len = int_data->buf_len;
        int_data->base.pending = false;
        irq_restore(state);

        int_data->base.in_cb = true;
        while (!int_data->base.deleted) {
            if (start == end)
                break;
            int_data->rx_cb((void *)int_data->data, int_data->buf[start]);
            start = (start + 1) % len;
        }
        int_data->base.in_cb = false;
        if (int_data->base.deleted)
            interrupt_scheduler_handler_free(int_data);
        else
            int_data->buf_next_read = start;
        break;
    }
#endif
#ifdef NETWORK
    case GNRC_NETAPI_MSG_TYPE_RCV:
    case GNRC_NETAPI_MSG_TYPE_SND:
    case GNRC_NETAPI_MSG_TYPE_SET:
    case GNRC_NETAPI_MSG_TYPE_GET:
        sol_network_msg_dispatch(msg);
        break;
#endif
    }
}
void
sol_interrupt_scheduler_gpio_stop(gpio_t dev, void *handler)
{
    unsigned int state;

    state = irq_disable();
    gpio_irq_disable(dev);
    interrupt_scheduler_handler_free(handler);
    irq_restore(state);
}
void
sol_interrupt_scheduler_uart_stop(uart_t uart, void *handler)
{
    /*
     * Looking at RIOT's code, there are not guarantees that using
     * uart_init_blocking() will not keep the previously set interruptions
     * alive, and uart_poweroff() may not always be implemented, so the only
     * safe way to stop handling interruptions is to keep using our functions
     * with a NULL data pointer and check for that there, doing nothing if
     * that's the case. If uart_poweroff() works, it will be called by the
     * sol_uart implementation after this function.
     */
    uart_init(uart, 9600, uart_rx_cb, NULL);
    interrupt_scheduler_handler_free(handler);
}
void
sol_interrupt_scheduler_uart_stop(uart_t uart, void *handler)
{
    uart_init_blocking(uart, 9600);
    interrupt_scheduler_handler_free(handler);
}
void
sol_interrupt_scheduler_gpio_stop(gpio_t dev, void *handler)
{
    gpio_init_in(dev, GPIO_NOPULL);
    interrupt_scheduler_handler_free(handler);
}