mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-09 17:02:46 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
44
drivers/isdn/capi/Kconfig
Normal file
44
drivers/isdn/capi/Kconfig
Normal file
|
@ -0,0 +1,44 @@
|
|||
config CAPI_TRACE
|
||||
bool "CAPI trace support"
|
||||
default y
|
||||
help
|
||||
If you say Y here, the kernelcapi driver can make verbose traces
|
||||
of CAPI messages. This feature can be enabled/disabled via IOCTL for
|
||||
every controller (default disabled).
|
||||
This will increase the size of the kernelcapi module by 20 KB.
|
||||
If unsure, say Y.
|
||||
|
||||
config ISDN_CAPI_CAPI20
|
||||
tristate "CAPI2.0 /dev/capi20 support"
|
||||
help
|
||||
This option will provide the CAPI 2.0 interface to userspace
|
||||
applications via /dev/capi20. Applications should use the
|
||||
standardized libcapi20 to access this functionality. You should say
|
||||
Y/M here.
|
||||
|
||||
config ISDN_CAPI_MIDDLEWARE
|
||||
bool "CAPI2.0 Middleware support"
|
||||
depends on ISDN_CAPI_CAPI20 && TTY
|
||||
help
|
||||
This option will enhance the capabilities of the /dev/capi20
|
||||
interface. It will provide a means of moving a data connection,
|
||||
established via the usual /dev/capi20 interface to a special tty
|
||||
device. If you want to use pppd with pppdcapiplugin to dial up to
|
||||
your ISP, say Y here.
|
||||
|
||||
config ISDN_CAPI_CAPIDRV
|
||||
tristate "CAPI2.0 capidrv interface support"
|
||||
depends on ISDN_I4L
|
||||
help
|
||||
This option provides the glue code to hook up CAPI driven cards to
|
||||
the legacy isdn4linux link layer. If you have a card which is
|
||||
supported by a CAPI driver, but still want to use old features like
|
||||
ippp interfaces or ttyI emulation, say Y/M here.
|
||||
|
||||
config ISDN_CAPI_CAPIDRV_VERBOSE
|
||||
bool "Verbose reason code reporting"
|
||||
depends on ISDN_CAPI_CAPIDRV
|
||||
help
|
||||
If you say Y here, the capidrv interface will give verbose reasons
|
||||
for disconnecting. This will increase the size of the kernel by 7 KB.
|
||||
If unsure, say N.
|
14
drivers/isdn/capi/Makefile
Normal file
14
drivers/isdn/capi/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Makefile for the CAPI subsystem.
|
||||
|
||||
# Ordering constraints: kernelcapi.o first
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_ISDN_CAPI) += kernelcapi.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPI20) += capi.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPIDRV) += capidrv.o
|
||||
|
||||
# Multipart objects.
|
||||
|
||||
kernelcapi-y := kcapi.o capiutil.o capilib.o
|
||||
kernelcapi-$(CONFIG_PROC_FS) += kcapi_proc.o
|
1454
drivers/isdn/capi/capi.c
Normal file
1454
drivers/isdn/capi/capi.c
Normal file
File diff suppressed because it is too large
Load diff
2538
drivers/isdn/capi/capidrv.c
Normal file
2538
drivers/isdn/capi/capidrv.c
Normal file
File diff suppressed because it is too large
Load diff
140
drivers/isdn/capi/capidrv.h
Normal file
140
drivers/isdn/capi/capidrv.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* $Id: capidrv.h,v 1.2.8.2 2001/09/23 22:24:33 kai Exp $
|
||||
*
|
||||
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
|
||||
*
|
||||
* Copyright 1997 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CAPIDRV_H__
|
||||
#define __CAPIDRV_H__
|
||||
|
||||
/*
|
||||
* LISTEN state machine
|
||||
*/
|
||||
#define ST_LISTEN_NONE 0 /* L-0 */
|
||||
#define ST_LISTEN_WAIT_CONF 1 /* L-0.1 */
|
||||
#define ST_LISTEN_ACTIVE 2 /* L-1 */
|
||||
#define ST_LISTEN_ACTIVE_WAIT_CONF 3 /* L-1.1 */
|
||||
|
||||
|
||||
#define EV_LISTEN_REQ 1 /* L-0 -> L-0.1
|
||||
L-1 -> L-1.1 */
|
||||
#define EV_LISTEN_CONF_ERROR 2 /* L-0.1 -> L-0
|
||||
L-1.1 -> L-1 */
|
||||
#define EV_LISTEN_CONF_EMPTY 3 /* L-0.1 -> L-0
|
||||
L-1.1 -> L-0 */
|
||||
#define EV_LISTEN_CONF_OK 4 /* L-0.1 -> L-1
|
||||
L-1.1 -> L.1 */
|
||||
|
||||
/*
|
||||
* per plci state machine
|
||||
*/
|
||||
#define ST_PLCI_NONE 0 /* P-0 */
|
||||
#define ST_PLCI_OUTGOING 1 /* P-0.1 */
|
||||
#define ST_PLCI_ALLOCATED 2 /* P-1 */
|
||||
#define ST_PLCI_ACTIVE 3 /* P-ACT */
|
||||
#define ST_PLCI_INCOMING 4 /* P-2 */
|
||||
#define ST_PLCI_FACILITY_IND 5 /* P-3 */
|
||||
#define ST_PLCI_ACCEPTING 6 /* P-4 */
|
||||
#define ST_PLCI_DISCONNECTING 7 /* P-5 */
|
||||
#define ST_PLCI_DISCONNECTED 8 /* P-6 */
|
||||
#define ST_PLCI_RESUMEING 9 /* P-0.Res */
|
||||
#define ST_PLCI_RESUME 10 /* P-Res */
|
||||
#define ST_PLCI_HELD 11 /* P-HELD */
|
||||
|
||||
#define EV_PLCI_CONNECT_REQ 1 /* P-0 -> P-0.1
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_CONF_ERROR 2 /* P-0.1 -> P-0
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_CONF_OK 3 /* P-0.1 -> P-1
|
||||
*/
|
||||
#define EV_PLCI_FACILITY_IND_UP 4 /* P-0 -> P-1
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_IND 5 /* P-0 -> P-2
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_ACTIVE_IND 6 /* P-1 -> P-ACT
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_REJECT 7 /* P-2 -> P-5
|
||||
P-3 -> P-5
|
||||
*/
|
||||
#define EV_PLCI_DISCONNECT_REQ 8 /* P-1 -> P-5
|
||||
P-2 -> P-5
|
||||
P-3 -> P-5
|
||||
P-4 -> P-5
|
||||
P-ACT -> P-5
|
||||
P-Res -> P-5 (*)
|
||||
P-HELD -> P-5 (*)
|
||||
*/
|
||||
#define EV_PLCI_DISCONNECT_IND 9 /* P-1 -> P-6
|
||||
P-2 -> P-6
|
||||
P-3 -> P-6
|
||||
P-4 -> P-6
|
||||
P-5 -> P-6
|
||||
P-ACT -> P-6
|
||||
P-Res -> P-6 (*)
|
||||
P-HELD -> P-6 (*)
|
||||
*/
|
||||
#define EV_PLCI_FACILITY_IND_DOWN 10 /* P-0.1 -> P-5
|
||||
P-1 -> P-5
|
||||
P-ACT -> P-5
|
||||
P-2 -> P-5
|
||||
P-3 -> P-5
|
||||
P-4 -> P-5
|
||||
*/
|
||||
#define EV_PLCI_DISCONNECT_RESP 11 /* P-6 -> P-0
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_RESP 12 /* P-6 -> P-0
|
||||
*/
|
||||
|
||||
#define EV_PLCI_RESUME_REQ 13 /* P-0 -> P-0.Res
|
||||
*/
|
||||
#define EV_PLCI_RESUME_CONF_OK 14 /* P-0.Res -> P-Res
|
||||
*/
|
||||
#define EV_PLCI_RESUME_CONF_ERROR 15 /* P-0.Res -> P-0
|
||||
*/
|
||||
#define EV_PLCI_RESUME_IND 16 /* P-Res -> P-ACT
|
||||
*/
|
||||
#define EV_PLCI_HOLD_IND 17 /* P-ACT -> P-HELD
|
||||
*/
|
||||
#define EV_PLCI_RETRIEVE_IND 18 /* P-HELD -> P-ACT
|
||||
*/
|
||||
#define EV_PLCI_SUSPEND_IND 19 /* P-ACT -> P-5
|
||||
*/
|
||||
#define EV_PLCI_CD_IND 20 /* P-2 -> P-5
|
||||
*/
|
||||
|
||||
/*
|
||||
* per ncci state machine
|
||||
*/
|
||||
#define ST_NCCI_PREVIOUS -1
|
||||
#define ST_NCCI_NONE 0 /* N-0 */
|
||||
#define ST_NCCI_OUTGOING 1 /* N-0.1 */
|
||||
#define ST_NCCI_INCOMING 2 /* N-1 */
|
||||
#define ST_NCCI_ALLOCATED 3 /* N-2 */
|
||||
#define ST_NCCI_ACTIVE 4 /* N-ACT */
|
||||
#define ST_NCCI_RESETING 5 /* N-3 */
|
||||
#define ST_NCCI_DISCONNECTING 6 /* N-4 */
|
||||
#define ST_NCCI_DISCONNECTED 7 /* N-5 */
|
||||
|
||||
#define EV_NCCI_CONNECT_B3_REQ 1 /* N-0 -> N-0.1 */
|
||||
#define EV_NCCI_CONNECT_B3_IND 2 /* N-0 -> N.1 */
|
||||
#define EV_NCCI_CONNECT_B3_CONF_OK 3 /* N-0.1 -> N.2 */
|
||||
#define EV_NCCI_CONNECT_B3_CONF_ERROR 4 /* N-0.1 -> N.0 */
|
||||
#define EV_NCCI_CONNECT_B3_REJECT 5 /* N-1 -> N-4 */
|
||||
#define EV_NCCI_CONNECT_B3_RESP 6 /* N-1 -> N-2 */
|
||||
#define EV_NCCI_CONNECT_B3_ACTIVE_IND 7 /* N-2 -> N-ACT */
|
||||
#define EV_NCCI_RESET_B3_REQ 8 /* N-ACT -> N-3 */
|
||||
#define EV_NCCI_RESET_B3_IND 9 /* N-3 -> N-ACT */
|
||||
#define EV_NCCI_DISCONNECT_B3_IND 10 /* N-4 -> N.5 */
|
||||
#define EV_NCCI_DISCONNECT_B3_CONF_ERROR 11 /* N-4 -> previous */
|
||||
#define EV_NCCI_DISCONNECT_B3_REQ 12 /* N-1 -> N-4
|
||||
N-2 -> N-4
|
||||
N-3 -> N-4
|
||||
N-ACT -> N-4 */
|
||||
#define EV_NCCI_DISCONNECT_B3_RESP 13 /* N-5 -> N-0 */
|
||||
|
||||
#endif /* __CAPIDRV_H__ */
|
201
drivers/isdn/capi/capilib.c
Normal file
201
drivers/isdn/capi/capilib.c
Normal file
|
@ -0,0 +1,201 @@
|
|||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/isdn/capilli.h>
|
||||
|
||||
#define DBG(format, arg...) do { \
|
||||
printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \
|
||||
} while (0)
|
||||
|
||||
struct capilib_msgidqueue {
|
||||
struct capilib_msgidqueue *next;
|
||||
u16 msgid;
|
||||
};
|
||||
|
||||
struct capilib_ncci {
|
||||
struct list_head list;
|
||||
u16 applid;
|
||||
u32 ncci;
|
||||
u32 winsize;
|
||||
int nmsg;
|
||||
struct capilib_msgidqueue *msgidqueue;
|
||||
struct capilib_msgidqueue *msgidlast;
|
||||
struct capilib_msgidqueue *msgidfree;
|
||||
struct capilib_msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NCCI Handling
|
||||
|
||||
static inline void mq_init(struct capilib_ncci *np)
|
||||
{
|
||||
u_int i;
|
||||
np->msgidqueue = NULL;
|
||||
np->msgidlast = NULL;
|
||||
np->nmsg = 0;
|
||||
memset(np->msgidpool, 0, sizeof(np->msgidpool));
|
||||
np->msgidfree = &np->msgidpool[0];
|
||||
for (i = 1; i < np->winsize; i++) {
|
||||
np->msgidpool[i].next = np->msgidfree;
|
||||
np->msgidfree = &np->msgidpool[i];
|
||||
}
|
||||
}
|
||||
|
||||
static inline int mq_enqueue(struct capilib_ncci *np, u16 msgid)
|
||||
{
|
||||
struct capilib_msgidqueue *mq;
|
||||
if ((mq = np->msgidfree) == NULL)
|
||||
return 0;
|
||||
np->msgidfree = mq->next;
|
||||
mq->msgid = msgid;
|
||||
mq->next = NULL;
|
||||
if (np->msgidlast)
|
||||
np->msgidlast->next = mq;
|
||||
np->msgidlast = mq;
|
||||
if (!np->msgidqueue)
|
||||
np->msgidqueue = mq;
|
||||
np->nmsg++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int mq_dequeue(struct capilib_ncci *np, u16 msgid)
|
||||
{
|
||||
struct capilib_msgidqueue **pp;
|
||||
for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
|
||||
if ((*pp)->msgid == msgid) {
|
||||
struct capilib_msgidqueue *mq = *pp;
|
||||
*pp = mq->next;
|
||||
if (mq == np->msgidlast)
|
||||
np->msgidlast = NULL;
|
||||
mq->next = np->msgidfree;
|
||||
np->msgidfree = mq;
|
||||
np->nmsg--;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize)
|
||||
{
|
||||
struct capilib_ncci *np;
|
||||
|
||||
np = kmalloc(sizeof(*np), GFP_ATOMIC);
|
||||
if (!np) {
|
||||
printk(KERN_WARNING "capilib_new_ncci: no memory.\n");
|
||||
return;
|
||||
}
|
||||
if (winsize > CAPI_MAXDATAWINDOW) {
|
||||
printk(KERN_ERR "capi_new_ncci: winsize %d too big\n",
|
||||
winsize);
|
||||
winsize = CAPI_MAXDATAWINDOW;
|
||||
}
|
||||
np->applid = applid;
|
||||
np->ncci = ncci;
|
||||
np->winsize = winsize;
|
||||
mq_init(np);
|
||||
list_add_tail(&np->list, head);
|
||||
DBG("kcapi: appl %d ncci 0x%x up", applid, ncci);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_new_ncci);
|
||||
|
||||
void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci)
|
||||
{
|
||||
struct list_head *l;
|
||||
struct capilib_ncci *np;
|
||||
|
||||
list_for_each(l, head) {
|
||||
np = list_entry(l, struct capilib_ncci, list);
|
||||
if (np->applid != applid)
|
||||
continue;
|
||||
if (np->ncci != ncci)
|
||||
continue;
|
||||
printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", applid, ncci);
|
||||
list_del(&np->list);
|
||||
kfree(np);
|
||||
return;
|
||||
}
|
||||
printk(KERN_ERR "capilib_free_ncci: ncci 0x%x not found\n", ncci);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_free_ncci);
|
||||
|
||||
void capilib_release_appl(struct list_head *head, u16 applid)
|
||||
{
|
||||
struct list_head *l, *n;
|
||||
struct capilib_ncci *np;
|
||||
|
||||
list_for_each_safe(l, n, head) {
|
||||
np = list_entry(l, struct capilib_ncci, list);
|
||||
if (np->applid != applid)
|
||||
continue;
|
||||
printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", applid, np->ncci);
|
||||
list_del(&np->list);
|
||||
kfree(np);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_release_appl);
|
||||
|
||||
void capilib_release(struct list_head *head)
|
||||
{
|
||||
struct list_head *l, *n;
|
||||
struct capilib_ncci *np;
|
||||
|
||||
list_for_each_safe(l, n, head) {
|
||||
np = list_entry(l, struct capilib_ncci, list);
|
||||
printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", np->applid, np->ncci);
|
||||
list_del(&np->list);
|
||||
kfree(np);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_release);
|
||||
|
||||
u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid)
|
||||
{
|
||||
struct list_head *l;
|
||||
struct capilib_ncci *np;
|
||||
|
||||
list_for_each(l, head) {
|
||||
np = list_entry(l, struct capilib_ncci, list);
|
||||
if (np->applid != applid)
|
||||
continue;
|
||||
if (np->ncci != ncci)
|
||||
continue;
|
||||
|
||||
if (mq_enqueue(np, msgid) == 0)
|
||||
return CAPI_SENDQUEUEFULL;
|
||||
|
||||
return CAPI_NOERROR;
|
||||
}
|
||||
printk(KERN_ERR "capilib_data_b3_req: ncci 0x%x not found\n", ncci);
|
||||
return CAPI_NOERROR;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_data_b3_req);
|
||||
|
||||
void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid)
|
||||
{
|
||||
struct list_head *l;
|
||||
struct capilib_ncci *np;
|
||||
|
||||
list_for_each(l, head) {
|
||||
np = list_entry(l, struct capilib_ncci, list);
|
||||
if (np->applid != applid)
|
||||
continue;
|
||||
if (np->ncci != ncci)
|
||||
continue;
|
||||
|
||||
if (mq_dequeue(np, msgid) == 0) {
|
||||
printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",
|
||||
msgid, ncci);
|
||||
}
|
||||
return;
|
||||
}
|
||||
printk(KERN_ERR "capilib_data_b3_conf: ncci 0x%x not found\n", ncci);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_data_b3_conf);
|
900
drivers/isdn/capi/capiutil.c
Normal file
900
drivers/isdn/capi/capiutil.c
Normal file
|
@ -0,0 +1,900 @@
|
|||
/* $Id: capiutil.c,v 1.13.6.4 2001/09/23 22:24:33 kai Exp $
|
||||
*
|
||||
* CAPI 2.0 convert capi message to capi message struct
|
||||
*
|
||||
* From CAPI 2.0 Development Kit AVM 1995 (msg.c)
|
||||
* Rewritten for Linux 1996 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/isdn/capiutil.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* from CAPI2.0 DDK AVM Berlin GmbH */
|
||||
|
||||
typedef struct {
|
||||
int typ;
|
||||
size_t off;
|
||||
} _cdef;
|
||||
|
||||
#define _CBYTE 1
|
||||
#define _CWORD 2
|
||||
#define _CDWORD 3
|
||||
#define _CSTRUCT 4
|
||||
#define _CMSTRUCT 5
|
||||
#define _CEND 6
|
||||
|
||||
static _cdef cdef[] =
|
||||
{
|
||||
/*00 */
|
||||
{_CEND},
|
||||
/*01 */
|
||||
{_CEND},
|
||||
/*02 */
|
||||
{_CEND},
|
||||
/*03 */
|
||||
{_CDWORD, offsetof(_cmsg, adr.adrController)},
|
||||
/*04 */
|
||||
{_CMSTRUCT, offsetof(_cmsg, AdditionalInfo)},
|
||||
/*05 */
|
||||
{_CSTRUCT, offsetof(_cmsg, B1configuration)},
|
||||
/*06 */
|
||||
{_CWORD, offsetof(_cmsg, B1protocol)},
|
||||
/*07 */
|
||||
{_CSTRUCT, offsetof(_cmsg, B2configuration)},
|
||||
/*08 */
|
||||
{_CWORD, offsetof(_cmsg, B2protocol)},
|
||||
/*09 */
|
||||
{_CSTRUCT, offsetof(_cmsg, B3configuration)},
|
||||
/*0a */
|
||||
{_CWORD, offsetof(_cmsg, B3protocol)},
|
||||
/*0b */
|
||||
{_CSTRUCT, offsetof(_cmsg, BC)},
|
||||
/*0c */
|
||||
{_CSTRUCT, offsetof(_cmsg, BChannelinformation)},
|
||||
/*0d */
|
||||
{_CMSTRUCT, offsetof(_cmsg, BProtocol)},
|
||||
/*0e */
|
||||
{_CSTRUCT, offsetof(_cmsg, CalledPartyNumber)},
|
||||
/*0f */
|
||||
{_CSTRUCT, offsetof(_cmsg, CalledPartySubaddress)},
|
||||
/*10 */
|
||||
{_CSTRUCT, offsetof(_cmsg, CallingPartyNumber)},
|
||||
/*11 */
|
||||
{_CSTRUCT, offsetof(_cmsg, CallingPartySubaddress)},
|
||||
/*12 */
|
||||
{_CDWORD, offsetof(_cmsg, CIPmask)},
|
||||
/*13 */
|
||||
{_CDWORD, offsetof(_cmsg, CIPmask2)},
|
||||
/*14 */
|
||||
{_CWORD, offsetof(_cmsg, CIPValue)},
|
||||
/*15 */
|
||||
{_CDWORD, offsetof(_cmsg, Class)},
|
||||
/*16 */
|
||||
{_CSTRUCT, offsetof(_cmsg, ConnectedNumber)},
|
||||
/*17 */
|
||||
{_CSTRUCT, offsetof(_cmsg, ConnectedSubaddress)},
|
||||
/*18 */
|
||||
{_CDWORD, offsetof(_cmsg, Data)},
|
||||
/*19 */
|
||||
{_CWORD, offsetof(_cmsg, DataHandle)},
|
||||
/*1a */
|
||||
{_CWORD, offsetof(_cmsg, DataLength)},
|
||||
/*1b */
|
||||
{_CSTRUCT, offsetof(_cmsg, FacilityConfirmationParameter)},
|
||||
/*1c */
|
||||
{_CSTRUCT, offsetof(_cmsg, Facilitydataarray)},
|
||||
/*1d */
|
||||
{_CSTRUCT, offsetof(_cmsg, FacilityIndicationParameter)},
|
||||
/*1e */
|
||||
{_CSTRUCT, offsetof(_cmsg, FacilityRequestParameter)},
|
||||
/*1f */
|
||||
{_CWORD, offsetof(_cmsg, FacilitySelector)},
|
||||
/*20 */
|
||||
{_CWORD, offsetof(_cmsg, Flags)},
|
||||
/*21 */
|
||||
{_CDWORD, offsetof(_cmsg, Function)},
|
||||
/*22 */
|
||||
{_CSTRUCT, offsetof(_cmsg, HLC)},
|
||||
/*23 */
|
||||
{_CWORD, offsetof(_cmsg, Info)},
|
||||
/*24 */
|
||||
{_CSTRUCT, offsetof(_cmsg, InfoElement)},
|
||||
/*25 */
|
||||
{_CDWORD, offsetof(_cmsg, InfoMask)},
|
||||
/*26 */
|
||||
{_CWORD, offsetof(_cmsg, InfoNumber)},
|
||||
/*27 */
|
||||
{_CSTRUCT, offsetof(_cmsg, Keypadfacility)},
|
||||
/*28 */
|
||||
{_CSTRUCT, offsetof(_cmsg, LLC)},
|
||||
/*29 */
|
||||
{_CSTRUCT, offsetof(_cmsg, ManuData)},
|
||||
/*2a */
|
||||
{_CDWORD, offsetof(_cmsg, ManuID)},
|
||||
/*2b */
|
||||
{_CSTRUCT, offsetof(_cmsg, NCPI)},
|
||||
/*2c */
|
||||
{_CWORD, offsetof(_cmsg, Reason)},
|
||||
/*2d */
|
||||
{_CWORD, offsetof(_cmsg, Reason_B3)},
|
||||
/*2e */
|
||||
{_CWORD, offsetof(_cmsg, Reject)},
|
||||
/*2f */
|
||||
{_CSTRUCT, offsetof(_cmsg, Useruserdata)}
|
||||
};
|
||||
|
||||
static unsigned char *cpars[] =
|
||||
{
|
||||
/* ALERT_REQ */ [0x01] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",
|
||||
/* CONNECT_REQ */ [0x02] = "\x03\x14\x0e\x10\x0f\x11\x0d\x06\x08\x0a\x05\x07\x09\x01\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01",
|
||||
/* DISCONNECT_REQ */ [0x04] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",
|
||||
/* LISTEN_REQ */ [0x05] = "\x03\x25\x12\x13\x10\x11\x01",
|
||||
/* INFO_REQ */ [0x08] = "\x03\x0e\x04\x0c\x27\x2f\x1c\x01\x01",
|
||||
/* FACILITY_REQ */ [0x09] = "\x03\x1f\x1e\x01",
|
||||
/* SELECT_B_PROTOCOL_REQ */ [0x0a] = "\x03\x0d\x06\x08\x0a\x05\x07\x09\x01\x01",
|
||||
/* CONNECT_B3_REQ */ [0x0b] = "\x03\x2b\x01",
|
||||
/* DISCONNECT_B3_REQ */ [0x0d] = "\x03\x2b\x01",
|
||||
/* DATA_B3_REQ */ [0x0f] = "\x03\x18\x1a\x19\x20\x01",
|
||||
/* RESET_B3_REQ */ [0x10] = "\x03\x2b\x01",
|
||||
/* ALERT_CONF */ [0x13] = "\x03\x23\x01",
|
||||
/* CONNECT_CONF */ [0x14] = "\x03\x23\x01",
|
||||
/* DISCONNECT_CONF */ [0x16] = "\x03\x23\x01",
|
||||
/* LISTEN_CONF */ [0x17] = "\x03\x23\x01",
|
||||
/* MANUFACTURER_REQ */ [0x18] = "\x03\x2a\x15\x21\x29\x01",
|
||||
/* INFO_CONF */ [0x1a] = "\x03\x23\x01",
|
||||
/* FACILITY_CONF */ [0x1b] = "\x03\x23\x1f\x1b\x01",
|
||||
/* SELECT_B_PROTOCOL_CONF */ [0x1c] = "\x03\x23\x01",
|
||||
/* CONNECT_B3_CONF */ [0x1d] = "\x03\x23\x01",
|
||||
/* DISCONNECT_B3_CONF */ [0x1f] = "\x03\x23\x01",
|
||||
/* DATA_B3_CONF */ [0x21] = "\x03\x19\x23\x01",
|
||||
/* RESET_B3_CONF */ [0x22] = "\x03\x23\x01",
|
||||
/* CONNECT_IND */ [0x26] = "\x03\x14\x0e\x10\x0f\x11\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01",
|
||||
/* CONNECT_ACTIVE_IND */ [0x27] = "\x03\x16\x17\x28\x01",
|
||||
/* DISCONNECT_IND */ [0x28] = "\x03\x2c\x01",
|
||||
/* MANUFACTURER_CONF */ [0x2a] = "\x03\x2a\x15\x21\x29\x01",
|
||||
/* INFO_IND */ [0x2c] = "\x03\x26\x24\x01",
|
||||
/* FACILITY_IND */ [0x2d] = "\x03\x1f\x1d\x01",
|
||||
/* CONNECT_B3_IND */ [0x2f] = "\x03\x2b\x01",
|
||||
/* CONNECT_B3_ACTIVE_IND */ [0x30] = "\x03\x2b\x01",
|
||||
/* DISCONNECT_B3_IND */ [0x31] = "\x03\x2d\x2b\x01",
|
||||
/* DATA_B3_IND */ [0x33] = "\x03\x18\x1a\x19\x20\x01",
|
||||
/* RESET_B3_IND */ [0x34] = "\x03\x2b\x01",
|
||||
/* CONNECT_B3_T90_ACTIVE_IND */ [0x35] = "\x03\x2b\x01",
|
||||
/* CONNECT_RESP */ [0x38] = "\x03\x2e\x0d\x06\x08\x0a\x05\x07\x09\x01\x16\x17\x28\x04\x0c\x27\x2f\x1c\x01\x01",
|
||||
/* CONNECT_ACTIVE_RESP */ [0x39] = "\x03\x01",
|
||||
/* DISCONNECT_RESP */ [0x3a] = "\x03\x01",
|
||||
/* MANUFACTURER_IND */ [0x3c] = "\x03\x2a\x15\x21\x29\x01",
|
||||
/* INFO_RESP */ [0x3e] = "\x03\x01",
|
||||
/* FACILITY_RESP */ [0x3f] = "\x03\x1f\x01",
|
||||
/* CONNECT_B3_RESP */ [0x41] = "\x03\x2e\x2b\x01",
|
||||
/* CONNECT_B3_ACTIVE_RESP */ [0x42] = "\x03\x01",
|
||||
/* DISCONNECT_B3_RESP */ [0x43] = "\x03\x01",
|
||||
/* DATA_B3_RESP */ [0x45] = "\x03\x19\x01",
|
||||
/* RESET_B3_RESP */ [0x46] = "\x03\x01",
|
||||
/* CONNECT_B3_T90_ACTIVE_RESP */ [0x47] = "\x03\x01",
|
||||
/* MANUFACTURER_RESP */ [0x4e] = "\x03\x2a\x15\x21\x29\x01",
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------*/
|
||||
|
||||
#define byteTLcpy(x, y) *(u8 *)(x) = *(u8 *)(y);
|
||||
#define wordTLcpy(x, y) *(u16 *)(x) = *(u16 *)(y);
|
||||
#define dwordTLcpy(x, y) memcpy(x, y, 4);
|
||||
#define structTLcpy(x, y, l) memcpy(x, y, l)
|
||||
#define structTLcpyovl(x, y, l) memmove(x, y, l)
|
||||
|
||||
#define byteTRcpy(x, y) *(u8 *)(y) = *(u8 *)(x);
|
||||
#define wordTRcpy(x, y) *(u16 *)(y) = *(u16 *)(x);
|
||||
#define dwordTRcpy(x, y) memcpy(y, x, 4);
|
||||
#define structTRcpy(x, y, l) memcpy(y, x, l)
|
||||
#define structTRcpyovl(x, y, l) memmove(y, x, l)
|
||||
|
||||
/*-------------------------------------------------------*/
|
||||
static unsigned command_2_index(unsigned c, unsigned sc)
|
||||
{
|
||||
if (c & 0x80)
|
||||
c = 0x9 + (c & 0x0f);
|
||||
else if (c == 0x41)
|
||||
c = 0x9 + 0x1;
|
||||
if (c > 0x18)
|
||||
c = 0x00;
|
||||
return (sc & 3) * (0x9 + 0x9) + c;
|
||||
}
|
||||
|
||||
/**
|
||||
* capi_cmd2par() - find parameter string for CAPI 2.0 command/subcommand
|
||||
* @cmd: command number
|
||||
* @subcmd: subcommand number
|
||||
*
|
||||
* Return value: static string, NULL if command/subcommand unknown
|
||||
*/
|
||||
|
||||
static unsigned char *capi_cmd2par(u8 cmd, u8 subcmd)
|
||||
{
|
||||
return cpars[command_2_index(cmd, subcmd)];
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------*/
|
||||
#define TYP (cdef[cmsg->par[cmsg->p]].typ)
|
||||
#define OFF (((u8 *)cmsg) + cdef[cmsg->par[cmsg->p]].off)
|
||||
|
||||
static void jumpcstruct(_cmsg *cmsg)
|
||||
{
|
||||
unsigned layer;
|
||||
for (cmsg->p++, layer = 1; layer;) {
|
||||
/* $$$$$ assert (cmsg->p); */
|
||||
cmsg->p++;
|
||||
switch (TYP) {
|
||||
case _CMSTRUCT:
|
||||
layer++;
|
||||
break;
|
||||
case _CEND:
|
||||
layer--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------*/
|
||||
static void pars_2_message(_cmsg *cmsg)
|
||||
{
|
||||
|
||||
for (; TYP != _CEND; cmsg->p++) {
|
||||
switch (TYP) {
|
||||
case _CBYTE:
|
||||
byteTLcpy(cmsg->m + cmsg->l, OFF);
|
||||
cmsg->l++;
|
||||
break;
|
||||
case _CWORD:
|
||||
wordTLcpy(cmsg->m + cmsg->l, OFF);
|
||||
cmsg->l += 2;
|
||||
break;
|
||||
case _CDWORD:
|
||||
dwordTLcpy(cmsg->m + cmsg->l, OFF);
|
||||
cmsg->l += 4;
|
||||
break;
|
||||
case _CSTRUCT:
|
||||
if (*(u8 **) OFF == NULL) {
|
||||
*(cmsg->m + cmsg->l) = '\0';
|
||||
cmsg->l++;
|
||||
} else if (**(_cstruct *) OFF != 0xff) {
|
||||
structTLcpy(cmsg->m + cmsg->l, *(_cstruct *) OFF, 1 + **(_cstruct *) OFF);
|
||||
cmsg->l += 1 + **(_cstruct *) OFF;
|
||||
} else {
|
||||
_cstruct s = *(_cstruct *) OFF;
|
||||
structTLcpy(cmsg->m + cmsg->l, s, 3 + *(u16 *) (s + 1));
|
||||
cmsg->l += 3 + *(u16 *) (s + 1);
|
||||
}
|
||||
break;
|
||||
case _CMSTRUCT:
|
||||
/*----- Metastruktur 0 -----*/
|
||||
if (*(_cmstruct *) OFF == CAPI_DEFAULT) {
|
||||
*(cmsg->m + cmsg->l) = '\0';
|
||||
cmsg->l++;
|
||||
jumpcstruct(cmsg);
|
||||
}
|
||||
/*----- Metastruktur wird composed -----*/
|
||||
else {
|
||||
unsigned _l = cmsg->l;
|
||||
unsigned _ls;
|
||||
cmsg->l++;
|
||||
cmsg->p++;
|
||||
pars_2_message(cmsg);
|
||||
_ls = cmsg->l - _l - 1;
|
||||
if (_ls < 255)
|
||||
(cmsg->m + _l)[0] = (u8) _ls;
|
||||
else {
|
||||
structTLcpyovl(cmsg->m + _l + 3, cmsg->m + _l + 1, _ls);
|
||||
(cmsg->m + _l)[0] = 0xff;
|
||||
wordTLcpy(cmsg->m + _l + 1, &_ls);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* capi_cmsg2message() - assemble CAPI 2.0 message from _cmsg structure
|
||||
* @cmsg: _cmsg structure
|
||||
* @msg: buffer for assembled message
|
||||
*
|
||||
* Return value: 0 for success
|
||||
*/
|
||||
|
||||
unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg)
|
||||
{
|
||||
cmsg->m = msg;
|
||||
cmsg->l = 8;
|
||||
cmsg->p = 0;
|
||||
cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand);
|
||||
if (!cmsg->par)
|
||||
return 1; /* invalid command/subcommand */
|
||||
|
||||
pars_2_message(cmsg);
|
||||
|
||||
wordTLcpy(msg + 0, &cmsg->l);
|
||||
byteTLcpy(cmsg->m + 4, &cmsg->Command);
|
||||
byteTLcpy(cmsg->m + 5, &cmsg->Subcommand);
|
||||
wordTLcpy(cmsg->m + 2, &cmsg->ApplId);
|
||||
wordTLcpy(cmsg->m + 6, &cmsg->Messagenumber);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------*/
|
||||
static void message_2_pars(_cmsg *cmsg)
|
||||
{
|
||||
for (; TYP != _CEND; cmsg->p++) {
|
||||
|
||||
switch (TYP) {
|
||||
case _CBYTE:
|
||||
byteTRcpy(cmsg->m + cmsg->l, OFF);
|
||||
cmsg->l++;
|
||||
break;
|
||||
case _CWORD:
|
||||
wordTRcpy(cmsg->m + cmsg->l, OFF);
|
||||
cmsg->l += 2;
|
||||
break;
|
||||
case _CDWORD:
|
||||
dwordTRcpy(cmsg->m + cmsg->l, OFF);
|
||||
cmsg->l += 4;
|
||||
break;
|
||||
case _CSTRUCT:
|
||||
*(u8 **) OFF = cmsg->m + cmsg->l;
|
||||
|
||||
if (cmsg->m[cmsg->l] != 0xff)
|
||||
cmsg->l += 1 + cmsg->m[cmsg->l];
|
||||
else
|
||||
cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
|
||||
break;
|
||||
case _CMSTRUCT:
|
||||
/*----- Metastruktur 0 -----*/
|
||||
if (cmsg->m[cmsg->l] == '\0') {
|
||||
*(_cmstruct *) OFF = CAPI_DEFAULT;
|
||||
cmsg->l++;
|
||||
jumpcstruct(cmsg);
|
||||
} else {
|
||||
unsigned _l = cmsg->l;
|
||||
*(_cmstruct *) OFF = CAPI_COMPOSE;
|
||||
cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
|
||||
cmsg->p++;
|
||||
message_2_pars(cmsg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* capi_message2cmsg() - disassemble CAPI 2.0 message into _cmsg structure
|
||||
* @cmsg: _cmsg structure
|
||||
* @msg: buffer for assembled message
|
||||
*
|
||||
* Return value: 0 for success
|
||||
*/
|
||||
|
||||
unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg)
|
||||
{
|
||||
memset(cmsg, 0, sizeof(_cmsg));
|
||||
cmsg->m = msg;
|
||||
cmsg->l = 8;
|
||||
cmsg->p = 0;
|
||||
byteTRcpy(cmsg->m + 4, &cmsg->Command);
|
||||
byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
|
||||
cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand);
|
||||
if (!cmsg->par)
|
||||
return 1; /* invalid command/subcommand */
|
||||
|
||||
message_2_pars(cmsg);
|
||||
|
||||
wordTRcpy(msg + 0, &cmsg->l);
|
||||
wordTRcpy(cmsg->m + 2, &cmsg->ApplId);
|
||||
wordTRcpy(cmsg->m + 6, &cmsg->Messagenumber);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* capi_cmsg_header() - initialize header part of _cmsg structure
|
||||
* @cmsg: _cmsg structure
|
||||
* @_ApplId: ApplID field value
|
||||
* @_Command: Command field value
|
||||
* @_Subcommand: Subcommand field value
|
||||
* @_Messagenumber: Message Number field value
|
||||
* @_Controller: Controller/PLCI/NCCI field value
|
||||
*
|
||||
* Return value: 0 for success
|
||||
*/
|
||||
|
||||
unsigned capi_cmsg_header(_cmsg *cmsg, u16 _ApplId,
|
||||
u8 _Command, u8 _Subcommand,
|
||||
u16 _Messagenumber, u32 _Controller)
|
||||
{
|
||||
memset(cmsg, 0, sizeof(_cmsg));
|
||||
cmsg->ApplId = _ApplId;
|
||||
cmsg->Command = _Command;
|
||||
cmsg->Subcommand = _Subcommand;
|
||||
cmsg->Messagenumber = _Messagenumber;
|
||||
cmsg->adr.adrController = _Controller;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------*/
|
||||
|
||||
static char *mnames[] =
|
||||
{
|
||||
[0x01] = "ALERT_REQ",
|
||||
[0x02] = "CONNECT_REQ",
|
||||
[0x04] = "DISCONNECT_REQ",
|
||||
[0x05] = "LISTEN_REQ",
|
||||
[0x08] = "INFO_REQ",
|
||||
[0x09] = "FACILITY_REQ",
|
||||
[0x0a] = "SELECT_B_PROTOCOL_REQ",
|
||||
[0x0b] = "CONNECT_B3_REQ",
|
||||
[0x0d] = "DISCONNECT_B3_REQ",
|
||||
[0x0f] = "DATA_B3_REQ",
|
||||
[0x10] = "RESET_B3_REQ",
|
||||
[0x13] = "ALERT_CONF",
|
||||
[0x14] = "CONNECT_CONF",
|
||||
[0x16] = "DISCONNECT_CONF",
|
||||
[0x17] = "LISTEN_CONF",
|
||||
[0x18] = "MANUFACTURER_REQ",
|
||||
[0x1a] = "INFO_CONF",
|
||||
[0x1b] = "FACILITY_CONF",
|
||||
[0x1c] = "SELECT_B_PROTOCOL_CONF",
|
||||
[0x1d] = "CONNECT_B3_CONF",
|
||||
[0x1f] = "DISCONNECT_B3_CONF",
|
||||
[0x21] = "DATA_B3_CONF",
|
||||
[0x22] = "RESET_B3_CONF",
|
||||
[0x26] = "CONNECT_IND",
|
||||
[0x27] = "CONNECT_ACTIVE_IND",
|
||||
[0x28] = "DISCONNECT_IND",
|
||||
[0x2a] = "MANUFACTURER_CONF",
|
||||
[0x2c] = "INFO_IND",
|
||||
[0x2d] = "FACILITY_IND",
|
||||
[0x2f] = "CONNECT_B3_IND",
|
||||
[0x30] = "CONNECT_B3_ACTIVE_IND",
|
||||
[0x31] = "DISCONNECT_B3_IND",
|
||||
[0x33] = "DATA_B3_IND",
|
||||
[0x34] = "RESET_B3_IND",
|
||||
[0x35] = "CONNECT_B3_T90_ACTIVE_IND",
|
||||
[0x38] = "CONNECT_RESP",
|
||||
[0x39] = "CONNECT_ACTIVE_RESP",
|
||||
[0x3a] = "DISCONNECT_RESP",
|
||||
[0x3c] = "MANUFACTURER_IND",
|
||||
[0x3e] = "INFO_RESP",
|
||||
[0x3f] = "FACILITY_RESP",
|
||||
[0x41] = "CONNECT_B3_RESP",
|
||||
[0x42] = "CONNECT_B3_ACTIVE_RESP",
|
||||
[0x43] = "DISCONNECT_B3_RESP",
|
||||
[0x45] = "DATA_B3_RESP",
|
||||
[0x46] = "RESET_B3_RESP",
|
||||
[0x47] = "CONNECT_B3_T90_ACTIVE_RESP",
|
||||
[0x4e] = "MANUFACTURER_RESP"
|
||||
};
|
||||
|
||||
/**
|
||||
* capi_cmd2str() - convert CAPI 2.0 command/subcommand number to name
|
||||
* @cmd: command number
|
||||
* @subcmd: subcommand number
|
||||
*
|
||||
* Return value: static string
|
||||
*/
|
||||
|
||||
char *capi_cmd2str(u8 cmd, u8 subcmd)
|
||||
{
|
||||
char *result;
|
||||
|
||||
result = mnames[command_2_index(cmd, subcmd)];
|
||||
if (result == NULL)
|
||||
result = "INVALID_COMMAND";
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------*/
|
||||
|
||||
#ifdef CONFIG_CAPI_TRACE
|
||||
|
||||
/*-------------------------------------------------------*/
|
||||
|
||||
static char *pnames[] =
|
||||
{
|
||||
/*00 */ NULL,
|
||||
/*01 */ NULL,
|
||||
/*02 */ NULL,
|
||||
/*03 */ "Controller/PLCI/NCCI",
|
||||
/*04 */ "AdditionalInfo",
|
||||
/*05 */ "B1configuration",
|
||||
/*06 */ "B1protocol",
|
||||
/*07 */ "B2configuration",
|
||||
/*08 */ "B2protocol",
|
||||
/*09 */ "B3configuration",
|
||||
/*0a */ "B3protocol",
|
||||
/*0b */ "BC",
|
||||
/*0c */ "BChannelinformation",
|
||||
/*0d */ "BProtocol",
|
||||
/*0e */ "CalledPartyNumber",
|
||||
/*0f */ "CalledPartySubaddress",
|
||||
/*10 */ "CallingPartyNumber",
|
||||
/*11 */ "CallingPartySubaddress",
|
||||
/*12 */ "CIPmask",
|
||||
/*13 */ "CIPmask2",
|
||||
/*14 */ "CIPValue",
|
||||
/*15 */ "Class",
|
||||
/*16 */ "ConnectedNumber",
|
||||
/*17 */ "ConnectedSubaddress",
|
||||
/*18 */ "Data32",
|
||||
/*19 */ "DataHandle",
|
||||
/*1a */ "DataLength",
|
||||
/*1b */ "FacilityConfirmationParameter",
|
||||
/*1c */ "Facilitydataarray",
|
||||
/*1d */ "FacilityIndicationParameter",
|
||||
/*1e */ "FacilityRequestParameter",
|
||||
/*1f */ "FacilitySelector",
|
||||
/*20 */ "Flags",
|
||||
/*21 */ "Function",
|
||||
/*22 */ "HLC",
|
||||
/*23 */ "Info",
|
||||
/*24 */ "InfoElement",
|
||||
/*25 */ "InfoMask",
|
||||
/*26 */ "InfoNumber",
|
||||
/*27 */ "Keypadfacility",
|
||||
/*28 */ "LLC",
|
||||
/*29 */ "ManuData",
|
||||
/*2a */ "ManuID",
|
||||
/*2b */ "NCPI",
|
||||
/*2c */ "Reason",
|
||||
/*2d */ "Reason_B3",
|
||||
/*2e */ "Reject",
|
||||
/*2f */ "Useruserdata"
|
||||
};
|
||||
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/*-------------------------------------------------------*/
|
||||
static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt, ...)
|
||||
{
|
||||
va_list f;
|
||||
size_t n, r;
|
||||
|
||||
if (!cdb)
|
||||
return NULL;
|
||||
va_start(f, fmt);
|
||||
r = cdb->size - cdb->pos;
|
||||
n = vsnprintf(cdb->p, r, fmt, f);
|
||||
va_end(f);
|
||||
if (n >= r) {
|
||||
/* truncated, need bigger buffer */
|
||||
size_t ns = 2 * cdb->size;
|
||||
u_char *nb;
|
||||
|
||||
while ((ns - cdb->pos) <= n)
|
||||
ns *= 2;
|
||||
nb = kmalloc(ns, GFP_ATOMIC);
|
||||
if (!nb) {
|
||||
cdebbuf_free(cdb);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(nb, cdb->buf, cdb->pos);
|
||||
kfree(cdb->buf);
|
||||
nb[cdb->pos] = 0;
|
||||
cdb->buf = nb;
|
||||
cdb->p = cdb->buf + cdb->pos;
|
||||
cdb->size = ns;
|
||||
va_start(f, fmt);
|
||||
r = cdb->size - cdb->pos;
|
||||
n = vsnprintf(cdb->p, r, fmt, f);
|
||||
va_end(f);
|
||||
}
|
||||
cdb->p += n;
|
||||
cdb->pos += n;
|
||||
return cdb;
|
||||
}
|
||||
|
||||
static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 *m, unsigned len)
|
||||
{
|
||||
unsigned hex = 0;
|
||||
|
||||
if (!cdb)
|
||||
return NULL;
|
||||
for (; len; len--, m++)
|
||||
if (isalnum(*m) || *m == ' ') {
|
||||
if (hex)
|
||||
cdb = bufprint(cdb, ">");
|
||||
cdb = bufprint(cdb, "%c", *m);
|
||||
hex = 0;
|
||||
} else {
|
||||
if (!hex)
|
||||
cdb = bufprint(cdb, "<%02x", *m);
|
||||
else
|
||||
cdb = bufprint(cdb, " %02x", *m);
|
||||
hex = 1;
|
||||
}
|
||||
if (hex)
|
||||
cdb = bufprint(cdb, ">");
|
||||
return cdb;
|
||||
}
|
||||
|
||||
static _cdebbuf *printstruct(_cdebbuf *cdb, u8 *m)
|
||||
{
|
||||
unsigned len;
|
||||
|
||||
if (m[0] != 0xff) {
|
||||
len = m[0];
|
||||
m += 1;
|
||||
} else {
|
||||
len = ((u16 *) (m + 1))[0];
|
||||
m += 3;
|
||||
}
|
||||
cdb = printstructlen(cdb, m, len);
|
||||
return cdb;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------*/
|
||||
#define NAME (pnames[cmsg->par[cmsg->p]])
|
||||
|
||||
static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level)
|
||||
{
|
||||
if (!cmsg->par)
|
||||
return NULL; /* invalid command/subcommand */
|
||||
|
||||
for (; TYP != _CEND; cmsg->p++) {
|
||||
int slen = 29 + 3 - level;
|
||||
int i;
|
||||
|
||||
if (!cdb)
|
||||
return NULL;
|
||||
cdb = bufprint(cdb, " ");
|
||||
for (i = 0; i < level - 1; i++)
|
||||
cdb = bufprint(cdb, " ");
|
||||
|
||||
switch (TYP) {
|
||||
case _CBYTE:
|
||||
cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l));
|
||||
cmsg->l++;
|
||||
break;
|
||||
case _CWORD:
|
||||
cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l));
|
||||
cmsg->l += 2;
|
||||
break;
|
||||
case _CDWORD:
|
||||
cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l));
|
||||
cmsg->l += 4;
|
||||
break;
|
||||
case _CSTRUCT:
|
||||
cdb = bufprint(cdb, "%-*s = ", slen, NAME);
|
||||
if (cmsg->m[cmsg->l] == '\0')
|
||||
cdb = bufprint(cdb, "default");
|
||||
else
|
||||
cdb = printstruct(cdb, cmsg->m + cmsg->l);
|
||||
cdb = bufprint(cdb, "\n");
|
||||
if (cmsg->m[cmsg->l] != 0xff)
|
||||
cmsg->l += 1 + cmsg->m[cmsg->l];
|
||||
else
|
||||
cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
|
||||
|
||||
break;
|
||||
|
||||
case _CMSTRUCT:
|
||||
/*----- Metastruktur 0 -----*/
|
||||
if (cmsg->m[cmsg->l] == '\0') {
|
||||
cdb = bufprint(cdb, "%-*s = default\n", slen, NAME);
|
||||
cmsg->l++;
|
||||
jumpcstruct(cmsg);
|
||||
} else {
|
||||
char *name = NAME;
|
||||
unsigned _l = cmsg->l;
|
||||
cdb = bufprint(cdb, "%-*s\n", slen, name);
|
||||
cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
|
||||
cmsg->p++;
|
||||
cdb = protocol_message_2_pars(cdb, cmsg, level + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cdb;
|
||||
}
|
||||
/*-------------------------------------------------------*/
|
||||
|
||||
static _cdebbuf *g_debbuf;
|
||||
static u_long g_debbuf_lock;
|
||||
static _cmsg *g_cmsg;
|
||||
|
||||
static _cdebbuf *cdebbuf_alloc(void)
|
||||
{
|
||||
_cdebbuf *cdb;
|
||||
|
||||
if (likely(!test_and_set_bit(1, &g_debbuf_lock))) {
|
||||
cdb = g_debbuf;
|
||||
goto init;
|
||||
} else
|
||||
cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC);
|
||||
if (!cdb)
|
||||
return NULL;
|
||||
cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC);
|
||||
if (!cdb->buf) {
|
||||
kfree(cdb);
|
||||
return NULL;
|
||||
}
|
||||
cdb->size = CDEBUG_SIZE;
|
||||
init:
|
||||
cdb->buf[0] = 0;
|
||||
cdb->p = cdb->buf;
|
||||
cdb->pos = 0;
|
||||
return cdb;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdebbuf_free() - free CAPI debug buffer
|
||||
* @cdb: buffer to free
|
||||
*/
|
||||
|
||||
void cdebbuf_free(_cdebbuf *cdb)
|
||||
{
|
||||
if (likely(cdb == g_debbuf)) {
|
||||
test_and_clear_bit(1, &g_debbuf_lock);
|
||||
return;
|
||||
}
|
||||
if (likely(cdb))
|
||||
kfree(cdb->buf);
|
||||
kfree(cdb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* capi_message2str() - format CAPI 2.0 message for printing
|
||||
* @msg: CAPI 2.0 message
|
||||
*
|
||||
* Allocates a CAPI debug buffer and fills it with a printable representation
|
||||
* of the CAPI 2.0 message in @msg.
|
||||
* Return value: allocated debug buffer, NULL on error
|
||||
* The returned buffer should be freed by a call to cdebbuf_free() after use.
|
||||
*/
|
||||
|
||||
_cdebbuf *capi_message2str(u8 *msg)
|
||||
{
|
||||
_cdebbuf *cdb;
|
||||
_cmsg *cmsg;
|
||||
|
||||
cdb = cdebbuf_alloc();
|
||||
if (unlikely(!cdb))
|
||||
return NULL;
|
||||
if (likely(cdb == g_debbuf))
|
||||
cmsg = g_cmsg;
|
||||
else
|
||||
cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC);
|
||||
if (unlikely(!cmsg)) {
|
||||
cdebbuf_free(cdb);
|
||||
return NULL;
|
||||
}
|
||||
cmsg->m = msg;
|
||||
cmsg->l = 8;
|
||||
cmsg->p = 0;
|
||||
byteTRcpy(cmsg->m + 4, &cmsg->Command);
|
||||
byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
|
||||
cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand);
|
||||
|
||||
cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n",
|
||||
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
|
||||
((unsigned short *) msg)[1],
|
||||
((unsigned short *) msg)[3],
|
||||
((unsigned short *) msg)[0]);
|
||||
|
||||
cdb = protocol_message_2_pars(cdb, cmsg, 1);
|
||||
if (unlikely(cmsg != g_cmsg))
|
||||
kfree(cmsg);
|
||||
return cdb;
|
||||
}
|
||||
|
||||
/**
|
||||
* capi_cmsg2str() - format _cmsg structure for printing
|
||||
* @cmsg: _cmsg structure
|
||||
*
|
||||
* Allocates a CAPI debug buffer and fills it with a printable representation
|
||||
* of the CAPI 2.0 message stored in @cmsg by a previous call to
|
||||
* capi_cmsg2message() or capi_message2cmsg().
|
||||
* Return value: allocated debug buffer, NULL on error
|
||||
* The returned buffer should be freed by a call to cdebbuf_free() after use.
|
||||
*/
|
||||
|
||||
_cdebbuf *capi_cmsg2str(_cmsg *cmsg)
|
||||
{
|
||||
_cdebbuf *cdb;
|
||||
|
||||
if (!cmsg->m)
|
||||
return NULL; /* no message */
|
||||
cdb = cdebbuf_alloc();
|
||||
if (!cdb)
|
||||
return NULL;
|
||||
cmsg->l = 8;
|
||||
cmsg->p = 0;
|
||||
cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n",
|
||||
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
|
||||
((u16 *) cmsg->m)[1],
|
||||
((u16 *) cmsg->m)[3],
|
||||
((u16 *) cmsg->m)[0]);
|
||||
cdb = protocol_message_2_pars(cdb, cmsg, 1);
|
||||
return cdb;
|
||||
}
|
||||
|
||||
int __init cdebug_init(void)
|
||||
{
|
||||
g_cmsg = kmalloc(sizeof(_cmsg), GFP_KERNEL);
|
||||
if (!g_cmsg)
|
||||
return -ENOMEM;
|
||||
g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL);
|
||||
if (!g_debbuf) {
|
||||
kfree(g_cmsg);
|
||||
return -ENOMEM;
|
||||
}
|
||||
g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL);
|
||||
if (!g_debbuf->buf) {
|
||||
kfree(g_cmsg);
|
||||
kfree(g_debbuf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
g_debbuf->size = CDEBUG_GSIZE;
|
||||
g_debbuf->buf[0] = 0;
|
||||
g_debbuf->p = g_debbuf->buf;
|
||||
g_debbuf->pos = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit cdebug_exit(void)
|
||||
{
|
||||
if (g_debbuf)
|
||||
kfree(g_debbuf->buf);
|
||||
kfree(g_debbuf);
|
||||
kfree(g_cmsg);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_CAPI_TRACE */
|
||||
|
||||
static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0};
|
||||
|
||||
_cdebbuf *capi_message2str(u8 *msg)
|
||||
{
|
||||
return &g_debbuf;
|
||||
}
|
||||
|
||||
_cdebbuf *capi_cmsg2str(_cmsg *cmsg)
|
||||
{
|
||||
return &g_debbuf;
|
||||
}
|
||||
|
||||
void cdebbuf_free(_cdebbuf *cdb)
|
||||
{
|
||||
}
|
||||
|
||||
int __init cdebug_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit cdebug_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(cdebbuf_free);
|
||||
EXPORT_SYMBOL(capi_cmsg2message);
|
||||
EXPORT_SYMBOL(capi_message2cmsg);
|
||||
EXPORT_SYMBOL(capi_cmsg_header);
|
||||
EXPORT_SYMBOL(capi_cmd2str);
|
||||
EXPORT_SYMBOL(capi_cmsg2str);
|
||||
EXPORT_SYMBOL(capi_message2str);
|
1316
drivers/isdn/capi/kcapi.c
Normal file
1316
drivers/isdn/capi/kcapi.c
Normal file
File diff suppressed because it is too large
Load diff
51
drivers/isdn/capi/kcapi.h
Normal file
51
drivers/isdn/capi/kcapi.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/isdn/capilli.h>
|
||||
|
||||
#ifdef KCAPI_DEBUG
|
||||
#define DBG(format, arg...) do { \
|
||||
printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DBG(format, arg...) /* */
|
||||
#endif
|
||||
|
||||
enum {
|
||||
CAPI_CTR_DETACHED = 0,
|
||||
CAPI_CTR_DETECTED = 1,
|
||||
CAPI_CTR_LOADING = 2,
|
||||
CAPI_CTR_RUNNING = 3,
|
||||
};
|
||||
|
||||
extern struct list_head capi_drivers;
|
||||
extern struct mutex capi_drivers_lock;
|
||||
|
||||
extern struct capi_ctr *capi_controller[CAPI_MAXCONTR];
|
||||
extern struct mutex capi_controller_lock;
|
||||
|
||||
extern struct capi20_appl *capi_applications[CAPI_MAXAPPL];
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
void kcapi_proc_init(void);
|
||||
void kcapi_proc_exit(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline void kcapi_proc_init(void) { };
|
||||
static inline void kcapi_proc_exit(void) { };
|
||||
|
||||
#endif
|
322
drivers/isdn/capi/kcapi_proc.c
Normal file
322
drivers/isdn/capi/kcapi_proc.c
Normal file
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* Kernel CAPI 2.0 Module - /proc/capi handling
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "kcapi.h"
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
static char *state2str(unsigned short state)
|
||||
{
|
||||
switch (state) {
|
||||
case CAPI_CTR_DETECTED: return "detected";
|
||||
case CAPI_CTR_LOADING: return "loading";
|
||||
case CAPI_CTR_RUNNING: return "running";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
||||
// /proc/capi
|
||||
// ===========================================================================
|
||||
|
||||
// /proc/capi/controller:
|
||||
// cnr driver cardstate name driverinfo
|
||||
// /proc/capi/contrstats:
|
||||
// cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void *controller_start(struct seq_file *seq, loff_t *pos)
|
||||
__acquires(capi_controller_lock)
|
||||
{
|
||||
mutex_lock(&capi_controller_lock);
|
||||
|
||||
if (*pos < CAPI_MAXCONTR)
|
||||
return &capi_controller[*pos];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *controller_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||
{
|
||||
++*pos;
|
||||
if (*pos < CAPI_MAXCONTR)
|
||||
return &capi_controller[*pos];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void controller_stop(struct seq_file *seq, void *v)
|
||||
__releases(capi_controller_lock)
|
||||
{
|
||||
mutex_unlock(&capi_controller_lock);
|
||||
}
|
||||
|
||||
static int controller_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct capi_ctr *ctr = *(struct capi_ctr **) v;
|
||||
|
||||
if (!ctr)
|
||||
return 0;
|
||||
|
||||
seq_printf(seq, "%d %-10s %-8s %-16s %s\n",
|
||||
ctr->cnr, ctr->driver_name,
|
||||
state2str(ctr->state),
|
||||
ctr->name,
|
||||
ctr->procinfo ? ctr->procinfo(ctr) : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int contrstats_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct capi_ctr *ctr = *(struct capi_ctr **) v;
|
||||
|
||||
if (!ctr)
|
||||
return 0;
|
||||
|
||||
seq_printf(seq, "%d %lu %lu %lu %lu\n",
|
||||
ctr->cnr,
|
||||
ctr->nrecvctlpkt,
|
||||
ctr->nrecvdatapkt,
|
||||
ctr->nsentctlpkt,
|
||||
ctr->nsentdatapkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct seq_operations seq_controller_ops = {
|
||||
.start = controller_start,
|
||||
.next = controller_next,
|
||||
.stop = controller_stop,
|
||||
.show = controller_show,
|
||||
};
|
||||
|
||||
static const struct seq_operations seq_contrstats_ops = {
|
||||
.start = controller_start,
|
||||
.next = controller_next,
|
||||
.stop = controller_stop,
|
||||
.show = contrstats_show,
|
||||
};
|
||||
|
||||
static int seq_controller_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &seq_controller_ops);
|
||||
}
|
||||
|
||||
static int seq_contrstats_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &seq_contrstats_ops);
|
||||
}
|
||||
|
||||
static const struct file_operations proc_controller_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = seq_controller_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
static const struct file_operations proc_contrstats_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = seq_contrstats_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
// /proc/capi/applications:
|
||||
// applid l3cnt dblkcnt dblklen #ncci recvqueuelen
|
||||
// /proc/capi/applstats:
|
||||
// applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void *applications_start(struct seq_file *seq, loff_t *pos)
|
||||
__acquires(capi_controller_lock)
|
||||
{
|
||||
mutex_lock(&capi_controller_lock);
|
||||
|
||||
if (*pos < CAPI_MAXAPPL)
|
||||
return &capi_applications[*pos];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
applications_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||
{
|
||||
++*pos;
|
||||
if (*pos < CAPI_MAXAPPL)
|
||||
return &capi_applications[*pos];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void applications_stop(struct seq_file *seq, void *v)
|
||||
__releases(capi_controller_lock)
|
||||
{
|
||||
mutex_unlock(&capi_controller_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
applications_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct capi20_appl *ap = *(struct capi20_appl **) v;
|
||||
|
||||
if (!ap)
|
||||
return 0;
|
||||
|
||||
seq_printf(seq, "%u %d %d %d\n",
|
||||
ap->applid,
|
||||
ap->rparam.level3cnt,
|
||||
ap->rparam.datablkcnt,
|
||||
ap->rparam.datablklen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
applstats_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct capi20_appl *ap = *(struct capi20_appl **) v;
|
||||
|
||||
if (!ap)
|
||||
return 0;
|
||||
|
||||
seq_printf(seq, "%u %lu %lu %lu %lu\n",
|
||||
ap->applid,
|
||||
ap->nrecvctlpkt,
|
||||
ap->nrecvdatapkt,
|
||||
ap->nsentctlpkt,
|
||||
ap->nsentdatapkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct seq_operations seq_applications_ops = {
|
||||
.start = applications_start,
|
||||
.next = applications_next,
|
||||
.stop = applications_stop,
|
||||
.show = applications_show,
|
||||
};
|
||||
|
||||
static const struct seq_operations seq_applstats_ops = {
|
||||
.start = applications_start,
|
||||
.next = applications_next,
|
||||
.stop = applications_stop,
|
||||
.show = applstats_show,
|
||||
};
|
||||
|
||||
static int
|
||||
seq_applications_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &seq_applications_ops);
|
||||
}
|
||||
|
||||
static int
|
||||
seq_applstats_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &seq_applstats_ops);
|
||||
}
|
||||
|
||||
static const struct file_operations proc_applications_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = seq_applications_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
static const struct file_operations proc_applstats_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = seq_applstats_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void *capi_driver_start(struct seq_file *seq, loff_t *pos)
|
||||
__acquires(&capi_drivers_lock)
|
||||
{
|
||||
mutex_lock(&capi_drivers_lock);
|
||||
return seq_list_start(&capi_drivers, *pos);
|
||||
}
|
||||
|
||||
static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||
{
|
||||
return seq_list_next(v, &capi_drivers, pos);
|
||||
}
|
||||
|
||||
static void capi_driver_stop(struct seq_file *seq, void *v)
|
||||
__releases(&capi_drivers_lock)
|
||||
{
|
||||
mutex_unlock(&capi_drivers_lock);
|
||||
}
|
||||
|
||||
static int capi_driver_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct capi_driver *drv = list_entry(v, struct capi_driver, list);
|
||||
|
||||
seq_printf(seq, "%-32s %s\n", drv->name, drv->revision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct seq_operations seq_capi_driver_ops = {
|
||||
.start = capi_driver_start,
|
||||
.next = capi_driver_next,
|
||||
.stop = capi_driver_stop,
|
||||
.show = capi_driver_show,
|
||||
};
|
||||
|
||||
static int
|
||||
seq_capi_driver_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int err;
|
||||
err = seq_open(file, &seq_capi_driver_ops);
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct file_operations proc_driver_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = seq_capi_driver_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void __init
|
||||
kcapi_proc_init(void)
|
||||
{
|
||||
proc_mkdir("capi", NULL);
|
||||
proc_mkdir("capi/controllers", NULL);
|
||||
proc_create("capi/controller", 0, NULL, &proc_controller_ops);
|
||||
proc_create("capi/contrstats", 0, NULL, &proc_contrstats_ops);
|
||||
proc_create("capi/applications", 0, NULL, &proc_applications_ops);
|
||||
proc_create("capi/applstats", 0, NULL, &proc_applstats_ops);
|
||||
proc_create("capi/driver", 0, NULL, &proc_driver_ops);
|
||||
}
|
||||
|
||||
void __exit
|
||||
kcapi_proc_exit(void)
|
||||
{
|
||||
remove_proc_entry("capi/driver", NULL);
|
||||
remove_proc_entry("capi/controller", NULL);
|
||||
remove_proc_entry("capi/contrstats", NULL);
|
||||
remove_proc_entry("capi/applications", NULL);
|
||||
remove_proc_entry("capi/applstats", NULL);
|
||||
remove_proc_entry("capi/controllers", NULL);
|
||||
remove_proc_entry("capi", NULL);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue