Anybody in SA got Telkom ADSL + Linux working?

rylan76

New Member
Joined
Jun 19, 2004
Messages
3
Hi guys

I am having extreme amounts of trouble getting Telkom ADSL to work with Linux. I dual boot W98 and Rh9, and of course the ADSL connection works fine in Windows. In Linux, I have installed and configured Rp-PPPOE but it absolutely refuses to work - I get messages in my /var/log/messages like this:

Jun 19 03:52:35 StefanLinux pppd[3519]: pppd 2.4.1 started by root, uid 0
Jun 19 03:52:35 StefanLinux pppd[3519]: Using interface ppp0
Jun 19 03:52:35 StefanLinux pppd[3519]: Connect: ppp0 <--> /dev/pts/3
Jun 19 03:52:35 StefanLinux /etc/hotplug/net.agent: assuming ppp0 is already up
Jun 19 03:53:06 StefanLinux pppd[3519]: LCP: timeout sending Config-Requests
Jun 19 03:53:06 StefanLinux pppd[3519]: Connection terminated.
Jun 19 03:53:07 StefanLinux /etc/hotplug/net.agent: NET unregister event not
supported
Jun 19 03:53:10 StefanLinux pppoe[3520]: Timeout waiting for PADO packets
Jun 19 03:53:10 StefanLinux pppd[3519]: Exit.

So the Telkom POTS is not responding to LCP requests required to configure a connection.

How can I get the Telkom ADSL router/modem to work with Linux? Or is this absolutely impossible? I have also tried dhclient eth0 but that does not work either - ifconfig does not list a new ppp0 interface afterward and opening a browser just results in "unknown site" i. e. there is still no connection to ADSL.

ANYBODY ANYWHERE in SA got Telkom ADSL to work with Linux??

Any help appreciated!

Stefan Viljoen
Software Support Technician
Polar Design Solutions
 

podo

Well-Known Member
Joined
Apr 16, 2004
Messages
288
I have it working on two separate UNIX installations. One is an antiquated Debian Linux machine at a client. The other is the FreeBSD machine at my house.

First off, I recommend you get FreeBSD, since the FreeBSD userspace ppp(8) program can do PPPoE directly, as long as you have the NETGRAPH_PPPOE option in your kernel, or load the module before starting ppp(8). This works much better than the Linux solution, but using Linux isn't impossible.

RP-PPPoE should have an adsl-setup script supplied with it to allow you to configure the system for PPPoE. Make sure you have everything set up right first. If that doesn't help, you might have some other problems.

First off, you MUST have an ethernet bridge type ADSL modem for this to work. A router type modem will work too, but if you have that, I highly recommend using the router's built in PPPoE client instead.

If you have the USB modem, ADSL will NOT work in Linux for you. While some third party drivers can be found for some USB modems, there is absolutely no support what so ever for the Telkom Marconi USB modems.

If you have an ethernet modem, make sure it is set to use IP Bridged LLC mode with VPI 8 and VCI 35. If you have an ethernet router modem, set up the router's PPPoE client to connect and do NAT, then configure your PCs to use the router as a default gateway. This way, your PCs do not handle the internet connection themselves.

If you are stuck with the USB modem, you are pretty much stuck. I'm fairly certain Telkom won't take it back, so your only option for getting rid of it will be the second hand market. Once you are rid of it, get yourself an ethernet bridge type modem or a router.

If you're on a budget, go for the bridge type modem. With this kind of modem, your PC must still run the PPPoE client, but since the modem is connected via ethernet, no driver support is necessary for the modem itself to operate.

At both of my working UNIX based installations, I use the D-Link DSL300G. It offers excellent stability and while it is only useful as a bridge, it's great value for money. If you know where to shop, you should be able to pick one up for about R750.

Willie Viljoen
Web Developer

Adaptive Web Development
 

neobyte

Well-Known Member
Joined
Oct 30, 2003
Messages
387
I've got the USB version working fine. It was a mission to set up though. Check out the Alcatel USB modem site for details on how to install the USB version. But, it ends up quite a mess.
 

podo

Well-Known Member
Joined
Apr 16, 2004
Messages
288
neobyte,

That would work if you are lucky enough to have the Alcatal USB modem. All the new installations that take a modem from Telkom get the Marconi USB modem. If you have that, there's no Linux (or any UNIX) support at all. [:(]

Willie Viljoen
Web Developer

Adaptive Web Development
 

neobyte

