cregit-Linux how code gets into the kernel

Release 4.11 drivers/isdn/capi/kcapi.c

/* $Id: kcapi.c,v 1.1.2.8 2004/03/26 19:57:20 armin Exp $
 *
 * Kernel CAPI 2.0 Module
 *
 * Copyright 1999 by Carsten Paeth <calle@calle.de>
 * Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
 *
 * This software may be used and distributed according to the terms
 * of the GNU General Public License, incorporated herein by reference.
 *
 */


#define AVMB1_COMPAT

#include "kcapi.h"
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/proc_fs.h>
#include <linux/sched/signal.h>
#include <linux/seq_file.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
#ifdef AVMB1_COMPAT
#include <linux/b1lli.h>
#endif
#include <linux/mutex.h>
#include <linux/rcupdate.h>


static int showcapimsgs = 0;

static struct workqueue_struct *kcapi_wq;

MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
module_param(showcapimsgs, uint, 0);

/* ------------------------------------------------------------- */


struct capictr_event {
	
struct work_struct work;
	
unsigned int type;
	
u32 controller;
};

/* ------------------------------------------------------------- */


static struct capi_version driver_version = {2, 0, 1, 1 << 4};

static char driver_serial[CAPI_SERIAL_LEN] = "0004711";

static char capi_manufakturer[64] = "AVM Berlin";


#define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)


LIST_HEAD(capi_drivers);

DEFINE_MUTEX(capi_drivers_lock);


struct capi_ctr *capi_controller[CAPI_MAXCONTR];

DEFINE_MUTEX(capi_controller_lock);


struct capi20_appl *capi_applications[CAPI_MAXAPPL];


static int ncontrollers;

static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list);

/* -------- controller ref counting -------------------------------------- */


static inline struct capi_ctr * capi_ctr_get(struct capi_ctr *ctr) { if (!try_module_get(ctr->owner)) return NULL; return ctr; }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski2480.00%125.00%
Jan Kiszka310.00%125.00%
Karsten Keil26.67%125.00%
Christoph Hellwig13.33%125.00%
Total30100.00%4100.00%


static inline void capi_ctr_put(struct capi_ctr *ctr) { module_put(ctr->owner); }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski1578.95%125.00%
Jan Kiszka210.53%125.00%
Karsten Keil15.26%125.00%
Christoph Hellwig15.26%125.00%
Total19100.00%4100.00%

/* ------------------------------------------------------------- */
static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr) { if (contr < 1 || contr - 1 >= CAPI_MAXCONTR) return NULL; return capi_controller[contr - 1]; }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski3085.71%133.33%
Dan Carpenter411.43%133.33%
Jan Kiszka12.86%133.33%
Total35100.00%3100.00%


static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid) { lockdep_assert_held(&capi_controller_lock); if (applid < 1 || applid - 1 >= CAPI_MAXAPPL) return NULL; return capi_applications[applid - 1]; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka3790.24%150.00%
Dan Carpenter49.76%150.00%
Total41100.00%2100.00%


static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid) { if (applid < 1 || applid - 1 >= CAPI_MAXAPPL) return NULL; return rcu_dereference(capi_applications[applid - 1]); }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski2976.32%350.00%
Dan Carpenter410.53%116.67%
Jan Kiszka37.89%116.67%
Linus Torvalds (pre-git)25.26%116.67%
Total38100.00%6100.00%

