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

Quelle  dsp_pipeline.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * dsp_pipeline.c: pipelined audio processing
 *
 * Copyright (C) 2007, Nadi Sarrar
 *
 * Nadi Sarrar <nadi@beronet.com>
 */


#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/string.h>
#include <linux/mISDNif.h>
#include <linux/mISDNdsp.h>
#include <linux/export.h>
#include "dsp.h"
#include "dsp_hwec.h"

struct dsp_pipeline_entry {
 struct mISDN_dsp_element *elem;
 void                *p;
 struct list_head     list;
};
struct dsp_element_entry {
 struct mISDN_dsp_element *elem;
 struct device      dev;
 struct list_head     list;
};

static LIST_HEAD(dsp_elements);

/* sysfs */
static const struct class elements_class = {
 .name = "dsp_pipeline",
};

static ssize_t
attr_show_args(struct device *dev, struct device_attribute *attr, char *buf)
{
 struct mISDN_dsp_element *elem = dev_get_drvdata(dev);
 int i;
 char *p = buf;

 *buf = 0;
 for (i = 0; i < elem->num_args; i++)
  p += sprintf(p, "Name: %s\n%s%s%sDescription: %s\n\n",
        elem->args[i].name,
        elem->args[i].def ? "Default: " : "",
        elem->args[i].def ? elem->args[i].def : "",
        elem->args[i].def ? "\n" : "",
        elem->args[i].desc);

 return p - buf;
}

static struct device_attribute element_attributes[] = {
 __ATTR(args, 0444, attr_show_args, NULL),
};

static void
mISDN_dsp_dev_release(struct device *dev)
{
 struct dsp_element_entry *entry =
  container_of(dev, struct dsp_element_entry, dev);
 list_del(&entry->list);
 kfree(entry);
}

int mISDN_dsp_element_register(struct mISDN_dsp_element *elem)
{
 struct dsp_element_entry *entry;
 int ret, i;

 if (!elem)
  return -EINVAL;

 entry = kzalloc(sizeof(struct dsp_element_entry), GFP_ATOMIC);
 if (!entry)
  return -ENOMEM;

 INIT_LIST_HEAD(&entry->list);
 entry->elem = elem;

 entry->dev.class = &elements_class;
 entry->dev.release = mISDN_dsp_dev_release;
 dev_set_drvdata(&entry->dev, elem);
 dev_set_name(&entry->dev, "%s", elem->name);
 ret = device_register(&entry->dev);
 if (ret) {
  printk(KERN_ERR "%s: failed to register %s\n",
         __func__, elem->name);
  goto err1;
 }
 list_add_tail(&entry->list, &dsp_elements);

 for (i = 0; i < ARRAY_SIZE(element_attributes); ++i) {
  ret = device_create_file(&entry->dev,
      &element_attributes[i]);
  if (ret) {
   printk(KERN_ERR "%s: failed to create device file\n",
          __func__);
   goto err2;
  }
 }

 return 0;

err2:
 device_unregister(&entry->dev);
 return ret;
err1:
 put_device(&entry->dev);
 return ret;
}
EXPORT_SYMBOL(mISDN_dsp_element_register);

void mISDN_dsp_element_unregister(struct mISDN_dsp_element *elem)
{
 struct dsp_element_entry *entry, *n;

 if (!elem)
  return;

 list_for_each_entry_safe(entry, n, &dsp_elements, list)
  if (entry->elem == elem) {
   device_unregister(&entry->dev);
   return;
  }
 printk(KERN_ERR "%s: element %s not in list.\n", __func__, elem->name);
}
EXPORT_SYMBOL(mISDN_dsp_element_unregister);

int dsp_pipeline_module_init(void)
{
 int err;

 err = class_register(&elements_class);
 if (err)
  return err;

 dsp_hwec_init();

 return 0;
}