Well-Known Member
Joined
Oct 30, 2003
Messages
387
The modem I have is the Marconi USB modem. I got it when ADSL first came out in SA (so I got screwed by Telkom in terms of the price). However, I emailed Marconi USA and about a week later got a reply saying that they based on the Alcatel chipset on the version I had. Something similar to how most modems/ethernet have a Rockwell chipset. So after much browsing managed to find an Alcatel set up guide... The follwing site helped me a lot and only minor tweaking had to be done in the end...

http://linux-usb.sourceforge.net/SpeedTouch/docs/howto.html

Although I must admit in the end I did not use the drivers provided as Fedora Core 2 picked up a modem one the USB port as something else... (External PPPoE Router)... But it was a lot of tweaking.
 

thomasa

Active Member
Joined
Jul 8, 2004
Messages
30
I also have a marconi telkom usb adsl modem. Do these drivers/methods really work on Linux with this modem? If so, can anyone write a quick HOWTO on how this has been achieved so that people like myself arent in the dark?

Thanks
 

neobyte

Well-Known Member
Joined
Oct 30, 2003
Messages
387
I have not tried it... I went the long way round to give me full control so if something went wrong I knew exactly where it happened. The HOWTO is not too bad to follow. You can try the firmware.bin and if that does not work apply your mind to the task of the tutorial.
 

thomasa

Active Member
Joined
Jul 8, 2004
Messages
30
right, i have modified softtch.c to use the ID of my modem which is 0bb9/a5a5 instead of 0bb9/4061

I assume this is what you did aswell? Did you use the firmware .sys file that came with the driver on the telkom cd ? I dont find the one that they make mention to , but there are some other .sys files which look interesting.... or havent you done it yet?
 

neobyte

Well-Known Member
Joined
Oct 30, 2003
Messages
387
I dont remember using any other software except for the downloads the HOWTO describes. I do remember that I had to do another thing, make sure you have enabled the HOT SWAP and other USB features in your kernal. With regards to editing the c files, if it builds it will generally work. I think I eventually got all the info from my modem using usbprobe (or a similar tool). Just make sure you have recompilled the kernel with all the USB stuff. It is disabled for security (i.e. to stop people walking in with a memory stick and taking ur data)
 

neobyte

Well-Known Member
Joined
Oct 30, 2003
Messages
387
Another thing though is if you are having trouble have try a VMWare solution?
 

thomasa

Active Member
Joined
Jul 8, 2004
Messages
30
I think my problem is with the firmware I am using. Will it be possible for me to get a copy of the firmware binary file you're using?

Thanks
 

neobyte

Well-Known Member
Joined
Oct 30, 2003
Messages
387
//Make sure you call the init method!!!

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/proc_fs.h>
#include <linux/malloc.h>
#include <linux/list.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#include <linux/smp_lock.h>

#include <linux/atm.h>
#include <linux/atmdev.h>

#include "sarlib.h"

/*
#define DEBUG 1
*/
#define DEBUG_PACKET 1

#ifdef DEBUG
#define PDEBUG(arg...) printk(KERN_DEBUG "SpeedTouch USB: " arg)
#else
#define PDEBUG(arg...)
#endif


#ifdef DEBUG_PACKET
#define PACKETDEBUG(arg...) udsl_print_packet ( arg )
#else
#define PACKETDEBUG(arg...)
#endif

MODULE_AUTHOR ("Johan Verrept (Johan.Verrept@advalvas.be)");
MODULE_DESCRIPTION ("Driver for the Alcatel Speed Touch USB ADSL modem.");

#define SPEEDTOUCH_VENDORID 0x0466
#define SPEEDTOUCH_PRODUCTID 0x4261

#define MAX_UDSL 1
#define UDSL_OBUF_SIZE 32768
#define UDSL_MINOR 48
#define UDSL_NUMBER_RCV_URBS 1
#define UDSL_RECEIVE_BUFFER_SIZE 64*53
#define UDSL_MAX_AAL5_MRU 1500 /* max should be (1500 IP mtu + 2 ppp bytes + 32 * 5 cellheader overhead) for PPPoA and (1500 + 14 + 32*5 cellheader overhead) for PPPoE */
#define UDSL_SEND_CONTEXTS 8

#define UDSL_IOCTL_START 1
#define UDSL_IOCTL_STOP 2

/* endpoint declarations */

#define UDSL_ENDPOINT_DATA_OUT 0x7
#define UDSL_ENDPOINT_DATA_IN 0x87

