2009-11-22 08:08:58

by Gernot Hillier

[permalink] [raw]
Subject: [PATCH] Add support for Mobilcom Debitel USB UMTS Surf-Stick to option driver

From: Gernot Hillier <[email protected]>

This patch adds the vendor and device id for the Mobilcom Debitel UMTS surf
stick (a.k.a. 4G Systems XSStick W14, MobiData MBD-200HU, ...).

To see these ids, you need to switch the stick to modem operation first with the
help of usb_modeswitch. This makes it switch from 1c9e:f000 to 1c9e:9603 and
thus be recognized by the option driver.

In addition, this device seems to ignore setting of RTS/DTR by option_send_
setup and doesn't answer the usb_control_msg leading to a 5 s timeout
(USB_CTRL_SET_TIMEOUT) in userspace open() and other operations. As this
confused several impatient userspace applications like Minicom and ModemManager,
I decided to reduce the timeout to more reasonable 1000 ms. I don't think the
usual USB GSM stick needs longer, so this should be safe.

Signed-off-by: Gernot Hillier <[email protected]>

diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 319aaf9..296009f 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -336,6 +336,11 @@ static int option_resume(struct usb_serial *serial);
#define AIRPLUS_VENDOR_ID 0x1011
#define AIRPLUS_PRODUCT_MCD650 0x3198

+/* 4G Systems XS W14 a.k.a Mobilcom Debitel Surf-Stick a.k.a.
+ MobiData MBD-200HU a.k.a. ST Mobile Connect HSUPA USB Modem ... */
+#define FOUR_G_SYSTEMS_VENDOR_ID 0x1c9e
+#define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603
+
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -599,6 +604,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
+ { USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1176,9 +1182,11 @@ static int option_send_setup(struct usb_serial_port *port)
if (portdata->rts_state)
val |= 0x02;

+ /* use a short timeout of 1 s here to not block userspace too long when
+ device ignores this message (as 4GS W14 does) */
return usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
- 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ 0x22, 0x21, val, ifNum, NULL, 0, 1000);
}

static int option_startup(struct usb_serial *serial)


2009-11-22 08:20:10

by Oliver Neukum

[permalink] [raw]
Subject: Re: [PATCH] Add support for Mobilcom Debitel USB UMTS Surf-Stick to option driver

Am Sonntag, 22. November 2009 09:08:44 schrieb Gernot Hillier:
> In addition, this device seems to ignore setting of RTS/DTR by option_send_
> setup and doesn't answer the usb_control_msg leading to a 5 s timeout
> (USB_CTRL_SET_TIMEOUT) in userspace open() and other operations. As this
> confused several impatient userspace applications like Minicom and
> ModemManager, I decided to reduce the timeout to more reasonable 1000 ms.
> I don't think the usual USB GSM stick needs longer, so this should be
> safe.

Unfortunately the 5s timeout comes from the USB spec for control
messages. So reducing it is a serious matter. In this case I'd prefer
if you introduce a special case for these devices and fail the operation
without doing any IO.

Regards
Oliver

2009-11-24 18:00:50

by Gernot Hillier

[permalink] [raw]
Subject: Re: [PATCH] Add support for Mobilcom Debitel USB UMTS Surf-Stick to option driver

Hi!

Oliver Neukum schrieb:
> Am Sonntag, 22. November 2009 09:08:44 schrieb Gernot Hillier:
>> In addition, this device seems to ignore setting of RTS/DTR by option_send_
>> setup and doesn't answer the usb_control_msg leading to a 5 s timeout
>> (USB_CTRL_SET_TIMEOUT) in userspace open() and other operations. As this
>> confused several impatient userspace applications like Minicom and
>> ModemManager, I decided to reduce the timeout to more reasonable 1000 ms.
>> I don't think the usual USB GSM stick needs longer, so this should be
>> safe.
>
> Unfortunately the 5s timeout comes from the USB spec for control
> messages. So reducing it is a serious matter. In this case I'd prefer
> if you introduce a special case for these devices and fail the operation
> without doing any IO.

