Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/trusty/trusty/user/base/lib/spi/srv/batch/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 6 kB image not shown  

Quelle  batch.c

  Sprache: C
 

/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include <interface/spi/spi.h>
#include <lib/spi/common/utils.h>
#include <lib/spi/srv/batch/dev.h>
#include <lib/spi/srv/common/common.h>
#include <lk/compiler.h>
#include <uapi/err.h>

#ifdef TRUSTY_USERSPACE
#define TLOG_TAG "spi-srv-batch"
#include <trusty_log.h>
#else
#include <stdio.h>
#define TLOGE(fmt, ...) \
    fprintf(stderr, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
#endif

static int handle_xfer_args(struct spi_dev_ctx* spi, struct mem_buf* shm) {
    int rc;
    struct spi_xfer_args* xfer_args;
    uint32_t xfer_args_len;
    uint32_t xfer_args_flags;
    void* payload;
    void* tx;
    void* rx;

    xfer_args = mb_advance_pos(shm, sizeof(*xfer_args));
    if (!xfer_args) {
        TLOGE("failed to read SPI xfer request arguments from shared memory\n");
        return ERR_NO_MEMORY;
    }
    xfer_args_len = READ_ONCE(xfer_args->len);
    xfer_args_flags = READ_ONCE(xfer_args->flags);

    payload = mb_advance_pos(shm, xfer_args_len);
    if (!payload) {
        TLOGE("failed to get payload from shared memory\n");
        return ERR_NO_MEMORY;
    }

    tx = (xfer_args_flags & SPI_XFER_FLAGS_TX) ? payload : NULL;
    rx = (xfer_args_flags & SPI_XFER_FLAGS_RX) ? payload : NULL;

    rc = spi_req_xfer(spi, tx, rx, xfer_args_len);
    if (rc != NO_ERROR) {
        TLOGE("spi xfer failed (%d)\n", rc);
    }

    /* don't modify @xfer_args as a response */
    return rc;
}

static int handle_clk_args(struct spi_dev_ctx* spi, struct mem_buf* shm) {
    int rc;
    struct spi_clk_args* clk_args;

    clk_args = mb_advance_pos(shm, sizeof(*clk_args));
    if (!clk_args) {
        TLOGE("failed to read SPI clk request arguments from shared memory\n");
        return ERR_NO_MEMORY;
    }

    rc = spi_req_set_clk(spi, &clk_args->clk_hz);
    if (rc != NO_ERROR) {
        TLOGE("failed (%d) to set SPI clock speed\n", rc);
    }

    /* @clk_args response is handled by driver implementation */
    return rc;
}

static int handle_delay_args(struct spi_dev_ctx* spi, struct mem_buf* shm) {
    int rc = 0;
    struct spi_delay_args* delay_args;

    delay_args = mb_advance_pos(shm, sizeof(*delay_args));
    if (!delay_args) {
        TLOGE("failed to read delay request arguments from shared memory\n");
        return ERR_NO_MEMORY;
    }

    rc = spi_req_delay(spi, delay_args->delay_ns);
    if (rc != NO_ERROR) {
        TLOGE("failed (%d) to request delay\n", rc);
    }

    delay_args->delay_ns = 0;
    return rc;
}

static int unpack_shm(struct spi_dev_ctx* spi,
                      struct mem_buf* shm,
                      size_t len,
                      struct spi_batch_state* state) {
    int rc;
    struct spi_shm_hdr* shm_hdr;
    uint32_t shm_hdr_cmd;

    /*
     * Resize @shm, so that we don't process more than batch length. And rewind
     * @shm position back to the beginning.
     */

    mb_resize(shm, len);

    while (mb_curr_pos(shm) < len) {
        shm_hdr = mb_advance_pos(shm, sizeof(*shm_hdr));
        if (!shm_hdr) {
            TLOGE("failed to read spi_shm_hdr in shared memory\n");
            return ERR_NO_MEMORY;
        }
        shm_hdr_cmd = READ_ONCE(shm_hdr->cmd);

        switch (shm_hdr_cmd) {
        case SPI_CMD_SHM_OP_XFER:
            if (state->cs) {
                rc = handle_xfer_args(spi, shm);
            } else {
                rc = ERR_NOT_READY;
            }
            break;

        case SPI_CMD_SHM_OP_CS_ASSERT:
            if (state->cs) {
                rc = ERR_BUSY;
            } else {
                rc = spi_req_cs_assert(spi);
                state->cs = true;
            }
            break;

        case SPI_CMD_SHM_OP_CS_DEASSERT:
            if (state->cs) {
                rc = spi_req_cs_deassert(spi);
                state->cs = false;
            } else {
                rc = ERR_NOT_READY;
            }
            break;

        case SPI_CMD_SHM_OP_SET_CLK:
            rc = handle_clk_args(spi, shm);
            break;

        case SPI_CMD_SHM_OP_DELAY:
            rc = handle_delay_args(spi, shm);
            break;

        default:
            TLOGE("cmd 0x%x: unknown command\n", shm_hdr_cmd);
            rc = ERR_CMD_UNKNOWN;
        }

        WRITE_ONCE(shm_hdr->cmd, shm_hdr_cmd | SPI_CMD_RESP_BIT);
        WRITE_ONCE(shm_hdr->status, translate_lk_err(rc));

        if (rc != NO_ERROR) {
            TLOGE("failed (%d) to unpack SPI request at index: %zu\n", rc,
                  state->num_cmds);
            return rc;
        }
        state->num_cmds++;
    }

    return NO_ERROR;
}

int spi_srv_handle_batch(struct spi_dev_ctx* spi,
                         struct mem_buf* shm,
                         struct spi_batch_req* batch_req,
                         struct spi_batch_state* state) {
    int rc = NO_ERROR;

    if (batch_req->len > shm->capacity) {
        TLOGE("requests batch size(%d) is larger than shared memory(%zu)\n",
              batch_req->len, shm->capacity);
        return ERR_TOO_BIG;
    }

    /* SPI devices with shared bus must be deasserted before command sequence */
    assert(!state->cs || !spi_is_bus_shared(spi));

    rc = spi_seq_begin(spi, batch_req->num_cmds);
    if (rc != NO_ERROR) {
        TLOGE("failed (%d) to begin SPI requests\n", rc);
        return rc;
    }

    rc = unpack_shm(spi, shm, batch_req->len, state);
    if (rc != NO_ERROR) {
        TLOGE("failed (%d) to unpack SPI requests, aborting sequence\n", rc);
        goto err;
    }

    if (state->num_cmds != batch_req->num_cmds) {
        TLOGE("number of commands in shared memory(%zu) and in request(%d) "
              "are different\n",
              state->num_cmds, batch_req->num_cmds);
        rc = ERR_INVALID_ARGS;
        goto err;
    }

    if (mb_curr_pos(shm) != batch_req->len) {
        TLOGE("response size (%zu) and request size (%d) are different\n",
              mb_curr_pos(shm), batch_req->len);
        rc = ERR_BAD_LEN;
        goto err;
    }

    /* SPI devices with shared bus must be deasserted after command sequence */
    if (state->cs && spi_is_bus_shared(spi)) {
        rc = ERR_BAD_STATE;
        goto err;
    }

    rc = spi_seq_commit(spi);
    if (rc != NO_ERROR) {
        TLOGE("failed (%d) to commit SPI requests\n", rc);
        goto err;
    }

    return NO_ERROR;

err:
    spi_seq_abort(spi);
    return rc;
}

Messung V0.5 in Prozent
C=91 H=94 G=92

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-06-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.