/* usb_device_id struct */

static struct usb_device_id udsl_usb_ids [] =
{
{ USB_DEVICE (SPEEDTOUCH_VENDORID, SPEEDTOUCH_PRODUCTID) },
{ } /* list terminator */
};

/* not exporting this prevents the depmod from generating the map that causes the modules to be isnserted as driver.
* we do not want this, we want the script run.
MODULE_DEVICE_TABLE ( usb, udsl_usb_ids);
*/
/* context declarations */

typedef struct udsl_data_ctx {
struct sk_buff *skb;
urb_t *urb;
struct udsl_instance_data *instance;
} udsl_data_ctx_t;

typedef struct udsl_usb_send_data_context {
urb_t urb;
struct sk_buff *skb;
struct atm_vcc *vcc;
} udsl_usb_send_data_context_t;

/*
* UDSL main driver data
*/

struct udsl_instance_data {
int minor;

/* usb device part */
struct usb_device *usb_dev;
udsl_data_ctx_t *rcvbufs;
struct sk_buff_head skb_queue;
udsl_usb_send_data_context_t send_ctx;
int data_started;

/* atm device part */
struct atm_dev *atm_dev;
struct sk_buff_head recvqueue;
struct sarlib_vcc_data *sarlib_vcc_list;
};

struct udsl_instance_data *minor_data[MAX_UDSL];

static const char udsl_driver_name[] = "Alcatel SpeedTouch USB";

/* data thread */
static int datapid = 0;
DECLARE_WAIT_QUEUE_HEAD(udsl_wqh);

#ifdef DEBUG_PACKET
int udsl_print_packet (const unsigned char *data, int len);
#endif

/*
* atm driver prototypes and stuctures
*/

static int udsl_atm_open(struct atm_vcc *vcc, short vpi, int vci);
static void udsl_atm_close(struct atm_vcc *vcc);
static int udsl_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg);
static int udsl_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
int udsl_atm_proc_read (struct atm_dev * atm_dev, loff_t * pos, char * page);
void udsl_atm_processqueue ( struct udsl_instance_data *instance);

static struct atmdev_ops udsl_atm_devops =
{
open: udsl_atm_open,
close: udsl_atm_close,
ioctl: udsl_atm_ioctl,
send: udsl_atm_send,
proc_read: udsl_atm_proc_read,
};

typedef struct udsl_atm_dev_data {
struct sarlib_vcc_data *sarlib_vcc;
} udsl_atm_dev_data_t;

/*
* usb driver prototypes and structures
*/
static void * udsl_usb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id);
static void udsl_usb_disconnect(struct usb_device *dev, void *ptr);
int udsl_usb_send_data (struct udsl_instance_data *instance, struct atm_vcc *vcc, struct sk_buff *skb);
static int udsl_usb_ioctl (struct usb_device *hub, unsigned int code, void *user_data);

static struct usb_driver udsl_usb_driver =
{
name: udsl_driver_name,
probe: udsl_usb_probe,
disconnect: udsl_usb_disconnect,
ioctl: udsl_usb_ioctl,
id_table: udsl_usb_ids,
};

/************
** ATM **
************/

/***************************************************************************
*
* init functions
*
****************************************************************************/

struct atm_dev *udsl_atm_startdevice(struct udsl_instance_data *instance, struct atmdev_ops *devops) {
MOD_INC_USE_COUNT;

instance->atm_dev = atm_dev_register(udsl_driver_name, devops, -1, 0);
instance->atm_dev->dev_data = instance;
instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX;
instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX;
instance->atm_dev->signal = ATM_PHY_SIG_LOST;

skb_queue_head_init(&instance->recvqueue);

/* tmp init atm device, set to 128kbit */
instance->atm_dev->link_rate = 128*1000/424;

return instance->atm_dev;
}

void udsl_atm_stopdevice(struct udsl_instance_data *instance) {
struct atm_vcc *walk;
struct sk_buff *skb;
struct atm_dev *atm_dev;

if (!instance->atm_dev)
return;

atm_dev = instance->atm_dev;

/* clean queue */
while (!skb_queue_empty(&instance->recvqueue)) {
skb = skb_dequeue (&instance->recvqueue);
dev_kfree_skb(skb);
};

atm_dev->signal = ATM_PHY_SIG_LOST;
walk = atm_dev->vccs;
shutdown_atm_dev(atm_dev);

for (; walk; walk = walk->next)
wake_up(&walk->sleep);

MOD_DEC_USE_COUNT;
}

void udsl_atm_set_mac(struct udsl_instance_data *instance, const char mac[6]) {
if (!instance->atm_dev)
return;

memcpy (instance->atm_dev->esi, mac, 6);
}

/***************************************************************************
*
* ATM helper functions
*
****************************************************************************/
struct sk_buff * udsl_atm_alloc_tx(struct atm_vcc *vcc,unsigned int size) {
sarlib_vcc_data_t *sarlib_vcc = ((struct udsl_atm_dev_data *)vcc->dev_data)->sarlib_vcc;

if (sarlib_vcc)
return sarlib_alloc_tx(sarlib_vcc, size);

printk(KERN_INFO "SpeedTouch USB: udsl_atm_alloc_tx could not find correct alloc_tx function !\n");
return NULL;
}

int udsl_atm_proc_read (struct atm_dev * atm_dev, loff_t * pos, char * page) {
struct udsl_instance_data *instance = (struct udsl_instance_data *) atm_dev->dev_data;
int left = *pos;

if (!left--)
return sprintf(page, "Speed Touch USB:%d (%02x:%02x:%02x:%02x:%02x:%02x)\n", instance->minor,
atm_dev->esi[0], atm_dev->esi[1], atm_dev->esi[2], atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]);

if (!left--)
return sprintf(page, "AAL0: tx %d ( %d err ), rx %d ( %d err, %d drop )\n",
atomic_read(&atm_dev->stats.aal0.tx), atomic_read(&atm_dev->stats.aal0.tx_err),
atomic_read(&atm_dev->stats.aal0.rx), atomic_read(&atm_dev->stats.aal0.rx_err), atomic_read(&atm_dev->stats.aal0.rx_drop));

if (!left--)
return sprintf(page, "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n",
atomic_read(&atm_dev->stats.aal5.tx), atomic_read(&atm_dev->stats.aal5.tx_err),
atomic_read(&atm_dev->stats.aal5.rx), atomic_read(&atm_dev->stats.aal5.rx_err), atomic_read(&atm_dev->stats.aal5.rx_drop));

return 0;
}

/***************************************************************************
*
* ATM DATA functions
*
****************************************************************************/
int udsl_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) {
struct udsl_atm_dev_data *dev_data = (struct udsl_atm_dev_data *) vcc->dev_data;
struct udsl_instance_data *instance = (struct udsl_instance_data *) vcc->dev->dev_data;
struct sk_buff *new = NULL;
int err;

PDEBUG("udsl_atm_send called\n");

if (!dev_data)
return -EINVAL;

switch (vcc->qos.aal) {
case ATM_AAL5:
new = sarlib_encode_aal5(dev_data->sarlib_vcc, skb);
if (!new) return -ENOMEM;
if (new != skb) {
vcc->pop(vcc, skb);
skb = new;
}
new = sarlib_encode_rawcell(dev_data->sarlib_vcc, skb);
if (!new) return -ENOMEM;
if (new != skb) {
vcc->pop(vcc, skb);
skb = new;
}
err = udsl_usb_send_data (instance, vcc, skb);
PDEBUG("udsl_atm_send successfull (%d)\n", err);
return err;
break;
default:
return -EINVAL;
};

PDEBUG("udsl_atm_send unsuccessfull\n");
return 0;
};


void udsl_atm_processqueue ( struct udsl_instance_data *instance) {
struct sarlib_vcc_data *sarlib_vcc = NULL;
struct sk_buff *new = NULL, *skb = NULL;

/* quick check */
if (skb_queue_empty(&instance->recvqueue))
return;

PDEBUG("udsl_atm_processqueue entered\n");

while (!skb_queue_empty(&instance->recvqueue)) {
skb = skb_dequeue (&instance->recvqueue);
PDEBUG("skb = %p, skb->len = %d\n", skb, skb->len);

PACKETDEBUG (skb->data, skb->len);

while ( (new = sarlib_decode_rawcell (instance->sarlib_vcc_list, skb, &sarlib_vcc)) != NULL) {
PDEBUG("(after cell processing)skb->len = %d\n", new->len);
switch (sarlib_vcc->type) {
case SARLIB_TYPE_AAL5:
new = sarlib_decode_aal5 (sarlib_vcc, new);

/* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */
if (new) {
PDEBUG("(after aal5 decap) skb->len = %d\n", new->len);
if (new->len && atm_charge(sarlib_vcc->vcc, new->truesize)) {
PACKETDEBUG (new->data, new->len);
sarlib_vcc->vcc->push(sarlib_vcc->vcc, new);
}
else {
PDEBUG("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d\n", atomic_read(&sarlib_vcc->vcc->rx_inuse), sarlib_vcc->vcc->sk->rcvbuf, new->truesize);
dev_kfree_skb(new);
}
}
else
PDEBUG("sarlib_decode_aal5 returned NULL!\n");
break;
default:
/* not supported. we delete the skb. */
printk(KERN_INFO "SpeedTouch USB: illegal vcc type. Dropping packet.\n");
dev_kfree_skb(new);
break;
}
};
dev_kfree_skb (skb);
};
PDEBUG("udsl_atm_processqueue successfull\n");
}

int udsl_atm_processqueue_thread (void *data) {
int i=0;
DECLARE_WAITQUEUE(wait, current);

lock_kernel();
exit_files(current); /* daemonize doesn't do exit_files */
daemonize();

/* Setup a nice name */
strcpy(current->comm, "kSpeedSARd");

add_wait_queue(&udsl_wqh, &wait);

for(;;) {
interruptible_sleep_on(&udsl_wqh);
if (signal_pending(current)) break;
PDEBUG("SpeedSARd awoke\n");
for (i=0; i < MAX_UDSL ; i++)
if (minor_data)
udsl_atm_processqueue(minor_data);
};

datapid = 0;
PDEBUG("SpeedSARd is exiting\n");
return 0;
}


void udsl_atm_sar_start (void) {
datapid = kernel_thread(udsl_atm_processqueue_thread, (void *)NULL,
CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
}

void udsl_atm_sar_stop (void) {
int ret;

/* Kill the thread */
ret = kill_proc(datapid, SIGTERM, 1);
if (!ret) {
/* Wait 10 seconds */
int count = 10 * 100;

while (datapid && --count) {
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(1);
}

if (!count)
err("giving up on killing SpeedSAR thread.");
}
}

/***************************************************************************
*
* SAR driver entries
*
****************************************************************************/
int udsl_atm_open(struct atm_vcc *vcc, short vpi, int vci) {
struct udsl_atm_dev_data *dev_data;
struct udsl_instance_data *instance = (struct udsl_instance_data *)vcc->dev->dev_data;

PDEBUG("udsl_atm_open called\n");

/* at the moment only AAL5 support */
if (vcc->qos.aal != ATM_AAL5)
return -EINVAL;

MOD_INC_USE_COUNT;
dev_data = (struct udsl_atm_dev_data *)kmalloc (sizeof(struct udsl_atm_dev_data), GFP_KERNEL);
if (!dev_data)
return -ENOMEM;

dev_data->sarlib_vcc = sarlib_open (&(instance->sarlib_vcc_list), vcc, SARLIB_TYPE_AAL5, vpi, vci, 0, 0, SARLIB_USE_53BYTE_CELL | SARLIB_SET_PTI);
if (!dev_data->sarlib_vcc) {
kfree(dev_data);
return -ENOMEM; /* this is the only reason sarlib_open can fail... */
}

vcc->vpi = vpi;
vcc->vci = vci;
set_bit(ATM_VF_ADDR, &vcc->flags);
set_bit(ATM_VF_PARTIAL, &vcc->flags);
set_bit(ATM_VF_READY, &vcc->flags);
vcc->dev_data = dev_data;
vcc->alloc_tx = udsl_atm_alloc_tx;

dev_data->sarlib_vcc->mtu = UDSL_MAX_AAL5_MRU;

PDEBUG("udsl_atm_open successfull\n");
return 0;
}

void udsl_atm_close(struct atm_vcc *vcc) {
struct udsl_atm_dev_data *dev_data = (struct udsl_atm_dev_data *)vcc->dev_data;
struct udsl_instance_data *instance = (struct udsl_instance_data *)vcc->dev->dev_data;

PDEBUG("udsl_atm_close called\n");

/* freeing resources */
sarlib_close (&(instance->sarlib_vcc_list), dev_data->sarlib_vcc);
kfree (dev_data);
vcc->dev_data = NULL;
clear_bit(ATM_VF_PARTIAL, &vcc->flags);

/* freeing address */
vcc->vpi = ATM_VPI_UNSPEC;
vcc->vci = ATM_VCI_UNSPEC;
clear_bit(ATM_VF_ADDR, &vcc->flags);

MOD_DEC_USE_COUNT;

PDEBUG("udsl_atm_close successfull\n");
return;
};

int udsl_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) {
switch (cmd) {
case ATM_QUERYLOOP:
return put_user(ATM_LM_NONE, (int *) arg) ? -EFAULT : 0;
default:
return -ENOIOCTLCMD;
}
};


