|
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 |