Rt3070usb

From PaparazziUAV
Jump to: navigation, search

Intro

This page explains how to get the rt3070usb (aka rt3070sta) linux driver working in openembedded for the overo on Lisa.

Background

I have an edimax EW-7711UAn usb wifi stick I needed to get working with Lisa. Its USB id is 7392:7711.

Manufacturer and available at Amazon

My initial search seemed to show the rt2870usb driver was the one to use, and I guess at one time that might have been the case for the chip in this stick. But rt3070usb is now the one to use.

There's a recipe for the rt3070 driver in openembedded (which I'm pulling from : ). The recipe pulls the source code from the ralink website (or get it from this page), patches it, and builds. It's pretty impressive that this driver cross compiles and just works. Well, for me it doesn't compile for me for two reasons :

  • 1. My linux kernel has real-time patches so the init_MUTEX() in the driver source can't be found
  • 2. Some sort of device structure change has occurred in the kernel since who knows when

The fixes are:

Building

The recipe will be fixed (patch files available here), but until then, here are instructions for building :

In the overo-oe directory type:

bitbake rt3070

this should bomb while compiling with the following error :

common/rtmp_init.c:3709: error: implicit declaration of function ‘init_MUTEX’

Then, go to the following directory : overo-oe/tmp/work/overo-angstrom-linux-gnueabi/rt3070-2.1.1.0-r80/2009_0525_RT3070_Linux_STA_v2.1.1.0

Patch common/rtmp_init.c with the one line change : replace init_MUTEX as indicated above

Then, apply patch (at the bottom of this page or here) as follows :

paul@paul-laptop:~/overo-oe/tmp/work/overo-angstrom-linux-gnueabi/rt3070-2.1.1.0-r80$ patch -p0 < rt3070.patch

Now, if all is well, doing another "bitbake rt3070" should succeed but before doing that, a quick way to make sure is to attempt the recompilation right from this tmp/work area as follows :

cd to ~/overo-oe/tmp/work/overo-angstrom-linux-gnueabi/rt3070-2.1.1.0-r80/temp$

then execute the run.do_compile.xxxxx script
./run.do_compile.17833

The resulting module is not small :

paul@paul-laptop:~/overo-oe/tmp/work/overo-angstrom-linux-gnueabi/rt3070-2.1.1.0-r80/2009_0525_RT3070_Linux_STA_v2.1.1.0$ ls -l os/linux/rt3070sta.ko 
-rw-rw-r-- 1 paul paul 9059652 2010-07-29 18:44 os/linux/rt3070sta.ko

I haven't looked into it, but I'm guessing the firmware is now included in the module file and perhaps there's firmware for a bunch of different controllers/cards. The file system space isn't too precious, but this doesn't have an impact on load time (and therefore boot time), so it would be good to resolve this and get it down to a reasonable size.

Update : after rebuilding and deploying my new SD card image I no longer seem to have a big module (now around 600kB). The first time I rebuilt i had a do_setscene warning about get_kernelmajorversion not working followed by do_strip error (probably due to first). retrying without using the bitbake -b method worked, though. Paulcox 16:40, 30 July 2010 (CEST)

To test we can copy the .ko file directly to our overo root filesystem as well as create the /etc/Wireless/blah to put the .dat file or we can simply add the rt3070 recipe to our image recipe, rebuild our omap3-lisa-image. omap3-lisa-image, and create a new sd card.

overo-oe$ vi org.openembedded.dev/recipes/images/omap3-lisa-image.bb

# omap3 image for Lisa board

require omap3-console-image.bb

ANGSTROM_EXTRA_INSTALL ?= ""

LISA_LIBS = " \
  libevent \
 "

LISA_EXTRAS = " \
  rt3070 \
  screen \
 "

IMAGE_INSTALL += " \
  ${LISA_LIBS} \
  ${LISA_EXTRAS} \
 "

Configuration