/************
** USB **
************/

/***************************************************************************
*
* usb data functions
*
****************************************************************************/

typedef struct udsl_cb {
struct atm_vcc *vcc;
} udsl_cb_t;

static void udsl_usb_send_data_complete(urb_t *urb) {
struct udsl_instance_data *instance = (struct udsl_instance_data *)urb->context;
udsl_usb_send_data_context_t *ctx = &instance->send_ctx;
int err;

PDEBUG("udsl_usb_send_data_completion (vcc = %p, skb = %p, status %d)\n", ctx->vcc, ctx->skb, urb->status);

/* remove completed skb */
ctx->skb = skb_dequeue(&(instance->skb_queue));
ctx->vcc->pop (ctx->vcc, ctx->skb);
ctx->skb = NULL;

if (skb_queue_empty(&instance->skb_queue))
return;

/* submit next skb */
ctx->skb = skb_peek (&(instance->skb_queue));
ctx->vcc = ((udsl_cb_t *)(ctx->skb->cb))->vcc;

FILL_BULK_URB(urb,
instance->usb_dev,
usb_sndbulkpipe(instance->usb_dev, UDSL_ENDPOINT_DATA_OUT),
(unsigned char *)ctx->skb->data,
ctx->skb->len,
(usb_complete_t)udsl_usb_send_data_complete,
instance
);

err = usb_submit_urb(urb);

PDEBUG("udsl_usb_send_data_completion (send packet %p with length %d), retval = %d\n", ctx->skb, ctx->skb->len, err);
}

/**** send ******/
int udsl_usb_send_data (struct udsl_instance_data *instance, struct atm_vcc *vcc, struct sk_buff *skb) {
int err;
urb_t *urb;

PDEBUG("udsl_usb_send_data entered, sending packet %p with length %d\n", skb, skb->len);

if (!instance->data_started)
return -EAGAIN;

PACKETDEBUG (skb->data, skb->len);

if (!skb_queue_empty(&instance->skb_queue)) {
((udsl_cb_t *)skb->cb)->vcc = vcc;
skb_queue_tail (&instance->skb_queue, skb);
PDEBUG("udsl_usb_send_data: skb (0x%p) queued\n", skb);
return 0;
}

((udsl_cb_t *)skb->cb)->vcc = vcc;
skb_queue_tail (&instance->skb_queue, skb);

/* submit packet */
urb = &(instance->send_ctx.urb);
instance->send_ctx.skb = skb;
instance->send_ctx.vcc = vcc;

FILL_BULK_URB(urb,
instance->usb_dev,
usb_sndbulkpipe(instance->usb_dev, UDSL_ENDPOINT_DATA_OUT),
(unsigned char *)skb->data,
skb->len,
(usb_complete_t)udsl_usb_send_data_complete,
instance
);

err = usb_submit_urb(urb);

if (err != 0)
skb_unlink(skb);

PDEBUG("udsl_usb_send_data done (retval = %d)\n", err);
return err;
}

/********* receive *******/
void udsl_usb_data_receive(urb_t *urb) {
udsl_data_ctx_t *ctx;
struct udsl_instance_data *instance;

if (!urb) return;

PDEBUG("udsl_usb_receive_data entered, got packet %p with length %d an status %d\n", urb, urb->actual_length, urb->status);

ctx = (udsl_data_ctx_t *)urb->context;
if (!ctx || !ctx->skb) return;

instance = ctx->instance;

switch (urb->status) {
case 0:
PDEBUG("udsl_usb_data_receive: processing urb with ctx %p, urb %p (%p), skb %p\n", ctx, ctx ? ctx->urb : NULL , urb, ctx ? ctx->skb : NULL);

/* update the skb structure */
skb_put(ctx->skb, urb->actual_length);

/* queue the skb for processing and wake the SAR */
skb_queue_tail (&instance->recvqueue, ctx->skb);
wake_up(&udsl_wqh);

/* get a new skb */
ctx->skb = dev_alloc_skb(UDSL_RECEIVE_BUFFER_SIZE);
if (!ctx->skb) {
PDEBUG("No skb, loosing urb.\n");
usb_free_urb(ctx->urb);
ctx->urb = NULL;
return;
}
break;
case -EPIPE: /* stall or babble */
usb_clear_halt(urb->dev, usb_rcvbulkpipe(urb->dev, UDSL_ENDPOINT_DATA_IN));
break;
case -ENOENT: /* buffer was unlinked */
case -EILSEQ: /* unplug or timeout */
case -ETIMEDOUT: /* unplug or timeout */
/*
* we don't do anything here and we don't resubmit
*/
return;
}

FILL_BULK_URB(urb,
instance->usb_dev,
usb_rcvbulkpipe(instance->usb_dev, UDSL_ENDPOINT_DATA_IN),
(unsigned char *)ctx->skb->data,
UDSL_RECEIVE_BUFFER_SIZE,
(usb_complete_t)udsl_usb_data_receive,
ctx
);
urb->transfer_flags |= USB_QUEUE_BULK;

usb_submit_urb(urb);

return;
};