/* -------- util functions ------------------------------------ */
static inline int capi_cmd_valid(u8 cmd) { switch (cmd) { case CAPI_ALERT: case CAPI_CONNECT: case CAPI_CONNECT_ACTIVE: case CAPI_CONNECT_B3_ACTIVE: case CAPI_CONNECT_B3: case CAPI_CONNECT_B3_T90_ACTIVE: case CAPI_DATA_B3: case CAPI_DISCONNECT_B3: case CAPI_DISCONNECT: case CAPI_FACILITY: case CAPI_INFO: case CAPI_LISTEN: case CAPI_MANUFACTURER: case CAPI_RESET_B3: case CAPI_SELECT_B_PROTOCOL: return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski6191.04%150.00%
Linus Torvalds (pre-git)68.96%150.00%
Total67100.00%2100.00%


static inline int capi_subcmd_valid(u8 subcmd) { switch (subcmd) { case CAPI_REQ: case CAPI_CONF: case CAPI_IND: case CAPI_RESP: return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski2882.35%150.00%
Linus Torvalds (pre-git)617.65%150.00%
Total34100.00%2100.00%

/* ------------------------------------------------------------ */
static void register_appl(struct capi_ctr *ctr, u16 applid, capi_register_params *rparam) { ctr = capi_ctr_get(ctr); if (ctr) ctr->register_appl(ctr, applid, rparam); else printk(KERN_WARNING "%s: cannot get controller resources\n", __func__); }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski3163.27%240.00%
Karsten Keil1020.41%120.00%
Jan Kiszka714.29%120.00%
Harvey Harrison12.04%120.00%
Total49100.00%5100.00%


static void release_appl(struct capi_ctr *ctr, u16 applid) { DBG("applid %#x", applid); ctr->release_appl(ctr, applid); capi_ctr_put(ctr); }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski3188.57%480.00%
Jan Kiszka411.43%120.00%
Total35100.00%5100.00%


static void notify_up(u32 contr) { struct capi20_appl *ap; struct capi_ctr *ctr; u16 applid; mutex_lock(&capi_controller_lock); if (showcapimsgs & 1) printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); ctr = get_capi_ctr_by_nr(contr); if (ctr) { if (ctr->state == CAPI_CTR_RUNNING) goto unlock_out; ctr->state = CAPI_CTR_RUNNING; for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = __get_capi_appl_by_nr(applid); if (ap) register_appl(ctr, applid, &ap->rparam); } wake_up_interruptible_all(&ctr->state_wait_queue); } else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); unlock_out: mutex_unlock(&capi_controller_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka6547.45%436.36%
Kai Germaschewski3021.90%436.36%
Linus Torvalds (pre-git)2014.60%19.09%
Karsten Keil1611.68%19.09%
Andrew Morton64.38%19.09%
Total137100.00%11100.00%


static void ctr_down(struct capi_ctr *ctr, int new_state) { struct capi20_appl *ap; u16 applid; if (ctr->state == CAPI_CTR_DETECTED || ctr->state == CAPI_CTR_DETACHED) return; ctr->state = new_state; memset(ctr->manu, 0, sizeof(ctr->manu)); memset(&ctr->version, 0, sizeof(ctr->version)); memset(&ctr->profile, 0, sizeof(ctr->profile)); memset(ctr->serial, 0, sizeof(ctr->serial)); for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = __get_capi_appl_by_nr(applid); if (ap) capi_ctr_put(ctr); } wake_up_interruptible_all(&ctr->state_wait_queue); }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka10369.59%337.50%
Kai Germaschewski2617.57%337.50%
Linus Torvalds (pre-git)1610.81%112.50%
Andrew Morton32.03%112.50%
Total148100.00%8100.00%


static void notify_down(u32 contr) { struct capi_ctr *ctr; mutex_lock(&capi_controller_lock); if (showcapimsgs & 1) printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr); ctr = get_capi_ctr_by_nr(contr); if (ctr) ctr_down(ctr, CAPI_CTR_DETECTED); else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); mutex_unlock(&capi_controller_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka69100.00%2100.00%
Total69100.00%2100.00%


static int notify_handler(struct notifier_block *nb, unsigned long val, void *v) { u32 contr = (long)v; switch (val) { case CAPICTR_UP: notify_up(contr); break; case CAPICTR_DOWN: notify_down(contr); break; } return NOTIFY_OK; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka2648.15%125.00%
Linus Torvalds (pre-git)2138.89%125.00%
Andrew Morton611.11%125.00%
David Howells11.85%125.00%
Total54100.00%4100.00%


static void do_notify_work(struct work_struct *work) { struct capictr_event *event = container_of(work, struct capictr_event, work); blocking_notifier_call_chain(&ctr_notifier_list, event->type, (void *)(long)event->controller); kfree(event); }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka4790.38%133.33%
Andrew Morton47.69%133.33%
Linus Torvalds (pre-git)11.92%133.33%
Total52100.00%3100.00%

/* * The notifier will result in adding/deleteing of devices. Devices can * only removed in user process, not in bh. */
static int notify_push(unsigned int event_type, u32 controller) { struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC); if (!event) return -ENOMEM; INIT_WORK(&event->work, do_notify_work); event->type = event_type; event->controller = controller; queue_work(kcapi_wq, &event->work); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton4054.79%114.29%
Jan Kiszka1216.44%114.29%
Linus Torvalds (pre-git)810.96%228.57%
Kai Germaschewski810.96%114.29%
Tejun Heo34.11%114.29%
Karsten Keil22.74%114.29%
Total73100.00%7100.00%


int register_capictr_notifier(struct notifier_block *nb) { return blocking_notifier_chain_register(&ctr_notifier_list, nb); }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka19100.00%1100.00%
Total19100.00%1100.00%

EXPORT_SYMBOL_GPL(register_capictr_notifier);
int unregister_capictr_notifier(struct notifier_block *nb) { return blocking_notifier_chain_unregister(&ctr_notifier_list, nb); }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka19100.00%1100.00%
Total19100.00%1100.00%

EXPORT_SYMBOL_GPL(unregister_capictr_notifier); /* -------- Receiver ------------------------------------------ */
static void recv_handler(struct work_struct *work) { struct sk_buff *skb; struct capi20_appl *ap = container_of(work, struct capi20_appl, recv_work); if ((!ap) || (ap->release_in_progress)) return; mutex_lock(&ap->recv_mtx); while ((skb = skb_dequeue(&ap->recv_queue))) { if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND) ap->nrecvdatapkt++; else ap->nrecvctlpkt++; ap->recv_message(ap, skb); } mutex_unlock(&ap->recv_mtx); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4440.74%111.11%
Andrew Morton3431.48%333.33%
Kai Germaschewski1614.81%333.33%
David Howells109.26%111.11%
Matthias Kaehlcke43.70%111.11%
Total108100.00%9100.00%

/** * capi_ctr_handle_message() - handle incoming CAPI message * @ctr: controller descriptor structure. * @appl: application ID. * @skb: message. * * Called by hardware driver to pass a CAPI message to the application. */
void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, struct sk_buff *skb) { struct capi20_appl *ap; int showctl = 0; u8 cmd, subcmd; _cdebbuf *cdb; if (ctr->state != CAPI_CTR_RUNNING) { cdb = capi_message2str(skb->data); if (cdb) { printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s", ctr->cnr, cdb->buf); cdebbuf_free(cdb); } else printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n", ctr->cnr); goto error; } cmd = CAPIMSG_COMMAND(skb->data); subcmd = CAPIMSG_SUBCOMMAND(skb->data); if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) { ctr->nrecvdatapkt++; if (ctr->traceflag > 2) showctl |= 2; } else { ctr->nrecvctlpkt++; if (ctr->traceflag) showctl |= 2; } showctl |= (ctr->traceflag & 1); if (showctl & 2) { if (showctl & 1) { printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n", ctr->cnr, CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { cdb = capi_message2str(skb->data); if (cdb) { printk(KERN_DEBUG "kcapi: got [%03d] %s\n", ctr->cnr, cdb->buf); cdebbuf_free(cdb); } else printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n", ctr->cnr, CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } } rcu_read_lock(); ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data)); if (!ap) { rcu_read_unlock(); cdb = capi_message2str(skb->data); if (cdb) { printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", CAPIMSG_APPID(skb->data), cdb->buf); cdebbuf_free(cdb); } else printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s) cannot trace\n", CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd)); goto error; } skb_queue_tail(&ap->recv_queue, skb); queue_work(kcapi_wq, &ap->recv_work); rcu_read_unlock(); return; error: kfree_skb(skb); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)19648.64%330.00%
Karsten Keil12631.27%110.00%
Andrew Morton5513.65%110.00%
Jan Kiszka204.96%220.00%
Tejun Heo30.74%110.00%
Kai Germaschewski30.74%220.00%
Total403100.00%10100.00%

