?

Log in

Adventures in device driver hacking - Mike Quin's Journal [entries|archive|friends|userinfo]
Mike Quin

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Adventures in device driver hacking [Jan. 21st, 2011|10:57 am]
Mike Quin
So, for a little project I'm cooking up I needed a couple of USB Ethernet interfaces. There's no shortage of ebay sellers of these so I grabbed a couple from the first UK seller I found, with them arriving promptly the next day.

Now, in the last few years Linux's hardware support has improved to the point that I don't spend as much time worrying about whether things will work: they invariably do.

So, plug and play, right? Sadly in this case I was disappointed. Plugging in the adapter prompted a report that it was there and was indeed a 10/100 Ethernet device, but nothing further. No driver support on the plain-vanilla Debian install currently gracing my netbook. That was surprise one.

Surprise two was finding that the supplied driver CD (how quaint!) had a Linux directory. Fortunately out-of-tree drivers follow a reasonably standardised structure so the Chinese README wasn't a problem. However it wasn't all plain sailing.

% make
Building QF9700 USB2NET chip driver...
make[1]: Entering directory `/usr/src/linux-headers-2.6.32-trunk-amd64'
  CC [M]  /home/mrq1/tmp/qf9700/qf9700.o
/home/mrq1/tmp/qf9700/qf9700.c: In function ‘qf9700_bind’:
/home/mrq1/tmp/qf9700/qf9700.c:380: error: ‘struct net_device’ has no member named ‘do_ioctl’
/home/mrq1/tmp/qf9700/qf9700.c:381: error: ‘struct net_device’ has no member named ‘set_multicast_list’
/home/mrq1/tmp/qf9700/qf9700.c: In function ‘qf9700_rx_fixup’:
/home/mrq1/tmp/qf9700/qf9700.c:443: error: ‘struct usbnet’ has no member named ‘stats’
/home/mrq1/tmp/qf9700/qf9700.c:444: error: ‘struct usbnet’ has no member named ‘stats’
/home/mrq1/tmp/qf9700/qf9700.c:445: error: ‘struct usbnet’ has no member named ‘stats’
/home/mrq1/tmp/qf9700/qf9700.c:446: error: ‘struct usbnet’ has no member named ‘stats’
/home/mrq1/tmp/qf9700/qf9700.c:447: error: ‘struct usbnet’ has no member named ‘stats’
make[4]: *** [/home/mrq1/tmp/qf9700/qf9700.o] Error 1
make[3]: *** [_module_/home/mrq1/tmp/qf9700] Error 2
make[2]: *** [sub-make] Error 2
make[1]: *** [all] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-trunk-amd64'
make: *** [all] Error 2




At this point I'm wondering if I've bought an (admittedly cheap) lemon.

Undeterred, I took the somewhat blunt approach of commenting out the lines that GCC had complained about, and lo and behold, it builds!

Better than that, it loaded without crashing the machine and appeared to work as intended, and with a little bit of poking around on google and refering to the source of other usbnet drivers I was able to bring the driver (hopefully) in line with the current network device API.


diff -ru a/qf9700.c b/qf9700.c
--- a/qf9700.c	2010-10-09 09:50:52.000000000 +0100
+++ b/qf9700.c	2011-01-21 09:59:58.019399508 +0000
@@ -368,6 +368,17 @@
 	qf_write_async(dev, MAR, QF_MCAST_SIZE, hashes);
 	qf_write_reg_async(dev, RCR, rx_ctl);
 }
+static const struct net_device_ops qf9700_netdev_ops = {
+	.ndo_open		= usbnet_open,
+	.ndo_stop		= usbnet_stop,
+	.ndo_start_xmit		= usbnet_start_xmit,
+	.ndo_tx_timeout		= usbnet_tx_timeout,
+	.ndo_change_mtu		= usbnet_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_do_ioctl		= qf9700_ioctl,
+	.ndo_set_multicast_list = qf9700_set_multicast,
+};
 
 static int qf9700_bind(struct usbnet *dev, struct usb_interface *intf)
 {
@@ -377,8 +388,7 @@
 	if (ret)
 		goto out;
 
-	dev->net->do_ioctl = qf9700_ioctl;
-	dev->net->set_multicast_list = qf9700_set_multicast;
+        dev->net->netdev_ops = &qf9700_netdev_ops;
 	dev->net->ethtool_ops = &qf9700_ethtool_ops;
 	dev->net->hard_header_len += QF_TX_OVERHEAD;
 	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
@@ -440,11 +450,11 @@
 	len = (skb->data[1] | (skb->data[2] << 8)) - 4;
 
 	if (unlikely(status & 0xbf)) {
-		if (status & 0x01) dev->stats.rx_fifo_errors++;
-		if (status & 0x02) dev->stats.rx_crc_errors++;
-		if (status & 0x04) dev->stats.rx_frame_errors++;
-		if (status & 0x20) dev->stats.rx_missed_errors++;
-		if (status & 0x90) dev->stats.rx_length_errors++;
+		if (status & 0x01) dev->net->stats.rx_fifo_errors++;
+		if (status & 0x02) dev->net->stats.rx_crc_errors++;
+		if (status & 0x04) dev->net->stats.rx_frame_errors++;
+		if (status & 0x20) dev->net->stats.rx_missed_errors++;
+		if (status & 0x90) dev->net->stats.rx_length_errors++;
 		return 0;
 	}
 




As it doesn't appear to have a home on the web anywhere I've dropped the original driver and my changes here, should anyone else need it.

LinkReply

Comments:
(Deleted comment)
From: tagno25
2011-07-08 08:43 pm (UTC)
That let me compile the driver and load the interface, but the MAC address is incorrect (and I can only use one).

00:e0:4c:53:44:58
The mac address that is showing up is 00:e0:4c:53:44:58, but it should be 00:07:08:0f:1A:1E according to Windows XP
(Reply) (Thread)
From: (Anonymous)
2011-08-08 07:56 am (UTC)

QF9700

Hi,
from header file qf9700.h it looks like this chip is clone of Davicom DM9601, possible you can use Davicom driver?
(Reply) (Thread)
From: (Anonymous)
2013-07-29 10:44 pm (UTC)
My distro delares that the QF9600 is an alias of DM9601 and installs the DM9601 module. It tells me that the link is connected at 100Mbps, Full duplex and everything looks fantastic!

But as it turns out, the DM9601 driver, when used with this device, will only connect at 10Mbps, half duplex and always reports 100Mbps, Full duplex regardless of the actual negotiated link speed.
(Reply) (Parent) (Thread)
From: (Anonymous)
2011-08-11 05:42 pm (UTC)

qf9700.ko on kernel 2.6.33.7-server-2mnb Mandriva 2010.2

Thanks for your job.
your patch works parfectly on a Mandriva 2010.2 32b :

usb 1-5.2: new full speed USB device using ehci_hcd and address 3
usb 1-5.2: New USB device found, idVendor=0fe6, idProduct=9700
usb 1-5.2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
usb 1-5.2: Product: USB 2.0 10/100M Ethernet Adaptor
eth0: register 'qf9700' at usb-0000:00:1d.7-5.2, QF9700 USB Ethernet, 00:e0:4c:zz:yy:xx
usbcore: registered new interface driver qf9700
udev: renamed network interface eth0 to eth3
eth3: link up, 100Mbps, full-duplex, lpa 0xFFFF

Best Regards
(Reply) (Thread)
[User Picture]From: Lloyd Standish
2011-12-25 06:45 am (UTC)

Re: qf9700.ko on kernel 2.6.33.7-server-2mnb Mandriva 2010.2

Thanks very much for posting this patch. It allowed me to fix the driver for use on Debian Squeeze.
(Reply) (Parent) (Thread)
From: (Anonymous)
2012-03-17 02:23 am (UTC)
Thank you very much
my device :ID 0fe6:9700 Kontron
and my kerenl is 2.6.33.20
at first I compile dm9601 but it doesn't work
finally i found your blog
and use your qf9700-2.6.32
my USB Ethernet interface now works well
(Reply) (Thread)
[User Picture]From: tobestool
2012-04-01 08:59 pm (UTC)
Thanks for posting that, it's been a big help.

For anyone else who's trying to compile it on / for an Arm processor (I'm experimenting with running a Pogoplug as a router), I found that it was necessary to replace all occourances of udelay() with ndelay() in qf9700.c

I will confess I do not understand the difference This has mostly been from experimenting with Google-translated forums in Chinese. I therefore take no responsibility if it causes a massive traffic storm on your network, but I seem to have a working eth1 interface now. I will update if I find more out.

Thanks again!
(Reply) (Thread)
From: (Anonymous)
2012-05-28 07:02 pm (UTC)
Can you help me i have a this device, if i execute the "lsusb" comand in terminal this is the result:

Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 004: ID 0458:003a KYE Systems Corp. (Mouse Systems)
Bus 003 Device 002: ID 0fe6:9700
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

There is "Bus 003 Device 002: ID 0fe6:9700"

if use CentOS 6.2 i386 or x86_64 with kernel 2.6.32-220.2.1 this pach will work in it?

thx and sorry for my poor english

(Reply) (Thread)
[User Picture]From: mquin
2012-06-20 01:22 pm (UTC)
Looks like the same bus ID as the devices I have, so I would expect it to work.
(Reply) (Parent) (Thread)
From: (Anonymous)
2012-06-20 12:50 pm (UTC)
Thank you for your post.
I can work my USB Ethernet in Ubuntu 10.04.

dmesg
[ 8679.647855] eth1: register 'qf9700' at usb-0000:00:1d.1-1, QF9700 USB Ethernet, 00:06:14:10:0b:1a
[ 8679.649208] usbcore: registered new interface driver qf9700

Thank you again.
(Reply) (Thread)
From: (Anonymous)
2012-07-27 07:37 am (UTC)
Can anyone help? I compiled the qf9700 module OK, but not sure how to install it. I get "Unknown symbol in module".


root@debian-jpb:/home/john/Downloads/qf9700# uname -a
Linux debian-jpb 2.6.32-5-686 #1 SMP Sun May 6 04:01:19 UTC 2012 i686 GNU/Linux
root@debian-jpb:/home/john/Downloads/qf9700# make clean; make
rm -f *.o *.ko .*.cmd .*.flags .mii.mod.o.d *.mod.c Module.symvers Module.markers modules.order version.h
rm -rf .tmp_versions
Building QF9700 USB2NET chip driver...
make[1]: Entering directory `/usr/src/linux-headers-2.6.32-5-686'
CC [M] /home/john/Downloads/qf9700/qf9700.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/john/Downloads/qf9700/qf9700.mod.o
LD [M] /home/john/Downloads/qf9700/qf9700.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-5-686'
root@debian-jpb:/home/john/Downloads/qf9700# insmod qf9700.ko
insmod: error inserting 'qf9700.ko': -1 Unknown symbol in module
(Reply) (Thread)
[User Picture]From: mquin
2012-07-27 08:44 am (UTC)
Copy the .ko file into /lib/modules/2.6.32-5-686/kernel/drivers/net/usb/ then do 'depmod -a && modprobe qf9700'
(Reply) (Parent) (Thread)
From: (Anonymous)
2012-07-27 04:39 pm (UTC)
Thank you very much for your quick help! That did it, and my cheap USB-LAN adaptor is now working (this post via that connection now.) By the way, mine was advertised and labelled as "USB 2.0 to Fast Ethernet Adapter" although it is in fact a USB 1.1 ("full speed") device.
(Reply) (Parent) (Thread)
From: (Anonymous)
2012-09-06 03:29 pm (UTC)
Its a really Good patch, working fine on mu ubuntu 10.04 :D
(Reply) (Thread)
From: (Anonymous)
2012-09-13 10:41 pm (UTC)
Hi there, am able to compile, and I copied the ko file over, but then when I run: depmod -a && modprobe qf9700

FATAL: Error inserting qf9700 (/lib/modules/3.0.0-12-generic/kernel/drivers/net/usb/qf9700.ko): Operation not permitted
(Reply) (Thread)
[User Picture]From: mquin
2012-09-14 10:35 am (UTC)
At the risk of stating the obvious, were you root when you tried that?
(Reply) (Parent) (Thread)
From: (Anonymous)
2012-10-25 12:38 pm (UTC)
I am confused as to how to go about installing the driver and patch, I am somewhat new to Linux, and struggling to get this working. Is it possible for someone to list the steps on how to go about installing this?

Thanks in advance.
(Reply) (Thread)
[User Picture]From: mquin
2012-10-27 01:05 pm (UTC)
In brief:

Grab one of the patched tarfiles (qf9700-2.6.32.tar.gz or qf9700-2.6.37.tar.gz), and extract it

Edit the KERNEL_DIR and KERNEL_VERSION lines at the top of the Makefile as necessary

run 'make', and if everything goes well 'make install'

after that copy the .ko file into /lib/modules/2.6.32-5-686/kernel/drivers/net/usb/ then do 'depmod -a && modprobe qf9700'

(Reply) (Parent) (Thread)
From: (Anonymous)
2012-12-28 07:09 pm (UTC)
make works fine!

