root/net/caif/cfutill.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cfutill_create
  2. cfutill_receive
  3. cfutill_transmit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) ST-Ericsson AB 2010
   4  * Author:      Sjur Brendeland
   5  */
   6 
   7 #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/types.h>
  11 #include <linux/slab.h>
  12 #include <linux/errno.h>
  13 #include <net/caif/caif_layer.h>
  14 #include <net/caif/cfsrvl.h>
  15 #include <net/caif/cfpkt.h>
  16 
  17 #define container_obj(layr) ((struct cfsrvl *) layr)
  18 #define UTIL_PAYLOAD  0x00
  19 #define UTIL_CMD_BIT  0x80
  20 #define UTIL_REMOTE_SHUTDOWN 0x82
  21 #define UTIL_FLOW_OFF 0x81
  22 #define UTIL_FLOW_ON  0x80
  23 
  24 static int cfutill_receive(struct cflayer *layr, struct cfpkt *pkt);
  25 static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt);
  26 
  27 struct cflayer *cfutill_create(u8 channel_id, struct dev_info *dev_info)
  28 {
  29         struct cfsrvl *util = kzalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
  30         if (!util)
  31                 return NULL;
  32         caif_assert(offsetof(struct cfsrvl, layer) == 0);
  33         cfsrvl_init(util, channel_id, dev_info, true);
  34         util->layer.receive = cfutill_receive;
  35         util->layer.transmit = cfutill_transmit;
  36         snprintf(util->layer.name, CAIF_LAYER_NAME_SZ, "util1");
  37         return &util->layer;
  38 }
  39 
  40 static int cfutill_receive(struct cflayer *layr, struct cfpkt *pkt)
  41 {
  42         u8 cmd = -1;
  43         struct cfsrvl *service = container_obj(layr);
  44         caif_assert(layr != NULL);
  45         caif_assert(layr->up != NULL);
  46         caif_assert(layr->up->receive != NULL);
  47         caif_assert(layr->up->ctrlcmd != NULL);
  48         if (cfpkt_extr_head(pkt, &cmd, 1) < 0) {
  49                 pr_err("Packet is erroneous!\n");
  50                 cfpkt_destroy(pkt);
  51                 return -EPROTO;
  52         }
  53 
  54         switch (cmd) {
  55         case UTIL_PAYLOAD:
  56                 return layr->up->receive(layr->up, pkt);
  57         case UTIL_FLOW_OFF:
  58                 layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0);
  59                 cfpkt_destroy(pkt);
  60                 return 0;
  61         case UTIL_FLOW_ON:
  62                 layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0);
  63                 cfpkt_destroy(pkt);
  64                 return 0;
  65         case UTIL_REMOTE_SHUTDOWN:      /* Remote Shutdown Request */
  66                 pr_err("REMOTE SHUTDOWN REQUEST RECEIVED\n");
  67                 layr->ctrlcmd(layr, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, 0);
  68                 service->open = false;
  69                 cfpkt_destroy(pkt);
  70                 return 0;
  71         default:
  72                 cfpkt_destroy(pkt);
  73                 pr_warn("Unknown service control %d (0x%x)\n", cmd, cmd);
  74                 return -EPROTO;
  75         }
  76 }
  77 
  78 static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt)
  79 {
  80         u8 zero = 0;
  81         struct caif_payload_info *info;
  82         int ret;
  83         struct cfsrvl *service = container_obj(layr);
  84         caif_assert(layr != NULL);
  85         caif_assert(layr->dn != NULL);
  86         caif_assert(layr->dn->transmit != NULL);
  87 
  88         if (!cfsrvl_ready(service, &ret)) {
  89                 cfpkt_destroy(pkt);
  90                 return ret;
  91         }
  92 
  93         cfpkt_add_head(pkt, &zero, 1);
  94         /* Add info for MUX-layer to route the packet out. */
  95         info = cfpkt_info(pkt);
  96         info->channel_id = service->layer.id;
  97         /*
  98          * To optimize alignment, we add up the size of CAIF header before
  99          * payload.
 100          */
 101         info->hdr_len = 1;
 102         info->dev_info = &service->dev_info;
 103         return layr->dn->transmit(layr->dn, pkt);
 104 }

/* [<][>][^][v][top][bottom][index][help] */