Patch du driver rt2570 pour permettre le changement d’adresse MAC

Note : depuis mon patch à été ajouté directement dans les drivers natif …

Le drivers rt2570, correspondant aux chip USB ralink souffre d’un petit bug, à moins qu’il ne s’agisse d’une fonctionnalité, je ne sais pas ! il n’est pas possible de changer leur adresse MAC.

Après analyse du problème, il s’avère que lorsque l’on remonte le driver par un ifconfig rausb0 up celui-ci effectue une réinitialisation complète du périphérique incluant donc le rechargement de l’adresse MAC d’origine et venant donc écraser celle configurée précédemment par le ifconfig rausb0 hw ether ….

La solution a ce problème est assez simple, lors de l’init que l’on trouve dans rtusb_main.c il suffit de tester si l’adresse MAC du net_dev vaut 00, auquel cas on charge celle de la carte (premier appel) sinon, on conserve la valeur du net_dev qui correspond à celle forcée.
Ce qui se traduit par :

Dans la fonction usb_rtusb_open, ligne 1231 environ
RTUSBCmd_kill =0;
CreateThreads(net_dev);
memcpy(pAdapter->net->dev_addr, pAdapter->CurrentAddress, pAdapter->net->addr_len);
// Clear Reset Flag before starting receiving/transmitting
RTMP_CLEAR_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS);

Va devenir:

RTUSBCmd_kill =0;
CreateThreads(net_dev);
// at every open handler, copy mac address.
// PATCH >>>>>>>>>>>>>>>>>>
if ( net_dev->dev_addr[0] == 0 && net_dev->dev_addr[1] == 0 && net_dev->dev_addr[2] == 0 &&
net_dev->dev_addr[3] == 0 && net_dev->dev_addr[4] == 0 && net_dev->dev_addr[5] == 0 ) {
// First time initialization
memcpy(pAdapter->net->dev_addr, pAdapter->CurrentAddress, pAdapter->net->addr_len);
} else {
// Next time “la vérité est ailleurs!”
memcpy(pAdapter->CurrentAddress, pAdapter->net->dev_addr, pAdapter->net->addr_len);
}
// <<<<<<<<<<<<<<<<< PATCH

// Clear Reset Flag before starting receiving/transmitting
RTMP_CLEAR_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS);

Après on recompile, et la solution a l’air de fonctionner …. ??? et bien en fait non elle ne fonctionne pas !! oups.. j’aurais dû un peu plus tester … j’avais un petit oubli … voila qui est corrigé ! merci à larbig d’avoir complété le boulo.
Il semble en effet que l’adresse MAC doit être la même entre le pAdapter et le net_dev sans quoi les trames ne sont pas emises dans l’air … ennuyeux. voici donc le patch complet et cette fois testé !! sisi !! Les modifications sont cette fois dans rtusb_init.c où il faut modifier la fonction NICReadEEPROMParameters de la façon suivante :

VOID    NICReadEEPROMParameters(
        IN      PRT2570ADAPTER  pAdapter)
{
        USHORT                  i;
        int                     value;
        UCHAR                   TmpPhy;
        EEPROM_TX_PWR_STRUC     Power;
        EEPROM_ANTENNA_STRUC    Antenna;//blue
//      EEPROM_VERSION_STRUC    Version;

        DBGPRINT(RT_DEBUG_TRACE,"--> NICReadEEPROMParameters ");

        //Read MAC address.
        RTUSBReadEEPROM(pAdapter, EEPROM_MAC_ADDRESS_BASE_OFFSET, pAdapter->PermanentAddress, ETH_LENGTH_OF_ADDRESS);
        DBGPRINT_RAW(RT_DEBUG_TRACE,"MAC address ReadEEPROM : ");
        for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++)
                DBGPRINT_RAW(RT_DEBUG_TRACE,"%02x ", pAdapter->PermanentAddress[i]);
        DBGPRINT_RAW(RT_DEBUG_TRACE," ");

        if (pAdapter->PortCfg.bLocalAdminMAC != TRUE)
        {
                pAdapter->CurrentAddress[0] = pAdapter->PermanentAddress[0];
                pAdapter->CurrentAddress[1] = pAdapter->PermanentAddress[1];
                pAdapter->CurrentAddress[2] = pAdapter->PermanentAddress[2];
                pAdapter->CurrentAddress[3] = pAdapter->PermanentAddress[3];
                pAdapter->CurrentAddress[4] = pAdapter->PermanentAddress[4];
                pAdapter->CurrentAddress[5] = pAdapter->PermanentAddress[5];
        }

