Docbook revised.
This commit is contained in:
parent
abff2ffe45
commit
e749b19cdd
|
@ -21,8 +21,9 @@
|
|||
|
||||
<revhistory>
|
||||
<revision>
|
||||
<revnumber>$Revision$</revnumber>
|
||||
<date>$Date$</date>
|
||||
<revnumber></revnumber>
|
||||
<date></date>
|
||||
<revremark>Working Draft</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
|
@ -42,10 +43,9 @@
|
|||
</para>
|
||||
|
||||
<para>
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -61,43 +61,44 @@
|
|||
<title>Introduction</title>
|
||||
|
||||
<para>
|
||||
<acronym>CAPI</> (COMMON-ISDN-API) is a message oriented and event
|
||||
driven programming interface used by applications to access
|
||||
<acronym>ISDN</> hardware equipment in a standardized and
|
||||
straightforward way. Publisher of the <acronym>CAPI</> standard is the
|
||||
<ulink url="http://www.capi.org">CAPI-Association</ulink>, a non-profit
|
||||
<acronym>CAPI</> (COMMON-ISDN-API) is a message oriented and event driven
|
||||
programming interface, used by applications to access <acronym>ISDN</>
|
||||
hardware equipment in a standardized and straightforward way. Publisher
|
||||
of the <acronym>CAPI</> standard is the <ulink
|
||||
url="http://www.capi.org">CAPI-Association</ulink>, a non-profit
|
||||
international consortium of hardware and software manufactures and
|
||||
telecommunications institutions. The <acronym>CAPI</> standard is
|
||||
freely available for download on their website.
|
||||
telecommunications institutions; the <acronym>CAPI</> standard is freely
|
||||
available for download on their website.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <acronym>CAPI</> standard defines a set of messages,
|
||||
protocols, and operations. While the messages and protocols are
|
||||
interoperable, the interface to the operations is specific to
|
||||
each supported operating-system. For Linux, the standard
|
||||
defines <acronym>CAPI</> interfaces for user- and kernel-space.
|
||||
The <acronym>CAPI</> standard defines a set of messages, protocols, and
|
||||
operations. While the messages and protocols are interoperable, the
|
||||
interface to the operations is specific to each supported
|
||||
operating system. For Linux, the standard defines <acronym>CAPI</>
|
||||
interfaces for user and kernel space.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<ulink url="http://www.capi4linux.org/ngc"><emphasis>Next
|
||||
Generation CAPI</emphasis></ulink> (<acronym>NGC</>) is an
|
||||
<emphasis>experimental</emphasis> implementation of the
|
||||
<acronym>CAPI 2.0</> standard, and it started as a fork of <ulink
|
||||
url="http://www.isdn4linux.org">CAPI4Linux</ulink>.
|
||||
<ulink url="http://www.capi4linux.org/ngc"><emphasis>Next Generation
|
||||
CAPI</emphasis></ulink> (<acronym>NGC</>) is an
|
||||
<emphasis>experimental</emphasis> implementation of the <acronym>CAPI</>
|
||||
2.0 standard and derived from <ulink
|
||||
url="http://www.capi4linux.org">CAPI4Linux</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The heart of the <acronym>NGC</> subsystem is the
|
||||
<emphasis>capicore</emphasis> and, as such, it is crucial to the
|
||||
performance and the stability of the whole subsystem. Basically, the
|
||||
<emphasis>capicore</emphasis> provides an infrastructure for the
|
||||
communication between applications and device-drivers. Applications are
|
||||
interfaced with the <emphasis>capicore</emphasis> via <acronym>CAPI</>,
|
||||
and device-drivers via an interface proprietary to Linux. This white
|
||||
paper is related to these interfaces, and it is assumed that the reader
|
||||
is familiar with the basic concepts and terms of the <acronym>CAPI</>
|
||||
standard and with Linux kernel programming in general.
|
||||
The heart of the <acronym>NGC</> subsystem is the capicore and, as such,
|
||||
it is crucial to the performance and the stability of the whole
|
||||
subsystem. Basically, the capicore provides an infrastructure for the
|
||||
communication between applications and device drivers. Applications are
|
||||
interfaced with the capicore via <acronym>CAPI</>, and device drivers via
|
||||
a custom made interface proprietary to Linux. This white paper is
|
||||
concerned with these interfaces, and describes them from the viewpoint of
|
||||
a device driver and an application developer, respectively. Further, it
|
||||
is assumed that the reader is familiar with the basic concepts and terms
|
||||
of the <acronym>CAPI</> standard and with Linux kernel programming in
|
||||
general.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
|
@ -105,9 +106,9 @@
|
|||
<title>Structures and Data Types</title>
|
||||
|
||||
<para>
|
||||
The <emphasis>capicore</emphasis> provides a set of common structures
|
||||
and data types, forming the basis of communication between the various
|
||||
layers of the <acronym>CAPI</> subsystem.
|
||||
The capicore provides a common set of structures and data types forming
|
||||
the basis of communication between the various layers of the
|
||||
<acronym>NGC</> subsystem.
|
||||
</para>
|
||||
|
||||
!Iinclude/linux/isdn/capinfo.h
|
||||
|
@ -120,64 +121,64 @@
|
|||
<title>Device Driver Interface</title>
|
||||
|
||||
<para>
|
||||
Device-drivers and applications communicate together via the
|
||||
<emphasis>capicore</emphasis> in an asynchronous way by exchanging
|
||||
messages according to the <acronym>CAPI</> standard. While the
|
||||
implementation of a device-driver might be rather complex internally,
|
||||
the interface with the <emphasis>capicore</emphasis> is simple. The
|
||||
declarations to this interface can be found in <filename
|
||||
class="headerfile">linux/isdn/capidevice.h</filename>.
|
||||
Device drivers and applications communicate together, via the capicore,
|
||||
in an asynchronous way by exchanging messages according to the
|
||||
<acronym>CAPI</> standard. While the implementation of a device driver
|
||||
might be rather complex internally, the interface with the capicore is
|
||||
pretty simple. The declarations to this interface can be found in
|
||||
<filename class="headerfile">linux/isdn/capidevice.h</filename>.
|
||||
</para>
|
||||
|
||||
<sect1>
|
||||
<title>Overview</title>
|
||||
|
||||
<para>
|
||||
Devices are represented to the <emphasis>capicore</emphasis> by
|
||||
objects of the generic <structname>capi_device</structname> structure.
|
||||
This structure forms the basis of communication between the
|
||||
<emphasis>capicore</emphasis> and device-drivers. Devices are
|
||||
reference counted objects and need to be dynamically allocated by the
|
||||
device-driver via the function <function>capi_device_alloc</function>.
|
||||
When the device-driver is done with the device (i.e.: after removing
|
||||
the device from the <emphasis>capicore</emphasis>), it should drop its
|
||||
reference to it via the function <function>capi_device_put</function>.
|
||||
Devices are represented to the capicore by objects of the generic
|
||||
<structname>capi_device</structname> structure. This structure forms
|
||||
the basis of communication between the capicore and device drivers.
|
||||
Devices are reference counted objects and need to be dynamically
|
||||
allocated by the device driver via the function
|
||||
<function>capi_device_alloc</function>. Destroying a device is
|
||||
done by releasing all references to it via the function
|
||||
<function>capi_device_put</function>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once a generic <structname>capi_device</structname> object is
|
||||
initialized, the device-driver can register it with the
|
||||
<emphasis>capicore</emphasis> via the function
|
||||
<function>capi_device_register</function>. Removing the device from
|
||||
the <emphasis>capicore</emphasis> is done via the function
|
||||
<function>capi_device_unregister</function>.
|
||||
initialized, the device driver can register it with the capicore via
|
||||
the function <function>capi_device_register</function>. Removing the
|
||||
device from the capicore is done via the function
|
||||
<function>capi_device_unregister</function>; subsequently, the
|
||||
device driver can release the device via the function
|
||||
<function>capi_device_put</function>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The device-driver has to provide three functions for calling by the
|
||||
<emphasis>capicore</emphasis> via the
|
||||
<structname>capi_driver</structname> structure. This enables the
|
||||
<emphasis>capicore</emphasis> to register and remove applications with
|
||||
devices, and transfering messages to them.
|
||||
The device driver has to provide three functions for calling by the
|
||||
capicore via the <structname>capi_driver</structname> structure,
|
||||
enabling the registration and removal of applications with the device
|
||||
driver's devices and the transfer of messages to them.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Each application owns a message queue by which devices are
|
||||
transferring messages to the application. Adding messages to the
|
||||
application queue is done via the function
|
||||
<function>capi_appl_enqueue_message</function>, and informing the
|
||||
application about new messages via the function
|
||||
<function>capi_appl_signal</function>. If the device-driver
|
||||
encounters an error concerning the message exchange, it should inform
|
||||
the corresponding application about this event via the function
|
||||
<function>capi_appl_signal_error</function>.
|
||||
Each application owns a message queue by which devices are transferring
|
||||
messages to the application. Adding messages to the application queue
|
||||
is done via the function
|
||||
<function>capi_appl_enqueue_message</function>. Upon that, the device
|
||||
driver should <emphasis>wakeup</emphasis> the application via the
|
||||
function <function>capi_appl_signal</function>. If the device driver
|
||||
encounters an error related to a message (i.e., in the context of an
|
||||
application), it should inform the concerned application about that
|
||||
condition via the function <function>capi_appl_signal_error</function>,
|
||||
causing the application to release.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Besides that, since <acronym>CAPI</> devices are <emphasis>class
|
||||
devices</emphasis>, they can easily export own attributes to the
|
||||
<emphasis>sysfs</emphasis>. See <filename
|
||||
class="headerfile">linux/device.h</filename> for more information.
|
||||
devices</emphasis>, they can easily export own attributes to the sysfs,
|
||||
enabling the device driver to offer device specific features to the
|
||||
user. See <filename class="headerfile">linux/device.h</filename> for
|
||||
more information.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
@ -193,19 +194,19 @@
|
|||
<title>Application Interface</title>
|
||||
|
||||
<para>
|
||||
Applications and device-drivers communicate together via the
|
||||
<emphasis>capicore</emphasis> in an asynchronous way by exchanging
|
||||
messages according to the <acronym>CAPI</> standard. While the
|
||||
implementation of an application might be rather complex internally, the
|
||||
interface with the <emphasis>capicore</emphasis> is simple.
|
||||
Applications and device drivers communicate together, via the capicore,
|
||||
in an asynchronous way by exchanging messages according to the
|
||||
<acronym>CAPI</> standard. While the implementation of an application
|
||||
might be rather complex internally, the interface with the capicore is
|
||||
pretty simple.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For Linux, the <acronym>CAPI</> standard defines interfaces for user-
|
||||
and kernel-space applications. Unfortunately, the specification to the
|
||||
kernel-space <acronym>CAPI</> is too unspecific. To give developers the
|
||||
required backing in writing safe kernel-space applications, the
|
||||
<emphasis>capicore</emphasis> introduces an alternative interface which
|
||||
For Linux, the <acronym>CAPI</> standard defines <acronym>CAPI</>
|
||||
interfaces for user and kernel space applications. Unfortunately, the
|
||||
specification to the kernel space <acronym>CAPI</> is too unspecific. To
|
||||
give developers the required backing in writing safe kernel space
|
||||
applications, the capicore introduces an alternative interface which
|
||||
we're going to describe here in detail. The declarations to this
|
||||
interface can be found in <filename
|
||||
class="headerfile">linux/isdn/capiappl.h</filename>.
|
||||
|
@ -215,21 +216,23 @@
|
|||
<title>Overview</title>
|
||||
|
||||
<para>
|
||||
Applications are represented to the <emphasis>capicore</emphasis> by
|
||||
objects of the generic <structname>capi_appl</structname> structure.
|
||||
This structure forms the basis of communication between the
|
||||
<emphasis>capicore</emphasis> and applications. Once a generic
|
||||
<structname>capi_appl</structname> object is initialized, the
|
||||
application can register it with the <emphasis>capicore</emphasis> via
|
||||
the function <function>capi_register</function>. Removing
|
||||
applications from the <emphasis>capicore</emphasis> is done via the
|
||||
function <function>capi_release</function>.
|
||||
Applications are represented to the capicore by objects of the generic
|
||||
<structname>capi_appl</structname> structure. This structure forms the
|
||||
basis of communication between the capicore and applications.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Applications need to register a signal-handler via the function
|
||||
<function>capi_set_signal</function>. The signal-handler serves as a
|
||||
notification mechanism for asynchronous events such as:
|
||||
Once a generic <structname>capi_appl</structname> object is
|
||||
initialized, the application can register it with the capicore via the
|
||||
function <function>capi_register</function>. Removing an application
|
||||
from the capicore is done via the function
|
||||
<function>capi_release</function>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Applications need to install a signal handler via the function
|
||||
<function>capi_set_signal</function>. The signal handler serves as a
|
||||
notification mechanism for asynchronous events, such as:
|
||||
|
||||
<itemizedlist mark=opencircle>
|
||||
<listitem>
|
||||
|
@ -239,19 +242,40 @@
|
|||
<para>the clearance of queue-full/busy conditions</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>occurred message exchange errors</para>
|
||||
<para>errors</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
The signal-handler is not meant to be a
|
||||
<emphasis>workhorse</emphasis>, but a mechanism for waking-up and
|
||||
Note that a signal handler is not meant to be a
|
||||
<emphasis>workhorse</emphasis>, but just a mechanism for waking up and
|
||||
scheduling applications.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Applications transfer messages via the function
|
||||
<function>capi_put_message</function>, and fetch them via the function
|
||||
<function>capi_get_message</function>.
|
||||
<function>capi_get_message</function>. They can put back messages via
|
||||
the function <function>capi_unget_message</function>, and check for
|
||||
pending messages via the function
|
||||
<function>capi_peek_message</function>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Applications can retrieve informations from <acronym>CAPI</> devices
|
||||
via the functions: <function>capi_get_manufacturer</function>,
|
||||
<function>capi_get_serial_number</function>,
|
||||
<function>capi_get_version</function>,
|
||||
<function>capi_get_profile</function>, and
|
||||
<function>capi_get_product</function>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Since <acronym>CAPI</> devices are <emphasis>class devices</emphasis>,
|
||||
applications can install a <emphasis>class interface</emphasis> with
|
||||
the Linux device driver core to get informed when <acronym>CAPI</>
|
||||
devices are being registered and removed with the capicore. See
|
||||
<filename class="headerfile">linux/device.h</filename> for more
|
||||
information.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
|
|
@ -40,19 +40,20 @@ atomic_t nr_capi_devs = ATOMIC_INIT(0);
|
|||
|
||||
|
||||
/**
|
||||
* capi_device_alloc - allocate a device structure
|
||||
* capi_device_alloc - allocate a device control structure
|
||||
*
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* Allocate a device structure and initialize the reference counter
|
||||
* to one.
|
||||
* Allocate a new device control structure and initialize its reference
|
||||
* counter to one.
|
||||
*
|
||||
* Upon successful allocation, the pointer to the new device structure
|
||||
* is returned. Otherwise, NULL is returned.
|
||||
* Upon successful allocation, a pointer to the new device control
|
||||
* structure is returned. Otherwise, NULL is returned.
|
||||
*
|
||||
* Note: The device structure must not be freed by simply calling
|
||||
* kfree(), but by a call to capi_device_put(). This will cause the
|
||||
* device structure to be freed if the reference counter reaches zero.
|
||||
* Note: The device control structure must not be freed by simply calling
|
||||
* kfree(), but by a call to capi_device_put(), which will cause the
|
||||
* device control structure to be freed when the reference counter reaches
|
||||
* zero.
|
||||
*/
|
||||
struct capi_device*
|
||||
capi_device_alloc(void)
|
||||
|
@ -155,10 +156,12 @@ unregister_capi_device(struct capi_device* dev)
|
|||
*
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* The device is assigned a unique device number, and all applications
|
||||
* will be registered with the device in turn. If the device fails to
|
||||
* register an application, the device is marked as erroneous for that
|
||||
* application.
|
||||
* @dev is assigned a unique device number, and all applications are
|
||||
* registered with @dev in turn. If the device driver fails to register
|
||||
* an application with @dev, @dev is marked as erroneous on that
|
||||
* application. Finally, @dev is registered with the sysfs, which in
|
||||
* turn could result in applications issuing messages, from installed
|
||||
* class interfaces, to @dev.
|
||||
*
|
||||
* Upon successful registration, 0 is returned. Otherwise, a negative
|
||||
* error code is returned.
|
||||
|
@ -197,16 +200,20 @@ capi_device_register(struct capi_device* dev)
|
|||
*
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* The device-driver must ensure that by the time it is calling this
|
||||
* function for @dev, no thread will be executing in a call to any
|
||||
* of the functions capi_appl_enqueue_message(), capi_appl_signal(),
|
||||
* or capi_appl_signal_error() in the name of @dev.
|
||||
* The device driver must ensure that by the time it is calling this
|
||||
* function for @dev, no thread is and will be executing, in the context
|
||||
* of @dev, in a call to any of these functions capi_appl_signal_error(),
|
||||
* capi_appl_enqueue_message(), or capi_appl_signal().
|
||||
*
|
||||
* Furthermore, the capicore ensures that by the time this function
|
||||
* returns for @dev, no thread will be executing in a call from the
|
||||
* capicore to that device-driver's device operations for @dev.
|
||||
* Furthermore, the capicore ensures that by the time the call to this
|
||||
* function returns for @dev, no thread is and will be executing in a call
|
||||
* from the capicore to any of @dev's device driver operations for @dev.
|
||||
*
|
||||
* capi_device_put() should be called afterwards for @dev.
|
||||
* By the time the device driver calls this function, applications could
|
||||
* be in a passive state (e.g., listen state L-1) waiting for events from
|
||||
* CAPI. The device driver should leave those applications as-is, even if
|
||||
* they would wait forever; it is the responsibility of the user to deal
|
||||
* with such situations.
|
||||
*/
|
||||
void
|
||||
capi_device_unregister(struct capi_device* dev)
|
||||
|
@ -264,10 +271,9 @@ bind_capi_appl(struct capi_appl* appl)
|
|||
*
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* The application is assigned a unique application number, and is
|
||||
* registered with each device in turn. If a device fails to register
|
||||
* the application, the device is marked as erroneous for that
|
||||
* application.
|
||||
* @appl is assigned a unique application number, and is registered with
|
||||
* each device in turn. If a device fails to register @appl, that device
|
||||
* is marked as erroneous on @appl.
|
||||
*
|
||||
* Upon successful registration, %CAPINFO_0X10_NOERR is returned.
|
||||
* Otherwise, a value indicting an error is returned.
|
||||
|
@ -309,18 +315,17 @@ capi_device_listed(struct capi_device* dev)
|
|||
*
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* The @appl is removed from each device registered with.
|
||||
*
|
||||
* The application must ensure that by the time it is calling this
|
||||
* function for @appl, no thread will be executing in a call from the
|
||||
* application to the function capi_put_message() for @appl.
|
||||
* function for @appl, no thread is and will be executing in a call to
|
||||
* any of these functions capi_put_message(), capi_get_message(),
|
||||
* capi_unget_message(), or capi_peek_message() for @appl.
|
||||
*
|
||||
* Furthermore, the capicore ensures that by the time this function
|
||||
* returns for @appl, no thread will be executing in a call from the
|
||||
* capicore to that application's signal-handler.
|
||||
* Furthermore, the capicore ensures that by the time a call to this
|
||||
* function returns for @appl, no thread is and will be executing in a
|
||||
* call from the capicore to the signal handler installed with @appl.
|
||||
*
|
||||
* Upon successful removal, %CAPINFO_0X11_NOERR is returned. Otherwise,
|
||||
* an error is returned.
|
||||
* a value indicating an error is returned.
|
||||
*/
|
||||
capinfo_0x11_t
|
||||
capi_release(struct capi_appl* appl)
|
||||
|
@ -357,19 +362,22 @@ capi_release(struct capi_appl* appl)
|
|||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* In the case of a data transfer message (DATA_B3_REQ), the data must be
|
||||
* appended to the message (this is contrary to the CAPI standard which
|
||||
* intends a shared buffer scheme) and the Data field will be ignored.
|
||||
*
|
||||
* %CAPINFO_0X11_QUEUEFULL or %CAPINFO_0X11_BUSY is returned if the
|
||||
* message could not be accepted, but this does not imply that messages
|
||||
* cannot be accepted directed to another device, PLCI or NCCI. This is
|
||||
* a temporary condition and the application should retry sometime later
|
||||
* after being signaled. Care must be taken by the application to
|
||||
* implement the retransmit logic in race-free manner.
|
||||
* %CAPINFO_0X11_QUEUEFULL or %CAPINFO_0X11_BUSY is returned if @msg
|
||||
* could not be accepted, but this does not imply that messages cannot be
|
||||
* accepted directed to another application, device, PLCI, or NCCI. This
|
||||
* is a temporary condition and the application of @appl should retry
|
||||
* sometime later after being signaled by the signal handler installed
|
||||
* with @appl.
|
||||
*
|
||||
* If the message was accepted, %CAPINFO_0X11_NOERR is returned.
|
||||
* Otherwise, a value indicating an error is returned.
|
||||
*
|
||||
* In the case of a data transfer message (DATA_B3_REQ), the data must be
|
||||
* appended to the message (this is contrary to the CAPI standard which
|
||||
* intends a shared buffer scheme), and the Data field will be ignored.
|
||||
*
|
||||
* The application should adhere to the CAPI data window protocol.
|
||||
*
|
||||
*/
|
||||
capinfo_0x11_t
|
||||
capi_put_message(struct capi_appl* appl, struct sk_buff* msg)
|
||||
|
@ -401,11 +409,11 @@ capi_put_message(struct capi_appl* appl, struct sk_buff* msg)
|
|||
|
||||
|
||||
/**
|
||||
* capi_isinstalled - determine whether a device is available
|
||||
* capi_isinstalled - check whether any device is installed
|
||||
*
|
||||
* Context: in_irq()
|
||||
*
|
||||
* If a device is available, %CAPINFO_0X11_NOERR is returned.
|
||||
* If any device is installed, %CAPINFO_0X11_NOERR is returned.
|
||||
* Otherwise, %CAPINFO_0X11_NOTINSTALLED is returned.
|
||||
*/
|
||||
capinfo_0x11_t
|
||||
|
@ -442,12 +450,12 @@ try_get_capi_device_by_id(int id)
|
|||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* Copy the manufacturer string of the device denoted by @id, to the
|
||||
* Copy the manufacturer string of the device, denoted by @id, to the
|
||||
* target buffer. If @id is 0, copy the manufacturer string of the
|
||||
* capicore.
|
||||
*
|
||||
* @manufacturer is returned if the device was available. Otherwise,
|
||||
* NULL is returned.
|
||||
* NULL is returned if there is no such device with @id. Otherwise,
|
||||
* @manufacturer is returned.
|
||||
*/
|
||||
u8*
|
||||
capi_get_manufacturer(int id, u8 manufacturer[CAPI_MANUFACTURER_LEN])
|
||||
|
@ -473,12 +481,12 @@ capi_get_manufacturer(int id, u8 manufacturer[CAPI_MANUFACTURER_LEN])
|
|||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* Copy the serial number string of the device denoted by @id, to the
|
||||
* Copy the serial number string of the device, denoted by @id, to the
|
||||
* target buffer. If @id is 0, copy the serial number string of the
|
||||
* capicore.
|
||||
*
|
||||
* @serial is returned if the device was available. Otherwise,
|
||||
* NULL is returned.
|
||||
* NULL is returned if there is no such device with @id. Otherwise,
|
||||
* @serial is returned.
|
||||
*/
|
||||
u8*
|
||||
capi_get_serial_number(int id, u8 serial[CAPI_SERIAL_LEN])
|
||||
|
@ -504,12 +512,12 @@ capi_get_serial_number(int id, u8 serial[CAPI_SERIAL_LEN])
|
|||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* Copy the version structure of the device denoted by @id, to the
|
||||
* Copy the version structure of the device, denoted by @id, to the
|
||||
* target buffer. If @id is 0, copy the version structure of the
|
||||
* capicore.
|
||||
*
|
||||
* @version is returned if the device was available. Otherwise,
|
||||
* NULL is returned.
|
||||
* NULL is returned if there is no such device with @id. Otherwise,
|
||||
* @version is returned.
|
||||
*/
|
||||
struct capi_version*
|
||||
capi_get_version(int id, struct capi_version* version)
|
||||
|
@ -537,11 +545,11 @@ capi_get_version(int id, struct capi_version* version)
|
|||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* Copy the capabilities of the device denoted by @id, to the target
|
||||
* buffer. If @id is 0, copy just the the number of installed devices.
|
||||
* Copy the capabilities of the device, denoted by @id, to the target
|
||||
* buffer. If @id is 0, copy just the number of installed devices.
|
||||
*
|
||||
* @profile is returned if the device was available. Otherwise,
|
||||
* NULL is returned.
|
||||
* CAPINFO_0X11_OSRESERR is returned if there is no such device with @id.
|
||||
* Otherwise, CAPINFO_0X11_NOERR is returned.
|
||||
*/
|
||||
capinfo_0x11_t
|
||||
capi_get_profile(int id, struct capi_profile* profile)
|
||||
|
@ -568,10 +576,10 @@ capi_get_profile(int id, struct capi_profile* profile)
|
|||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* Copy the name of the device denoted by @id, to the target buffer.
|
||||
* Copy the name of the device, denoted by @id, to the target buffer.
|
||||
*
|
||||
* @product is returned if the device was available. Otherwise,
|
||||
* NULL is returned.
|
||||
* NULL is returned if there is no such device with @id. Otherwise,
|
||||
* @product is returned.
|
||||
*/
|
||||
u8*
|
||||
capi_get_product(int id, u8 product[CAPI_PRODUCT_LEN])
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
* struct capi_register_params - application parameters structure
|
||||
* @level3cnt: maximum number of logical connections the application
|
||||
* can concurrently maintain
|
||||
* @datablkcnt: maximum number of received data blocks that can be
|
||||
* reported to the application simultaneously for each
|
||||
* logical connection
|
||||
* @datablkcnt: maximum number of received data blocks (i.e., the
|
||||
* receive data window) that can be reported to the
|
||||
* application simultaneously for each logical connection
|
||||
* @datablklen: maximum size of the application data block to be
|
||||
* transmitted and received
|
||||
*/
|
||||
|
@ -79,7 +79,7 @@ typedef struct capi_version {
|
|||
|
||||
/**
|
||||
* struct capi_profile - device capabilities structure
|
||||
* @ncontroller: number of devices
|
||||
* @ncontroller: number of installed devices
|
||||
* @nbchannel: number of B-Channels
|
||||
* @goptions: global options
|
||||
* @support1: B1 protocols
|
||||
|
@ -87,9 +87,6 @@ typedef struct capi_version {
|
|||
* @support3: B3 protocols
|
||||
* @reserved: reserved
|
||||
* @manu: manufacturer specific information
|
||||
*
|
||||
* For more information about the individual bit-fields,
|
||||
* see the CAPI standard.
|
||||
*/
|
||||
typedef struct capi_profile {
|
||||
__u16 ncontroller;
|
||||
|
|
|
@ -59,14 +59,17 @@ typedef void (*capi_signal_handler_t) (struct capi_appl* appl, unsigned long par
|
|||
|
||||
|
||||
/**
|
||||
* struct capi_appl - structure representing an application instance
|
||||
* @id: number
|
||||
* struct capi_appl - application control structure
|
||||
* @id: application number
|
||||
* @stats: I/O statistics
|
||||
* @params: parameters
|
||||
* @data: private data
|
||||
*
|
||||
* The application is responsible for updating the application
|
||||
* The application is responsible for updating the application's
|
||||
* I/O statistics, and may freely use the @stats.lock.
|
||||
*
|
||||
* More fields are present, but not documented, since they are
|
||||
* not part of the public interface.
|
||||
*/
|
||||
struct capi_appl {
|
||||
u16 id;
|
||||
|
@ -89,25 +92,24 @@ struct capi_appl {
|
|||
|
||||
|
||||
/**
|
||||
* capi_set_signal - register a signal handler
|
||||
* capi_set_signal - install a signal handler
|
||||
* @appl: application
|
||||
* @signal: signal handler
|
||||
* @signal: signal handler (in_irq() context)
|
||||
* @param: parameter to signal handler
|
||||
*
|
||||
* The signal-handler informs the application about new messages, errors,
|
||||
* or cleared queue-full/busy conditions. The signal-handler is not
|
||||
* meant to be a workhorse, but a mechanism for waking-up and scheduling
|
||||
* applications.
|
||||
* The capicore ensures that by the time a call to the function
|
||||
* capi_release() returns for @appl, no thread is and will be executing
|
||||
* in a call from the capicore to @signal for @appl.
|
||||
*
|
||||
* The signal handler informs the application of @appl about new messages,
|
||||
* errors, or cleared queue-full/busy conditions. The signal handler is
|
||||
* not meant to be a workhorse, but just a mechanism for waking up and
|
||||
* scheduling applications.
|
||||
*
|
||||
* The signal handler must be reentrant and will be called from in_irq()
|
||||
* context. Consequently, it should be as lightweight and fast as
|
||||
* possible.
|
||||
* context; consequently, it should be as simple and fast as possible.
|
||||
*
|
||||
* The capicore ensures that by the time the function capi_release()
|
||||
* returns for @appl, no thread will be executing in a call from the
|
||||
* capicore to @signal for @appl.
|
||||
*
|
||||
* The application must provide a signal-handler, and must not
|
||||
* The application must install a signal handler for @appl, and must not
|
||||
* reset it once registered.
|
||||
*/
|
||||
static inline void
|
||||
|
@ -122,19 +124,21 @@ capi_set_signal(struct capi_appl* appl, capi_signal_handler_t signal, unsigned l
|
|||
|
||||
|
||||
/**
|
||||
* capi_get_message - fetch message from an application queue
|
||||
* capi_get_message - fetch a message from an application queue
|
||||
* @appl: application
|
||||
* @msg: message
|
||||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* Fetch a message from the message queue of @appl. Upon successfully
|
||||
* fetching a message, %CAPINFO_0X11_NOERR is returned and a pointer to
|
||||
* the message is passed via @msg. If there wasn't a message pending,
|
||||
* return immediately passing %CAPINFO_0X11_QUEUEEMPTY as return value.
|
||||
* Otherwise, a value indicating an error is returned.
|
||||
*
|
||||
* In the case of a data transfer message (DATA_B3_IND), the data is
|
||||
* appended to the message (this is contrary to the CAPI standard which
|
||||
* intends a shared buffer scheme) and the Data field is undefined.
|
||||
*
|
||||
* Upon fetching a message successfully, %CAPINFO_0X11_NOERR is returned.
|
||||
* If there was no message available, %CAPINFO_0X11_QUEUEEMPTY is
|
||||
* returned. Otherwise, a value indicating an error is returned.
|
||||
* intends a shared buffer scheme), and the Data field is undefined.
|
||||
*/
|
||||
static inline capinfo_0x11_t
|
||||
capi_get_message(struct capi_appl* appl, struct sk_buff** msg)
|
||||
|
@ -149,14 +153,14 @@ capi_get_message(struct capi_appl* appl, struct sk_buff** msg)
|
|||
|
||||
|
||||
/**
|
||||
* capi_unget_message - reinsert the message to an application queue
|
||||
* capi_unget_message - reinsert a message to an application queue
|
||||
* @appl: application
|
||||
* @msg: message
|
||||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* The message is placed at the head of the application queue, so that
|
||||
* the message will be fetched next.
|
||||
* @msg is placed at the head of the message queue of @appl, so that
|
||||
* it will be fetched next.
|
||||
*/
|
||||
static inline void
|
||||
capi_unget_message(struct capi_appl* appl, struct sk_buff* msg)
|
||||
|
@ -166,14 +170,14 @@ capi_unget_message(struct capi_appl* appl, struct sk_buff* msg)
|
|||
|
||||
|
||||
/**
|
||||
* capi_peek_message - determine whether a message is available
|
||||
* capi_peek_message - check whether a message is pending
|
||||
* @appl: application
|
||||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* If a message is available, %CAPINFO_0X11_NOERR is returned.
|
||||
* If there was no message, %CAPINFO_0X11_QUEUEEMPTY is returned.
|
||||
* Otherwise, a value indicting an error is returned.
|
||||
* If a message is pending on the message queue of @appl,
|
||||
* %CAPINFO_0X11_NOERR is returned. If not, %CAPINFO_0X11_QUEUEEMPTY
|
||||
* is returned. Otherwise, a value indicating an error is returned.
|
||||
*/
|
||||
static inline capinfo_0x11_t
|
||||
capi_peek_message(struct capi_appl* appl)
|
||||
|
|
|
@ -41,28 +41,33 @@ struct capi_device;
|
|||
|
||||
/**
|
||||
* struct capi_driver - device operations structure
|
||||
* @capi_register: register an application
|
||||
* @capi_release: remove an application
|
||||
* @capi_put_message: transfer a message
|
||||
* @capi_register: callback function registering an application
|
||||
* @capi_release: callback function removing an application
|
||||
* @capi_put_message: callback function transferring a message
|
||||
*
|
||||
* The device-driver must provide three functions for calling by the
|
||||
* capicore. This enables the capicore to register and remove
|
||||
* applications with devices, and transferring messages to them.
|
||||
* The device driver must provide three functions for calling by the
|
||||
* capicore via this structure, enabling the registration and removal of
|
||||
* applications with the device driver's devices and the transfer of
|
||||
* messages to them.
|
||||
*
|
||||
* The device-driver must ensure that by the time @capi_release returns
|
||||
* for an application, no thread will be executing in a call from the
|
||||
* device-driver to any of the functions capi_appl_enqueue_message(),
|
||||
* capi_appl_signal(), or capi_appl_signal_error() for that application.
|
||||
* The device driver must ensure that by the time a call to the callback
|
||||
* function @capi_release returns, no thread is and will be executing,
|
||||
* in the context of @dev, in a call to any of these functions
|
||||
* capi_appl_signal_error(), capi_appl_enqueue_message(), or
|
||||
* capi_appl_signal() for @appl.
|
||||
*
|
||||
* If @capi_put_message can not accept messages due to flow-control or
|
||||
* busy reasons, it has the option of rejecting the message by either
|
||||
* returning %CAPINFO_0X11_QUEUEFULL or %CAPINFO_0X11_BUSY, respectively.
|
||||
* In this case, the device-driver should call capi_appl_signal() at a
|
||||
* later time, when it can accept messages again.
|
||||
* The device driver has the option of rejecting @msg by either returning
|
||||
* %CAPINFO_0X11_QUEUEFULL or %CAPINFO_0X11_BUSY from the callback function
|
||||
* @capi_put_message. In this case, @appl could block waiting for the
|
||||
* clearance of the pending condition, and the device driver must call the
|
||||
* function capi_appl_signal() for @appl either when the device driver can
|
||||
* accept messages again for @dev or when the device driver has enqueued
|
||||
* any message for @appl, whichever happens first.
|
||||
*
|
||||
* While @capi_register and @capi_release are called from process context
|
||||
* and may block, @capi_put_message is called from bottom-half context and
|
||||
* may not block. All three functions must be reentrant.
|
||||
* While the callback functions @capi_register and @capi_release are called
|
||||
* from process context and may block (but mustn't be slow, i.e., blocking
|
||||
* indefinitely), @capi_put_message is called from bottom half context and
|
||||
* must not block. All three callback functions must be reentrant.
|
||||
*/
|
||||
struct capi_driver {
|
||||
capinfo_0x10_t (*capi_register) (struct capi_device* dev, struct capi_appl* appl);
|
||||
|
@ -72,9 +77,9 @@ struct capi_driver {
|
|||
|
||||
|
||||
/**
|
||||
* struct capi_device - structure representing a device instance
|
||||
* @id: number
|
||||
* @product: name
|
||||
* struct capi_device - device control structure
|
||||
* @id: device number
|
||||
* @product: device name
|
||||
* @manufacturer: manufacturer
|
||||
* @serial: serial number
|
||||
* @version: version
|
||||
|
@ -83,8 +88,11 @@ struct capi_driver {
|
|||
* @stats: I/O statistics
|
||||
* @class_dev: class device
|
||||
*
|
||||
* The device-driver is responsible for updating the device
|
||||
* The device driver is responsible for updating the device's
|
||||
* I/O statistics, and may freely use the @stats.lock.
|
||||
*
|
||||
* More fields are present, but not documented, since they are
|
||||
* not part of the public interface.
|
||||
*/
|
||||
struct capi_device {
|
||||
unsigned short id;
|
||||
|
@ -112,10 +120,13 @@ void capi_device_unregister (struct capi_device* dev);
|
|||
|
||||
|
||||
/**
|
||||
* capi_device_get - increment the reference counter for a device
|
||||
* capi_device_get - get another reference to a device
|
||||
* @dev: device
|
||||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* Get another reference to @dev by incrementing its reference counter
|
||||
* by one. Return @dev.
|
||||
*/
|
||||
static inline struct capi_device*
|
||||
capi_device_get(struct capi_device* dev)
|
||||
|
@ -130,13 +141,13 @@ capi_device_get(struct capi_device* dev)
|
|||
|
||||
|
||||
/**
|
||||
* capi_device_put - decrement the reference counter for a device
|
||||
* capi_device_put - release a reference to a device
|
||||
* @dev: device
|
||||
*
|
||||
* Context: !in_irq()
|
||||
*
|
||||
* Decrement the reference counter for device, and if zero, free the
|
||||
* device structure.
|
||||
* Release a reference to @dev by decrementing its reference counter
|
||||
* by one and, if zero, free @dev.
|
||||
*/
|
||||
static inline void
|
||||
capi_device_put(struct capi_device* dev)
|
||||
|
@ -146,7 +157,7 @@ capi_device_put(struct capi_device* dev)
|
|||
|
||||
|
||||
/**
|
||||
* capi_device_set_devdata - set the private data pointer
|
||||
* capi_device_set_devdata - set private data pointer
|
||||
* @dev: device
|
||||
* @data: private data
|
||||
*/
|
||||
|
@ -158,7 +169,7 @@ capi_device_set_devdata(struct capi_device* dev, void* data)
|
|||
|
||||
|
||||
/**
|
||||
* capi_device_get_devdata - return the private data pointer
|
||||
* capi_device_get_devdata - return private data pointer
|
||||
* @dev: device
|
||||
*/
|
||||
static inline void*
|
||||
|
@ -169,7 +180,7 @@ capi_device_get_devdata(struct capi_device* dev)
|
|||
|
||||
|
||||
/**
|
||||
* capi_device_set_dev - set the device pointer
|
||||
* capi_device_set_dev - set generic device pointer
|
||||
* @capi_dev: device
|
||||
* @dev: device
|
||||
*/
|
||||
|
@ -181,7 +192,7 @@ capi_device_set_dev(struct capi_device* capi_dev, struct device* dev)
|
|||
|
||||
|
||||
/**
|
||||
* capi_device_get_dev - return the device pointer
|
||||
* capi_device_get_dev - return generic device pointer
|
||||
* @capi_dev: device
|
||||
*/
|
||||
static inline struct device*
|
||||
|
@ -192,7 +203,7 @@ capi_device_get_dev(const struct capi_device* capi_dev)
|
|||
|
||||
|
||||
/**
|
||||
* to_capi_device - cast to device structure
|
||||
* to_capi_device - downcast to generic CAPI device control structure
|
||||
* @cd: class device
|
||||
*/
|
||||
static inline struct capi_device*
|
||||
|
@ -204,37 +215,22 @@ extern struct class capi_class;
|
|||
|
||||
|
||||
/**
|
||||
* capi_appl_signal - wakeup an application
|
||||
* @appl: application
|
||||
*
|
||||
* Context: in_irq()
|
||||
*
|
||||
* The device-driver should wakeup the application after either
|
||||
* enqueuing messages, or clearing a queue-fulf/busy condition.
|
||||
* The device-driver may batch messages.
|
||||
*/
|
||||
static inline void
|
||||
capi_appl_signal(struct capi_appl* appl)
|
||||
{
|
||||
appl->sig(appl, appl->sig_param);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* capi_appl_enqueue_message - add a message to the application queue
|
||||
* capi_appl_enqueue_message - add a message to an application queue
|
||||
* @appl: application
|
||||
* @msg: message
|
||||
*
|
||||
* Context: in_irq()
|
||||
*
|
||||
* The application queue has unbounded capacity, and the device-driver
|
||||
* must adhere to the CAPI data window protocol in order to prevent the
|
||||
* queue from growing immensely. If the device-driver needs to drop a
|
||||
* messages, it should signal this event to the corresponding application.
|
||||
* The message queue of @appl has unbounded capacity; hence the device
|
||||
* driver must adhere to the CAPI data window protocol to prevent that
|
||||
* queue from growing immensely. A full data window should cause the
|
||||
* device driver to trigger flow control on the line, if supported by
|
||||
* the line protocol; otherwise, the device driver should drop @msg and
|
||||
* notify @appl about that condition.
|
||||
*
|
||||
* In the case of a data transfer message (DATA_B3_IND), the data must be
|
||||
* appended to the message (this is contrary to the CAPI standard which
|
||||
* intends a shared buffer scheme) and the Data field will be ignored.
|
||||
* intends a shared buffer scheme), and the Data field will be ignored.
|
||||
*/
|
||||
static inline void
|
||||
capi_appl_enqueue_message(struct capi_appl* appl, struct sk_buff* msg)
|
||||
|
@ -244,15 +240,29 @@ capi_appl_enqueue_message(struct capi_appl* appl, struct sk_buff* msg)
|
|||
|
||||
|
||||
/**
|
||||
* capi_appl_signal_error - inform an application about an error
|
||||
* capi_appl_signal - wakeup an application
|
||||
* @appl: application
|
||||
*
|
||||
* Context: in_irq()
|
||||
*
|
||||
* @appl should be woken up either after enqueuing messages or clearing a
|
||||
* queue-full/busy condition on @appl, respectively.
|
||||
*/
|
||||
static inline void
|
||||
capi_appl_signal(struct capi_appl* appl)
|
||||
{
|
||||
appl->sig(appl, appl->sig_param);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* capi_appl_signal_error - signal an error to an application
|
||||
* @appl: application
|
||||
* @info: error
|
||||
*
|
||||
* Context: in_irq()
|
||||
*
|
||||
* Signal a non-recoverable message exchange error to the application.
|
||||
* This usually implies that messages have been lost, and the only recovery
|
||||
* for the application is to do a release.
|
||||
* The only recovery for @appl, from this condition, is to do a release.
|
||||
*/
|
||||
static inline void
|
||||
capi_appl_signal_error(struct capi_appl* appl, capinfo_0x11_t info)
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
/**
|
||||
* typedef capinfo_0x10_t - info class 0x10xx
|
||||
*
|
||||
* Represents application registration errors.
|
||||
* Enumeration representing application registration errors.
|
||||
*/
|
||||
typedef enum {
|
||||
CAPINFO_0X10_NOERR = 0x0000,
|
||||
|
@ -54,7 +54,7 @@ typedef enum {
|
|||
/**
|
||||
* typedef capinfo_0x11_t - info class 0x11xx
|
||||
*
|
||||
* Represents message exchange errors.
|
||||
* Enumeration representing message exchange errors.
|
||||
*/
|
||||
typedef enum {
|
||||
CAPINFO_0X11_NOERR = 0x0000,
|
||||
|
|
Loading…
Reference in New Issue