emulator/emulatorbsp/specific/ethernet.cpp
changeset 0 cec860690d41
equal deleted inserted replaced
-1:000000000000 0:cec860690d41
       
     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