1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/boardsupport/emulator/emulatorbsp/specific/ethernet.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,996 @@
1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// wins\specific\ethernet.cpp
1.18 +// PDD for the Ethernet under the windows emulator
1.19 +//
1.20 +//
1.21 +
1.22 +/**
1.23 + @file wins/specific/ethernet.cpp
1.24 +*/
1.25 +
1.26 +
1.27 +#include <ethernet.h>
1.28 +#include "nk_priv.h"
1.29 +#include "nk_plat.h"
1.30 +#include <property.h>
1.31 +
1.32 +#include "pcap.h"
1.33 +
1.34 +
1.35 +/** @addtogroup enet Ethernet Drivers
1.36 + * Kernel Ethernet Support
1.37 + */
1.38 +
1.39 +/** @addtogroup enet_pdd Driver PDD's
1.40 + * @ingroup enet
1.41 + */
1.42 +
1.43 +/** @addtogroup enet_byplatform Ethernet support by platform
1.44 + * @ingroup enet
1.45 + */
1.46 +
1.47 +/** @addtogroup enet_wins WINS (Emulator) Ethernet support
1.48 + * @ingroup enet_byplatform
1.49 + */
1.50 +
1.51 +
1.52 +// strings potentially written to ethernet.ini by netcards.exe
1.53 +#define KEpocIniEthSpeed10Mbps "10Mbps"
1.54 +#define KEpocIniEthSpeed100Mbps "100Mbps"
1.55 +
1.56 +// entries in epoc.ini file:
1.57 +#define KEpocIniEthSpeedEntry "ETHER_SPEED"
1.58 +#define KEpocIniEthNIFEntry "ETHER_NIF"
1.59 +#define KEpocIniEthMACEntry "ETHER_MAC"
1.60 +
1.61 +#define KEthDrvPanicCategory "D32ETHER"
1.62 +
1.63 +#define KLocalDriverNameMax 256
1.64 +
1.65 +#define PCAP_FILTER "ether dst %x:%x:%x:%x:%x:%x or ether multicast and ether src not %x:%x:%x:%x:%x:%x"
1.66 +
1.67 +_LIT(KPddName, "Ethernet.Wins");
1.68 +
1.69 +// needs ldd version..
1.70 +const TInt KMinimumLddMajorVersion=1;
1.71 +const TInt KMinimumLddMinorVersion=0;
1.72 +const TInt KMinimumLddBuild=122;
1.73 +
1.74 +/** @addtogroup enet_windows Windows Emulator Ethernet Pdd
1.75 + * @ingroup enet_pdd
1.76 + * @ingroup enet_wins
1.77 + * @{
1.78 + */
1.79 +
1.80 +/**
1.81 + * The Windows specific Ethernet physical device (factory) class
1.82 + * @internalTechnology belongs to PDD which sits internally in kernel
1.83 + */
1.84 +class DDriverEthernet : public DPhysicalDevice
1.85 + {
1.86 +public:
1.87 +
1.88 + /**
1.89 + * The constructor
1.90 + * Sets the drivers version number. Limits possible
1.91 + * number of units to one only (unit 0)
1.92 + */
1.93 + DDriverEthernet();
1.94 +
1.95 + /**
1.96 + * Inherited from DPhysicalDevice.
1.97 + * Install the driver by setting it's name
1.98 + * @return KErrNone on success, other error code on failure
1.99 + */
1.100 + virtual TInt Install();
1.101 +
1.102 + /**
1.103 + * Inherited from DPhysicalDevice.
1.104 + * Get the Capabilites of the driver
1.105 + * NOT supported but required as implementation of
1.106 + * pure virtual in base class
1.107 + */
1.108 + virtual void GetCaps(TDes8 &aDes) const;
1.109 +
1.110 + /**
1.111 + * Inherited from DPhysicalDevice.
1.112 + * Create a channel to a device
1.113 + * @param aChannel a reference to a newly created channel object
1.114 + * @param aUnit a unit for which the channel is being created
1.115 + * @param anInfo pointer to a descriptor with additional info (may be NULL)
1.116 + * @param aVer a requested version
1.117 + * @return KErrNone on success, other error code on failure
1.118 + */
1.119 + virtual TInt Create(DBase*& aChannel, TInt aUnit,
1.120 + const TDesC8* anInfo, const TVersion &aVer);
1.121 +
1.122 + /**
1.123 + * Inherited from DPhysicalDevice.
1.124 + * Validate that the info supplied would create a valid channel
1.125 + * @param aUnit a unit for which validation is to be done
1.126 + * @param anInfo pointer to a descriptor with additional info (may be NULL)
1.127 + * @param aVer a version to be validated
1.128 + * @return KErrNone if valid, KErrNotSupported otherwise
1.129 + */
1.130 + virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer);
1.131 + };
1.132 +
1.133 +
1.134 +/**
1.135 + * The WINS specific Ethernet channel class for the libpcap library
1.136 + * @internalTechnology belongs to PDD which sits internally in kernel
1.137 + */
1.138 +class DEthernetWins : public DEthernet
1.139 + {
1.140 +
1.141 + /**
1.142 + * The Worker Thread
1.143 + * @param aDEthernetWins Pointer to this object
1.144 + * @return Should never return
1.145 + */
1.146 + friend TInt WorkThread(DEthernetWins * aDEthernetWins);
1.147 +
1.148 +public:
1.149 +
1.150 + enum TWinsEtherPanic
1.151 + {
1.152 + EBadMacAddress = 1, // means bad MAC address in ini file or entry for it missing or ini file missing
1.153 + ENoNetInterface, // means entry for network interface name missing in ini file or ini file missing
1.154 + EPcapNull // means Wpcap couldn't be initialised - potentially not installed or name of network interface in ini file wrong
1.155 + };
1.156 +
1.157 + /**
1.158 + * The Constructor.
1.159 + */
1.160 + DEthernetWins();
1.161 +
1.162 + /**
1.163 + * The Destructor.
1.164 + */
1.165 + ~DEthernetWins();
1.166 +
1.167 + /**
1.168 + * The Isr plays a role of the pcap callback.
1.169 + * Do NOT call the function directly
1.170 + * @param thisObject a pointer to this object
1.171 + * @param header the received packet's pcap header
1.172 + * @param pkt_data the received packet
1.173 + * @post new packet is copied to LDD's RX buffers' queue
1.174 + */
1.175 + static void Isr(u_char *thisObject,
1.176 + const struct pcap_pkthdr *header,
1.177 + const u_char *pkt_data);
1.178 +
1.179 + /**
1.180 + * The DoCreate Method.
1.181 + * Sets up the channel as part of the object creation
1.182 + * and retrieves the MAC address from epoc.ini file.
1.183 + * Also creates wpcap handler and thread for wpcap loop.
1.184 + * @pre epoc32\\data\\epoc.ini must exist with entries: "ETHER-NIF=..", "ETHER-MAC=..", "ETHER-SPEED=.."
1.185 + * @param aUnit a unit for which the channel is being created
1.186 + * @panic D32ETHER reason: (1) can't get proper MAC address (2) can't get
1.187 + * network interface name (3) can't initialise wpcap
1.188 + * @return KErrNone on success, other error code on failure
1.189 + */
1.190 + TInt DoCreate(TInt aUnit);
1.191 +
1.192 + /**
1.193 + * DEthernet implementation.
1.194 + * Start the receiver.
1.195 + * Resumes pcap thread. Sets status to ready.
1.196 + * @return KErrNone on success or suitable error code on failure
1.197 + */
1.198 + virtual TInt Start();
1.199 +
1.200 + /**
1.201 + * DEthernet implementation.
1.202 + * Stop the receiver.
1.203 + * @param aMode possible values are: EStopNormal (=0), EStopEmergency (=1)
1.204 + * @post pcap thread suspended, status set to not ready
1.205 + */
1.206 + virtual void Stop(TStopMode aMode);
1.207 +
1.208 + /**
1.209 + * DEthernet implementation.
1.210 + * Validates a new configuration - should be called before Configure()
1.211 + * @param aConfig is the configuration to be validated
1.212 + * @return KErrNone if aConfig valid, KErrNotSupported otherwise
1.213 + * @see Configure()
1.214 + */
1.215 + virtual TInt ValidateConfig(const TEthernetConfigV01 &aConfig) const;
1.216 +
1.217 + /**
1.218 + * DEthernet implementation.
1.219 + * Configure the PDD and pcap library
1.220 + * Reconfigure the library using the new configuration supplied.
1.221 + * Sets pcap filter to read only frames with destination address set to
1.222 + * broadcast, multicast or MAC addresss from defaultConfig.
1.223 + * This will not change the MAC address.
1.224 + * @param aConfig The new configuration
1.225 + * @return KErrNone on success, suitable error code otherwise
1.226 + * @see ValidateConfig()
1.227 + * @see MacConfigure()
1.228 + */
1.229 + virtual TInt Configure(TEthernetConfigV01 &aConfig);
1.230 +
1.231 + /**
1.232 + * DEthernet implementation.
1.233 + * Change the MAC address - writes new MAC address in defaultConfig.
1.234 + * If new settings are to have any effect then pcap filter
1.235 + * ought to be set again which is done by 'Configure()'
1.236 + * @param aConfig a configuration structure containing the new MAC
1.237 + * @see Configure()
1.238 + */
1.239 + virtual void MacConfigure(TEthernetConfigV01 &aConfig);
1.240 +
1.241 + /**
1.242 + * DEthernet implementation.
1.243 + * Get the current config from defaultConfig member varaiable
1.244 + * which is assumed to be up to date.
1.245 + * Fills in the following fields:
1.246 + * The Transmit Speed
1.247 + * The Duplex Setting
1.248 + * The MAC address
1.249 + * @param aConfig is a TEthernetConfigV01 reference that will be filled in
1.250 + */
1.251 + virtual void GetConfig(TEthernetConfigV01 &aConfig) const;
1.252 +
1.253 + /**
1.254 + * DEthernet implementation.
1.255 + * Dummy method, required as pure virtual in base class
1.256 + */
1.257 + virtual void CheckConfig(TEthernetConfigV01 &aConfig);
1.258 +
1.259 + /**
1.260 + * DEthernet implementation.
1.261 + * Should query the capabilites.
1.262 + * NOT supported but required as pure virtual in base class
1.263 + */
1.264 + virtual void Caps(TDes8 &aCaps) const;
1.265 +
1.266 + /**
1.267 + * DEthernet implementation.
1.268 + * Transmit data via wpcap
1.269 + * @param aBuffer reference to the data to be sent
1.270 + * @return KErrNone on success, other error code on failure
1.271 + */
1.272 + virtual TInt Send(TBuf8<KMaxEthernetPacket+32> &aBuffer);
1.273 +
1.274 + /**
1.275 + * DEthernet implementation.
1.276 + * Retrieve data
1.277 + * Pull the received data out of the pcap library and into the supplied buffer.
1.278 + * Need to be told if the buffer is OK
1.279 + * @param aBuffer Reference to the buffer to be used to store the data in
1.280 + * @param okToUse Bool to indicate if the buffer is usable
1.281 + * @return KErrNone on success, other error code on failure
1.282 + */
1.283 + virtual TInt ReceiveFrame(TBuf8<KMaxEthernetPacket+32> &aBuffer, TBool okToUse);
1.284 +
1.285 + /**
1.286 + * DEthernet implementation.
1.287 + * Disables all IRQ's
1.288 + * @return The IRQ level before it was changed
1.289 + * @see RestoreIrqs()
1.290 + */
1.291 + virtual TInt DisableIrqs();
1.292 +
1.293 + /**
1.294 + * DEthernet implementation.
1.295 + * Restore the IRQ's to the supplied level
1.296 + * @param aIrq The level to set the irqs to.
1.297 + * @see DisableIrqs()
1.298 + */
1.299 + virtual void RestoreIrqs(TInt aIrq);
1.300 +
1.301 + /**
1.302 + * DEthernet implementation.
1.303 + * Return the DFC Queue that this device should use
1.304 + * @param aUnit a channel's unit number (ignored - only one unit possible)
1.305 + * @return a DFC Queue to use
1.306 + */
1.307 + virtual TDfcQue* DfcQ(TInt aUnit);
1.308 +
1.309 +
1.310 +private:
1.311 + static TBool DEthernetWins::IsTcp(TDesC8 &aFrame);
1.312 + static TInt DEthernetWins::GetTcpAckNumber(TDesC8 &frame);
1.313 + static TInt DEthernetWins::GetTcpSeqNumber(TDesC8 &frame);
1.314 + /**
1.315 + * Read network interface to be used from configuration file. Panic if
1.316 + * pre-conditions are not satisfied.
1.317 + * @pre epoc32\\data\\epoc.ini must exist with entry: "ETHER-NIF=existing_nif_name"
1.318 + * @post network interface name put in a member variable: iNetInterfaceName
1.319 + * @panic D32ETHER reason: (2) can't get network interface name
1.320 + */
1.321 + void SetDriverName();
1.322 +
1.323 + /**
1.324 + * Read MAC address from a configuration file and put it
1.325 + * into defaultConfig member variable checking before if the
1.326 + * one from the file is correct. Panic if pre-conditions are not satisfied
1.327 + * (although in case when MAC address is improper).
1.328 + * @pre epoc32\\data\\epoc.ini must exist with entry: "ETHER-MAC=proper_mac_address"
1.329 + * @panic D32ETHER reason: EBadMacAddress
1.330 + * @return KErrNone on success (panics on failure)
1.331 + */
1.332 + TInt SetMacAddress();
1.333 +
1.334 +
1.335 +private:
1.336 +
1.337 + /**
1.338 + * The handle to the pcap interface - wpcap specific
1.339 + */
1.340 + pcap_t * iPcapPtr;
1.341 +
1.342 + /**
1.343 + * Saved received packet information - wpcap specific:
1.344 + * pointer to a structure that holds general information about the packet:
1.345 + * the time in which it was sniffed, the length of this packet,
1.346 + * and the length of his specific portion (in case it is fragmented)
1.347 + */
1.348 + const struct pcap_pkthdr * iPcapHeader;
1.349 +
1.350 + /**
1.351 + * Saved receive packet data - wpcap specific
1.352 + */
1.353 + const u_char * iPcapPktData;
1.354 +
1.355 + /**
1.356 + * Id of the receiver - wpcap thread
1.357 + */
1.358 + unsigned long iWorkerThreadId;
1.359 +
1.360 + /**
1.361 + * Contains the handle to wpcap thread.
1.362 + */
1.363 + HANDLE iThreadHandle;
1.364 +
1.365 + /**
1.366 + * Stores the unit number (only one interface possible in
1.367 + * this implementation, so it will have value "0")
1.368 + */
1.369 + TInt iUnit;
1.370 +
1.371 + /**
1.372 + * Is ETrue if the chip has been fully configured and is ready
1.373 + * for receiving frames. Is set to ETrue in Start(), to EFalse
1.374 + * in Stop(). Initialized in constructor as EFalse.
1.375 + */
1.376 + TBool iReady;
1.377 +
1.378 + /**
1.379 + * Contains the default/current configuration of the driver.
1.380 + * Updated whenever configuration is to be changed.
1.381 + */
1.382 + TEthernetConfigV01 defaultConfig;
1.383 +
1.384 + /**
1.385 + * Contains the network interface name to be used
1.386 + * @see SetDriverName()
1.387 + */
1.388 + char iNetInterfaceName[KLocalDriverNameMax];
1.389 +
1.390 + };
1.391 +
1.392 +/** @} */ // End of wins ethernet pdd
1.393 +
1.394 +
1.395 +
1.396 +DDriverEthernet::DDriverEthernet()
1.397 +// Constructor
1.398 + {
1.399 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::DDriverEthernet()"));
1.400 + iUnitsMask=0x1; // support unit 0 only
1.401 + iVersion=TVersion(KEthernetMajorVersionNumber,
1.402 + KEthernetMinorVersionNumber,
1.403 + KEthernetBuildVersionNumber);
1.404 +
1.405 + }
1.406 +
1.407 +
1.408 +TInt DDriverEthernet::Install()
1.409 +// Install the driver
1.410 + {
1.411 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::Install()"));
1.412 + return SetName(&KPddName);
1.413 + }
1.414 +
1.415 +
1.416 +void GetWinsEthernetsCaps(TDes8 &aCaps, TInt aUnit=0)
1.417 + {
1.418 + __KTRACE_OPT(KHARDWARE, Kern::Printf("GetWinsEthernetsCaps(TDes8 &aCaps, TInt aUnit)"));
1.419 + TEthernetCaps capsBuf;
1.420 +
1.421 + aUnit=0;
1.422 +
1.423 + aCaps.FillZ(aCaps.MaxLength());
1.424 + aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength()));
1.425 + }
1.426 +
1.427 +void PanicFromWinsEtherDrv(TInt aReason)
1.428 + {
1.429 + Kern::Fault(KEthDrvPanicCategory, aReason);
1.430 + }
1.431 +
1.432 +void DDriverEthernet::GetCaps(TDes8 &aDes) const
1.433 +// Return the driver's capabilities
1.434 + {
1.435 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::GetCaps(TDes8 &aDes) const"));
1.436 + GetWinsEthernetsCaps(aDes);
1.437 + }
1.438 +
1.439 +
1.440 +TInt DDriverEthernet::Create(DBase*& aChannel,
1.441 + TInt aUnit,
1.442 + const TDesC8* aInfo,
1.443 + const TVersion& aVer)
1.444 +// Create a driver
1.445 + {
1.446 + __KTRACE_OPT(KHARDWARE,
1.447 + Kern::Printf("DDriverEthernet::Create(DBase*& aChannel, TInt aUnit, const TDesC8* nInfo, const TVersion& aVer)"));
1.448 +
1.449 + TInt ret;
1.450 +
1.451 + ret = Validate( aUnit, aInfo, aVer);
1.452 + if ( KErrNone != ret )
1.453 + return ret;
1.454 +
1.455 + ret = KErrNoMemory;
1.456 +
1.457 + DEthernetWins* ptrPdd = new DEthernetWins;
1.458 +
1.459 +
1.460 + if ( ptrPdd )
1.461 + {
1.462 + ret = ptrPdd->DoCreate(aUnit);
1.463 + if ( ret != KErrNone)
1.464 + {
1.465 + delete ptrPdd;
1.466 + }
1.467 + else
1.468 + aChannel = ptrPdd;
1.469 + }
1.470 +
1.471 +
1.472 + return ret;
1.473 + }
1.474 +
1.475 +
1.476 +TInt DDriverEthernet::Validate(TInt aUnit,
1.477 + const TDesC8* /*aInfo*/,
1.478 + const TVersion& aVer)
1.479 +// Validate the requested configuration
1.480 + {
1.481 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::Validate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)"));
1.482 + if ((!Kern::QueryVersionSupported(iVersion,aVer)) ||
1.483 + (!Kern::QueryVersionSupported(aVer,TVersion(KMinimumLddMajorVersion,
1.484 + KMinimumLddMinorVersion,
1.485 + KMinimumLddBuild))))
1.486 + {
1.487 + return KErrNotSupported;
1.488 + }
1.489 +
1.490 + if (aUnit != 0)
1.491 + {
1.492 + return KErrNotSupported;
1.493 + }
1.494 +
1.495 + return KErrNone;
1.496 + }
1.497 +
1.498 +
1.499 +DEthernetWins::DEthernetWins()
1.500 +// Constructor
1.501 + {
1.502 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DEthernetWins()"));
1.503 +
1.504 + iReady = EFalse;
1.505 +
1.506 + // set default configuration - must be set before DoCreate gets called
1.507 + defaultConfig.iEthSpeed = KEthSpeedUnknown;
1.508 + defaultConfig.iEthDuplex = KEthDuplexUnknown;
1.509 +
1.510 + // MAC address initially set to NULL
1.511 + defaultConfig.iEthAddress[0] = 0;
1.512 + defaultConfig.iEthAddress[1] = 0;
1.513 + defaultConfig.iEthAddress[2] = 0;
1.514 + defaultConfig.iEthAddress[3] = 0;
1.515 + defaultConfig.iEthAddress[4] = 0;
1.516 + defaultConfig.iEthAddress[5] = 0;
1.517 +
1.518 + iNetInterfaceName[0] = '\0';
1.519 +
1.520 + // wpcap
1.521 + iPcapPtr = NULL;
1.522 +
1.523 + }
1.524 +
1.525 +DEthernetWins::~DEthernetWins()
1.526 +// Destructor
1.527 + {
1.528 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::~DEthernetWins()"));
1.529 +
1.530 + if (iPcapPtr)
1.531 + {
1.532 + pcap_close(iPcapPtr);
1.533 + iPcapPtr = NULL;
1.534 + }
1.535 +
1.536 + }
1.537 +
1.538 +
1.539 +TInt DEthernetWins::DoCreate(TInt aUnit)//, const TDesC8* /*anInfo*/)
1.540 +// Sets up the PDD
1.541 + {
1.542 + __KTRACE_OPT(KHARDWARE,
1.543 + Kern::Printf("DEthernetWins::DoCreate(TInt aUnit, const TDesC8* /*anInfo*/)"));
1.544 +
1.545 + iUnit = aUnit;
1.546 +
1.547 + TInt ret = KErrNone;
1.548 +
1.549 + SetMacAddress(); // will panic if can't get proper MAC address
1.550 +
1.551 + const char* speedProperty = Property::GetString(KEpocIniEthSpeedEntry);
1.552 +
1.553 + if( (NULL==speedProperty) ? 0 : (0 == strcmp( speedProperty, KEpocIniEthSpeed10Mbps )) )
1.554 + {
1.555 + defaultConfig.iEthSpeed = KEthSpeed10BaseT;
1.556 + }
1.557 + else if ( (NULL==speedProperty) ? 0 : (0 == strcmp( speedProperty, KEpocIniEthSpeed100Mbps )) )
1.558 + {
1.559 + defaultConfig.iEthSpeed = KEthSpeed100BaseTX;
1.560 + }
1.561 +
1.562 + SetDriverName();
1.563 +
1.564 + char errPcap[PCAP_ERRBUF_SIZE];
1.565 +
1.566 + if( iPcapPtr == NULL )
1.567 + {
1.568 +
1.569 + if((iPcapPtr = pcap_open_live( iNetInterfaceName,
1.570 + 2000,
1.571 + 1,
1.572 + 20,
1.573 + errPcap)) != NULL)
1.574 + {
1.575 +
1.576 + if ((iThreadHandle = CreateThread(NULL,
1.577 + 0,
1.578 + (LPTHREAD_START_ROUTINE)WorkThread,
1.579 + this,
1.580 + CREATE_SUSPENDED,
1.581 + &iWorkerThreadId)) != NULL)
1.582 + {
1.583 + ret = Configure(defaultConfig);
1.584 + }
1.585 + else
1.586 + {
1.587 + __KTRACE_OPT(KHARDWARE, Kern::Printf("CreateThread() failed to create worker thread"));
1.588 + ret = KErrBadHandle;
1.589 + }
1.590 + }
1.591 + else
1.592 + {
1.593 + __KTRACE_OPT(KHARDWARE, Kern::Printf("pcap_open_live() failed to open"));
1.594 + //ret = KErrCouldNotConnect;
1.595 + PanicFromWinsEtherDrv( EPcapNull );
1.596 + }
1.597 +
1.598 + }
1.599 +
1.600 + if(ret != KErrNone)
1.601 + {
1.602 + // Failed to init all so tidy up
1.603 + if( iPcapPtr )
1.604 + {
1.605 + pcap_close(iPcapPtr);
1.606 + iPcapPtr = NULL;
1.607 + }
1.608 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DoCreate() returned with ERROR"));
1.609 + return ret;
1.610 + }
1.611 +
1.612 +
1.613 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DoCreate %2x:%2x:%2x:%2x:%2x:%2x",
1.614 + defaultConfig.iEthAddress[0],
1.615 + defaultConfig.iEthAddress[1],
1.616 + defaultConfig.iEthAddress[2],
1.617 + defaultConfig.iEthAddress[3],
1.618 + defaultConfig.iEthAddress[4],
1.619 + defaultConfig.iEthAddress[5]));
1.620 +
1.621 + return ret;
1.622 + }
1.623 +
1.624 +
1.625 +void DEthernetWins::SetDriverName()
1.626 + {
1.627 + __KTRACE_OPT(KHARDWARE,
1.628 + Kern::Printf("DEthernetWins::SetDriverName()"));
1.629 +
1.630 + const char* property = Property::GetString(KEpocIniEthNIFEntry);
1.631 +
1.632 + __ASSERT_ALWAYS( (NULL != property),
1.633 + PanicFromWinsEtherDrv(ENoNetInterface) );
1.634 +
1.635 + memcpy( iNetInterfaceName, property, strlen(property) );
1.636 + }
1.637 +
1.638 +
1.639 +TInt DEthernetWins::SetMacAddress()
1.640 +// reads MAC address from epoc.ini file and writes into defaultConfig
1.641 + {
1.642 +
1.643 + __KTRACE_OPT(KHARDWARE,
1.644 + Kern::Printf("DEthernetWins::SetMacAddress()"));
1.645 +
1.646 + TUint8 tempAddress[6];
1.647 +
1.648 + const char *tempBuffer = Property::GetString(KEpocIniEthMACEntry);
1.649 +
1.650 + __ASSERT_ALWAYS( ((tempBuffer != NULL) && (strlen(tempBuffer) >= 6)),
1.651 + PanicFromWinsEtherDrv(EBadMacAddress) );
1.652 +
1.653 +
1.654 + TBuf<20> validCharsLower(_L("0123456789abcdef"));
1.655 + TBuf<20> validCharsUpper(_L("0123456789ABCDEF"));
1.656 + TUint8 value;
1.657 + TUint8 upper=0;
1.658 + TChar c;
1.659 + TInt pos;
1.660 + TInt i;
1.661 + for( i=0; i<6; i++)
1.662 + {
1.663 + c = tempBuffer[2*i];
1.664 + if(((pos = validCharsLower.Locate(c)) == KErrNotFound) &&
1.665 + ((pos = validCharsUpper.Locate(c)) == KErrNotFound))
1.666 + {
1.667 + PanicFromWinsEtherDrv( EBadMacAddress );
1.668 + }
1.669 + upper = (TUint8)pos;
1.670 + c = tempBuffer[(2*i)+1];
1.671 + if( ((pos = validCharsLower.Locate(c)) == KErrNotFound) &&
1.672 + ((pos = validCharsUpper.Locate(c)) == KErrNotFound) )
1.673 + {
1.674 + PanicFromWinsEtherDrv( EBadMacAddress );
1.675 + }
1.676 +
1.677 + value = (TUint8)pos;
1.678 + value = (TUint8)((upper<<4) | value);
1.679 + tempAddress[i] = value;
1.680 + }
1.681 +
1.682 + for( i=0; i<6; i++ )
1.683 + {
1.684 + defaultConfig.iEthAddress[i] = tempAddress[i];
1.685 + }
1.686 +
1.687 + return KErrNone;
1.688 +
1.689 + }
1.690 +
1.691 +
1.692 +TDfcQue* DEthernetWins::DfcQ(TInt /*aUnit*/)
1.693 +// Return the DFC queue to be used for this device
1.694 + {
1.695 + __KTRACE_OPT(KHARDWARE,
1.696 + Kern::Printf("DEthernetWins::DfcQ(TInt )"));
1.697 + return Kern::DfcQue0();
1.698 + }
1.699 +
1.700 +
1.701 +TInt DEthernetWins::Start()
1.702 +// Start receiving frames
1.703 + {
1.704 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Start()"));
1.705 +
1.706 + TInt32 ret;
1.707 +
1.708 + // Start thread
1.709 + // ResumeThread() - from MSDN help:
1.710 + // This function decrements a thread’s suspend count.
1.711 + // When the suspend count is decremented to zero,
1.712 + // the execution of the thread is resumed.
1.713 + // Return value: The thread’s previous suspend count indicates success. 0xFFFFFFFF indicates failure
1.714 + ret = ResumeThread( iThreadHandle );
1.715 + if( (0xFFFFFFFF == ret) )//|| (ret > 1) )
1.716 + return KErrGeneral;
1.717 +
1.718 + iReady = ETrue;
1.719 +
1.720 + return KErrNone;
1.721 + }
1.722 +
1.723 +
1.724 +void DEthernetWins::Stop(TStopMode aMode)
1.725 +// Stop receiving frames
1.726 + {
1.727 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Stop(TStopMode aMode)"));
1.728 +
1.729 +
1.730 + switch (aMode)
1.731 + {
1.732 + case EStopNormal:
1.733 + case EStopEmergency:
1.734 + SuspendThread(iThreadHandle);
1.735 + iReady = EFalse;
1.736 + break;
1.737 + default:
1.738 + SuspendThread(iThreadHandle);
1.739 + iReady = EFalse;
1.740 + break;
1.741 + }
1.742 +
1.743 + }
1.744 +
1.745 +
1.746 +TInt DEthernetWins::ValidateConfig(const TEthernetConfigV01 &aConfig) const
1.747 +// Validate a config structure.
1.748 + {
1.749 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::ValidateConfig(const TEthernetConfigV01 &aConfig) const"));
1.750 + switch(aConfig.iEthSpeed)
1.751 + {
1.752 + case KEthSpeedUnknown:
1.753 + case KEthSpeedAuto:
1.754 + case KEthSpeed10BaseT:
1.755 + case KEthSpeed100BaseTX:
1.756 + break;
1.757 + default:
1.758 + return KErrNotSupported;
1.759 + }
1.760 +
1.761 + switch(aConfig.iEthDuplex)
1.762 + {
1.763 + case KEthDuplexUnknown:
1.764 + case KEthDuplexAuto:
1.765 + case KEthDuplexHalf:
1.766 + case KEthDuplexFull:
1.767 + break;
1.768 + default:
1.769 + return KErrNotSupported;
1.770 + }
1.771 +
1.772 + return KErrNone;
1.773 + }
1.774 +
1.775 +
1.776 +void DEthernetWins::CheckConfig(TEthernetConfigV01& /*aConfig*/)
1.777 +// dummy implementation of pure virtual function
1.778 + {
1.779 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::CheckConfig(TEthernetConfigV01& aConfig)"));
1.780 + }
1.781 +
1.782 +TInt DEthernetWins::Send(TBuf8<KMaxEthernetPacket+32> &aBuffer)
1.783 + {
1.784 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send(TBuf8<KMaxEthernetPacket+32> &aBuffer)"));
1.785 + TUint16 * dataP = (TUint16 *)aBuffer.Ptr();
1.786 + TUint16 length = TUint16(aBuffer.Length());
1.787 +
1.788 + TInt ret;
1.789 +
1.790 + if (iPcapPtr)
1.791 + {
1.792 + __KTRACE_OPT2(KHARDWARE, KSCRATCH, Kern::Printf(" >pdd tx: sending tcp seq=%u ack=%u", GetTcpSeqNumber(aBuffer), GetTcpAckNumber(aBuffer) ));
1.793 + if(pcap_sendpacket(iPcapPtr, (unsigned char *)dataP, length))
1.794 + {
1.795 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send - pcap_sendpacket() failed "));
1.796 +
1.797 + ret = KErrWrite;
1.798 + }
1.799 + else
1.800 + {
1.801 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send: \n*** completed pcap_sendpacket() ***\n"));
1.802 + ret = KErrNone;
1.803 + }
1.804 + }
1.805 + else
1.806 + {
1.807 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send() pcap adapter NOT open\n"));
1.808 + ret = KErrNotReady;
1.809 + }
1.810 +
1.811 + return ret;
1.812 + }
1.813 +
1.814 +
1.815 +TInt DEthernetWins::DisableIrqs()
1.816 +// Disable normal interrupts
1.817 + {
1.818 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DisableIrqs()"));
1.819 + return NKern::DisableInterrupts(1);
1.820 + }
1.821 +
1.822 +
1.823 +void DEthernetWins::RestoreIrqs(TInt aLevel)
1.824 +// Restore normal interrupts
1.825 + {
1.826 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::RestoreIrqs(TInt aLevel)"));
1.827 + NKern::RestoreInterrupts(aLevel);
1.828 + }
1.829 +
1.830 +
1.831 +void DEthernetWins::MacConfigure(TEthernetConfigV01 &aConfig)
1.832 + {
1.833 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::MacConfigure(TEthernetConfigV01 &aConfig)"));
1.834 + defaultConfig.iEthAddress[0] = aConfig.iEthAddress[0];
1.835 + defaultConfig.iEthAddress[1] = aConfig.iEthAddress[1];
1.836 + defaultConfig.iEthAddress[2] = aConfig.iEthAddress[2];
1.837 + defaultConfig.iEthAddress[3] = aConfig.iEthAddress[3];
1.838 + defaultConfig.iEthAddress[4] = aConfig.iEthAddress[4];
1.839 + defaultConfig.iEthAddress[5] = aConfig.iEthAddress[5];
1.840 + }
1.841 +
1.842 +
1.843 +TInt DEthernetWins::Configure(TEthernetConfigV01 & /*aConfig*/)
1.844 +// Set a wpcap filter
1.845 + {
1.846 +
1.847 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Configure(TEthernetConfigV01 &aConfig)"));
1.848 +
1.849 + char errPcap[PCAP_ERRBUF_SIZE];
1.850 + TInt ret = KErrNone;
1.851 + char filter[128];
1.852 + struct bpf_program fcode;
1.853 + bpf_u_int32 SubNet,NetMask;
1.854 +
1.855 + //obtain the subnet
1.856 + pcap_lookupnet( iNetInterfaceName, &SubNet, &NetMask, errPcap);
1.857 +
1.858 + sprintf(filter,
1.859 + PCAP_FILTER, //pcap_filter,
1.860 + defaultConfig.iEthAddress[0],
1.861 + defaultConfig.iEthAddress[1],
1.862 + defaultConfig.iEthAddress[2],
1.863 + defaultConfig.iEthAddress[3],
1.864 + defaultConfig.iEthAddress[4],
1.865 + defaultConfig.iEthAddress[5],
1.866 + defaultConfig.iEthAddress[0],
1.867 + defaultConfig.iEthAddress[1],
1.868 + defaultConfig.iEthAddress[2],
1.869 + defaultConfig.iEthAddress[3],
1.870 + defaultConfig.iEthAddress[4],
1.871 + defaultConfig.iEthAddress[5]);
1.872 +
1.873 +
1.874 + //compile the filter
1.875 + if( 0 != pcap_compile(iPcapPtr, &fcode, filter, 1, NetMask) )
1.876 + {
1.877 + // failed to compile:
1.878 + __KTRACE_OPT(KHARDWARE, Kern::Printf("pcap_compile() failed"));
1.879 + ret = KErrUnknown;
1.880 + }
1.881 + else
1.882 + {
1.883 + // compiled successfully: set the filter
1.884 + if( 0 != pcap_setfilter(iPcapPtr, &fcode))
1.885 + {
1.886 + __KTRACE_OPT(KHARDWARE, Kern::Printf("pcap_setfilter() failed"));
1.887 + ret = KErrUnknown;
1.888 + }
1.889 + }
1.890 +
1.891 + return ret;
1.892 + }
1.893 +
1.894 +
1.895 +void DEthernetWins::GetConfig(TEthernetConfigV01 &aConfig) const
1.896 +// Get the current config from defaultConfig member
1.897 + {
1.898 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::GetConfig(TEthernetConfigV01 &aConfig) const"));
1.899 + aConfig = defaultConfig;
1.900 + }
1.901 +
1.902 +
1.903 +void DEthernetWins::Caps(TDes8 &aCaps) const
1.904 +// return PDD's capabilites
1.905 + {
1.906 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Caps(TDes8 &aCaps) const"));
1.907 + GetWinsEthernetsCaps(aCaps,iUnit);
1.908 + }
1.909 +
1.910 +
1.911 +void DEthernetWins::Isr( u_char *thisObject,
1.912 + const struct pcap_pkthdr *header,
1.913 + const u_char *pkt_data)
1.914 +// pcap callback fuction
1.915 + {
1.916 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Isr()"));
1.917 +
1.918 + DEthernetWins& thisPdd = *(DEthernetWins*) thisObject;
1.919 +
1.920 + StartOfInterrupt();
1.921 +
1.922 + thisPdd.iPcapHeader = header;
1.923 + thisPdd.iPcapPktData = pkt_data;
1.924 +
1.925 + thisPdd.ReceiveIsr();
1.926 +
1.927 + EndOfInterrupt();
1.928 +
1.929 + return;
1.930 + }
1.931 +
1.932 +
1.933 +TInt DEthernetWins::ReceiveFrame(TBuf8<KMaxEthernetPacket+32> &aBuffer, TBool okToUse)
1.934 + {
1.935 + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::ReceiveFrame(TBuf8<KMaxEthernetPacket+32> &aBuffer)"));
1.936 +
1.937 + // If no buffer available dump frame
1.938 + if(!okToUse)
1.939 + {
1.940 + return KErrGeneral;
1.941 + }
1.942 +
1.943 + aBuffer.Copy(iPcapPktData, iPcapHeader->len);
1.944 + aBuffer.SetLength(iPcapHeader->len);
1.945 + __KTRACE_OPT2(KHARDWARE, KSCRATCH, Kern::Printf(" >pdd rx: tcp seq=%u ack=%u", GetTcpSeqNumber(aBuffer), GetTcpAckNumber(aBuffer) ));
1.946 +
1.947 + return KErrNone;
1.948 + }
1.949 +
1.950 +#ifdef _DEBUG
1.951 +const TUint8 ETHER2_TYPE_IP_MSB = 0x08;
1.952 +const TUint8 ETHER2_TYPE_IP_LSB = 0x00;
1.953 +const TUint8 IP_TYPE_TCP = 0x06;
1.954 +
1.955 +TBool DEthernetWins::IsTcp(TDesC8 &aFrame)
1.956 + {
1.957 + return (aFrame[12] == ETHER2_TYPE_IP_MSB && aFrame[13] == ETHER2_TYPE_IP_LSB && aFrame[23] == IP_TYPE_TCP);
1.958 + }
1.959 +
1.960 +TInt DEthernetWins::GetTcpSeqNumber(TDesC8 &aFrame)
1.961 + {
1.962 + TInt seqNum = 0;
1.963 + if (IsTcp(aFrame))
1.964 + seqNum = aFrame[38] << 24 | aFrame[39] << 16 | aFrame[40] << 8| aFrame[41];
1.965 + return seqNum;
1.966 + }
1.967 +
1.968 +TInt DEthernetWins::GetTcpAckNumber(TDesC8 &aFrame)
1.969 + {
1.970 + TInt ackNum = 0;
1.971 + if (IsTcp(aFrame))
1.972 + ackNum = aFrame[42] << 24 | aFrame[43] << 16 | aFrame[44] << 8| aFrame[45];
1.973 + return ackNum;
1.974 + }
1.975 +#endif
1.976 +
1.977 +TInt WorkThread(DEthernetWins * aDEthernetWins)
1.978 + {
1.979 + __KTRACE_OPT(KHARDWARE, Kern::Printf("WorkThread(DEthernetWins * aDEthernetWins)"));
1.980 +
1.981 + return pcap_loop(aDEthernetWins->iPcapPtr, 0, DEthernetWins::Isr, (unsigned char *)aDEthernetWins);
1.982 + }
1.983 +
1.984 +/**
1.985 + * @addtogroup enet_windows
1.986 + * @{
1.987 + */
1.988 +
1.989 +/**
1.990 + * Real entry point from the Kernel: return a new driver
1.991 + * (Macro wrapping: EXPORT_C DPhysicalDevice *CreatePhysicalDevice() )
1.992 + */
1.993 +DECLARE_STANDARD_PDD()
1.994 + {
1.995 + return new DDriverEthernet;
1.996 + }
1.997 +
1.998 +
1.999 +/** @} */ // end of windows group