EXPORT_SYMBOL(capi_ctr_handle_message); /** * capi_ctr_ready() - signal CAPI controller ready * @ctr: controller descriptor structure. * * Called by hardware driver to signal that the controller is up and running. */
void capi_ctr_ready(struct capi_ctr *ctr) { printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n", ctr->cnr, ctr->name); notify_push(CAPICTR_UP, ctr->cnr); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2266.67%233.33%
Jan Kiszka618.18%233.33%
Kai Germaschewski515.15%233.33%
Total33100.00%6100.00%

EXPORT_SYMBOL(capi_ctr_ready); /** * capi_ctr_down() - signal CAPI controller not ready * @ctr: controller descriptor structure. * * Called by hardware driver to signal that the controller is down and * unavailable for use. */
void capi_ctr_down(struct capi_ctr *ctr) { printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr); notify_push(CAPICTR_DOWN, ctr->cnr); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1965.52%233.33%
Jan Kiszka517.24%233.33%
Kai Germaschewski413.79%116.67%
Tilman Schmidt13.45%116.67%
Total29100.00%6100.00%

EXPORT_SYMBOL(capi_ctr_down); /** * capi_ctr_suspend_output() - suspend controller * @ctr: controller descriptor structure. * * Called by hardware driver to stop data flow. * * Note: The caller is responsible for synchronizing concurrent state changes * as well as invocations of capi_ctr_handle_message. */
void capi_ctr_suspend_output(struct capi_ctr *ctr) { if (!ctr->blocked) { printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n", ctr->cnr); ctr->blocked = 1; } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2777.14%125.00%
Jan Kiszka514.29%125.00%
Kai Germaschewski38.57%250.00%
Total35100.00%4100.00%

EXPORT_SYMBOL(capi_ctr_suspend_output); /** * capi_ctr_resume_output() - resume controller * @ctr: controller descriptor structure. * * Called by hardware driver to resume data flow. * * Note: The caller is responsible for synchronizing concurrent state changes * as well as invocations of capi_ctr_handle_message. */
void capi_ctr_resume_output(struct capi_ctr *ctr) { if (ctr->blocked) { printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n", ctr->cnr); ctr->blocked = 0; } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2676.47%125.00%
Jan Kiszka514.71%125.00%
Kai Germaschewski38.82%250.00%
Total34100.00%4100.00%

EXPORT_SYMBOL(capi_ctr_resume_output); /* ------------------------------------------------------------- */ /** * attach_capi_ctr() - register CAPI controller * @ctr: controller descriptor structure. * * Called by hardware driver to register a controller with the CAPI subsystem. * Return value: 0 on success, error code < 0 on error */
int attach_capi_ctr(struct capi_ctr *ctr) { int i; mutex_lock(&capi_controller_lock); for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i]) break; } if (i == CAPI_MAXCONTR) { mutex_unlock(&capi_controller_lock); printk(KERN_ERR "kcapi: out of controller slots\n"); return -EBUSY; } capi_controller[i] = ctr; ctr->nrecvctlpkt = 0; ctr->nrecvdatapkt = 0; ctr->nsentctlpkt = 0; ctr->nsentdatapkt = 0; ctr->cnr = i + 1; ctr->state = CAPI_CTR_DETECTED; ctr->blocked = 0; ctr->traceflag = showcapimsgs; init_waitqueue_head(&ctr->state_wait_queue); sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr); ncontrollers++; mutex_unlock(&capi_controller_lock); printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n", ctr->cnr, ctr->name); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)10353.65%218.18%
Jan Kiszka4221.88%218.18%
Kai Germaschewski3216.67%327.27%
Andrew Morton84.17%19.09%
Alexey Dobriyan42.08%19.09%
Arjan van de Ven21.04%19.09%
Al Viro10.52%19.09%
Total192100.00%11100.00%

EXPORT_SYMBOL(attach_capi_ctr); /** * detach_capi_ctr() - unregister CAPI controller * @ctr: controller descriptor structure. * * Called by hardware driver to remove the registration of a controller * with the CAPI subsystem. * Return value: 0 on success, error code < 0 on error */
int detach_capi_ctr(struct capi_ctr *ctr) { int err = 0; mutex_lock(&capi_controller_lock); ctr_down(ctr, CAPI_CTR_DETACHED); if (capi_controller[ctr->cnr - 1] != ctr) { err = -EINVAL; goto unlock_out; } capi_controller[ctr->cnr - 1] = NULL; ncontrollers--; if (ctr->procent) remove_proc_entry(ctr->procfn, NULL); printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n", ctr->cnr, ctr->name); unlock_out: mutex_unlock(&capi_controller_lock); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka6360.00%342.86%
Linus Torvalds (pre-git)3230.48%114.29%
Kai Germaschewski109.52%342.86%
Total105100.00%7100.00%

EXPORT_SYMBOL(detach_capi_ctr); /** * register_capi_driver() - register CAPI driver * @driver: driver descriptor structure. * * Called by hardware driver to register itself with the CAPI subsystem. */
void register_capi_driver(struct capi_driver *driver) { mutex_lock(&capi_drivers_lock); list_add_tail(&driver->list, &capi_drivers); mutex_unlock(&capi_drivers_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton2987.88%150.00%
Jan Kiszka412.12%150.00%
Total33100.00%2100.00%

EXPORT_SYMBOL(register_capi_driver); /** * unregister_capi_driver() - unregister CAPI driver * @driver: driver descriptor structure. * * Called by hardware driver to unregister itself from the CAPI subsystem. */
void unregister_capi_driver(struct capi_driver *driver) { mutex_lock(&capi_drivers_lock); list_del(&driver->list); mutex_unlock(&capi_drivers_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton2686.67%150.00%
Jan Kiszka413.33%150.00%
Total30100.00%2100.00%

EXPORT_SYMBOL(unregister_capi_driver); /* ------------------------------------------------------------- */ /* -------- CAPI2.0 Interface ---------------------------------- */ /* ------------------------------------------------------------- */ /** * capi20_isinstalled() - CAPI 2.0 operation CAPI_INSTALLED * * Return value: CAPI result code (CAPI_NOERROR if at least one ISDN controller * is ready for use, CAPI_REGNOTINSTALLED otherwise) */
u16 capi20_isinstalled(void) { u16 ret = CAPI_REGNOTINSTALLED; int i; mutex_lock(&capi_controller_lock); for (i = 0; i < CAPI_MAXCONTR; i++) if (capi_controller[i] && capi_controller[i]->state == CAPI_CTR_RUNNING) { ret = CAPI_NOERROR; break; } mutex_unlock(&capi_controller_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3248.48%228.57%
Jan Kiszka2740.91%228.57%
Kai Germaschewski710.61%342.86%
Total66100.00%7100.00%

EXPORT_SYMBOL(capi20_isinstalled); /** * capi20_register() - CAPI 2.0 operation CAPI_REGISTER * @ap: CAPI application descriptor structure. * * Register an application's presence with CAPI. * A unique application ID is assigned and stored in @ap->applid. * After this function returns successfully, the message receive * callback function @ap->recv_message() may be called at any time * until capi20_release() has been called for the same @ap. * Return value: CAPI result code */
u16 capi20_register(struct capi20_appl *ap) { int i; u16 applid; DBG(""); if (ap->rparam.datablklen < 128) return CAPI_LOGBLKSIZETOSMALL; ap->nrecvctlpkt = 0; ap->nrecvdatapkt = 0; ap->nsentctlpkt = 0; ap->nsentdatapkt = 0; mutex_init(&ap->recv_mtx); skb_queue_head_init(&ap->recv_queue); INIT_WORK(&ap->recv_work, recv_handler); ap->release_in_progress = 0; mutex_lock(&capi_controller_lock); for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { if (capi_applications[applid - 1] == NULL) break; } if (applid > CAPI_MAXAPPL) { mutex_unlock(&capi_controller_lock); return CAPI_TOOMANYAPPLS; } ap->applid = applid; capi_applications[applid - 1] = ap; for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i] || capi_controller[i]->state != CAPI_CTR_RUNNING) continue; register_appl(capi_controller[i], applid, &ap->rparam); } mutex_unlock(&capi_controller_lock); if (showcapimsgs & 1) { printk(KERN_DEBUG "kcapi: appl %d up\n", applid); } return CAPI_NOERROR; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka6327.63%323.08%
Linus Torvalds (pre-git)5925.88%17.69%
Kai Germaschewski5323.25%538.46%
Andrew Morton5021.93%215.38%
Matthias Kaehlcke20.88%17.69%
Arjan van de Ven10.44%17.69%
Total228100.00%13100.00%

EXPORT_SYMBOL(capi20_register); /** * capi20_release() - CAPI 2.0 operation CAPI_RELEASE * @ap: CAPI application descriptor structure. * * Terminate an application's registration with CAPI. * After this function returns successfully, the message receive * callback function @ap->recv_message() will no longer be called. * Return value: CAPI result code */
u16 capi20_release(struct capi20_appl *ap) { int i; DBG("applid %#x", ap->applid); mutex_lock(&capi_controller_lock); ap->release_in_progress = 1; capi_applications[ap->applid - 1] = NULL; synchronize_rcu(); for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i] || capi_controller[i]->state != CAPI_CTR_RUNNING) continue; release_appl(capi_controller[i], ap->applid); } mutex_unlock(&capi_controller_lock); flush_workqueue(kcapi_wq); skb_queue_purge(&ap->recv_queue); if (showcapimsgs & 1) { printk(KERN_DEBUG "kcapi: appl %d down\n", ap->applid); } return CAPI_NOERROR; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5138.35%17.69%
Andrew Morton4030.08%215.38%
Kai Germaschewski2720.30%538.46%
Jan Kiszka107.52%323.08%
Tejun Heo43.01%17.69%
Arjan van de Ven10.75%17.69%
Total133100.00%13100.00%

EXPORT_SYMBOL(capi20_release); /** * capi20_put_message() - CAPI 2.0 operation CAPI_PUT_MESSAGE * @ap: CAPI application descriptor structure. * @skb: CAPI message. * * Transfer a single message to CAPI. * Return value: CAPI result code */
u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) { struct capi_ctr *ctr; int showctl = 0; u8 cmd, subcmd; DBG("applid %#x", ap->applid); if (ncontrollers == 0) return CAPI_REGNOTINSTALLED; if ((ap->applid == 0) || ap->release_in_progress) return CAPI_ILLAPPNR; if (skb->len < 12 || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; /* * The controller reference is protected by the existence of the * application passed to us. We assume that the caller properly * synchronizes this service with capi20_release. */ ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; if (ctr->blocked) return CAPI_SENDQUEUEFULL; cmd = CAPIMSG_COMMAND(skb->data); subcmd = CAPIMSG_SUBCOMMAND(skb->data); if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ) { ctr->nsentdatapkt++; ap->nsentdatapkt++; if (ctr->traceflag > 2) showctl |= 2; } else { ctr->nsentctlpkt++; ap->nsentctlpkt++; if (ctr->traceflag) showctl |= 2; } showctl |= (ctr->traceflag & 1); if (showctl & 2) { if (showctl & 1) { printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n", CAPIMSG_CONTROLLER(skb->data), CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { _cdebbuf *cdb = capi_message2str(skb->data); if (cdb) { printk(KERN_DEBUG "kcapi: put [%03d] %s\n", CAPIMSG_CONTROLLER(skb->data), cdb->buf); cdebbuf_free(cdb); } else printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u cannot trace\n", CAPIMSG_CONTROLLER(skb->data), CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } } return ctr->send_message(ctr, skb); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)23365.45%19.09%
Karsten Keil5716.01%19.09%
Kai Germaschewski4412.36%654.55%
Jan Kiszka164.49%218.18%
Andrew Morton61.69%19.09%
Total356100.00%11100.00%

EXPORT_SYMBOL(capi20_put_message); /** * capi20_get_manufacturer() - CAPI 2.0 operation CAPI_GET_MANUFACTURER * @contr: controller number. * @buf: result buffer (64 bytes). * * Retrieve information about the manufacturer of the specified ISDN controller * or (for @contr == 0) the driver itself. * Return value: CAPI result code */
u16 capi20_get_manufacturer(u32 contr, u8 *buf) { struct capi_ctr *ctr; u16 ret; if (contr == 0) { strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } mutex_lock(&capi_controller_lock); ctr = get_capi_ctr_by_nr(contr); if (ctr && ctr->state == CAPI_CTR_RUNNING) { strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN); ret = CAPI_NOERROR; } else ret = CAPI_REGNOTINSTALLED; mutex_unlock(&capi_controller_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4042.55%112.50%
Jan Kiszka3638.30%225.00%
Kai Germaschewski1313.83%337.50%
Karsten Keil33.19%112.50%
Benjamin Collins22.13%112.50%
Total94100.00%8100.00%

EXPORT_SYMBOL(capi20_get_manufacturer); /** * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION * @contr: controller number. * @verp: result structure. * * Retrieve version information for the specified ISDN controller * or (for @contr == 0) the driver itself. * Return value: CAPI result code */
u16 capi20_get_version(u32 contr, struct capi_version *verp) { struct capi_ctr *ctr; u16 ret; if (contr == 0) { *verp = driver_version; return CAPI_NOERROR; } mutex_lock(&capi_controller_lock); ctr = get_capi_ctr_by_nr(contr); if (ctr && ctr->state == CAPI_CTR_RUNNING) { memcpy(verp, &ctr->version, sizeof(capi_version)); ret = CAPI_NOERROR; } else ret = CAPI_REGNOTINSTALLED; mutex_unlock(&capi_controller_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4749.47%116.67%
Jan Kiszka3637.89%233.33%
Kai Germaschewski1212.63%350.00%
Total95100.00%6100.00%

EXPORT_SYMBOL(capi20_get_version); /** * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER * @contr: controller number. * @serial: result buffer (8 bytes). * * Retrieve the serial number of the specified ISDN controller * or (for @contr == 0) the driver itself. * Return value: CAPI result code */
u16 capi20_get_serial(u32 contr, u8 *serial) { struct capi_ctr *ctr; u16 ret; if (contr == 0) { strlcpy(serial, driver_serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } mutex_lock(&capi_controller_lock); ctr = get_capi_ctr_by_nr(contr); if (ctr && ctr->state == CAPI_CTR_RUNNING) { strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN); ret = CAPI_NOERROR; } else ret = CAPI_REGNOTINSTALLED; mutex_unlock(&capi_controller_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3941.49%112.50%
Jan Kiszka3739.36%225.00%
Kai Germaschewski1313.83%337.50%
Karsten Keil33.19%112.50%
Benjamin Collins22.13%112.50%
Total94100.00%8100.00%

EXPORT_SYMBOL(capi20_get_serial); /** * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE * @contr: controller number. * @profp: result structure. * * Retrieve capability information for the specified ISDN controller * or (for @contr == 0) the number of installed controllers. * Return value: CAPI result code */
u16 capi20_get_profile(u32 contr, struct capi_profile *profp) { struct capi_ctr *ctr; u16 ret; if (contr == 0) { profp->ncontroller = ncontrollers; return CAPI_NOERROR; } mutex_lock(&capi_controller_lock); ctr = get_capi_ctr_by_nr(contr); if (ctr && ctr->state == CAPI_CTR_RUNNING) { memcpy(profp, &ctr->profile, sizeof(struct capi_profile)); ret = CAPI_NOERROR; } else ret = CAPI_REGNOTINSTALLED; mutex_unlock(&capi_controller_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4849.48%116.67%
Jan Kiszka3738.14%233.33%
Kai Germaschewski1212.37%350.00%
Total97100.00%6100.00%

EXPORT_SYMBOL(capi20_get_profile); /* Must be called with capi_controller_lock held. */
static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state) { DEFINE_WAIT(wait); int retval = 0; ctr = capi_ctr_get(ctr); if (!ctr) return -ESRCH; for (;;) { prepare_to_wait(&ctr->state_wait_queue, &wait, TASK_INTERRUPTIBLE); if (ctr->state == state) break; if (ctr->state == CAPI_CTR_DETACHED) { retval = -ESRCH; break; } if (signal_pending(current)) { retval = -EINTR; break; } mutex_unlock(&capi_controller_lock); schedule(); mutex_lock(&capi_controller_lock); } finish_wait(&ctr->state_wait_queue, &wait); capi_ctr_put(ctr); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kiszka135100.00%1100.00%
Total135100.00%1100.00%

#ifdef AVMB1_COMPAT
static int old_capi_manufacturer(unsigned int cmd, void __user *data) { avmb1_loadandconfigdef ldef; avmb1_extcarddef cdef; avmb1_resetdef rdef; capicardparams cparams; struct capi_ctr *ctr; struct capi_driver *driver = NULL; capiloaddata ldata; struct list_head *l; int retval; switch (cmd) { case AVMB1_ADDCARD: case AVMB1_ADDCARD_WITH_TYPE: if (cmd == AVMB1_ADDCARD) { if ((retval = copy_from_user(&cdef, data, sizeof(avmb1_carddef)))) return -EFAULT; cdef.cardtype = AVM_CARDTYPE_B1; cdef.cardnr = 0; } else { if ((retval = copy_from_user(&cdef, data, sizeof(avmb1_extcarddef)))) return -EFAULT; } cparams.port = cdef.port; cparams.irq = cdef.irq; cparams.cardnr = cdef.cardnr; mutex_lock(&capi_drivers_lock); switch (cdef.cardtype) { case AVM_CARDTYPE_B1: list_for_each(l, &capi_drivers) { driver = list_entry(l, struct capi_driver, list); if (strcmp(driver->name, "b1isa") == 0) break; } break; case AVM_CARDTYPE_T1: list_for_each(l, &capi_drivers) { driver = list_entry(l, struct capi_driver, list); if (strcmp(driver->name, "t1isa") == 0) break; } break; default: driver = NULL; break; } if (!driver) { printk(KERN_ERR "kcapi: driver not loaded.\n"); retval = -EIO; } else if (!driver->add_card) { printk(KERN_ERR "kcapi: driver has no add card function.\n"); retval = -EIO; } else retval = driver->add_card(driver, &cparams); mutex_unlock(&capi_drivers_lock); return retval; case AVMB1_LOAD: case AVMB1_LOAD_AND_CONFIG: if (cmd == AVMB1_LOAD) { if (copy_from_user(&ldef, data, sizeof(avmb1_loaddef))) return -EFAULT; ldef.t4config.len = 0; ldef.t4config.data = NULL; } else { if (copy_from_user(&ldef, data, sizeof(avmb1_loadandconfigdef))) return -EFAULT; } mutex_lock(&capi_controller_lock); ctr = get_capi_ctr_by_nr(ldef.contr); if (!ctr) { retval = -EINVAL; goto load_unlock_out; } if (ctr->load_firmware == NULL) { printk(KERN_DEBUG "kcapi: load: no load function\n"); retval = -ESRCH; goto load_unlock_out; } if (ldef.t4file.len <= 0) { printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); retval = -EINVAL; goto load_unlock_out; } if (ldef.t4file.data == NULL) { printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); retval = -EINVAL; goto load_unlock_out; } ldata.firmware.user = 1; ldata.firmware.data = ldef.t4file.data; ldata.firmware.len = ldef.t4file.len; ldata.configuration.user = 1; ldata.configuration.data = ldef.t4config.data; ldata.configuration.len = ldef.t4config.len; if (ctr->state != CAPI_CTR_DETECTED) { printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); retval = -EBUSY; goto load_unlock_out; } ctr->state = CAPI_CTR_LOADING; retval = ctr->load_firmware(ctr, &ldata); if (retval) { ctr->state = CAPI_CTR_DETECTED; goto load_unlock_out; } retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING); load_unlock_out: mutex_unlock(&capi_controller_lock); return retval; case AVMB1_RESETCARD: if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) return -EFAULT; retval = 0; mutex_lock(&capi_controller_lock); ctr = get_capi_ctr_by_nr(rdef.contr); if (!ctr) { retval = -ESRCH; goto reset_unlock_out; } if (ctr->state == CAPI_CTR_DETECTED) goto reset_unlock_out; if (ctr->reset_ctr == NULL) { printk(KERN_DEBUG "kcapi: reset: no reset function\n"); retval = -ESRCH; goto reset_unlock_out; } ctr->reset_ctr(ctr); retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED); reset_unlock_out: mutex_unlock(&capi_controller_lock); return retval; } return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)32843.04%211.76%
Andrew Morton25032.81%15.88%
Jan Kiszka12115.88%317.65%
Tilman Schmidt243.15%15.88%
Kai Germaschewski111.44%317.65%
Arnd Bergmann60.79%15.88%
Arnaldo Carvalho de Melo60.79%15.88%
Jesper Juhl60.79%15.88%
Al Viro40.52%211.76%
Dan Carpenter40.52%15.88%
Harvey Harrison20.26%15.88%
Total762100.00%17100.00%

#endif /** * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER * @cmd: command. * @data: parameter. * * Perform manufacturer specific command. * Return value: CAPI result code */
int capi20_manufacturer(unsigned long cmd, void __user *data) { struct capi_ctr *ctr; int retval; switch (cmd) { #ifdef AVMB1_COMPAT case AVMB1_LOAD: case AVMB1_LOAD_AND_CONFIG: case AVMB1_RESETCARD: case AVMB1_GET_CARDINFO: case AVMB1_REMOVECARD: return old_capi_manufacturer(cmd, data); #endif case KCAPI_CMD_TRACE: { kcapi_flagdef fdef; if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef))) return -EFAULT; mutex_lock(&capi_controller_lock); ctr = get_capi_ctr_by_nr(fdef.contr); if (ctr) { ctr->traceflag = fdef.flag; printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", ctr->cnr, ctr->traceflag); retval = 0; } else retval = -ESRCH; mutex_unlock(&capi_controller_lock); return retval; } case KCAPI_CMD_ADDCARD: { struct list_head *l; struct capi_driver *driver = NULL; capicardparams cparams; kcapi_carddef cdef; if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) return -EFAULT; cparams.port = cdef.port; cparams.irq = cdef.irq; cparams.membase = cdef.membase; cparams.cardnr = cdef.cardnr; cparams.cardtype = 0; cdef.driver[sizeof(cdef.driver) - 1] = 0; mutex_lock(&capi_drivers_lock); list_for_each(l, &capi_drivers) { driver = list_entry(l, struct capi_driver, list); if (strcmp(driver->name, cdef.driver) == 0) break; } if (driver == NULL) { printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", cdef.driver); retval = -ESRCH; } else if (!driver->add_card) { printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); retval = -EIO; } else retval = driver->add_card(driver, &cparams); mutex_unlock(&capi_drivers_lock); return retval; } default: printk(KERN_ERR "kcapi: manufacturer command %lu unknown.\n", cmd); break; } return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton18349.33%16.25%
Linus Torvalds (pre-git)11631.27%212.50%
Jan Kiszka5915.90%318.75%
Arnaldo Carvalho de Melo20.54%16.25%
Tilman Schmidt20.54%16.25%
Al Viro20.54%212.50%
Kai Germaschewski20.54%212.50%
Dan Carpenter20.54%16.25%
Robert P. J. Day10.27%16.25%
Karsten Keil10.27%16.25%
Harvey Harrison10.27%16.25%
Total371100.00%16100.00%

EXPORT_SYMBOL(capi20_manufacturer); /* ------------------------------------------------------------- */ /* -------- Init & Cleanup ------------------------------------- */ /* ------------------------------------------------------------- */ /* * init / exit functions */ static struct notifier_block capictr_nb = { .notifier_call = notify_handler, .priority = INT_MAX, };
static int __init kcapi_init(void) { int err; kcapi_wq = alloc_workqueue("kcapi", 0, 0); if (!kcapi_wq) return -ENOMEM; register_capictr_notifier(&capictr_nb); err = cdebug_init(); if (err) { unregister_capictr_notifier(&capictr_nb); destroy_workqueue(kcapi_wq); return err; } kcapi_proc_init(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Tejun Heo3753.62%114.29%
Linus Torvalds (pre-git)1318.84%228.57%
Karsten Keil913.04%114.29%
Jan Kiszka913.04%228.57%
Kai Germaschewski11.45%114.29%
Total69100.00%7100.00%


static void __exit kcapi_exit(void) { kcapi_proc_exit(); unregister_capictr_notifier(&capictr_nb); cdebug_exit(); destroy_workqueue(kcapi_wq); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1142.31%233.33%
Tejun Heo1038.46%116.67%
Karsten Keil311.54%116.67%
Kai Germaschewski13.85%116.67%
Andrew Morton13.85%116.67%
Total26100.00%6100.00%

module_init(kcapi_init); module_exit(kcapi_exit);

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)171235.49%56.85%
Jan Kiszka121625.21%810.96%
Andrew Morton75415.63%56.85%
Kai Germaschewski68214.14%1926.03%
Karsten Keil2344.85%45.48%
Tejun Heo661.37%22.74%
Tilman Schmidt390.81%45.48%
Dan Carpenter180.37%22.74%
Linus Torvalds130.27%22.74%
David Howells110.23%11.37%
Arnaldo Carvalho de Melo80.17%11.37%
Arjan van de Ven70.15%11.37%
Al Viro70.15%22.74%
Marcel Holtmann70.15%11.37%
Matthias Kaehlcke60.12%11.37%
Thomas Gleixner60.12%11.37%
Arnd Bergmann60.12%11.37%
Alexey Dobriyan60.12%22.74%
Jesper Juhl60.12%11.37%
Robert P. J. Day40.08%11.37%
Benjamin Collins40.08%11.37%
Harvey Harrison40.08%22.74%
Maximilian Attems30.06%11.37%
Christoph Hellwig20.04%22.74%
Ingo Molnar20.04%22.74%
Joe Perches10.02%11.37%
Total4824100.00%73100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.