make install output this error.
make: *** No rule to make target `install'. Stop.

Thanks for your efforts.
(Reply) (Parent) (Thread)
[User Picture]From: mquin
2012-12-28 09:04 pm (UTC)
I may have misremembered that step. If the 'make' went fine and there is a .ko file try the next steps.
(Reply) (Parent) (Thread)
From: (Anonymous)
2013-01-19 07:33 am (UTC)
depmod -a && modprobe qf9700 works fine for me on Ubuntu 10.4 .

Thanks.
(Reply) (Thread)
From: (Anonymous)
2013-04-21 11:43 am (UTC)
But when using multiple USBs(qf9700) same mac are showing. Any fix on this>
(Reply) (Thread)
From: (Anonymous)
2013-04-23 01:45 pm (UTC)
Hi mquin,

I need help, i have ubuntu 11.11. and my kernel version is 2.6.32-46-generic. I have followed your instruction thus far and copy the ko file to the mentioned directory

-rw-r--r-- 1 root root 18998 2013-04-23 21:35 qf9700.ko

upon executing sudo depmod -a && modprobe qf9700
i get the following error :
FATAL: Error inserting qf9700 (/lib/modules/2.6.32-46-generic/kernel/drivers/net/usb/qf9700.ko): Operation not permitted
(Reply) (Thread)
[User Picture]From: mquin
2013-04-23 02:31 pm (UTC)
you need to use sudo for the modprobe command as well:

sudo depmod -a && sudo modprobe qf9700

(Reply) (Parent) (Thread)
From: (Anonymous)
2013-04-23 03:36 pm (UTC)
managed to resolve it by doing insmod. However, i could not insert multiple qf9700 usb network adaptors. All will show the same mac address, and the next interface (eth3) will not shown

[ 962.149417] eth2: register 'qf9700' at usb-0000:00:1d.0-1.3.2, QF9700 USB Ethernet, 00:e0:4c:53:44:58
[ 962.149452] usbcore: registered new interface driver qf9700
[ 1108.246214] eth2: unregister 'qf9700' usb-0000:00:1d.0-1.3.2, QF9700 USB Ethernet
[ 1111.614060] eth2: register 'qf9700' at usb-0000:00:1d.0-1.3.2, QF9700 USB Ethernet, 00:e0:4c:53:44:58
[ 1277.850406] eth3: register 'qf9700' at usb-0000:00:1d.0-1.3.1, QF9700 USB Ethernet, 00:e0:4c:53:44:58

Attempt to change 1 of them to a different mac address will have no bearings as well.. however, in windows 7, each adaptor have a unique mac address.. please help.
(Reply) (Thread)
From: (Anonymous)
2013-08-23 01:43 pm (UTC)
Has anyone tried recently compiling this?

I tried the posted version & the version that came on a CD with an adapter (lsusb shows: 0fe6:9700).

make fails with…

mike-qf9700 version
make[1]: Entering directory `/usr/src/linux-headers-3.2.0-4-686-pae'
Building QF9700 USB2NET chip driver...
make[1]: Entering directory `/usr/src/linux-headers-3.2.0-4-686-pae'
CC [M] /root/qf9700/qf9700.o
/root/qf9700/qf9700.c: In function ‘qf_read’:
/root/qf9700/qf9700.c:36:2: error: implicit declaration of function ‘devdbg’ [-Werror=implicit-function-declaration]
/root/qf9700/qf9700.c: In function ‘qf_write_async_helper’:
/root/qf9700/qf9700.c:115:3: error: implicit declaration of function ‘deverr’ [-Werror=implicit-function-declaration]
/root/qf9700/qf9700.c: In function ‘qf9700_set_multicast’:
/root/qf9700/qf9700.c:356:45: error: ‘struct net_device’ has no member named ‘mc_count’
/root/qf9700/qf9700.c:358:16: error: ‘struct net_device’ has no member named ‘mc_count’
/root/qf9700/qf9700.c:359:36: error: ‘struct net_device’ has no member named ‘mc_list’
/root/qf9700/qf9700.c:362:22: error: ‘struct net_device’ has no member named ‘mc_count’
/root/qf9700/qf9700.c:362:56: error: dereferencing pointer to incomplete type
/root/qf9700/qf9700.c:363:14: error: dereferencing pointer to incomplete type
/root/qf9700/qf9700.c: In function ‘qf9700_bind’:
/root/qf9700/qf9700.c:380:10: error: ‘struct net_device’ has no member named ‘do_ioctl’
/root/qf9700/qf9700.c:381:10: error: ‘struct net_device’ has no member named ‘set_multicast_list’
/root/qf9700/qf9700.c: In function ‘qf9700_rx_fixup’:
/root/qf9700/qf9700.c:443:25: error: ‘struct usbnet’ has no member named ‘stats’
/root/qf9700/qf9700.c:444:25: error: ‘struct usbnet’ has no member named ‘stats’
/root/qf9700/qf9700.c:445:25: error: ‘struct usbnet’ has no member named ‘stats’
/root/qf9700/qf9700.c:446:25: error: ‘struct usbnet’ has no member named ‘stats’
/root/qf9700/qf9700.c:447:25: error: ‘struct usbnet’ has no member named ‘stats’
cc1: some warnings being treated as errors
make[4]: *** [/root/qf9700/qf9700.o] Error 1
make[3]: *** [_module_/root/qf9700] Error 2
make[2]: *** [sub-make] Error 2
make[1]: *** [all] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.2.0-4-686-pae'
make: *** [all] Error 2


Any suggestions on where to start, the built in dm9601 driver doesn't allow this device to get a carrier so it never comes up. Is it worth trying to get the 2.6 kernel installed?

(Reply) (Thread)