os/boardsupport/emulator/emulatorbsp/specific/ethernet.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // wins\specific\ethernet.cpp
    15 // PDD for the Ethernet under the windows emulator
    16 // 
    17 //
    18 
    19 /**
    20  @file wins/specific/ethernet.cpp
    21 */
    22 
    23 
    24 #include <ethernet.h>
    25 #include "nk_priv.h"
    26 #include "nk_plat.h"
    27 #include <property.h>
    28 
    29 #include "pcap.h"
    30 
    31 
    32 /** @addtogroup enet Ethernet Drivers
    33  *  Kernel Ethernet Support
    34  */
    35 
    36 /** @addtogroup enet_pdd Driver PDD's
    37  * @ingroup enet
    38  */
    39 
    40 /** @addtogroup enet_byplatform Ethernet support by platform
    41  * @ingroup enet
    42  */
    43 
    44 /** @addtogroup enet_wins WINS (Emulator) Ethernet support
    45  * @ingroup enet_byplatform
    46  */
    47 
    48 
    49 // strings potentially written to ethernet.ini by netcards.exe
    50 #define	KEpocIniEthSpeed10Mbps	"10Mbps"
    51 #define	KEpocIniEthSpeed100Mbps	"100Mbps"
    52 
    53 // entries in epoc.ini file:
    54 #define	KEpocIniEthSpeedEntry	"ETHER_SPEED"
    55 #define	KEpocIniEthNIFEntry	"ETHER_NIF"
    56 #define	KEpocIniEthMACEntry	"ETHER_MAC"
    57 
    58 #define KEthDrvPanicCategory "D32ETHER"
    59 
    60 #define KLocalDriverNameMax				256
    61 
    62 #define PCAP_FILTER "ether dst %x:%x:%x:%x:%x:%x or ether multicast and ether src not %x:%x:%x:%x:%x:%x"
    63 
    64 _LIT(KPddName, "Ethernet.Wins");
    65 
    66 // needs ldd version..
    67 const TInt KMinimumLddMajorVersion=1;
    68 const TInt KMinimumLddMinorVersion=0;
    69 const TInt KMinimumLddBuild=122;
    70 
    71 /** @addtogroup enet_windows Windows Emulator Ethernet Pdd
    72  * @ingroup enet_pdd
    73  * @ingroup enet_wins
    74  * @{
    75  */
    76 
    77 /**
    78  * The Windows specific Ethernet physical device (factory) class 
    79  * @internalTechnology belongs to PDD which sits internally in kernel 
    80  */
    81 class DDriverEthernet : public DPhysicalDevice
    82     {
    83 public:
    84 
    85     /**
    86      * The constructor
    87      * Sets the drivers version number. Limits possible
    88 	 * number of units to one only (unit 0)
    89      */
    90     DDriverEthernet();
    91 
    92     /**
    93      * Inherited from DPhysicalDevice.
    94 	 * Install the driver by setting it's name
    95 	 * @return KErrNone on success, other error code on failure
    96      */
    97     virtual TInt Install();
    98 
    99     /**
   100      * Inherited from DPhysicalDevice.
   101 	 * Get the Capabilites of the driver
   102      * NOT supported but required as implementation of
   103 	 * pure virtual in base class
   104      */
   105     virtual void GetCaps(TDes8 &aDes) const;
   106 
   107     /**
   108      * Inherited from DPhysicalDevice.
   109 	 * Create a channel to a device
   110 	 * @param aChannel a reference to a newly created channel object
   111 	 * @param aUnit a unit for which the channel is being created
   112 	 * @param anInfo pointer to a descriptor with additional info (may be NULL)
   113 	 * @param aVer a requested version
   114      * @return KErrNone on success, other error code on failure
   115      */
   116     virtual TInt Create(DBase*& aChannel, TInt aUnit, 
   117 						const TDesC8* anInfo, const TVersion &aVer);
   118 
   119     /**
   120      * Inherited from DPhysicalDevice.
   121 	 * Validate that the info supplied would create a valid channel
   122 	 * @param aUnit a unit for which validation is to be done
   123 	 * @param anInfo pointer to a descriptor with additional info (may be NULL)
   124 	 * @param aVer a version to be validated
   125      * @return KErrNone if valid, KErrNotSupported otherwise
   126 	 */
   127     virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer);
   128 	};
   129 
   130 
   131 /**
   132  * The WINS specific Ethernet channel class for the libpcap library
   133  * @internalTechnology belongs to PDD which sits internally in kernel 
   134  */
   135 class DEthernetWins : public DEthernet
   136     {
   137 
   138 	/**
   139      * The Worker Thread
   140      * @param aDEthernetWins Pointer to this object
   141      * @return Should never return
   142      */
   143     friend TInt WorkThread(DEthernetWins * aDEthernetWins);
   144 
   145 public:
   146 
   147 	enum TWinsEtherPanic
   148 	{
   149 	EBadMacAddress = 1, // means bad MAC address in ini file or entry for it missing or ini file missing
   150 	ENoNetInterface, // means entry for network interface name missing in ini file or ini file missing
   151 	EPcapNull	// means Wpcap couldn't be initialised - potentially not installed or name of network interface in ini file wrong
   152 	};
   153 
   154     /**
   155      * The Constructor.
   156      */
   157     DEthernetWins();
   158 
   159     /**
   160      * The Destructor.
   161      */
   162     ~DEthernetWins();
   163 
   164 	/**
   165      * The Isr plays a role of the pcap callback.
   166      * Do NOT call the function directly
   167      * @param thisObject a pointer to this object
   168      * @param header the received packet's pcap header
   169      * @param pkt_data the received packet
   170 	 * @post new packet is copied to LDD's RX buffers' queue
   171 	 */
   172     static void Isr(u_char *thisObject,   
   173                      const struct pcap_pkthdr *header, 
   174                      const u_char *pkt_data);
   175 
   176     /**
   177      * The DoCreate Method.
   178      * Sets up the channel as part of the object creation
   179      * and retrieves the MAC address from epoc.ini file.
   180 	 * Also creates wpcap handler and thread for wpcap loop.
   181 	 * @pre epoc32\\data\\epoc.ini must exist with entries: "ETHER-NIF=..", "ETHER-MAC=..", "ETHER-SPEED=.."
   182 	 * @param aUnit a unit for which the channel is being created
   183 	 * @panic D32ETHER reason: (1) can't get proper MAC address (2) can't get
   184 	 * network interface name (3) can't initialise wpcap
   185 	 * @return KErrNone on success, other error code on failure
   186 	 */
   187     TInt DoCreate(TInt aUnit); 
   188 
   189     /**
   190      * DEthernet implementation.
   191 	 * Start the receiver.
   192      * Resumes pcap thread. Sets status to ready.
   193 	 * @return KErrNone on success or suitable error code on failure
   194      */
   195     virtual TInt Start();
   196 
   197     /**
   198      * DEthernet implementation.
   199 	 * Stop the receiver.
   200      * @param aMode possible values are: EStopNormal (=0), EStopEmergency (=1)
   201 	 * @post pcap thread suspended, status set to not ready
   202      */
   203     virtual void Stop(TStopMode aMode);
   204 
   205     /**
   206      * DEthernet implementation.
   207 	 * Validates a new configuration - should be called before Configure()
   208      * @param aConfig is the configuration to be validated
   209      * @return KErrNone if aConfig valid, KErrNotSupported otherwise
   210      * @see Configure()
   211      */
   212     virtual TInt ValidateConfig(const TEthernetConfigV01 &aConfig) const;
   213 
   214     /**
   215      * DEthernet implementation.
   216 	 * Configure the PDD and pcap library
   217      * Reconfigure the library using the new configuration supplied.
   218 	 * Sets pcap filter to read only frames with destination address set to
   219 	 * broadcast, multicast or MAC addresss from defaultConfig.
   220      * This will not change the MAC address.
   221      * @param aConfig The new configuration
   222 	 * @return KErrNone on success, suitable error code otherwise
   223      * @see ValidateConfig()
   224      * @see MacConfigure()
   225      */
   226     virtual TInt Configure(TEthernetConfigV01 &aConfig);
   227 
   228     /**
   229      * DEthernet implementation.
   230 	 * Change the MAC address - writes new MAC address in defaultConfig.
   231 	 * If new settings are to have any effect then pcap filter
   232 	 * ought to be set again which is done by 'Configure()'
   233 	 * @param aConfig a configuration structure containing the new MAC
   234      * @see Configure()
   235      */
   236     virtual void MacConfigure(TEthernetConfigV01 &aConfig);
   237 
   238 	/**
   239      * DEthernet implementation.
   240 	 * Get the current config from defaultConfig member varaiable
   241 	 * which is assumed to be up to date.
   242      * Fills in the following fields:
   243      * The Transmit Speed
   244      * The Duplex Setting
   245      * The MAC address
   246      * @param aConfig is a TEthernetConfigV01 reference that will be filled in
   247      */
   248     virtual void GetConfig(TEthernetConfigV01 &aConfig) const;
   249 
   250 	/**
   251      * DEthernet implementation.
   252 	 * Dummy method, required as pure virtual in base class
   253      */
   254     virtual void CheckConfig(TEthernetConfigV01 &aConfig);
   255 
   256 	/**
   257      * DEthernet implementation.
   258 	 * Should query the capabilites.
   259      * NOT supported but required as pure virtual in base class
   260      */
   261     virtual void Caps(TDes8 &aCaps) const;
   262 
   263     /**
   264      * DEthernet implementation.
   265 	 * Transmit data via wpcap
   266      * @param aBuffer reference to the data to be sent
   267      * @return KErrNone on success, other error code on failure
   268      */
   269     virtual TInt Send(TBuf8<KMaxEthernetPacket+32> &aBuffer);
   270 
   271     /**
   272      * DEthernet implementation.
   273 	 * Retrieve data
   274      * Pull the received data out of the pcap library and into the supplied buffer. 
   275      * Need to be told if the buffer is OK 
   276      * @param aBuffer Reference to the buffer to be used to store the data in
   277      * @param okToUse Bool to indicate if the buffer is usable
   278      * @return KErrNone on success, other error code on failure
   279      */
   280     virtual TInt ReceiveFrame(TBuf8<KMaxEthernetPacket+32> &aBuffer, TBool okToUse);
   281 
   282 	/**
   283      * DEthernet implementation.
   284 	 * Disables all IRQ's 
   285      * @return The IRQ level before it was changed
   286      * @see RestoreIrqs()
   287      */
   288     virtual TInt DisableIrqs();
   289 
   290     /**
   291      * DEthernet implementation.
   292 	 * Restore the IRQ's to the supplied level
   293 	 * @param aIrq The level to set the irqs to.
   294      * @see DisableIrqs()
   295      */
   296     virtual void RestoreIrqs(TInt aIrq);
   297 
   298 	/**
   299      * DEthernet implementation.
   300 	 * Return the DFC Queue that this device should use
   301      * @param aUnit a channel's unit number (ignored - only one unit possible)
   302      * @return a DFC Queue to use
   303      */
   304     virtual TDfcQue* DfcQ(TInt aUnit);
   305     
   306 		
   307 private:
   308  	static TBool DEthernetWins::IsTcp(TDesC8 &aFrame);
   309  	static TInt DEthernetWins::GetTcpAckNumber(TDesC8 &frame);
   310  	static TInt DEthernetWins::GetTcpSeqNumber(TDesC8 &frame);
   311 	/**
   312      * Read network interface to be used from configuration file. Panic if
   313 	 * pre-conditions are not satisfied.
   314 	 * @pre epoc32\\data\\epoc.ini must exist with entry: "ETHER-NIF=existing_nif_name"
   315 	 * @post network interface name put in a member variable: iNetInterfaceName
   316 	 * @panic D32ETHER reason: (2) can't get network interface name 
   317      */
   318 	void  SetDriverName();
   319 
   320 	/**
   321 	 * Read MAC address from a configuration file and put it
   322 	 * into defaultConfig member variable checking before if the
   323 	 * one from the file is correct. Panic if pre-conditions are not satisfied
   324 	 * (although in case when MAC address is improper).
   325 	 * @pre epoc32\\data\\epoc.ini must exist with entry: "ETHER-MAC=proper_mac_address"
   326 	 * @panic D32ETHER reason:  EBadMacAddress
   327 	 * @return KErrNone on success (panics on failure)
   328 	 */
   329 	TInt SetMacAddress();
   330 
   331     
   332 private:
   333 
   334     /**
   335      * The handle to the pcap interface - wpcap specific
   336      */
   337     pcap_t * iPcapPtr;
   338 
   339     /**
   340      * Saved received packet information - wpcap specific:
   341 	 * pointer to a structure that holds general information about the packet:
   342 	 * the time in which it was sniffed, the length of this packet, 
   343 	 * and the length of his specific portion (in case it is fragmented)
   344      */
   345     const struct pcap_pkthdr * iPcapHeader; 
   346 
   347     /**
   348      * Saved receive packet data - wpcap specific
   349      */
   350     const u_char * iPcapPktData;
   351 
   352     /**
   353      * Id of the receiver - wpcap thread
   354      */
   355     unsigned long iWorkerThreadId;
   356 
   357 	/**
   358      * Contains the handle to wpcap thread. 
   359      */
   360 	HANDLE				iThreadHandle;
   361 
   362     /**
   363      * Stores the unit number (only one interface possible in 
   364 	 * this implementation, so it will have value "0")
   365      */
   366     TInt  iUnit;
   367 	
   368     /**
   369      * Is ETrue if the chip has been fully configured and is ready
   370 	 * for receiving frames. Is set to ETrue in Start(), to EFalse
   371 	 * in Stop(). Initialized in constructor as EFalse.
   372      */
   373     TBool iReady;
   374 
   375     /**
   376      * Contains the default/current configuration of the driver.
   377 	 * Updated whenever configuration is to be changed.
   378      */
   379     TEthernetConfigV01 defaultConfig;
   380 
   381 	/**
   382      * Contains the network interface name to be used 
   383 	 * @see SetDriverName()
   384      */
   385 	char	iNetInterfaceName[KLocalDriverNameMax];
   386 	
   387     };
   388 
   389 /** @} */ // End of wins ethernet pdd
   390 
   391 
   392  
   393 DDriverEthernet::DDriverEthernet()
   394 // Constructor
   395     {
   396     __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::DDriverEthernet()"));
   397     iUnitsMask=0x1;	// support unit 0 only
   398     iVersion=TVersion(KEthernetMajorVersionNumber,
   399                       KEthernetMinorVersionNumber,
   400                       KEthernetBuildVersionNumber);
   401 	
   402 	}
   403 
   404 
   405 TInt DDriverEthernet::Install()
   406 // Install the driver
   407     {
   408     __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::Install()"));
   409     return SetName(&KPddName);
   410     }
   411 
   412 
   413 void GetWinsEthernetsCaps(TDes8 &aCaps, TInt aUnit=0)
   414     {
   415     __KTRACE_OPT(KHARDWARE, Kern::Printf("GetWinsEthernetsCaps(TDes8 &aCaps, TInt aUnit)"));
   416     TEthernetCaps capsBuf;
   417 	
   418 	aUnit=0;
   419 
   420     aCaps.FillZ(aCaps.MaxLength());
   421     aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength()));
   422     }
   423 
   424 void PanicFromWinsEtherDrv(TInt aReason)
   425 	{
   426 	Kern::Fault(KEthDrvPanicCategory, aReason);
   427 	}
   428 
   429 void DDriverEthernet::GetCaps(TDes8 &aDes) const
   430 // Return the driver's capabilities
   431     {
   432     __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::GetCaps(TDes8 &aDes) const"));
   433     GetWinsEthernetsCaps(aDes);	
   434     }
   435 
   436 
   437 TInt DDriverEthernet::Create(DBase*& aChannel, 
   438                              TInt aUnit, 
   439                              const TDesC8* aInfo, 
   440                              const TVersion& aVer)
   441 // Create a driver
   442     {
   443     __KTRACE_OPT(KHARDWARE, 
   444 		Kern::Printf("DDriverEthernet::Create(DBase*& aChannel, TInt aUnit, const TDesC8* nInfo, const TVersion& aVer)"));
   445 	
   446     TInt ret;
   447 
   448 	ret = Validate( aUnit, aInfo, aVer);
   449 	if ( KErrNone != ret )
   450 		return ret;
   451 
   452 	ret = KErrNoMemory;
   453 
   454 	DEthernetWins* ptrPdd = new DEthernetWins;
   455 
   456 	
   457 	if ( ptrPdd )
   458         {
   459         ret = ptrPdd->DoCreate(aUnit);
   460         if ( ret != KErrNone)
   461 			{
   462             delete ptrPdd;
   463 			}	
   464 		else
   465 			aChannel = ptrPdd;
   466         }
   467 
   468 	
   469     return ret;
   470     }
   471 
   472 
   473 TInt DDriverEthernet::Validate(TInt aUnit, 
   474                                const TDesC8* /*aInfo*/, 
   475                                const TVersion& aVer)
   476 //	Validate the requested configuration
   477     {
   478     __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::Validate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)"));
   479     if ((!Kern::QueryVersionSupported(iVersion,aVer)) || 
   480         (!Kern::QueryVersionSupported(aVer,TVersion(KMinimumLddMajorVersion,
   481                                                     KMinimumLddMinorVersion,
   482                                                     KMinimumLddBuild))))
   483 		{
   484         return KErrNotSupported;
   485 		}
   486     
   487 	if (aUnit != 0)
   488 		{
   489         return KErrNotSupported;
   490 		}
   491 
   492 	return KErrNone;
   493     }
   494 
   495 
   496 DEthernetWins::DEthernetWins()
   497 // Constructor
   498 	{
   499     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DEthernetWins()"));
   500 
   501     iReady = EFalse;
   502     
   503 	// set default configuration - must be set before DoCreate gets called
   504 	defaultConfig.iEthSpeed  = KEthSpeedUnknown;
   505     defaultConfig.iEthDuplex = KEthDuplexUnknown;
   506 							
   507 	// MAC address initially set to NULL
   508 	defaultConfig.iEthAddress[0] = 0; 
   509     defaultConfig.iEthAddress[1] = 0; 
   510     defaultConfig.iEthAddress[2] = 0; 
   511 	defaultConfig.iEthAddress[3] = 0; 
   512     defaultConfig.iEthAddress[4] = 0; 
   513     defaultConfig.iEthAddress[5] = 0; 
   514 	
   515 	iNetInterfaceName[0] = '\0';
   516 
   517 	// wpcap
   518 	iPcapPtr = NULL;
   519 
   520 	}
   521 
   522 DEthernetWins::~DEthernetWins()
   523 // Destructor
   524 	{
   525     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::~DEthernetWins()"));
   526 
   527 	if (iPcapPtr)
   528 		{
   529 		pcap_close(iPcapPtr);
   530 		iPcapPtr = NULL;
   531 		}
   532   
   533 	}
   534 
   535 
   536 TInt DEthernetWins::DoCreate(TInt aUnit)//, const TDesC8* /*anInfo*/)
   537 // Sets up the PDD
   538 	{
   539 	__KTRACE_OPT(KHARDWARE, 
   540 		Kern::Printf("DEthernetWins::DoCreate(TInt aUnit, const TDesC8* /*anInfo*/)"));
   541    
   542 	iUnit = aUnit;
   543 
   544 	TInt ret = KErrNone;
   545 
   546 	SetMacAddress(); // will panic if can't get proper MAC address
   547 
   548 	const char* speedProperty = Property::GetString(KEpocIniEthSpeedEntry);
   549 
   550 	if( (NULL==speedProperty) ? 0 : (0 == strcmp( speedProperty, KEpocIniEthSpeed10Mbps )) )
   551 		{
   552 		defaultConfig.iEthSpeed = KEthSpeed10BaseT;
   553 		}
   554 	else if ( (NULL==speedProperty) ? 0 : (0 == strcmp( speedProperty, KEpocIniEthSpeed100Mbps )) )
   555 		{
   556 		defaultConfig.iEthSpeed = KEthSpeed100BaseTX;
   557 		}
   558 
   559 	SetDriverName();
   560 
   561 	char errPcap[PCAP_ERRBUF_SIZE];
   562 
   563 	if( iPcapPtr == NULL )
   564 		{
   565 		
   566 		if((iPcapPtr = pcap_open_live( iNetInterfaceName,
   567 									   2000, 
   568                                       1, 
   569                                       20, 
   570                                       errPcap)) != NULL)
   571 			{
   572 	 	    
   573 			if ((iThreadHandle = CreateThread(NULL,
   574                                            0,
   575                                            (LPTHREAD_START_ROUTINE)WorkThread,
   576                                            this,
   577                                            CREATE_SUSPENDED,
   578                                            &iWorkerThreadId)) != NULL)
   579 				{
   580     			ret = Configure(defaultConfig);
   581 				}
   582 			else
   583 				{
   584 				__KTRACE_OPT(KHARDWARE, Kern::Printf("CreateThread() failed to create worker thread"));
   585 				ret = KErrBadHandle; 
   586 				}
   587 			}
   588 		else
   589 			{
   590 		    __KTRACE_OPT(KHARDWARE, Kern::Printf("pcap_open_live() failed to open"));
   591 			//ret = KErrCouldNotConnect;
   592 			PanicFromWinsEtherDrv( EPcapNull );
   593 			}
   594     
   595 		}
   596 	
   597     if(ret != KErrNone)
   598 		{
   599 		// Failed to init all so tidy up
   600 		if( iPcapPtr )
   601 			{
   602 			pcap_close(iPcapPtr);
   603 			iPcapPtr = NULL;
   604 			}
   605 		__KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DoCreate() returned with ERROR"));
   606 		return ret;
   607 		}
   608 
   609 
   610     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DoCreate %2x:%2x:%2x:%2x:%2x:%2x",
   611                                          defaultConfig.iEthAddress[0], 
   612                                          defaultConfig.iEthAddress[1],
   613                                          defaultConfig.iEthAddress[2], 
   614                                          defaultConfig.iEthAddress[3],
   615                                          defaultConfig.iEthAddress[4], 
   616                                          defaultConfig.iEthAddress[5]));
   617 
   618 	return ret;
   619 	}
   620 
   621 
   622 void  DEthernetWins::SetDriverName()
   623 	{
   624 	__KTRACE_OPT(KHARDWARE, 
   625 		Kern::Printf("DEthernetWins::SetDriverName()"));
   626 
   627 	const char* property = Property::GetString(KEpocIniEthNIFEntry);
   628 
   629 	__ASSERT_ALWAYS( (NULL != property),
   630 		PanicFromWinsEtherDrv(ENoNetInterface) );
   631 
   632 	memcpy( iNetInterfaceName, property, strlen(property) );
   633 	}
   634 
   635 
   636 TInt DEthernetWins::SetMacAddress()
   637 // reads MAC address from epoc.ini file and writes into defaultConfig
   638 	{
   639 	
   640 	__KTRACE_OPT(KHARDWARE, 
   641 		Kern::Printf("DEthernetWins::SetMacAddress()"));
   642 
   643 	TUint8 tempAddress[6];
   644 
   645 	const char *tempBuffer = Property::GetString(KEpocIniEthMACEntry);
   646 
   647 	__ASSERT_ALWAYS( ((tempBuffer != NULL) && (strlen(tempBuffer) >= 6)),
   648 		PanicFromWinsEtherDrv(EBadMacAddress) );
   649 
   650 
   651 	TBuf<20> validCharsLower(_L("0123456789abcdef"));
   652 	TBuf<20> validCharsUpper(_L("0123456789ABCDEF"));
   653 	TUint8 value;
   654 	TUint8 upper=0;
   655 	TChar c;
   656 	TInt pos; 
   657 	TInt i;
   658 	for( i=0; i<6; i++)
   659 		{
   660 		c = tempBuffer[2*i];
   661 		if(((pos = validCharsLower.Locate(c)) == KErrNotFound) &&
   662 			((pos = validCharsUpper.Locate(c)) == KErrNotFound))
   663 			{
   664 			PanicFromWinsEtherDrv( EBadMacAddress );
   665 			}
   666 		upper = (TUint8)pos;
   667 		c = tempBuffer[(2*i)+1];
   668 		if( ((pos = validCharsLower.Locate(c)) == KErrNotFound) &&
   669 			((pos = validCharsUpper.Locate(c)) == KErrNotFound) )
   670 			{
   671 			PanicFromWinsEtherDrv( EBadMacAddress );
   672 			}
   673 
   674 		value = (TUint8)pos;
   675 		value = (TUint8)((upper<<4) | value);
   676 		tempAddress[i] = value;
   677 		}
   678 
   679 	for( i=0; i<6; i++ )
   680 		{
   681 		defaultConfig.iEthAddress[i] = tempAddress[i];
   682 		}
   683 
   684 	return KErrNone;
   685 
   686 	}
   687 
   688 
   689 TDfcQue* DEthernetWins::DfcQ(TInt /*aUnit*/)
   690 // Return the DFC queue to be used for this device
   691 	{
   692     __KTRACE_OPT(KHARDWARE, 
   693 		Kern::Printf("DEthernetWins::DfcQ(TInt )"));
   694     return Kern::DfcQue0();
   695 	}
   696 
   697 
   698 TInt DEthernetWins::Start()
   699 // Start receiving frames
   700 	{
   701     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Start()"));
   702 
   703 	TInt32 ret;
   704 	
   705 	// Start thread
   706 	// ResumeThread() - from MSDN help:
   707 	// This function decrements a threadís suspend count. 
   708 	// When the suspend count is decremented to zero, 
   709 	// the execution of the thread is resumed. 
   710 	// Return value: The threadís previous suspend count indicates success. 0xFFFFFFFF indicates failure
   711 	ret = ResumeThread( iThreadHandle );
   712 	if( (0xFFFFFFFF == ret) )//|| (ret > 1) )
   713 		return KErrGeneral;
   714 	
   715     iReady = ETrue;
   716 
   717     return KErrNone;
   718 	}
   719 
   720 
   721 void DEthernetWins::Stop(TStopMode aMode)
   722 // Stop receiving frames
   723 	{
   724     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Stop(TStopMode aMode)"));
   725 
   726 	
   727     switch (aMode)
   728 		{
   729         case EStopNormal:
   730         case EStopEmergency:
   731 			SuspendThread(iThreadHandle);
   732 			iReady = EFalse;
   733 			break;
   734 		default:
   735 			SuspendThread(iThreadHandle);
   736 			iReady = EFalse;
   737 			break;
   738 		}
   739 
   740 	}
   741 
   742 
   743 TInt DEthernetWins::ValidateConfig(const TEthernetConfigV01 &aConfig) const
   744 // Validate a config structure.
   745 	{
   746     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::ValidateConfig(const TEthernetConfigV01 &aConfig) const"));
   747     switch(aConfig.iEthSpeed)
   748         {
   749         case KEthSpeedUnknown:
   750 		case KEthSpeedAuto: 
   751         case KEthSpeed10BaseT:
   752         case KEthSpeed100BaseTX:
   753 			break;
   754         default:		
   755         	return KErrNotSupported;
   756         }
   757 
   758     switch(aConfig.iEthDuplex)
   759         {
   760         case KEthDuplexUnknown:
   761 		case KEthDuplexAuto:
   762         case KEthDuplexHalf:
   763         case KEthDuplexFull:
   764 			break;
   765         default:
   766         	return KErrNotSupported;
   767         }
   768 
   769     return KErrNone;
   770 	}
   771 
   772 
   773 void DEthernetWins::CheckConfig(TEthernetConfigV01& /*aConfig*/)
   774 // dummy implementation of pure virtual function
   775 	{
   776     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::CheckConfig(TEthernetConfigV01& aConfig)"));
   777 	}
   778 
   779 TInt DEthernetWins::Send(TBuf8<KMaxEthernetPacket+32> &aBuffer)
   780 	{
   781     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send(TBuf8<KMaxEthernetPacket+32> &aBuffer)"));
   782     TUint16 * dataP = (TUint16 *)aBuffer.Ptr();
   783     TUint16 length = TUint16(aBuffer.Length());
   784 
   785 	TInt ret;
   786 
   787     if (iPcapPtr)
   788 	    {
   789 		__KTRACE_OPT2(KHARDWARE, KSCRATCH, Kern::Printf("  >pdd tx: sending tcp seq=%u ack=%u", GetTcpSeqNumber(aBuffer), GetTcpAckNumber(aBuffer) ));
   790         if(pcap_sendpacket(iPcapPtr, (unsigned char *)dataP, length))
   791 		    {
   792             __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send - pcap_sendpacket() failed "));
   793 
   794 		    ret = KErrWrite; 
   795 	        }
   796         else
   797 		    {
   798             __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send: \n*** completed pcap_sendpacket() ***\n"));
   799             ret = KErrNone;
   800             }
   801 		}
   802     else
   803 		{
   804         __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send() pcap adapter NOT open\n"));
   805         ret = KErrNotReady; 
   806 		}
   807     
   808     return ret;
   809 	}
   810 
   811 
   812 TInt DEthernetWins::DisableIrqs()
   813 // Disable normal interrupts
   814 	{
   815     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DisableIrqs()"));
   816     return NKern::DisableInterrupts(1);
   817 	}
   818 
   819 
   820 void DEthernetWins::RestoreIrqs(TInt aLevel)
   821 // Restore normal interrupts
   822 	{
   823     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::RestoreIrqs(TInt aLevel)"));
   824     NKern::RestoreInterrupts(aLevel);
   825 	}
   826 
   827 
   828 void DEthernetWins::MacConfigure(TEthernetConfigV01 &aConfig)
   829 	{
   830     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::MacConfigure(TEthernetConfigV01 &aConfig)"));
   831     defaultConfig.iEthAddress[0] = aConfig.iEthAddress[0]; 
   832 	defaultConfig.iEthAddress[1] = aConfig.iEthAddress[1];
   833 	defaultConfig.iEthAddress[2] = aConfig.iEthAddress[2];
   834 	defaultConfig.iEthAddress[3] = aConfig.iEthAddress[3];
   835 	defaultConfig.iEthAddress[4] = aConfig.iEthAddress[4];
   836 	defaultConfig.iEthAddress[5] = aConfig.iEthAddress[5];
   837 	}
   838 
   839 
   840 TInt DEthernetWins::Configure(TEthernetConfigV01 & /*aConfig*/)
   841 // Set a wpcap filter
   842 	{
   843 
   844 	__KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Configure(TEthernetConfigV01 &aConfig)"));
   845 	
   846     char errPcap[PCAP_ERRBUF_SIZE];
   847 	TInt ret = KErrNone;
   848     char filter[128];
   849     struct bpf_program fcode;
   850     bpf_u_int32 SubNet,NetMask;
   851 
   852 	//obtain the subnet
   853     pcap_lookupnet(	iNetInterfaceName, &SubNet, &NetMask, errPcap);
   854 
   855     sprintf(filter, 
   856             PCAP_FILTER, //pcap_filter, 
   857             defaultConfig.iEthAddress[0],
   858             defaultConfig.iEthAddress[1],
   859             defaultConfig.iEthAddress[2],
   860             defaultConfig.iEthAddress[3],
   861             defaultConfig.iEthAddress[4],
   862             defaultConfig.iEthAddress[5],
   863             defaultConfig.iEthAddress[0],
   864             defaultConfig.iEthAddress[1],
   865             defaultConfig.iEthAddress[2],
   866             defaultConfig.iEthAddress[3],
   867             defaultConfig.iEthAddress[4],
   868             defaultConfig.iEthAddress[5]);
   869 
   870 
   871 	//compile the filter
   872     if( 0 != pcap_compile(iPcapPtr, &fcode, filter, 1, NetMask) )
   873 		{
   874 		// failed to compile:
   875 		__KTRACE_OPT(KHARDWARE, Kern::Printf("pcap_compile() failed"));
   876 		ret = KErrUnknown; 
   877 		}
   878 	else
   879 		{
   880 		// compiled successfully: set the filter
   881 		if( 0 != pcap_setfilter(iPcapPtr, &fcode))
   882 			{
   883 			__KTRACE_OPT(KHARDWARE, Kern::Printf("pcap_setfilter() failed"));
   884 			ret = KErrUnknown; 
   885 			}
   886 		}
   887 
   888     return ret; 
   889 	}
   890 
   891 
   892 void DEthernetWins::GetConfig(TEthernetConfigV01 &aConfig) const
   893 // Get the current config from defaultConfig member
   894 	{
   895     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::GetConfig(TEthernetConfigV01 &aConfig) const"));
   896     aConfig = defaultConfig;
   897 	}
   898 
   899 
   900 void DEthernetWins::Caps(TDes8 &aCaps) const
   901 // return PDD's capabilites
   902     {
   903     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Caps(TDes8 &aCaps) const"));
   904     GetWinsEthernetsCaps(aCaps,iUnit); 
   905     }
   906 
   907 
   908 void DEthernetWins::Isr( u_char *thisObject,  
   909                        	const struct pcap_pkthdr *header, 
   910                         const u_char *pkt_data)
   911 // pcap callback fuction
   912 	{
   913     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Isr()"));
   914 
   915 	DEthernetWins& thisPdd = *(DEthernetWins*) thisObject;
   916     	
   917 	StartOfInterrupt();
   918 
   919 	thisPdd.iPcapHeader = header;
   920 	thisPdd.iPcapPktData = pkt_data;
   921 
   922     thisPdd.ReceiveIsr();
   923 	
   924 	EndOfInterrupt();
   925 
   926     return;
   927 	}
   928 
   929 
   930 TInt DEthernetWins::ReceiveFrame(TBuf8<KMaxEthernetPacket+32> &aBuffer, TBool okToUse)
   931 	{
   932     __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::ReceiveFrame(TBuf8<KMaxEthernetPacket+32> &aBuffer)"));
   933 
   934 	// If no buffer available dump frame
   935     if(!okToUse)
   936 		{
   937         return KErrGeneral;
   938 		}
   939 
   940     aBuffer.Copy(iPcapPktData, iPcapHeader->len);
   941     aBuffer.SetLength(iPcapHeader->len);
   942 	__KTRACE_OPT2(KHARDWARE, KSCRATCH, Kern::Printf("  >pdd rx: tcp seq=%u ack=%u", GetTcpSeqNumber(aBuffer), GetTcpAckNumber(aBuffer) ));
   943     
   944 	return KErrNone;
   945 	}
   946 
   947 #ifdef _DEBUG
   948 const TUint8 ETHER2_TYPE_IP_MSB = 0x08;
   949 const TUint8 ETHER2_TYPE_IP_LSB = 0x00;
   950 const TUint8 IP_TYPE_TCP        = 0x06;
   951 
   952 TBool DEthernetWins::IsTcp(TDesC8 &aFrame)
   953 	{
   954  	return (aFrame[12] == ETHER2_TYPE_IP_MSB && aFrame[13] == ETHER2_TYPE_IP_LSB && aFrame[23] == IP_TYPE_TCP);
   955 	}
   956 
   957 TInt DEthernetWins::GetTcpSeqNumber(TDesC8 &aFrame)
   958 	{
   959  	TInt seqNum = 0;
   960  	if (IsTcp(aFrame))
   961  		seqNum = aFrame[38] << 24 | aFrame[39] << 16 | aFrame[40] << 8| aFrame[41];
   962  	return seqNum;
   963  	}
   964 
   965 TInt DEthernetWins::GetTcpAckNumber(TDesC8 &aFrame)
   966  	{
   967  	TInt ackNum = 0;
   968  	if (IsTcp(aFrame))
   969  		ackNum = aFrame[42] << 24 | aFrame[43] << 16 | aFrame[44] << 8| aFrame[45];
   970  	return ackNum;
   971  	}
   972 #endif
   973 
   974 TInt WorkThread(DEthernetWins * aDEthernetWins)
   975 	{
   976     __KTRACE_OPT(KHARDWARE, Kern::Printf("WorkThread(DEthernetWins * aDEthernetWins)"));
   977 
   978     return pcap_loop(aDEthernetWins->iPcapPtr, 0, DEthernetWins::Isr, (unsigned char *)aDEthernetWins);
   979 	}
   980 
   981 /**
   982  * @addtogroup enet_windows
   983  * @{
   984  */
   985 
   986 /**
   987  * Real entry point from the Kernel: return a new driver
   988  * (Macro wrapping: EXPORT_C DPhysicalDevice *CreatePhysicalDevice() )
   989  */
   990 DECLARE_STANDARD_PDD()
   991 	{
   992 	return new DDriverEthernet;
   993 	}
   994 
   995 
   996 /** @} */ // end of windows group