Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/net/caif/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  cfsrvl.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) ST-Ericsson AB 2010
 * Author: Sjur Brendeland
 */


#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pkt_sched.h>
#include <net/caif/caif_layer.h>
#include <net/caif/cfsrvl.h>
#include <net/caif/cfpkt.h>
#include <net/caif/caif_dev.h>

#define SRVL_CTRL_PKT_SIZE 1
#define SRVL_FLOW_OFF 0x81
#define SRVL_FLOW_ON  0x80
#define SRVL_SET_PIN  0x82

#define container_obj(layr) container_of(layr, struct cfsrvl, layer)

static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
       int phyid)
{
 struct cfsrvl *service = container_obj(layr);

 if (layr->up == NULL || layr->up->ctrlcmd == NULL)
  return;

 switch (ctrl) {
 case CAIF_CTRLCMD_INIT_RSP:
  service->open = true;
  layr->up->ctrlcmd(layr->up, ctrl, phyid);
  break;
 case CAIF_CTRLCMD_DEINIT_RSP:
 case CAIF_CTRLCMD_INIT_FAIL_RSP:
  service->open = false;
  layr->up->ctrlcmd(layr->up, ctrl, phyid);
  break;
 case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND:
  if (phyid != service->dev_info.id)
   break;
  if (service->modem_flow_on)
   layr->up->ctrlcmd(layr->up,
       CAIF_CTRLCMD_FLOW_OFF_IND, phyid);
  service->phy_flow_on = false;
  break;
 case _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND:
  if (phyid != service->dev_info.id)
   return;
  if (service->modem_flow_on) {
   layr->up->ctrlcmd(layr->up,
        CAIF_CTRLCMD_FLOW_ON_IND,
        phyid);
  }
  service->phy_flow_on = true;
  break;
 case CAIF_CTRLCMD_FLOW_OFF_IND:
  if (service->phy_flow_on) {
   layr->up->ctrlcmd(layr->up,
       CAIF_CTRLCMD_FLOW_OFF_IND, phyid);
  }
  service->modem_flow_on = false;
  break;
 case CAIF_CTRLCMD_FLOW_ON_IND:
  if (service->phy_flow_on) {
   layr->up->ctrlcmd(layr->up,
       CAIF_CTRLCMD_FLOW_ON_IND, phyid);
  }
  service->modem_flow_on = true;
  break;
 case _CAIF_CTRLCMD_PHYIF_DOWN_IND:
  /* In case interface is down, let's fake a remove shutdown */
  layr->up->ctrlcmd(layr->up,
    CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, phyid);
  break;
 case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
  layr->up->ctrlcmd(layr->up, ctrl, phyid);
  break;
 default:
  pr_warn("Unexpected ctrl in cfsrvl (%d)\n", ctrl);
  /* We have both modem and phy flow on, send flow on */
  layr->up->ctrlcmd(layr->up, ctrl, phyid);
  service->phy_flow_on = true;
  break;
 }
}

static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl)
{
 struct cfsrvl *service = container_obj(layr);

 caif_assert(layr != NULL);
 caif_assert(layr->dn != NULL);
 caif_assert(layr->dn->transmit != NULL);

 if (!service->supports_flowctrl)
  return 0;

 switch (ctrl) {
 case CAIF_MODEMCMD_FLOW_ON_REQ:
  {
   struct cfpkt *pkt;
   struct caif_payload_info *info;
   u8 flow_on = SRVL_FLOW_ON;
   pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
   if (!pkt)
    return -ENOMEM;

   if (cfpkt_add_head(pkt, &flow_on, 1) < 0) {
    pr_err("Packet is erroneous!\n");
    cfpkt_destroy(pkt);
    return -EPROTO;
   }
   info = cfpkt_info(pkt);
   info->channel_id = service->layer.id;
   info->hdr_len = 1;
   info->dev_info = &service->dev_info;
   cfpkt_set_prio(pkt, TC_PRIO_CONTROL);
   return layr->dn->transmit(layr->dn, pkt);
  }
 case CAIF_MODEMCMD_FLOW_OFF_REQ:
  {
   struct cfpkt *pkt;
   struct caif_payload_info *info;
   u8 flow_off = SRVL_FLOW_OFF;
   pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
   if (!pkt)
    return -ENOMEM;

   if (cfpkt_add_head(pkt, &flow_off, 1) < 0) {
    pr_err("Packet is erroneous!\n");
    cfpkt_destroy(pkt);
    return -EPROTO;
   }
   info = cfpkt_info(pkt);
   info->channel_id = service->layer.id;
   info->hdr_len = 1;
   info->dev_info = &service->dev_info;
   cfpkt_set_prio(pkt, TC_PRIO_CONTROL);
   return layr->dn->transmit(layr->dn, pkt);
  }
 default:
   break;
 }
 return -EINVAL;
}

static void cfsrvl_release(struct cflayer *layer)
{
 struct cfsrvl *service = container_of(layer, struct cfsrvl, layer);
 kfree(service);
}

void cfsrvl_init(struct cfsrvl *service,
   u8 channel_id,
   struct dev_info *dev_info,
   bool supports_flowctrl)
{
 caif_assert(offsetof(struct cfsrvl, layer) == 0);
 service->open = false;
 service->modem_flow_on = true;
 service->phy_flow_on = true;
 service->layer.id = channel_id;
 service->layer.ctrlcmd = cfservl_ctrlcmd;
 service->layer.modemcmd = cfservl_modemcmd;
 service->dev_info = *dev_info;
 service->supports_flowctrl = supports_flowctrl;
 service->release = cfsrvl_release;
}

bool cfsrvl_ready(struct cfsrvl *service, int *err)
{
 if (!service->open) {
  *err = -ENOTCONN;
  return false;
 }
 return true;
}

bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
{
 struct cfsrvl *servl = container_obj(layer);
 return servl->dev_info.id == phyid;
}

void caif_free_client(struct cflayer *adap_layer)
{
 struct cfsrvl *servl;
 if (adap_layer == NULL || adap_layer->dn == NULL)
  return;
 servl = container_obj(adap_layer->dn);
 servl->release(&servl->layer);
}
EXPORT_SYMBOL(caif_free_client);

void caif_client_register_refcnt(struct cflayer *adapt_layer,
     void (*hold)(struct cflayer *lyr),
     void (*put)(struct cflayer *lyr))
{
 struct cfsrvl *service;

 if (WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL))
  return;
 service = container_of(adapt_layer->dn, struct cfsrvl, layer);
 service->hold = hold;
 service->put = put;
}
EXPORT_SYMBOL(caif_client_register_refcnt);

Messung V0.5
C=95 H=95 G=94

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

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.