void dsp_pipeline_module_exit(void)
{
 struct dsp_element_entry *entry, *n;

 dsp_hwec_exit();

 class_unregister(&elements_class);

 list_for_each_entry_safe(entry, n, &dsp_elements, list) {
  list_del(&entry->list);
  printk(KERN_WARNING "%s: element was still registered: %s\n",
         __func__, entry->elem->name);
  kfree(entry);
 }
}

int dsp_pipeline_init(struct dsp_pipeline *pipeline)
{
 if (!pipeline)
  return -EINVAL;

 INIT_LIST_HEAD(&pipeline->list);

 return 0;
}

static inline void _dsp_pipeline_destroy(struct dsp_pipeline *pipeline)
{
 struct dsp_pipeline_entry *entry, *n;

 list_for_each_entry_safe(entry, n, &pipeline->list, list) {
  list_del(&entry->list);
  if (entry->elem == dsp_hwec)
   dsp_hwec_disable(container_of(pipeline, struct dsp,
            pipeline));
  else
   entry->elem->free(entry->p);
  kfree(entry);
 }
}

void dsp_pipeline_destroy(struct dsp_pipeline *pipeline)
{

 if (!pipeline)
  return;

 _dsp_pipeline_destroy(pipeline);
}

int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
{
 int found = 0;
 char *dup, *next, *tok, *name, *args;
 struct dsp_element_entry *entry, *n;
 struct dsp_pipeline_entry *pipeline_entry;
 struct mISDN_dsp_element *elem;

 if (!pipeline)
  return -EINVAL;

 if (!list_empty(&pipeline->list))
  _dsp_pipeline_destroy(pipeline);

 dup = next = kstrdup(cfg, GFP_ATOMIC);
 if (!dup)
  return 0;
 while ((tok = strsep(&next, "|"))) {
  if (!strlen(tok))
   continue;
  name = strsep(&tok, "(");
  args = strsep(&tok, ")");
  if (args && !*args)
   args = NULL;

  list_for_each_entry_safe(entry, n, &dsp_elements, list)
   if (!strcmp(entry->elem->name, name)) {
    elem = entry->elem;

    pipeline_entry = kmalloc(sizeof(struct
        dsp_pipeline_entry), GFP_ATOMIC);
    if (!pipeline_entry) {
     printk(KERN_ERR "%s: failed to add "
            "entry to pipeline: %s (out of "
            "memory)\n", __func__, elem->name);
     goto _out;
    }
    pipeline_entry->elem = elem;

    if (elem == dsp_hwec) {
     /* This is a hack to make the hwec
   available as a pipeline module */

     dsp_hwec_enable(container_of(pipeline,
             struct dsp, pipeline), args);
     list_add_tail(&pipeline_entry->list,
            &pipeline->list);
    } else {
     pipeline_entry->p = elem->new(args);
     if (pipeline_entry->p) {
      list_add_tail(&pipeline_entry->
             list, &pipeline->list);
     } else {
      printk(KERN_ERR "%s: failed "
             "to add entry to pipeline: "
             "%s (new() returned NULL)\n",
             __func__, elem->name);
      kfree(pipeline_entry);
     }
    }
    found = 1;
    break;
   }

  if (found)
   found = 0;
  else
   printk(KERN_ERR "%s: element not found, skipping: "
          "%s\n", __func__, name);
 }

_out:
 if (!list_empty(&pipeline->list))
  pipeline->inuse = 1;
 else
  pipeline->inuse = 0;

 kfree(dup);
 return 0;
}

void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data, int len)
{
 struct dsp_pipeline_entry *entry;

 if (!pipeline)
  return;

 list_for_each_entry(entry, &pipeline->list, list)
  if (entry->elem->process_tx)
   entry->elem->process_tx(entry->p, data, len);
}

void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len,
        unsigned int txlen)
{
 struct dsp_pipeline_entry *entry;

 if (!pipeline)
  return;

 list_for_each_entry_reverse(entry, &pipeline->list, list)
  if (entry->elem->process_rx)
   entry->elem->process_rx(entry->p, data, len, txlen);
}

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

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet)  ¤

*© 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.