Thanks for the answer and suggestion. I looked into that - but
unfortunately (again), it isn't that easy. The device accepts the
option_set_setup triggered control message on *one* of its three
interfaces while it silently ignores it on the other two. :-(

I do see /dev/ttyUSB[0-2] - and on /dev/ttyUSB2, everything works as
expected (i.e. the control message *is* handled correctly) while ttyUSB0
and ttyUSB1 exhibit this strange timeout issue.

As you might have expected, I have no detailed spec about the device
which could explain this. I can only say that the device reacts on AT
commands on ttyUSB1 and ttyUSB2 while ttyUSB0 seems to serve other purposes.

What do you think - shall I disable sending the usb control message
depending on bInterfaceNumber? Any better ideas?

Here's the "lsusb -v" output in case this helps:

Bus 002 Device 007: ID 1c9e:9603
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x1c9e
idProduct 0x9603
bcdDevice 0.00
iManufacturer 2 USB Modem
iProduct 1 Modem Configuration
iSerial 3 1234567890ABCDEF
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 108
bNumInterfaces 4
bConfigurationValue 1
iConfiguration 1 Modem Configuration
bmAttributes 0xe0
Self Powered
Remote Wakeup
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 32
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 32
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 32
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 32
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 5
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 32
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 32
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 3
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 8 Mass Storage
bInterfaceSubClass 6 SCSI
bInterfaceProtocol 80 Bulk (Zip)
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x04 EP 4 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x85 EP 5 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Device Qualifier (for other device speed):
bLength 10
bDescriptorType 6
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
bNumConfigurations 1
Device Status: 0x0000
(Bus Powered)

--
Gernot

2009-11-24 18:19:03

by Oliver Neukum

[permalink] [raw]
Subject: Re: [PATCH] Add support for Mobilcom Debitel USB UMTS Surf-Stick to option driver

Am Dienstag, 24. November 2009 19:00:33 schrieb Gernot Hillier:
> As you might have expected, I have no detailed spec about the device
> which could explain this. I can only say that the device reacts on AT
> commands on ttyUSB1 and ttyUSB2 while ttyUSB0 seems to serve other
> purposes.
>
> What do you think - shall I disable sending the usb control message
> depending on bInterfaceNumber? Any better ideas?

I have no better idea.

Regards
Oliver

2009-11-27 12:49:33

by Gernot Hillier

[permalink] [raw]
Subject: Re: [PATCH] Add support for Mobilcom Debitel USB UMTS Surf-Stick to option driver

Oliver Neukum wrote:
> Am Dienstag, 24. November 2009 19:00:33 schrieb Gernot Hillier:
>> As you might have expected, I have no detailed spec about the device
>> which could explain this. I can only say that the device reacts on AT
>> commands on ttyUSB1 and ttyUSB2 while ttyUSB0 seems to serve other
>> purposes.
>>
>> What do you think - shall I disable sending the usb control message
>> depending on bInterfaceNumber? Any better ideas?
>
> I have no better idea.
>
> Regards
> Oliver
>

Ok, so here comes the update. The patch was tested to apply against 2.6.31
as well as 2.6-git. Please apply if you agree...

----------- SNIP -------------
From: Gernot Hillier <[email protected]>

This patch adds the vendor and device id for the Mobilcom Debitel UMTS surf
stick (a.k.a. 4G Systems XSStick W14, MobiData MBD-200HU, ...).

To see these ids, you need to switch the stick to modem operation first
with the help of usb_modeswitch. This makes it switch from 1c9e:f000 to
1c9e:9603 and thus be recognized by the option driver.

In addition, this device seems to ignore setting of RTS/DTR by option_send_
setup and doesn't answer the usb_control_msg leading to a 5 s timeout
(USB_CTRL_SET_TIMEOUT) in userspace open() and other operations. As this
confused several impatient userspace applications like Minicom and
ModemManager, I return immediately instead.

Signed-off-by: Gernot Hillier <[email protected]>

--- linux-source-2.6.31/drivers/usb/serial/option.c.orig 2009-11-24 08:17:31.000000000 +0100
+++ linux-source-2.6.31/drivers/usb/serial/option.c 2009-11-27 12:48:15.000000000 +0100
@@ -337,6 +337,10 @@
#define AIRPLUS_VENDOR_ID 0x1011
#define AIRPLUS_PRODUCT_MCD650 0x3198

+/* 4G Systems products */
+#define FOUR_G_SYSTEMS_VENDOR_ID 0x1c9e
+#define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603
+
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -600,6 +604,7 @@
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
+ { USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1171,6 +1176,13 @@
int val = 0;
dbg("%s", __func__);

+ /* 4G Systems W14 simply ignores this message on interface 0 & 1
+ and would cause long timeouts when calling usb_control_msg() */
+ if (serial->dev->descriptor.idVendor == FOUR_G_SYSTEMS_VENDOR_ID &&
+ serial->dev->descriptor.idProduct == FOUR_G_SYSTEMS_PRODUCT_W14 &&
+ (ifNum == 0 || ifNum == 1) )
+ return -EIO;
+
portdata = usb_get_serial_port_data(port);

if (portdata->dtr_state)

2009-11-27 13:32:17

by Matthias Urlichs

[permalink] [raw]
Subject: Re: [PATCH] Add support for Mobilcom Debitel USB UMTS Surf-Stick to option driver

On Fri, 2009-11-27 at 13:49 +0100, Gernot Hillier wrote:
> + /* 4G Systems W14 simply ignores this message on interface 0 & 1
> + and would cause long timeouts when calling usb_control_msg() */
> + if (serial->dev->descriptor.idVendor == FOUR_G_SYSTEMS_VENDOR_ID &&
> + serial->dev->descriptor.idProduct == FOUR_G_SYSTEMS_PRODUCT_W14 &&
> + (ifNum == 0 || ifNum == 1) )
> + return -EIO;
>
I'd appreciate if you'd implement this generically.

I.e., use the driver_info field of struct usb_device for an appropriate
blacklist flag. (It's not going to be the only one.)

2009-11-27 18:11:18

by Gernot Hillier

[permalink] [raw]
Subject: Re: [PATCH] Add support for Mobilcom Debitel USB UMTS Surf-Stick to option driver

Hi!

Matthias Urlichs schrieb:
> On Fri, 2009-11-27 at 13:49 +0100, Gernot Hillier wrote:
>> + /* 4G Systems W14 simply ignores this message on interface 0 & 1
>> + and would cause long timeouts when calling usb_control_msg() */
>> + if (serial->dev->descriptor.idVendor == FOUR_G_SYSTEMS_VENDOR_ID &&
>> + serial->dev->descriptor.idProduct == FOUR_G_SYSTEMS_PRODUCT_W14 &&
>> + (ifNum == 0 || ifNum == 1) )
>> + return -EIO;
>>
> I'd appreciate if you'd implement this generically.
>
> I.e., use the driver_info field of struct usb_device for an appropriate
> blacklist flag. (It's not going to be the only one.)

Sure. I'll have a look into that ASAP.

Could you do me a favor and apply the first two hunks (i.e. add the
vendor/device id) in the meantime?

This makes the driver functional in general. And - ehrm, would save me
some time, because these hunks have to be rebased frequently. ;-)

The 3rd hunk (we're talking about) is just an "optimization" to make
impatient userspace applications happy...

--
Gernot

2009-11-27 18:53:41

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH] Add support for Mobilcom Debitel USB UMTS Surf-Stick to option driver

On Fri, Nov 27, 2009 at 07:11:05PM +0100, Gernot Hillier wrote:
> Hi!
>
> Matthias Urlichs schrieb:
>> On Fri, 2009-11-27 at 13:49 +0100, Gernot Hillier wrote:
>>> + /* 4G Systems W14 simply ignores this message on interface 0 & 1
>>> + and would cause long timeouts when calling usb_control_msg()
>>> */
>>> + if (serial->dev->descriptor.idVendor == FOUR_G_SYSTEMS_VENDOR_ID &&
>>> + serial->dev->descriptor.idProduct == FOUR_G_SYSTEMS_PRODUCT_W14 &&
>>> + (ifNum == 0 || ifNum == 1) )
>>> + return -EIO;
>>>
>> I'd appreciate if you'd implement this generically.
>>
>> I.e., use the driver_info field of struct usb_device for an appropriate
>> blacklist flag. (It's not going to be the only one.)
>
> Sure. I'll have a look into that ASAP.
>
> Could you do me a favor and apply the first two hunks (i.e. add the
> vendor/device id) in the meantime?
>
> This makes the driver functional in general. And - ehrm, would save me some
> time, because these hunks have to be rebased frequently. ;-)
>
> The 3rd hunk (we're talking about) is just an "optimization" to make
> impatient userspace applications happy...

Yes, I'll queue that up to make it easier for you to add the later
options.

thanks,

greg k-h

2009-12-08 06:20:47

by Gernot Hillier

[permalink] [raw]
Subject: Re: [PATCH] Add support for Mobilcom Debitel USB UMTS Surf-Stick to option driver

Matthias Urlichs wrote:
> On Fri, 2009-11-27 at 13:49 +0100, Gernot Hillier wrote:
>> + /* 4G Systems W14 simply ignores this message on interface 0 & 1
>> + and would cause long timeouts when calling usb_control_msg() */
>> + if (serial->dev->descriptor.idVendor == FOUR_G_SYSTEMS_VENDOR_ID &&
>> + serial->dev->descriptor.idProduct == FOUR_G_SYSTEMS_PRODUCT_W14 &&
>> + (ifNum == 0 || ifNum == 1) )
>> + return -EIO;
>>
> I'd appreciate if you'd implement this generically.
>
> I.e., use the driver_info field of struct usb_device for an appropriate
> blacklist flag. (It's not going to be the only one.)
>

Ok, so here's my first shot at it. Code was mostly stolen from drivers/usb/
serial/sierra.c.

Additionally, I needed to add some pieces because blacklist info is needed
in option_send_setup() where I don't have easy access to struct usb_
device_id. So far, I had no better idea than remembering the info in our
private structure.

I also prepared things to include the D-Link DWM 652 exceptions from
option_probe() (that's the intention of OPTION_BLACKLIST_RESERVED_IF).

Could you please confirm if this is what you wanted - if yes, I can
probably repost the patch in three parts (blacklisting infrastructure, add
4G W14 blacklist info, port D-Link DWM 652 blacklist info) with
appropriate summaries.

--- drivers/usb/serial/option.c.orig 2009-12-08 05:52:13.000000000 +0100
+++ drivers/usb/serial/option.c 2009-12-08 06:53:43.000000000 +0100
@@ -340,6 +340,28 @@ static int option_resume(struct usb_ser
#define FOUR_G_SYSTEMS_VENDOR_ID 0x1c9e
#define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603

+/* some devices interfaces need special handling due to a number of reasons */
+typedef enum {
+ OPTION_BLACKLIST_NONE = 0,
+ OPTION_BLACKLIST_SENDSETUP = 1,
+ OPTION_BLACKLIST_RESERVED_IF = 2
+} option_blacklist_reason_t;
+
+struct option_blacklist_info {
+ const u32 infolen; /* number of interface numbers on blacklist */
+ const u8 *ifaceinfo; /* pointer to the array holding the numbers */
+ option_blacklist_reason_t reason;
+};
+
+static const u8 four_g_w14_no_sendsetup[] = { 0, 1 };
+static const struct option_blacklist_info four_g_w14_blacklist = {
+ .infolen = ARRAY_SIZE(four_g_w14_no_sendsetup),
+ .ifaceinfo = four_g_w14_no_sendsetup,
+ .reason = OPTION_BLACKLIST_SENDSETUP
+};
+
+
+
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -604,7 +626,9 @@ static struct usb_device_id option_ids[]
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
- { USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14) },
+ { USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
+ .driver_info = (kernel_ulong_t)&four_g_w14_blacklist
+ },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
@@ -668,6 +692,7 @@ struct option_intf_private {
spinlock_t susp_lock;
unsigned int suspended:1;
int in_flight;
+ struct option_blacklist_info *blacklist_info;
};

struct option_port_private {
@@ -737,9 +762,27 @@ static int option_probe(struct usb_seria
if (!data)
return -ENOMEM;
spin_lock_init(&data->susp_lock);
+ data->blacklist_info = (struct option_blacklist_info*) id->driver_info;
return 0;
}

+static option_blacklist_reason_t is_blacklisted(const u8 ifnum,
+ const struct option_blacklist_info *blacklist)
+{
+ const u8 *info;
+ int i;
+
+ if (blacklist) {
+ info = blacklist->ifaceinfo;
+
+ for (i = 0; i < blacklist->infolen; i++) {
+ if (info[i] == ifnum)
+ return blacklist->reason;
+ }
+ }
+ return OPTION_BLACKLIST_NONE;
+}
+
static void option_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
@@ -1170,11 +1213,18 @@ static void option_setup_urbs(struct usb
static int option_send_setup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
+ struct option_intf_private *intfdata = (struct option_intf_private *) serial->private;
struct option_port_private *portdata;
int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
int val = 0;
dbg("%s", __func__);

+ if (is_blacklisted(ifNum, intfdata->blacklist_info) ==
+ OPTION_BLACKLIST_SENDSETUP) {
+ dbg("No send_setup on blacklisted interface #%d\n", ifNum);
+ return -EIO;
+ }
+
portdata = usb_get_serial_port_data(port);

if (portdata->dtr_state)

2009-12-08 07:34:33

by Matthias Urlichs

[permalink] [raw]