Supposedly the driver will look for a configuration file : /etc/Wireless/RT2870STA/RT2870STA.dat but I configured manually instead as follows

insmod rt3070sta.ko
at this point iwconfig shows an ra0 interface
ifconfig ra0 up
iwconfig ra0 essid ap_h16

wpa_supplicant

As usual, the wpa key goes in /etc/wpa_supplicant.conf and started wpa_supplicant with

wpa_supplicant -ira0 -c/etc/wpa_supplicant.conf &

DHCP

dhclient ra0

Console output

root@overo:/home/paul# iwconfig ra0
ra0       RT2870 Wireless  ESSID:"ap_h16"  Nickname:"RT2870STA"
          Mode:Managed  Frequency=2.412 GHz  Access Point: 00:25:4B:06:E3:9F   
          Bit Rate=65 Mb/s   
          RTS thr:off   Fragment thr:off
          Encryption key:447F-01CB-C235-6BF1-0F8C-0E61-5C88-EEEA
          Link Quality=100/100  Signal level:-39 dBm  Noise level:-83 dBm
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

root@overo:/home/paul# lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 7392:7711  
root@overo:/home/paul# ping bill

PING bill.recherche.enac.fr (10.31.4.5) 56(84) bytes of data.
64 bytes from bill.recherche.enac.fr (10.31.4.5): icmp_seq=1 ttl=64 time=367 ms
^C
--- bill.recherche.enac.fr ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 367.279/367.279/367.279/0.000 ms
root@overo:/home/paul# WPA: Group rekeying completed with 00:25:4b:06:e3:9f [GTK=TKIP]

Patch

diff -rupN 2009_0525_RT3070_Linux_STA_v2.1.1.0.old/include/rtmp_os.h 2009_0525_RT3070_Linux_STA_v2.1.1.0/include/rtmp_os.h
--- 2009_0525_RT3070_Linux_STA_v2.1.1.0.old/include/rtmp_os.h	2009-05-20 23:33:56.000000000 -0400
+++ 2009_0525_RT3070_Linux_STA_v2.1.1.0/include/rtmp_os.h	2009-08-04 00:00:46.000000000 -0400
@@ -53,6 +53,7 @@
 */
 typedef struct _RTMP_OS_NETDEV_OP_HOOK_
 {
+  /*
 	void			*open;
 	void			*stop;
 	void			*xmit;
@@ -63,6 +64,8 @@ typedef struct _RTMP_OS_NETDEV_OP_HOOK_
 	unsigned char devAddr[6];
 	unsigned char	devName[16];
 	unsigned char	needProtcted;
+  */
+  struct net_device_ops *netdev_ops;
 }RTMP_OS_NETDEV_OP_HOOK, *PRTMP_OS_NETDEV_OP_HOOK;
 
 