devient

VOID    NICReadEEPROMParameters(
        IN      PRT2570ADAPTER  pAdapter, struct net_device *net_dev)
{
        USHORT                  i;
        int                     value;
        UCHAR                   TmpPhy;
        EEPROM_TX_PWR_STRUC     Power;
        EEPROM_ANTENNA_STRUC    Antenna;//blue
//      EEPROM_VERSION_STRUC    Version;

        DBGPRINT(RT_DEBUG_TRACE,"--> NICReadEEPROMParameters ");

        //Read MAC address.
        RTUSBReadEEPROM(pAdapter, EEPROM_MAC_ADDRESS_BASE_OFFSET, pAdapter->PermanentAddress, ETH_LENGTH_OF_ADDRESS);
        DBGPRINT_RAW(RT_DEBUG_TRACE,"MAC address ReadEEPROM :");
        for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++)
                DBGPRINT_RAW(RT_DEBUG_TRACE,"%02x ", pAdapter->PermanentAddress[i]);
        DBGPRINT_RAW(RT_DEBUG_TRACE,"");

        if (pAdapter->PortCfg.bLocalAdminMAC != TRUE)
        {

           if ( net_dev->dev_addr[0] == 0 && net_dev->dev_addr[1] == 0 && net_dev->dev_addr[2] == 0 &&
             net_dev->dev_addr[3] == 0 && net_dev->dev_addr[4] == 0 && net_dev->dev_addr[5] == 0    ) {
                // Startup time ... read the original MAC
                pAdapter->CurrentAddress[0] = pAdapter->PermanentAddress[0];
                pAdapter->CurrentAddress[1] = pAdapter->PermanentAddress[1];
                pAdapter->CurrentAddress[2] = pAdapter->PermanentAddress[2];
                pAdapter->CurrentAddress[3] = pAdapter->PermanentAddress[3];
                pAdapter->CurrentAddress[4] = pAdapter->PermanentAddress[4];
                pAdapter->CurrentAddress[5] = pAdapter->PermanentAddress[5];
           } else {
                // Next time, get the MAC from net_dev->dev_addr
                printk(KERN_INFO "net_dev supplies MAC, activating this one :%02x:%02x:%02x:%02x:%02x:%02x.",
                        net_dev->dev_addr[0], net_dev->dev_addr[1], net_dev->dev_addr[2],
                        net_dev->dev_addr[3], net_dev->dev_addr[4], net_dev->dev_addr[5]);
                memcpy(pAdapter->CurrentAddress, pAdapter->net->dev_addr, pAdapter->net->addr_len);
           }
        }

La mécanique est axactement la même que celle faite précédemment : lors du premier appel on fait comme si de rien n’etait et on recupère l’adresse en EEPROM, pour les appels suivant on choisit la MAC du net_dev à la place.
Pour que ca fonctionne il reste deux petites modifications, modifier le header de cette fonction : dans rt2570sw.h

VOID  NICReadEEPROMParameters(
      IN  PRT2570ADAPTER       pAdapter);

devient :

VOID  NICReadEEPROMParameters(
      IN  PRT2570ADAPTER       pAdapter, 
      struct net_device *net_dev);

enfin il reste l’appel de la fonction de lecture à modifier, dans rtusb_main.c:

   NICReadEEPROMParameters(pAdapter, net_dev);

Ca y est !!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.