int udsl_usb_data_init(struct udsl_instance_data *instance) {
int i, succes;

/* set alternate setting 1 on interface 1 */
usb_set_interface(instance->usb_dev, 1, 2);

PDEBUG("max packet size on endpoint %d is %d\n", UDSL_ENDPOINT_DATA_OUT, usb_maxpacket (instance->usb_dev, usb_sndbulkpipe(instance->usb_dev, UDSL_ENDPOINT_DATA_OUT), 0));

instance->rcvbufs = (udsl_data_ctx_t *)kmalloc (sizeof(udsl_data_ctx_t) * UDSL_NUMBER_RCV_URBS , GFP_KERNEL);
if (!instance->rcvbufs)
return -ENOMEM;

memset (instance->rcvbufs, 0, sizeof(udsl_data_ctx_t) * UDSL_NUMBER_RCV_URBS);

for (i=0, succes = 0 ; i < UDSL_NUMBER_RCV_URBS; i++) {
udsl_data_ctx_t *ctx = &(instance->rcvbufs);

ctx->urb = NULL;
ctx->skb = dev_alloc_skb(UDSL_RECEIVE_BUFFER_SIZE);
if (!ctx->skb) continue;

ctx->urb = usb_alloc_urb(0);
if (!ctx->urb) {
kfree_skb(ctx->skb);
ctx->skb = NULL;
break;
};

FILL_BULK_URB(ctx->urb,
instance->usb_dev,
usb_rcvbulkpipe(instance->usb_dev, UDSL_ENDPOINT_DATA_IN),
(unsigned char *)ctx->skb->data,
UDSL_RECEIVE_BUFFER_SIZE,
(usb_complete_t)udsl_usb_data_receive,
ctx
);
ctx->urb->transfer_flags |= USB_QUEUE_BULK;

ctx->instance = instance;

PDEBUG("udsl_usb_data_init: usb with skb->truesize = %d (Asked for %d)\n", ctx->skb->truesize, UDSL_RECEIVE_BUFFER_SIZE);

if (usb_submit_urb(ctx->urb) < 0)
PDEBUG("udsl_usb_data_init: Submit failed, loosing urb.\n");
else
succes++;
}

instance->data_started=1;
instance->atm_dev->signal = ATM_PHY_SIG_FOUND;

skb_queue_head_init(&instance->skb_queue);

PDEBUG("udsl_usb_data_init %d urb%s queued for receive\n", succes, (succes!=1) ? "s" : "");
return 0;
}

int udsl_usb_data_exit(struct udsl_instance_data *instance) {
int i;

if (!instance->data_started)
return 0;

if (!instance->rcvbufs)
return 0;

/* destroy urbs */
for (i=0; i < UDSL_NUMBER_RCV_URBS; i++) {
udsl_data_ctx_t *ctx = &(instance->rcvbufs);

if (!ctx->urb)
continue;

if (ctx->urb->status == -EINPROGRESS)
usb_unlink_urb(ctx->urb);

usb_free_urb(ctx->urb);
kfree_skb(ctx->skb);
};

/* free receive contexts */
kfree (instance->rcvbufs);
instance->rcvbufs = NULL;

instance->data_started=0;
instance->atm_dev->signal = ATM_PHY_SIG_LOST;

return 0;
};


/***************************************************************************
*
* usb driver entries
*
****************************************************************************/
#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) )