diff -rupN 2009_0525_RT3070_Linux_STA_v2.1.1.0.old/os/linux/rt_linux.c 2009_0525_RT3070_Linux_STA_v2.1.1.0/os/linux/rt_linux.c
--- 2009_0525_RT3070_Linux_STA_v2.1.1.0.old/os/linux/rt_linux.c	2009-05-20 23:33:56.000000000 -0400
+++ 2009_0525_RT3070_Linux_STA_v2.1.1.0/os/linux/rt_linux.c	2009-08-04 00:04:15.000000000 -0400
@@ -1506,20 +1506,21 @@ int RtmpOSNetDevAttach(
 	if (pDevOpHook)
 	{
 		PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(pNetDev);
-	
+		pNetDev->netdev_ops = pDevOpHook->netdev_ops;
+		/*	
 		pNetDev->open			= pDevOpHook->open;
 		pNetDev->stop			= pDevOpHook->stop;
 		pNetDev->hard_start_xmit	= (HARD_START_XMIT_FUNC)(pDevOpHook->xmit);
 		pNetDev->do_ioctl		= pDevOpHook->ioctl;
-		
+		*/
 		/* if you don't implement get_stats, just leave the callback function as NULL, a dummy 
 		     function will make kernel panic.
 		*/
-		if (pDevOpHook->get_stats)
+		/*if (pDevOpHook->get_stats)
 			pNetDev->get_stats = pDevOpHook->get_stats;
-
+		*/
 		/* OS specific flags, here we used to indicate if we are virtual interface */
-		pNetDev->priv_flags = pDevOpHook->priv_flags; 
+		//		pNetDev->priv_flags = pDevOpHook->priv_flags; 
 
 #if (WIRELESS_EXT < 21) && (WIRELESS_EXT >= 12)
 		pNetDev->get_wireless_stats = rt28xx_get_wireless_stats;
@@ -1544,15 +1545,15 @@ int RtmpOSNetDevAttach(
 #endif // CONFIG_APSTA_MIXED_SUPPORT //
 
 		// copy the net device mac address to the net_device structure.
-		NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], MAC_ADDR_LEN);
+		//		NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], MAC_ADDR_LEN);
 
-		rtnl_locked = pDevOpHook->needProtcted;
+		//		rtnl_locked = pDevOpHook->needProtcted;
 	}
-
+	/*
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
 	pNetDev->validate_addr = NULL;
 #endif
-
+	*/
 	if (rtnl_locked)
 		ret = register_netdevice(pNetDev);
 	else
diff -rupN 2009_0525_RT3070_Linux_STA_v2.1.1.0.old/os/linux/rt_main_dev.c 2009_0525_RT3070_Linux_STA_v2.1.1.0/os/linux/rt_main_dev.c
--- 2009_0525_RT3070_Linux_STA_v2.1.1.0.old/os/linux/rt_main_dev.c	2009-05-20 23:33:56.000000000 -0400
+++ 2009_0525_RT3070_Linux_STA_v2.1.1.0/os/linux/rt_main_dev.c	2009-08-04 00:06:08.000000000 -0400
@@ -504,6 +504,21 @@ err:
 	return (-1);
 } /* End of rt28xx_open */
 
+static const struct net_device_ops rt2870_netdev_ops = {
+  .ndo_open               = MainVirtualIF_open,//
+  .ndo_stop               = MainVirtualIF_close,//
+  .ndo_do_ioctl           = rt28xx_ioctl,//
+  .ndo_get_stats          = RT28xx_get_ether_stats,//
+  .ndo_validate_addr      = NULL,
+  .ndo_set_mac_address    = eth_mac_addr,
+  .ndo_change_mtu         = eth_change_mtu,
+#ifdef IKANOS_VX_1X0
+  .ndo_start_xmit         = IKANOS_DataFramesTx,//
+#else
+  .ndo_start_xmit         = rt28xx_send_packets,//
+#endif
+};
+
 
 PNET_DEV RtmpPhyNetDevInit(
 	IN RTMP_ADAPTER *pAd,
@@ -520,6 +535,8 @@ PNET_DEV RtmpPhyNetDevInit(
 	}
 
 	NdisZeroMemory((unsigned char *)pNetDevHook, sizeof(RTMP_OS_NETDEV_OP_HOOK));
+	pNetDevHook->netdev_ops = &rt2870_netdev_ops;
+	/*
 	pNetDevHook->open = MainVirtualIF_open;
 	pNetDevHook->stop = MainVirtualIF_close;
 	pNetDevHook->xmit = rt28xx_send_packets;
@@ -531,7 +548,7 @@ PNET_DEV RtmpPhyNetDevInit(
 	pNetDevHook->get_stats = RT28xx_get_ether_stats;
 
 	pNetDevHook->needProtcted = FALSE;
-
+	*/
 	RTMP_OS_NETDEV_SET_PRIV(net_dev, pAd);
 	//net_dev->priv = (PVOID)pAd;
 	pAd->net_dev = net_dev;