Switched to use USB_cdc.h definitions.

Expanded search in every configuration, not only first. ELSA USB modem for instance
publish two configurations, the first one being a vendor-specific one for
Windows NT.
ACMDevice now don't assume anymore union functional descriptor is always there.
The data interface index can be found also in Call Management (CM) functional
descriptor.

(Style cleanup pending...)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40092 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin 2011-01-03 17:15:18 +00:00
parent cf6bf46a66
commit c5f2df286e
11 changed files with 113 additions and 132 deletions

View File

@ -8,6 +8,7 @@
#include "ACM.h"
#include "Driver.h"
ACMDevice::ACMDevice(usb_device device, uint16 vendorID, uint16 productID,
const char *description)
: SerialDevice(device, vendorID, productID, description)
@ -23,32 +24,54 @@ ACMDevice::AddDevice(const usb_configuration_info *config)
status_t status = ENODEV;
uint8 masterIndex = 0;
uint8 slaveIndex = 0;
usb_cdc_cm_functional_descriptor* cmDesc = NULL;
usb_cdc_union_functional_descriptor* unionDesc = NULL;
usb_cdc_acm_functional_descriptor* acmDesc = NULL;
// Search ACM Communication Interface
for (size_t i = 0; i < config->interface_count && status < B_OK; i++) {
usb_interface_info *interface = config->interface[i].active;
usb_interface_descriptor *descriptor = interface->descr;
if (descriptor->interface_class == USB_INT_CLASS_CDC
&& descriptor->interface_subclass == USB_INT_SUBCLASS_ACM
&& interface->generic_count > 0) {
// try to find and interpret the union functional descriptor
if (descriptor->interface_class != USB_CDC_COMMUNICATION_INTERFACE_CLASS
|| descriptor->interface_subclass != USB_CDC_COMMUNICATION_INTERFACE_ACM_SUBCLASS)
continue;
// Found ACM Communication Interface!
// Get functional descriptors of some interest, if any
for (size_t j = 0; j < interface->generic_count; j++) {
usb_generic_descriptor *generic = &interface->generic[j]->generic;
if (generic->length >= 5
&& generic->data[0] == FUNCTIONAL_SUBTYPE_UNION) {
masterIndex = generic->data[1];
slaveIndex = generic->data[2];
status = B_OK;
switch (generic->data[0]) {
case USB_CDC_CM_FUNCTIONAL_DESCRIPTOR:
cmDesc = (usb_cdc_cm_functional_descriptor*)generic;
break;
case USB_CDC_ACM_FUNCTIONAL_DESCRIPTOR:
acmDesc = (usb_cdc_acm_functional_descriptor*)generic;
break;
case USB_CDC_UNION_FUNCTIONAL_DESCRIPTOR:
unionDesc = (usb_cdc_union_functional_descriptor*)generic;
break;
}
}
masterIndex = unionDesc ? unionDesc->master_interface : i;
slaveIndex = cmDesc ? cmDesc->data_interface
: unionDesc ? unionDesc->slave_interfaces[0] : 0;
TRACE("ACM device found on configuration #%d: master itf: %d, slave/data itf: %d\n",
config->descr->configuration, masterIndex, slaveIndex);
status = B_OK;
break;
}
}
if (status == B_OK && masterIndex < config->interface_count) {
// check that the indicated master interface fits our need
usb_interface_info *interface = config->interface[masterIndex].active;
usb_interface_descriptor *descriptor = interface->descr;
if ((descriptor->interface_class == USB_INT_CLASS_CDC
|| descriptor->interface_class == USB_INT_CLASS_CDC_DATA)
if ((descriptor->interface_class == USB_CDC_COMMUNICATION_INTERFACE_CLASS
|| descriptor->interface_class == USB_CDC_DATA_INTERFACE_CLASS)
&& interface->endpoint_count >= 1) {
SetControlPipe(interface->endpoint[0].handle);
} else
@ -59,14 +82,14 @@ ACMDevice::AddDevice(const usb_configuration_info *config)
// check that the indicated slave interface fits our need
usb_interface_info *interface = config->interface[slaveIndex].active;
usb_interface_descriptor *descriptor = interface->descr;
if (descriptor->interface_class == USB_INT_CLASS_CDC_DATA
if (descriptor->interface_class == USB_CDC_DATA_INTERFACE_CLASS
&& interface->endpoint_count >= 2) {
if (!(interface->endpoint[0].descr->endpoint_address & USB_EP_ADDR_DIR_IN))
if (!(interface->endpoint[0].descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN))
SetWritePipe(interface->endpoint[0].handle);
else
SetReadPipe(interface->endpoint[0].handle);
if (interface->endpoint[1].descr->endpoint_address & USB_EP_ADDR_DIR_IN)
if (interface->endpoint[1].descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
SetReadPipe(interface->endpoint[1].handle);
else
SetWritePipe(interface->endpoint[1].handle);
@ -80,7 +103,7 @@ ACMDevice::AddDevice(const usb_configuration_info *config)
status_t
ACMDevice::SetLineCoding(usb_serial_line_coding *lineCoding)
ACMDevice::SetLineCoding(usb_cdc_line_coding *lineCoding)
{
TRACE_FUNCALLS("> ACMDevice::SetLineCoding(0x%08x, {%d, 0x%02x, 0x%02x, 0x%02x})\n",
this, lineCoding->speed, lineCoding->stopbits, lineCoding->parity,
@ -89,8 +112,8 @@ ACMDevice::SetLineCoding(usb_serial_line_coding *lineCoding)
size_t length = 0;
status_t status = gUSBModule->send_request(Device(),
USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
SET_LINE_CODING, 0, 0,
sizeof(usb_serial_line_coding),
USB_CDC_SET_LINE_CODING, 0, 0,
sizeof(usb_cdc_line_coding),
lineCoding, &length);
TRACE_FUNCRET("< ACMDevice::SetLineCoding() returns: 0x%08x\n", status);
@ -106,7 +129,7 @@ ACMDevice::SetControlLineState(uint16 state)
size_t length = 0;
status_t status = gUSBModule->send_request(Device(),
USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
SET_CONTROL_LINE_STATE, state, 0, 0, NULL, &length);
USB_CDC_SET_CONTROL_LINE_STATE, state, 0, 0, NULL, &length);
TRACE_FUNCRET("< ACMDevice::SetControlLineState() returns: 0x%08x\n", status);
return status;

View File

@ -10,16 +10,6 @@
#include "SerialDevice.h"
/* requests for CDC ACM devices */
#define SEND_ENCAPSULATED_COMMAND 0x00
#define GET_ENCAPSULATED_RESPONSE 0x01
#define SET_LINE_CODING 0x20
#define SET_CONTROL_LINE_STATE 0x22
/* notifications for CDC ACM devices */
#define NETWORK_CONNECTION 0x00
#define RESPONSE_AVAILABLE 0x01
class ACMDevice : public SerialDevice {
public:
ACMDevice(usb_device device, uint16 vendorID,
@ -27,7 +17,7 @@ public:
virtual status_t AddDevice(const usb_configuration_info *config);
virtual status_t SetLineCoding(usb_serial_line_coding *coding);
virtual status_t SetLineCoding(usb_cdc_line_coding *coding);
virtual status_t SetControlLineState(uint16 state);
virtual void OnWrite(const char *buffer, size_t *numBytes,

View File

@ -40,18 +40,24 @@ usb_serial_device_added(usb_device device, void **cookie)
SerialDevice *serialDevice = SerialDevice::MakeDevice(device,
descriptor->vendor_id, descriptor->product_id);
const usb_configuration_info *configuration
= gUSBModule->get_nth_configuration(device, 0);
const usb_configuration_info *configuration;
for (int i = 0; i < descriptor->num_configurations; i++) {
configuration = gUSBModule->get_nth_configuration(device, 0);
if (!configuration)
return B_ERROR;
continue;
status = serialDevice->AddDevice(configuration);
if (status == B_OK)
// Found!
break;
}
if (status < B_OK) {
delete serialDevice;
return status;
}
acquire_sem(gDriverLock);
for (int32 i = 0; i < DEVICES_COUNT; i++) {
if (gSerialDevices[i] != NULL)

View File

@ -13,6 +13,8 @@
#include <OS.h>
#include <USB3.h>
#include <usb/USB_cdc.h>
#include <lock.h>
#include <string.h>
@ -33,48 +35,6 @@ extern "C" {
/* Default device buffer size */
#define DEF_BUFFER_SIZE 0x200
/* line coding defines ... Come from CDC USB specs? */
#define LC_STOP_BIT_1 0
#define LC_STOP_BIT_2 2
#define LC_PARITY_NONE 0
#define LC_PARITY_ODD 1
#define LC_PARITY_EVEN 2
/* struct that represents line coding */
typedef struct usb_serial_line_coding_s {
uint32 speed;
uint8 stopbits;
uint8 parity;
uint8 databits;
} usb_serial_line_coding;
/* control line states */
#define CLS_LINE_DTR 0x0001
#define CLS_LINE_RTS 0x0002
/* attributes etc ...*/
#ifndef USB_EP_ADDR_DIR_IN
#define USB_EP_ADDR_DIR_IN 0x80
#define USB_EP_ADDR_DIR_OUT 0x00
#endif
#ifndef USB_EP_ATTR_CONTROL
#define USB_EP_ATTR_CONTROL 0x00
#define USB_EP_ATTR_ISOCHRONOUS 0x01
#define USB_EP_ATTR_BULK 0x02
#define USB_EP_ATTR_INTERRUPT 0x03
#endif
/* USB class - communication devices */
#define USB_DEV_CLASS_COMM 0x02
#define USB_INT_CLASS_CDC 0x02
#define USB_INT_SUBCLASS_ACM 0x02
#define USB_INT_CLASS_CDC_DATA 0x0a
#define USB_INT_SUBCLASS_DATA 0x00
// communication device subtypes
#define FUNCTIONAL_SUBTYPE_UNION 0x06
extern usb_module_info *gUSBModule;
extern tty_module_info *gTTYModule;

View File

@ -28,8 +28,8 @@ FTDIDevice::AddDevice(const usb_configuration_info *config)
usb_interface_info *interface = config->interface[0].active;
for (size_t i = 0; i < interface->endpoint_count; i++) {
usb_endpoint_info *endpoint = &interface->endpoint[i];
if (endpoint->descr->attributes == USB_EP_ATTR_BULK) {
if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) {
if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) {
if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) {
SetReadPipe(endpoint->handle);
if (++pipesSet >= 3)
break;
@ -77,7 +77,7 @@ FTDIDevice::ResetDevice()
status_t
FTDIDevice::SetLineCoding(usb_serial_line_coding *lineCoding)
FTDIDevice::SetLineCoding(usb_cdc_line_coding *lineCoding)
{
TRACE_FUNCALLS("> FTDIDevice::SetLineCoding(0x%08x, {%d, 0x%02x, 0x%02x, 0x%02x})\n",
this, lineCoding->speed, lineCoding->stopbits, lineCoding->parity,
@ -137,8 +137,8 @@ FTDIDevice::SetLineCoding(usb_serial_line_coding *lineCoding)
int32 data = 0;
switch (lineCoding->stopbits) {
case LC_STOP_BIT_2: data = FTDI_SIO_SET_DATA_STOP_BITS_2; break;
case LC_STOP_BIT_1: data = FTDI_SIO_SET_DATA_STOP_BITS_1; break;
case USB_CDC_LINE_CODING_1_STOPBIT: data = FTDI_SIO_SET_DATA_STOP_BITS_2; break;
case USB_CDC_LINE_CODING_2_STOPBITS: data = FTDI_SIO_SET_DATA_STOP_BITS_1; break;
default:
TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong stopbits param: %d\n",
lineCoding->stopbits);
@ -146,9 +146,9 @@ FTDIDevice::SetLineCoding(usb_serial_line_coding *lineCoding)
}
switch (lineCoding->parity) {
case LC_PARITY_NONE: data |= FTDI_SIO_SET_DATA_PARITY_NONE; break;
case LC_PARITY_EVEN: data |= FTDI_SIO_SET_DATA_PARITY_EVEN; break;
case LC_PARITY_ODD: data |= FTDI_SIO_SET_DATA_PARITY_ODD; break;
case USB_CDC_LINE_CODING_NO_PARITY: data |= FTDI_SIO_SET_DATA_PARITY_NONE; break;
case USB_CDC_LINE_CODING_EVEN_PARITY: data |= FTDI_SIO_SET_DATA_PARITY_EVEN; break;
case USB_CDC_LINE_CODING_ODD_PARITY: data |= FTDI_SIO_SET_DATA_PARITY_ODD; break;
default:
TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong parity param: %d\n",
lineCoding->parity);
@ -183,7 +183,8 @@ FTDIDevice::SetControlLineState(uint16 state)
TRACE_FUNCALLS("> FTDIDevice::SetControlLineState(0x%08x, 0x%04x)\n", this, state);
int32 control;
control = (state & CLS_LINE_RTS) ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW;
control = (state & USB_CDC_CONTROL_SIGNAL_STATE_RTS) ? FTDI_SIO_SET_RTS_HIGH
: FTDI_SIO_SET_RTS_LOW;
size_t length = 0;
status_t status = gUSBModule->send_request(Device(),
@ -194,7 +195,9 @@ FTDIDevice::SetControlLineState(uint16 state)
if (status != B_OK)
TRACE_ALWAYS("= FTDIDevice::SetControlLineState(): control set request failed: 0x%08x\n", status);
control = (state & CLS_LINE_DTR) ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW;
control = (state & USB_CDC_CONTROL_SIGNAL_STATE_DTR) ? FTDI_SIO_SET_DTR_HIGH
: FTDI_SIO_SET_DTR_LOW;
status = gUSBModule->send_request(Device(),
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
FTDI_SIO_MODEM_CTRL, control,

View File

@ -27,7 +27,7 @@ virtual status_t AddDevice(const usb_configuration_info *config);
virtual status_t ResetDevice();
virtual status_t SetLineCoding(usb_serial_line_coding *coding);
virtual status_t SetLineCoding(usb_cdc_line_coding *coding);
virtual status_t SetControlLineState(uint16 state);
virtual void OnRead(char **buffer, size_t *numBytes);

View File

@ -26,28 +26,24 @@ KLSIDevice::AddDevice(const usb_configuration_info *config)
usb_interface_info *interface = config->interface[0].active;
for (size_t i = 0; i < interface->endpoint_count; i++) {
usb_endpoint_info *endpoint = &interface->endpoint[i];
if (endpoint->descr->attributes == USB_EP_ATTR_INTERRUPT) {
if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) {
if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_INTERRUPT) {
if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) {
SetControlPipe(endpoint->handle);
SetInterruptBufferSize(endpoint->descr->max_packet_size);
if (++pipesSet >= 3)
break;
}
} else if (endpoint->descr->attributes == USB_EP_ATTR_BULK) {
if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) {
} else if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) {
if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) {
SetReadBufferSize(ROUNDUP(endpoint->descr->max_packet_size, 16));
SetReadPipe(endpoint->handle);
if (++pipesSet >= 3)
break;
} else {
SetWriteBufferSize(ROUNDUP(endpoint->descr->max_packet_size, 16));
SetWritePipe(endpoint->handle);
}
}
if (++pipesSet >= 3)
break;
}
}
}
}
if (pipesSet >= 3)
status = B_OK;
@ -64,10 +60,10 @@ KLSIDevice::ResetDevice()
size_t length = 0;
status_t status;
usb_serial_line_coding linecoding = { 9600, 1, 0, 8 };
usb_cdc_line_coding lineCoding = { 9600, 1, 0, 8 };
uint8 linestate[2];
status = SetLineCoding(&linecoding);
status = SetLineCoding(&lineCoding);
status = gUSBModule->send_request(Device(),
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
KLSI_CONF_REQUEST,
@ -89,7 +85,7 @@ KLSIDevice::ResetDevice()
status_t
KLSIDevice::SetLineCoding(usb_serial_line_coding *lineCoding)
KLSIDevice::SetLineCoding(usb_cdc_line_coding *lineCoding)
{
TRACE_FUNCALLS("> KLSIDevice::SetLineCoding(0x%08x, {%d, 0x%02x, 0x%02x, 0x%02x})\n",
this, lineCoding->speed, lineCoding->stopbits, lineCoding->parity,

View File

@ -50,7 +50,7 @@ virtual status_t AddDevice(const usb_configuration_info *config);
virtual status_t ResetDevice();
virtual status_t SetLineCoding(usb_serial_line_coding *coding);
virtual status_t SetLineCoding(usb_cdc_line_coding *coding);
virtual void OnRead(char **buffer, size_t *numBytes);
virtual void OnWrite(const char *buffer, size_t *numBytes,

View File

@ -36,8 +36,8 @@ ProlificDevice::AddDevice(const usb_configuration_info *config)
usb_interface_info *interface = config->interface[0].active;
for (size_t i = 0; i < interface->endpoint_count; i++) {
usb_endpoint_info *endpoint = &interface->endpoint[i];
if (endpoint->descr->attributes == USB_EP_ATTR_INTERRUPT) {
if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) {
if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_INTERRUPT) {
if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) {
SetControlPipe(endpoint->handle);
pipesSet++;
}
@ -50,18 +50,16 @@ ProlificDevice::AddDevice(const usb_configuration_info *config)
for (size_t i = 0; i < interface->endpoint_count; i++) {
usb_endpoint_info *endpoint = &interface->endpoint[i];
if (endpoint->descr->attributes == USB_EP_ATTR_BULK) {
if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) {
if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) {
if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
SetReadPipe(endpoint->handle);
if (++pipesSet >= 3)
break;
} else {
else
SetWritePipe(endpoint->handle);
if (++pipesSet >= 3)
break;
}
}
}
if (pipesSet >= 3)
status = B_OK;

View File

@ -144,16 +144,17 @@ SerialDevice::SetModes(struct termios *tios)
if (baudIndex > baudCount)
baudIndex = baudCount - 1;
usb_serial_line_coding lineCoding;
usb_cdc_line_coding lineCoding;
lineCoding.speed = baudRates[baudIndex];
lineCoding.stopbits = (tios->c_cflag & CSTOPB) ? LC_STOP_BIT_2 : LC_STOP_BIT_1;
lineCoding.stopbits = (tios->c_cflag & CSTOPB)
? USB_CDC_LINE_CODING_2_STOPBITS : USB_CDC_LINE_CODING_1_STOPBIT;
if (tios->c_cflag & PARENB) {
lineCoding.parity = LC_PARITY_EVEN;
lineCoding.parity = USB_CDC_LINE_CODING_EVEN_PARITY;
if (tios->c_cflag & PARODD)
lineCoding.parity = LC_PARITY_ODD;
lineCoding.parity = USB_CDC_LINE_CODING_ODD_PARITY;
} else
lineCoding.parity = LC_PARITY_NONE;
lineCoding.parity = USB_CDC_LINE_CODING_NO_PARITY;
lineCoding.databits = (tios->c_cflag & CS8) ? 8 : 7;
@ -163,7 +164,7 @@ SerialDevice::SetModes(struct termios *tios)
SetControlLineState(newControl);
}
if (memcmp(&lineCoding, &fLineCoding, sizeof(usb_serial_line_coding)) != 0) {
if (memcmp(&lineCoding, &fLineCoding, sizeof(usb_cdc_line_coding)) != 0) {
fLineCoding.speed = lineCoding.speed;
fLineCoding.stopbits = lineCoding.stopbits;
fLineCoding.databits = lineCoding.databits;
@ -191,7 +192,8 @@ SerialDevice::Service(struct tty *tty, uint32 op, void *buffer, size_t length)
gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWDCD, enable);
gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWCTS, enable);
fControlOut = enable ? CLS_LINE_DTR | CLS_LINE_RTS : 0;
fControlOut = enable ? USB_CDC_CONTROL_SIGNAL_STATE_DTR
| USB_CDC_CONTROL_SIGNAL_STATE_RTS : 0;
SetControlLineState(fControlOut);
return true;
}
@ -205,7 +207,8 @@ SerialDevice::Service(struct tty *tty, uint32 op, void *buffer, size_t length)
case TTYGETSIGNALS:
TRACE("TTYGETSIGNALS\n");
gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWDCD,
(fControlOut & (CLS_LINE_DTR | CLS_LINE_RTS)) != 0);
(fControlOut & (USB_CDC_CONTROL_SIGNAL_STATE_DTR
| USB_CDC_CONTROL_SIGNAL_STATE_RTS)) != 0);
gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWCTS, !fInputStopped);
gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWDSR, false);
gTTYModule->tty_hardware_signal(fTTYCookie, TTYHWRI, false);
@ -220,7 +223,8 @@ SerialDevice::Service(struct tty *tty, uint32 op, void *buffer, size_t length)
case TTYSETRTS:
{
bool set = *(bool *)buffer;
uint8 bit = TTYSETDTR ? CLS_LINE_DTR : CLS_LINE_RTS;
uint8 bit = TTYSETDTR ? USB_CDC_CONTROL_SIGNAL_STATE_DTR
: USB_CDC_CONTROL_SIGNAL_STATE_RTS;
if (set)
fControlOut |= bit;
else
@ -283,7 +287,8 @@ SerialDevice::Open(uint32 flags)
resume_thread(fDeviceThread);
fControlOut = CLS_LINE_DTR | CLS_LINE_RTS;
fControlOut = USB_CDC_CONTROL_SIGNAL_STATE_DTR
| USB_CDC_CONTROL_SIGNAL_STATE_RTS;
SetControlLineState(fControlOut);
status_t status = gUSBModule->queue_interrupt(fControlPipe,
@ -475,7 +480,7 @@ SerialDevice::ResetDevice()
status_t
SerialDevice::SetLineCoding(usb_serial_line_coding *coding)
SerialDevice::SetLineCoding(usb_cdc_line_coding *coding)
{
// default implementation - does nothing
return B_OK;

View File

@ -64,7 +64,7 @@ virtual status_t AddDevice(const usb_configuration_info *config);
virtual status_t ResetDevice();
virtual status_t SetLineCoding(usb_serial_line_coding *coding);
virtual status_t SetLineCoding(usb_cdc_line_coding *coding);
virtual status_t SetControlLineState(uint16 state);
virtual void OnRead(char **buffer, size_t *numBytes);
@ -102,7 +102,7 @@ static void InterruptCallbackFunction(void *cookie,
usb_pipe fWritePipe;
/* line coding */
usb_serial_line_coding fLineCoding;
usb_cdc_line_coding fLineCoding;
/* data buffers */
area_id fBufferArea;