Merge pull request #1033 from marcin-/master

ndiswrapper: add dkms support
This commit is contained in:
marcin
2020-01-09 23:33:56 +01:00
committed by GitHub
8 changed files with 66 additions and 425 deletions
+11 -3
View File
@@ -4,17 +4,21 @@
# Licensed under the GNU General Public License, version 3. # Licensed under the GNU General Public License, version 3.
# See the file http://www.gnu.org/licenses/gpl.txt # See the file http://www.gnu.org/licenses/gpl.txt
from pisi.actionsapi import kerneltools from pisi.actionsapi import get
from pisi.actionsapi import autotools from pisi.actionsapi import autotools
from pisi.actionsapi import pisitools from pisi.actionsapi import pisitools
from pisi.actionsapi import shelltools from pisi.actionsapi import shelltools
from pisi.actionsapi import get from pisi.actionsapi import kerneltools
KDIR = kerneltools.getKernelVersion() KDIR = kerneltools.getKernelVersion()
def setup():
# dkms
shelltools.copytree("driver", "dkms")
pisitools.dosed("dkms.conf", "#MODULE_VERSION#", get.srcVERSION())
def build(): def build():
autotools.make("-C driver KVERS_UNAME=%s" % KDIR) autotools.make("-C driver KVERS_UNAME=%s" % KDIR)
autotools.make("-C utils") autotools.make("-C utils")
def install(): def install():
@@ -28,3 +32,7 @@ def install():
pisitools.dodir("/etc/ndiswrapper") pisitools.dodir("/etc/ndiswrapper")
pisitools.dodoc("README", "AUTHORS", "ChangeLog") pisitools.dodoc("README", "AUTHORS", "ChangeLog")
# dkms
pisitools.insinto("/usr/src/%s-%s" % (get.srcNAME(), get.srcVERSION()), "dkms/*")
pisitools.insinto("/usr/src/%s-%s" % (get.srcNAME(), get.srcVERSION()), "dkms.conf")
@@ -0,0 +1,7 @@
PACKAGE_NAME="ndiswrapper"
PACKAGE_VERSION="#MODULE_VERSION#"
AUTOINSTALL=yes
BUILT_MODULE_NAME[0]="ndiswrapper"
DEST_MODULE_LOCATION[0]="/extra"
MAKE[0]="make KVERS_UNAME=${kernelver}"
@@ -1,55 +0,0 @@
commit fa2aeeccd5366378ca2eb83c6daee64b511fe792
Author: Felix Yan <felixonmars@archlinux.org>
Date: Tue May 16 01:32:56 2017 +0800
Add support for Linux 4.11+
diff --git a/ndiswrapper/driver/ndis.c b/ndiswrapper/driver/ndis.c
index c1913a05..2ab4dd21 100644
--- a/ndiswrapper/driver/ndis.c
+++ b/ndiswrapper/driver/ndis.c
@@ -2258,7 +2258,9 @@ wstdcall void NdisMIndicateReceivePacket(struct ndis_mp_block *nmb,
WARNING("empty packet ignored");
continue;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
wnd->net_dev->last_rx = jiffies;
+#endif
/* get total number of bytes in packet */
NdisGetFirstBufferFromPacketSafe(packet, &buffer, &virt,
&length, &total_length,
@@ -2346,7 +2348,9 @@ wstdcall void EthRxIndicateHandler(struct ndis_mp_block *nmb, void *rx_ctx,
ERROR("nmb is NULL");
EXIT3(return);
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
wnd->net_dev->last_rx = jiffies;
+#endif
if (look_ahead_size < packet_size) {
struct ndis_packet *packet;
@@ -2461,7 +2465,9 @@ wstdcall void NdisMTransferDataComplete(struct ndis_mp_block *nmb,
WARNING("illegal packet");
EXIT3(return);
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
wnd->net_dev->last_rx = jiffies;
+#endif
oob_data = NDIS_PACKET_OOB_DATA(packet);
skb_size = sizeof(oob_data->header) + oob_data->look_ahead_size +
bytes_txed;
diff --git a/ndiswrapper/driver/ntoskernel.h b/ndiswrapper/driver/ntoskernel.h
index 3c4c6ff0..f1c52e51 100644
--- a/ndiswrapper/driver/ntoskernel.h
+++ b/ndiswrapper/driver/ntoskernel.h
@@ -296,6 +296,10 @@ static inline void (INIT_WORK)(struct work_struct *work, work_func_t func)
#define add_taint(flag, lockdep_ok) add_taint(flag)
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+#include <linux/sched/signal.h>
+#endif
+
#include "winnt_types.h"
#include "ndiswrapper.h"
#include "pe_linker.h"
@@ -1,27 +0,0 @@
commit eeac7ab831b3097005dadc64dd323f54ade30323
Author: Felix Yan <felixonmars@archlinux.org>
Date: Mon Sep 11 12:52:36 2017 +0800
Add support for linux 4.13+
diff --git a/ndiswrapper/driver/ntoskernel.h b/ndiswrapper/driver/ntoskernel.h
index f1c52e51..1422bd4d 100644
--- a/ndiswrapper/driver/ntoskernel.h
+++ b/ndiswrapper/driver/ntoskernel.h
@@ -119,9 +119,16 @@ static cpumask_t cpumasks[NR_CPUS];
*/
#include <asm/dma-mapping.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
#define PCI_DMA_ALLOC_COHERENT(pci_dev,size,dma_handle) \
dma_alloc_coherent(&pci_dev->dev,size,dma_handle, \
GFP_KERNEL | __GFP_REPEAT)
+#else
+#define PCI_DMA_ALLOC_COHERENT(pci_dev,size,dma_handle) \
+ dma_alloc_coherent(&pci_dev->dev,size,dma_handle, \
+ GFP_KERNEL | __GFP_RETRY_MAYFAIL)
+#endif
+
#define PCI_DMA_FREE_COHERENT(pci_dev,size,cpu_addr,dma_handle) \
dma_free_coherent(&pci_dev->dev,size,cpu_addr,dma_handle)
#define PCI_DMA_MAP_SINGLE(pci_dev,addr,size,direction) \
@@ -1,199 +0,0 @@
From: Seth Forshee <seth.forshee@canonical.com>
Date: Wed, 13 Dec 2017 15:53:31 -0600
Subject: [PATCH] Build fixes for Linux 4.15
Fixes two build issues for 4.15:
- init_timer() was eliminated in 4.15, and all callers were
converted to using timer_setup(). The callback prototype has
also changed to pass a timer_list argument instead of callback
data, and from_timer() must be used to get to the object in
which the timer is embedded.
- usb_get_status() was changed to take an additional argument,
and usb_get_std_status() was added as a wrapper for callers to
use as a replacment. Call the wrapper in 4.15 and later.
LP: #1737749
---
driver/ntoskernel.c | 19 ++++++++++++++++++-
driver/usb.c | 10 ++++++++--
driver/wrapndis.c | 28 ++++++++++++++++++++++++++++
3 files changed, 54 insertions(+), 3 deletions(-)
diff --git a/driver/ntoskernel.c b/driver/ntoskernel.c
index 4fe0dc1..156c688 100644
--- a/driver/ntoskernel.c
+++ b/driver/ntoskernel.c
@@ -77,7 +77,6 @@ u64 wrap_ticks_to_boot;
#if defined(CONFIG_X86_64)
static struct timer_list shared_data_timer;
struct kuser_shared_data kuser_shared_data;
-static void update_user_shared_data_proc(unsigned long data);
#endif
WIN_SYMBOL_MAP("KeTickCount", &jiffies)
@@ -91,7 +90,11 @@ DEFINE_PER_CPU(struct irql_info, irql_info);
#endif
#if defined(CONFIG_X86_64)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
static void update_user_shared_data_proc(unsigned long data)
+#else
+static void update_user_shared_data_proc(struct timer_list *t)
+#endif
{
/* timer is supposed to be scheduled every 10ms, but bigger
* intervals seem to work (tried up to 50ms) */
@@ -407,9 +410,15 @@ static void initialize_object(struct dispatcher_header *dh, enum dh_type type,
InitializeListHead(&dh->wait_blocks);
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
static void timer_proc(unsigned long data)
{
struct wrap_timer *wrap_timer = (struct wrap_timer *)data;
+#else
+static void timer_proc(struct timer_list *t)
+{
+ struct wrap_timer *wrap_timer = from_timer(wrap_timer, t, timer);
+#endif
struct nt_timer *nt_timer;
struct kdpc *kdpc;
@@ -452,9 +461,13 @@ void wrap_init_timer(struct nt_timer *nt_timer, enum timer_type type,
return;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
init_timer(&wrap_timer->timer);
wrap_timer->timer.data = (unsigned long)wrap_timer;
wrap_timer->timer.function = timer_proc;
+#else
+ timer_setup(&wrap_timer->timer, timer_proc, 0);
+#endif
wrap_timer->nt_timer = nt_timer;
#ifdef TIMER_DEBUG
wrap_timer->wrap_timer_magic = WRAP_TIMER_MAGIC;
@@ -2559,9 +2572,13 @@ int ntoskernel_init(void)
#if defined(CONFIG_X86_64)
memset(&kuser_shared_data, 0, sizeof(kuser_shared_data));
*((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601();
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
init_timer(&shared_data_timer);
shared_data_timer.function = update_user_shared_data_proc;
shared_data_timer.data = 0;
+#else
+ timer_setup(&shared_data_timer, update_user_shared_data_proc, 0);
+#endif
#endif
return 0;
}
diff --git a/driver/usb.c b/driver/usb.c
index 3e7021a..e55c2c6 100644
--- a/driver/usb.c
+++ b/driver/usb.c
@@ -750,6 +750,12 @@ static USBD_STATUS wrap_set_clear_feature(struct usb_device *udev,
USBEXIT(return NT_URB_STATUS(nt_urb));
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
+#define wrap_usb_get_status usb_get_status
+#else
+#define wrap_usb_get_status usb_get_std_status
+#endif
+
static USBD_STATUS wrap_get_status_request(struct usb_device *udev,
struct irp *irp)
{
@@ -776,8 +782,8 @@ static USBD_STATUS wrap_get_status_request(struct usb_device *udev,
return NT_URB_STATUS(nt_urb);
}
assert(status_req->transfer_buffer_length == sizeof(u16));
- ret = usb_get_status(udev, type, status_req->index,
- status_req->transfer_buffer);
+ ret = wrap_usb_get_status(udev, type, status_req->index,
+ status_req->transfer_buffer);
if (ret >= 0) {
assert(ret <= status_req->transfer_buffer_length);
status_req->transfer_buffer_length = ret;
diff --git a/driver/wrapndis.c b/driver/wrapndis.c
index 870e4c2..f653440 100644
--- a/driver/wrapndis.c
+++ b/driver/wrapndis.c
@@ -1093,9 +1093,15 @@ send_assoc_event:
EXIT2(return);
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
static void iw_stats_timer_proc(unsigned long data)
{
struct ndis_device *wnd = (struct ndis_device *)data;
+#else
+static void iw_stats_timer_proc(struct timer_list *t)
+{
+ struct ndis_device *wnd = from_timer(wnd, t, iw_stats_timer);
+#endif
ENTER2("%d", wnd->iw_stats_interval);
if (wnd->iw_stats_interval > 0) {
@@ -1111,8 +1117,12 @@ static void add_iw_stats_timer(struct ndis_device *wnd)
return;
if (wnd->iw_stats_interval < 0)
wnd->iw_stats_interval *= -1;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
wnd->iw_stats_timer.data = (unsigned long)wnd;
wnd->iw_stats_timer.function = iw_stats_timer_proc;
+#else
+ timer_setup(&wnd->iw_stats_timer, iw_stats_timer_proc, 0);
+#endif
mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval);
}
@@ -1124,9 +1134,15 @@ static void del_iw_stats_timer(struct ndis_device *wnd)
EXIT2(return);
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
static void hangcheck_proc(unsigned long data)
{
struct ndis_device *wnd = (struct ndis_device *)data;
+#else
+static void hangcheck_proc(struct timer_list *t)
+{
+ struct ndis_device *wnd = from_timer(wnd, t, hangcheck_timer);
+#endif
ENTER3("%d", wnd->hangcheck_interval);
if (wnd->hangcheck_interval > 0) {
@@ -1147,8 +1163,12 @@ void hangcheck_add(struct ndis_device *wnd)
wnd->hangcheck_interval = hangcheck_interval * HZ;
if (wnd->hangcheck_interval < 0)
wnd->hangcheck_interval *= -1;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
wnd->hangcheck_timer.data = (unsigned long)wnd;
wnd->hangcheck_timer.function = hangcheck_proc;
+#else
+ timer_setup(&wnd->hangcheck_timer, hangcheck_proc, 0);
+#endif
mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval);
EXIT2(return);
}
@@ -2138,9 +2158,17 @@ static NTSTATUS ndis_add_device(struct driver_object *drv_obj,
wnd->dma_map_count = 0;
wnd->dma_map_addr = NULL;
wnd->nick[0] = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
init_timer(&wnd->hangcheck_timer);
+#else
+ timer_setup(&wnd->hangcheck_timer, NULL, 0);
+#endif
wnd->scan_timestamp = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
init_timer(&wnd->iw_stats_timer);
+#else
+ timer_setup(&wnd->iw_stats_timer, NULL, 0);
+#endif
wnd->iw_stats_interval = 10 * HZ;
wnd->ndis_pending_work = 0;
memset(&wnd->essid, 0, sizeof(wnd->essid));
@@ -1,33 +0,0 @@
--- ndiswrapper-1.59.orig/driver/crt.c 2013-11-28 21:42:35.000000000 +0200
+++ ndiswrapper-1.59/driver/crt.c 2014-05-10 19:26:47.063312726 +0300
@@ -467,7 +467,7 @@
noregparm void WIN_FUNC(_win_srand,1)
(UINT seed)
{
- net_srandom(seed);
+ prandom_seed((__force u32)(seed));
}
noregparm int WIN_FUNC(rand,0)
--- ndiswrapper-1.59.orig/driver/ntoskernel.h 2013-11-28 21:42:36.000000000 +0200
+++ ndiswrapper-1.59/driver/ntoskernel.h 2014-05-10 19:28:42.113311836 +0300
@@ -347,7 +347,7 @@
#define netdev_notifier_info_to_dev(x) ((struct net_device *)(x))
#endif
-#ifdef INIT_COMPLETION
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
static inline void reinit_completion(struct completion *x)
{
INIT_COMPLETION(*x);
@@ -797,9 +797,8 @@
#define nt_spin_unlock_irqrestore(lock, flags) \
do { \
nt_spin_unlock(lock); \
- preempt_enable_no_resched(); \
+ preempt_enable(); \
local_irq_restore(flags); \
- preempt_check_resched(); \
} while (0)
static inline ULONG SPAN_PAGES(void *ptr, SIZE_T length)
@@ -1,100 +0,0 @@
diff -Nuar ndiswrapper-1.60.orig/ChangeLog ndiswrapper-1.60/ChangeLog
--- ndiswrapper-1.60.orig/ChangeLog 2016-07-27 19:05:10.594950240 +0300
+++ ndiswrapper-1.60/ChangeLog 2016-07-27 19:06:04.678949272 +0300
@@ -1,7 +1,3 @@
-Version 1.60 2016-05-01
-=======================
-* Support for Linux kernel up to 4.5
-
Version 1.59 2013-11-28
=======================
* Support for Linux kernels from 2.6.13 to 3.12
diff -Nuar ndiswrapper-1.60.orig/driver/.gitignore ndiswrapper-1.60/driver/.gitignore
--- ndiswrapper-1.60.orig/driver/.gitignore 1970-01-01 02:00:00.000000000 +0200
+++ ndiswrapper-1.60/driver/.gitignore 2016-07-27 19:06:04.678949272 +0300
@@ -0,0 +1,11 @@
+*.ko
+*.mod.c
+*.o
+.*.cmd
+*_exports.h
+/.tmp_versions/
+/Module.markers
+/Module.symvers
+/modules.order
+/ndis_exports.h
+/win2lin_stubs.h
diff -Nuar ndiswrapper-1.60.orig/driver/loader.h ndiswrapper-1.60/driver/loader.h
--- ndiswrapper-1.60.orig/driver/loader.h 2016-07-27 19:05:10.593950240 +0300
+++ ndiswrapper-1.60/driver/loader.h 2016-07-27 19:06:09.795949180 +0300
@@ -16,10 +16,6 @@
#ifndef _LOADER_H_
#define _LOADER_H_
-#if LINUX_VERSION_CODE > KERNEL_VERSION(4,0,0)
-#include <linux/vmalloc.h>
-#endif
-
#include "ndiswrapper.h"
#ifndef __KERNEL__
diff -Nuar ndiswrapper-1.60.orig/driver/ntoskernel.h ndiswrapper-1.60/driver/ntoskernel.h
--- ndiswrapper-1.60.orig/driver/ntoskernel.h 2016-07-27 19:05:10.593950240 +0300
+++ ndiswrapper-1.60/driver/ntoskernel.h 2016-07-27 19:06:13.834949108 +0300
@@ -46,6 +46,8 @@
#include <linux/percpu.h>
#include <linux/kthread.h>
#include <linux/workqueue.h>
+#include <linux/vmalloc.h>
+
#if !defined(CONFIG_X86) && !defined(CONFIG_X86_64)
#error "this module is for x86 or x86_64 architectures only"
@@ -358,8 +360,18 @@
#define prandom_seed(seed) net_srandom(seed)
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
-#define strncasecmp strnicmp
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+static int strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ strnicmp(s1, s2, n);
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+static inline void netif_trans_update(struct net_device *dev)
+{
+ dev->trans_start = jiffies;
+}
#endif
/* TICK is 100ns */
diff -Nuar ndiswrapper-1.60.orig/driver/wrapndis.c ndiswrapper-1.60/driver/wrapndis.c
--- ndiswrapper-1.60.orig/driver/wrapndis.c 2016-07-27 19:05:10.593950240 +0300
+++ ndiswrapper-1.60/driver/wrapndis.c 2016-07-27 19:06:23.295948938 +0300
@@ -704,7 +704,7 @@
n = wnd->max_tx_packets;
n = mp_tx_packets(wnd, wnd->tx_ring_start, n);
if (n) {
- wnd->net_dev->trans_start = jiffies;
+ netif_trans_update(wnd->net_dev);
wnd->tx_ring_start =
(wnd->tx_ring_start + n) % TX_RING_SIZE;
wnd->is_tx_ring_full = 0;
diff -Nuar ndiswrapper-1.60.orig/ndiswrapper.spec ndiswrapper-1.60/ndiswrapper.spec
--- ndiswrapper-1.60.orig/ndiswrapper.spec 2016-07-27 19:05:10.594950240 +0300
+++ ndiswrapper-1.60/ndiswrapper.spec 2016-07-27 19:06:28.472948846 +0300
@@ -1,5 +1,5 @@
# Define ndiswrapper_version only if it is not already defined.
-%{!?ndiswrapper_version: %define ndiswrapper_version 1.60}
+%{!?ndiswrapper_version: %define ndiswrapper_version svn}
%{!?ndiswrapper_release: %define ndiswrapper_release 1}
# Define kernel version if not already defined
diff -Nuar ndiswrapper-1.60.orig/utils/.gitignore ndiswrapper-1.60/utils/.gitignore
--- ndiswrapper-1.60.orig/utils/.gitignore 1970-01-01 02:00:00.000000000 +0200
+++ ndiswrapper-1.60/utils/.gitignore 2016-07-27 19:06:29.224948832 +0300
@@ -0,0 +1 @@
+/loadndisdriver
+45 -5
View File
@@ -14,6 +14,9 @@
<Summary>A network driver wrapper</Summary> <Summary>A network driver wrapper</Summary>
<Description>module-ndiswrapper allows you to use Windows XP drivers for WLAN cards without proper Linux drivers.</Description> <Description>module-ndiswrapper allows you to use Windows XP drivers for WLAN cards without proper Linux drivers.</Description>
<Archive sha1sum="d98b97ff7e88d39b7966b4a3e7b7deeb7dc6e192" type="targz">http://download.sourceforge.net/ndiswrapper/ndiswrapper-1.62.tar.gz</Archive> <Archive sha1sum="d98b97ff7e88d39b7966b4a3e7b7deeb7dc6e192" type="targz">http://download.sourceforge.net/ndiswrapper/ndiswrapper-1.62.tar.gz</Archive>
<AdditionalFiles>
<AdditionalFile owner="root" permission="0644" target="dkms.conf">dkms.conf</AdditionalFile>
</AdditionalFiles>
<BuildDependencies> <BuildDependencies>
<Dependency version="5.4.8">kernel-module-headers</Dependency> <Dependency version="5.4.8">kernel-module-headers</Dependency>
</BuildDependencies> </BuildDependencies>
@@ -24,12 +27,8 @@
</Source> </Source>
<Package> <Package>
<Name>ndiswrapper</Name> <Name>ndiswrapper-common</Name>
<RuntimeDependencies>
<Dependency version="5.4.8">kernel</Dependency>
</RuntimeDependencies>
<Files> <Files>
<Path fileType="library" permanent="true">/lib/modules</Path>
<Path fileType="man">/usr/share/man</Path> <Path fileType="man">/usr/share/man</Path>
<Path fileType="data">/etc/ndiswrapper</Path> <Path fileType="data">/etc/ndiswrapper</Path>
<Path fileType="executable">/usr/sbin</Path> <Path fileType="executable">/usr/sbin</Path>
@@ -41,7 +40,48 @@
</BuildFlags> </BuildFlags>
</Package> </Package>
<Package>
<Name>module-ndiswrapper</Name>
<RuntimeDependencies>
<Dependency version="5.4.8">kernel</Dependency>
<Dependency release="current">ndiswrapper-common</Dependency>
</RuntimeDependencies>
<Files>
<Path fileType="library">/lib/modules</Path>
</Files>
<BuildFlags>
<Flag>noDelta</Flag>
</BuildFlags>
<Conflicts>
<Package>ndiswrapper-dkms</Package>
</Conflicts>
</Package>
<Package>
<Name>ndiswrapper-dkms</Name>
<RuntimeDependencies>
<Dependency>dkms</Dependency>
<Dependency release="current">ndiswrapper-common</Dependency>
</RuntimeDependencies>
<Files>
<Path fileType="data">/usr/src/ndiswrapper-*</Path>
</Files>
<BuildFlags>
<Flag>noDelta</Flag>
</BuildFlags>
<Conflicts>
<Package>module-ndiswrapper</Package>
</Conflicts>
</Package>
<History> <History>
<Update release="28">
<Date>2020-01-09</Date>
<Version>1.62</Version>
<Comment>Add dkms support</Comment>
<Name>Marcin Bojara</Name>
<Email>marcin.bojara@gmail.com</Email>
</Update>
<Update release="27"> <Update release="27">
<Date>2019-12-27</Date> <Date>2019-12-27</Date>
<Version>1.62</Version> <Version>1.62</Version>