static int udsl_usb_ioctl (struct usb_device *dev, unsigned int code, void *user_data) {
struct udsl_instance_data *instance;
int i;

for (i=0; i < MAX_UDSL; i++)
if (minor_data && (minor_data->usb_dev == dev))
break;

if (i==MAX_UDSL)
return -EINVAL;

instance = minor_data;

switch(code) {
case UDSL_IOCTL_START:
return udsl_usb_data_init (instance);
break;
case UDSL_IOCTL_STOP:
return udsl_usb_data_exit (instance);
break;
default:
break;
}
return -EINVAL;
}

void *udsl_usb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
{
int i;
unsigned char mac[6];
unsigned char mac_str[13];
struct udsl_instance_data *instance = NULL;

PDEBUG("Trying device with Vendor=0x%x, Product=0x%x, ifnum %d\n", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);

if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC)||
(dev->descriptor.idVendor != SPEEDTOUCH_VENDORID)||
(dev->descriptor.idProduct != SPEEDTOUCH_PRODUCTID)||
(ifnum!=1))
return NULL;

MOD_INC_USE_COUNT;

for (i=0; i < MAX_UDSL; i++)
if (minor_data == NULL)
break;

if (i >= MAX_UDSL) {
printk(KERN_INFO "No minor table space available for SpeedTouch USB\n");
return NULL;
};

PDEBUG("Device Accepted, assigning minor %d\n", i);

/* device init */
instance = kmalloc(sizeof(struct udsl_instance_data), GFP_KERNEL);
if (!instance) {
PDEBUG("No memory for Instance data!\n");
return NULL;
}

/* initialize structure */
memset(instance, 0, sizeof(struct udsl_instance_data));
instance->minor = i;
instance->usb_dev = dev;
instance->rcvbufs = NULL;

udsl_atm_startdevice(instance, &udsl_atm_devops);

/* set MAC address, it is stored in the serial number */
usb_string(instance->usb_dev, instance->usb_dev->descriptor.iSerialNumber, mac_str, 13);
for (i=0; i<6; i++)
mac = (hex2int(mac_str[i*2])*16) + (hex2int(mac_str[i*2+1]));

PDEBUG("MAC is %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
udsl_atm_set_mac(instance, mac);

minor_data[instance->minor] = instance;

return instance;
}

void udsl_usb_disconnect(struct usb_device *dev, void *ptr)
{
struct udsl_instance_data *instance = (struct udsl_instance_data *)ptr;
int i = instance->minor;

/* unlinking receive buffers */
udsl_usb_data_exit(instance);

/* removing atm device */
if (instance->atm_dev)
udsl_atm_stopdevice(instance);

PDEBUG("disconnecting minor %d\n", i);

while (MOD_IN_USE > 1) {
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(1);
}

kfree (instance);
minor_data = NULL;

MOD_DEC_USE_COUNT;
}

/***************************************************************************
*
* Driver Init
*
****************************************************************************/
//Call this first -- neobyte
int udsl_usb_init(void)
{
int i;

PDEBUG ("Initializing driver\n");

for (i =0; i < MAX_UDSL ; i++)
minor_data = NULL;

init_waitqueue_head(&udsl_wqh);
udsl_atm_sar_start();

return usb_register(&udsl_usb_driver);
}

int udsl_usb_cleanup(void)
{
/* killing threads */
udsl_atm_sar_stop();

usb_deregister(&udsl_usb_driver);
return 0;
}

#ifdef MODULE
int init_module(void)
{
return udsl_usb_init();
}

int cleanup_module(void)
{
return udsl_usb_cleanup();
}
#endif

#ifdef DEBUG_PACKET
/*******************************************************************************
*
* Debug
*
*******************************************************************************/

int udsl_print_packet (const unsigned char *data, int len) {
unsigned char buffer[256];
int i=0, j=0;

for (i = 0; i < len ; ) {
buffer[0] = '\0';
sprintf(buffer,"%.3d :", i);
for (j = 0; (j < 16) && (i< len) ; j++, i++) {
sprintf(buffer, "%s %2.2x", buffer, data);
}
PDEBUG("%s\n", buffer);
}
return i;
};

#endif /* PACKETDEBUG */
 

antowan

Honorary Master
Joined
Nov 1, 2003
Messages
13,054
In Xwindows on RedHat9 go to,

System Settings
Network

Make a new connection using the Xdsl config

Make sure that your NIC eth0 points to DNS 196.25.0.1

Should work...

Cheers


He who does not understand the value of war at the right time, cannot comprehend the value of life at any time - Anonymous
 
Top