From 0f475af6131b885eeca83405c151c648f2978565 Mon Sep 17 00:00:00 2001 From: "Dimitrios Chr. Ioannidis" Date: Fri, 19 Mar 2021 15:58:29 +0200 Subject: [PATCH 01/10] Add OS Descriptor support and report to windows ( 8.1 and up ) that we are compatible with the winusb driver. --- firmware/main.c | 103 +++++++++++++++++++++++++++++++++++++++---- firmware/usbconfig.h | 4 +- 2 files changed, 97 insertions(+), 10 deletions(-) diff --git a/firmware/main.c b/firmware/main.c index 740c36b..e8af168 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -35,8 +35,93 @@ static unsigned int prog_pagesize; static uchar prog_blockflags; static uchar prog_pagecounter; +/* For Windows OS Descriptors we need to report that we support USB 2.0 */ + +PROGMEM const char usbDescriptorDevice[18] = { /* USB device descriptor */ + 18, /* sizeof(usbDescriptorDevice): length of descriptor in bytes */ + USBDESCR_DEVICE, /* descriptor type */ + 0x00, 0x02, /* USB version supported */ + USB_CFG_DEVICE_CLASS, + USB_CFG_DEVICE_SUBCLASS, + 0, /* protocol */ + 8, /* max packet size */ + /* the following two casts affect the first byte of the constant only, but + * that's sufficient to avoid a warning with the default values. + */ + (char)USB_CFG_VENDOR_ID,/* 2 bytes */ + (char)USB_CFG_DEVICE_ID,/* 2 bytes */ + USB_CFG_DEVICE_VERSION, /* 2 bytes */ + 1, /*USB_CFG_DESCR_PROPS_STRING_VENDOR != 0 ? 1 : 0,*/ /* manufacturer string index */ + 2, /*USB_CFG_DESCR_PROPS_STRING_PRODUCT != 0 ? 2 : 0, */ /* product string index */ + 3, /* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER != 0 ? 3 : 0, */ /* serial number string index */ + 1, /* number of configurations */ +}; + + +/* See https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeusb/c2f351f9-84d2-4a1b-9fe3-a6ca195f84d0 */ + +#define MS_VENDOR_CODE 0x5D + +PROGMEM const char OS_STRING_DESCRIPTOR[18] = { + 0x14, /* Length: An unsigned byte and MUST be set to 0x14. */ + 0x03, /* Type: An unsigned byte and MUST be set to 0x03. */ + 'M',0,'S',0,'F',0,'T',0,'1',0,'0',0,'0',0, /* Signature: A Unicode string and MUST be set to "MSFT100". */ + MS_VENDOR_CODE, /* MS Vendor Code: An unsigned byte, + it will be used to retrieve associated feature descriptors. */ + 0x00 /* Pad: An unsigned byte and MUST be set to 0x00. */ +}; + +/* TODO: Change them to progmem consts */ + +typedef struct +{ + uint32_t dwLength; + uint16_t bcdVersion; + uint16_t wIndex; + uint8_t bCount; + uint8_t reserved[7]; +} usbExtCompatHeader_t; + +typedef struct +{ + usbExtCompatHeader_t header; + uint8_t bFirstInterfaceNumber; + uint8_t reserved1; + char compatibleID[8]; + char subCompatibleID[8]; + uint8_t reserved2[6]; +} usbExtCompatDescriptor_t; + +static const usbExtCompatDescriptor_t msExtCompatDescriptor = +{ + { sizeof(usbExtCompatDescriptor_t), 0x0100, 0x0004, 1 }, + 0, + 1, + "WINUSB", + "" +}; + +usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { + + DBG1(0xEE, &rq->wValue.bytes[0], 2); + + /* 0xEE OS string descriptor reply */ + if ((rq->wValue.bytes[1] == USBRQ_GET_DESCRIPTOR) && (rq->wValue.bytes[0] == 0xEE)) { + + usbMsgPtr = (usbMsgPtr_t)&OS_STRING_DESCRIPTOR; + + return sizeof(OS_STRING_DESCRIPTOR); + + }; + + return 0; + +}; + uchar usbFunctionSetup(uchar data[8]) { + const usbRequest_t* request = (const usbRequest_t*)data; + uchar len = 0; if (data[1] == USBASP_FUNC_CONNECT) { @@ -178,15 +263,17 @@ uchar usbFunctionSetup(uchar data[8]) { prog_state = PROG_STATE_TPI_WRITE; len = 0xff; /* multiple out */ - } else if (data[1] == USBASP_FUNC_GETCAPABILITIES) { - replyBuffer[0] = USBASP_CAP_0_TPI; - replyBuffer[1] = 0; - replyBuffer[2] = 0; - replyBuffer[3] = 0; - len = 4; - } + } else if (request->bRequest == MS_VENDOR_CODE) { + if (request->wIndex.word == 0x0004) + { + usbMsgPtr = (usbMsgPtr_t)&msExtCompatDescriptor; + return sizeof(msExtCompatDescriptor); + } + + return 0; + } - usbMsgPtr = replyBuffer; + usbMsgPtr = replyBuffer; return len; } diff --git a/firmware/usbconfig.h b/firmware/usbconfig.h index d779fe0..7cc7276 100644 --- a/firmware/usbconfig.h +++ b/firmware/usbconfig.h @@ -210,7 +210,7 @@ the newest features and options. * */ -#define USB_CFG_DESCR_PROPS_DEVICE 0 +#define USB_CFG_DESCR_PROPS_DEVICE USB_PROP_LENGTH(18) #define USB_CFG_DESCR_PROPS_CONFIGURATION 0 #define USB_CFG_DESCR_PROPS_STRINGS 0 #define USB_CFG_DESCR_PROPS_STRING_0 0 @@ -219,7 +219,7 @@ the newest features and options. #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0 #define USB_CFG_DESCR_PROPS_HID 0 #define USB_CFG_DESCR_PROPS_HID_REPORT 0 -#define USB_CFG_DESCR_PROPS_UNKNOWN 0 +#define USB_CFG_DESCR_PROPS_UNKNOWN (USB_PROP_IS_DYNAMIC) /* ----------------------- Optional MCU Description ------------------------ */ From 35b7e8fb3354274f16ca8b1ae5b45dc4c070fcc7 Mon Sep 17 00:00:00 2001 From: "Dimitrios Chr. Ioannidis" Date: Sun, 21 Mar 2021 00:37:23 +0200 Subject: [PATCH 02/10] Add comments. --- firmware/main.c | 86 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/firmware/main.c b/firmware/main.c index e8af168..85c619f 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -35,6 +35,59 @@ static unsigned int prog_pagesize; static uchar prog_blockflags; static uchar prog_pagecounter; + +/* USBasp default winusb driver for Windows. + + To avoid using driver installation (Zadig, libusb) on Windows and use by default + the winusb default driver for USBasp, we need to useOS feature descriptors. + All USB 2.0 devices ,when they are enumerated for the first time, Windows asks if + there is a OS feature descriptor by sending a specidic standard GET_DESCRIPTOR request + with the format : + + -------------------------------------------------------------------------------------------------- + | bmRequestType | bRequest | wValue | wIndex | wLength | Data | + -------------------------------------------------------------------------------------------------- + | 1000 0000B | GET_DESCRIPTOR | 0x03EE | 0x0000 | 0x12 | Returned string | + -------------------------------------------------------------------------------------------------- + + It asks if there is a specific string descriptor at index 0xEE. Because this string + descriptor request, is not by default handled by the V-USB, we change the USB_CFG_DESCR_PROPS_UNKNOWN + to be dynamic (USB_PROP_IS_DYNAMIC). This effectively tell the V-USB that for every + unknown string index request to call the usbFunctionDescriptor function. + + usbFunctionDescriptor function returns a OS string descriptor using the version 1.00 format + which has a fixed length of 18 bytes, with a structure as shown in the following table. + + -------------------------------------------------------------------------- + | Length | Type | Signature | MS Vendor Code | Pad | + -------------------------------------------------------------------------- + | 0x14 | 0x03 | MSFT100 | unsigned byte | 0x00 | + -------------------------------------------------------------------------- + + Length: An unsigned byte and MUST be set to 0x14. + + Type: An unsigned byte and MUST be set to 0x03. + + Signature: A Unicode string and MUST be set to "MSFT100". + + MS Vendor Code: An unsigned byte, it will be used to retrieve associated feature descriptors. + + Pad: An unsigned byte and MUST be set to 0x00. + + The Signature field contains a Unicode character array that identifies the descriptor as an OS string descriptor and includes the version number. For version 1.00, this array must be set to "MSFT100" (0x4D00 0x5300 0x4600 0x5400 0x3100 0x3000 0x3000). + + The MS VendorCode field is used to retrieve the associated feature descriptors. This code is used as Request field in TS_URB_CONTROL_VENDOR_OR_CLASS_REQUEST section 2.2.9.12. + + In usbFunctionSetup we handle the feature request associated to MS Vendor Code we replied earlier + and send a Extended Compat ID with the information that we want Windows to load the winusb default driver. + + For More information see + + https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeusb/c2f351f9-84d2-4a1b-9fe3-a6ca195f84d0 +*/ + + /* For Windows OS Descriptors we need to report that we support USB 2.0 */ PROGMEM const char usbDescriptorDevice[18] = { /* USB device descriptor */ @@ -58,19 +111,6 @@ PROGMEM const char usbDescriptorDevice[18] = { /* USB device descriptor */ }; -/* See https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeusb/c2f351f9-84d2-4a1b-9fe3-a6ca195f84d0 */ - -#define MS_VENDOR_CODE 0x5D - -PROGMEM const char OS_STRING_DESCRIPTOR[18] = { - 0x14, /* Length: An unsigned byte and MUST be set to 0x14. */ - 0x03, /* Type: An unsigned byte and MUST be set to 0x03. */ - 'M',0,'S',0,'F',0,'T',0,'1',0,'0',0,'0',0, /* Signature: A Unicode string and MUST be set to "MSFT100". */ - MS_VENDOR_CODE, /* MS Vendor Code: An unsigned byte, - it will be used to retrieve associated feature descriptors. */ - 0x00 /* Pad: An unsigned byte and MUST be set to 0x00. */ -}; - /* TODO: Change them to progmem consts */ typedef struct @@ -101,12 +141,22 @@ static const usbExtCompatDescriptor_t msExtCompatDescriptor = "" }; +#define MS_VENDOR_CODE 0x5D +PROGMEM const char OS_STRING_DESCRIPTOR[18] = { + 0x14, /* Length: An unsigned byte and MUST be set to 0x14. */ + 0x03, /* Type: An unsigned byte and MUST be set to 0x03. */ + 'M',0,'S',0,'F',0,'T',0,'1',0,'0',0,'0',0, /* Signature: A Unicode string and MUST be set to "MSFT100". */ + MS_VENDOR_CODE, /* MS Vendor Code: An unsigned byte, + it will be used to retrieve associated feature descriptors. */ + 0x00 /* Pad: An unsigned byte and MUST be set to 0x00. */ +}; + usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { DBG1(0xEE, &rq->wValue.bytes[0], 2); - /* 0xEE OS string descriptor reply */ - if ((rq->wValue.bytes[1] == USBRQ_GET_DESCRIPTOR) && (rq->wValue.bytes[0] == 0xEE)) { + /* string (3) request at index 0xEE, is am OS string descriptor request */ + if ((rq->wValue.bytes[1] == 3) && (rq->wValue.bytes[0] == 0xEE)) { usbMsgPtr = (usbMsgPtr_t)&OS_STRING_DESCRIPTOR; @@ -263,9 +313,13 @@ uchar usbFunctionSetup(uchar data[8]) { prog_state = PROG_STATE_TPI_WRITE; len = 0xff; /* multiple out */ - } else if (request->bRequest == MS_VENDOR_CODE) { + /* Handle the OS feature request associated with the MS Vendor Code + we replied earlier in OS String Descriptor request. See usbFunctionDescriptor. */ + } else if (request->bRequest == MS_VENDOR_CODE) { if (request->wIndex.word == 0x0004) { + /* Send the Extended Compat ID OS feature descriptor, + requesting to load the default winusb driver for us */ usbMsgPtr = (usbMsgPtr_t)&msExtCompatDescriptor; return sizeof(msExtCompatDescriptor); } From a28012ca49a7e39fedbfecbb42942c74b4d84538 Mon Sep 17 00:00:00 2001 From: "Dimitrios Chr. Ioannidis" Date: Sun, 21 Mar 2021 00:49:00 +0200 Subject: [PATCH 03/10] Misc and spelling. --- firmware/main.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/firmware/main.c b/firmware/main.c index 85c619f..9ad2ba5 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -39,9 +39,9 @@ static uchar prog_pagecounter; /* USBasp default winusb driver for Windows. To avoid using driver installation (Zadig, libusb) on Windows and use by default - the winusb default driver for USBasp, we need to useOS feature descriptors. + the winusb default driver for USBasp, we need to use OS feature descriptors. All USB 2.0 devices ,when they are enumerated for the first time, Windows asks if - there is a OS feature descriptor by sending a specidic standard GET_DESCRIPTOR request + there is an OS feature descriptor by sending a specific standard GET_DESCRIPTOR request with the format : -------------------------------------------------------------------------------------------------- @@ -55,8 +55,8 @@ static uchar prog_pagecounter; to be dynamic (USB_PROP_IS_DYNAMIC). This effectively tell the V-USB that for every unknown string index request to call the usbFunctionDescriptor function. - usbFunctionDescriptor function returns a OS string descriptor using the version 1.00 format - which has a fixed length of 18 bytes, with a structure as shown in the following table. + usbFunctionDescriptor function returns an OS string descriptor using the version 1.00 format + which has a fixed length of 18 bytes, with a structure as shown in the following table : -------------------------------------------------------------------------- | Length | Type | Signature | MS Vendor Code | Pad | @@ -74,12 +74,15 @@ static uchar prog_pagecounter; Pad: An unsigned byte and MUST be set to 0x00. - The Signature field contains a Unicode character array that identifies the descriptor as an OS string descriptor and includes the version number. For version 1.00, this array must be set to "MSFT100" (0x4D00 0x5300 0x4600 0x5400 0x3100 0x3000 0x3000). + The Signature field contains a Unicode character array that identifies the descriptor as an + OS string descriptor and includes the version number. For version 1.00, this array must be set + to "MSFT100" (0x4D00 0x5300 0x4600 0x5400 0x3100 0x3000 0x3000). - The MS VendorCode field is used to retrieve the associated feature descriptors. This code is used as Request field in TS_URB_CONTROL_VENDOR_OR_CLASS_REQUEST section 2.2.9.12. + The MS VendorCode field is used to retrieve the associated feature descriptors. This code is + used as Request field in TS_URB_CONTROL_VENDOR_OR_CLASS_REQUEST section 2.2.9.12. In usbFunctionSetup we handle the feature request associated to MS Vendor Code we replied earlier - and send a Extended Compat ID with the information that we want Windows to load the winusb default driver. + and send an Extended Compat ID with the information that we want Windows to load the winusb default driver. For More information see @@ -155,7 +158,7 @@ usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { DBG1(0xEE, &rq->wValue.bytes[0], 2); - /* string (3) request at index 0xEE, is am OS string descriptor request */ + /* string (3) request at index 0xEE, is an OS string descriptor request */ if ((rq->wValue.bytes[1] == 3) && (rq->wValue.bytes[0] == 0xEE)) { usbMsgPtr = (usbMsgPtr_t)&OS_STRING_DESCRIPTOR; @@ -314,7 +317,7 @@ uchar usbFunctionSetup(uchar data[8]) { len = 0xff; /* multiple out */ /* Handle the OS feature request associated with the MS Vendor Code - we replied earlier in OS String Descriptor request. See usbFunctionDescriptor. */ + we replied earlier in the OS String Descriptor request. See usbFunctionDescriptor. */ } else if (request->bRequest == MS_VENDOR_CODE) { if (request->wIndex.word == 0x0004) { From 734d211c3655094d24e0123929ed9b61c221c58f Mon Sep 17 00:00:00 2001 From: "Dimitrios Chr. Ioannidis" Date: Sun, 21 Mar 2021 01:16:39 +0200 Subject: [PATCH 04/10] Changed the length of the OS String Descriptor after Ralph's posted the link https://docs.microsoft.com/en-us/windows-hardware/drivers/network/mb-interface-model-supplement in his message https://github.com/nerdralph/usbasp/pull/5#issuecomment-803476093 --- firmware/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/firmware/main.c b/firmware/main.c index 9ad2ba5..d724b80 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -61,7 +61,7 @@ static uchar prog_pagecounter; -------------------------------------------------------------------------- | Length | Type | Signature | MS Vendor Code | Pad | -------------------------------------------------------------------------- - | 0x14 | 0x03 | MSFT100 | unsigned byte | 0x00 | + | 0x12 | 0x03 | MSFT100 | unsigned byte | 0x00 | -------------------------------------------------------------------------- Length: An unsigned byte and MUST be set to 0x14. @@ -146,7 +146,8 @@ static const usbExtCompatDescriptor_t msExtCompatDescriptor = #define MS_VENDOR_CODE 0x5D PROGMEM const char OS_STRING_DESCRIPTOR[18] = { - 0x14, /* Length: An unsigned byte and MUST be set to 0x14. */ + 0x12, /* Length: An unsigned byte and MUST be set to 0x12. */ + /* https://docs.microsoft.com/en-us/windows-hardware/drivers/network/mb-interface-model-supplement */ 0x03, /* Type: An unsigned byte and MUST be set to 0x03. */ 'M',0,'S',0,'F',0,'T',0,'1',0,'0',0,'0',0, /* Signature: A Unicode string and MUST be set to "MSFT100". */ MS_VENDOR_CODE, /* MS Vendor Code: An unsigned byte, From 74b43ae221de234d43c523df627c7009926be256 Mon Sep 17 00:00:00 2001 From: "Dimitrios Chr. Ioannidis" Date: Sun, 21 Mar 2021 02:00:25 +0200 Subject: [PATCH 05/10] Aknowledge the Marius Greuel's hard work. --- firmware/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/firmware/main.c b/firmware/main.c index d724b80..02f310b 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -38,6 +38,9 @@ static uchar prog_pagecounter; /* USBasp default winusb driver for Windows. + Based on the hard work by Marius Greuel @mariusgreuel ( https://github.com/mariusgreuel/USBasp ). + This is a non intrusive version, using an unaltered V-USB with no changes in it's usbdrv code. + To avoid using driver installation (Zadig, libusb) on Windows and use by default the winusb default driver for USBasp, we need to use OS feature descriptors. All USB 2.0 devices ,when they are enumerated for the first time, Windows asks if From 1192c898d39698e1daad3b332d150015c3f67a98 Mon Sep 17 00:00:00 2001 From: "Dimitrios Chr. Ioannidis" Date: Sun, 21 Mar 2021 10:17:13 +0200 Subject: [PATCH 06/10] More comments. Add notice regarding the deletion of device registry key. Plus typo. --- firmware/main.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/firmware/main.c b/firmware/main.c index 02f310b..824efbf 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -67,7 +67,7 @@ static uchar prog_pagecounter; | 0x12 | 0x03 | MSFT100 | unsigned byte | 0x00 | -------------------------------------------------------------------------- - Length: An unsigned byte and MUST be set to 0x14. + Length: An unsigned byte and MUST be set to 0x12. Type: An unsigned byte and MUST be set to 0x03. @@ -91,6 +91,25 @@ static uchar prog_pagecounter; https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeusb/c2f351f9-84d2-4a1b-9fe3-a6ca195f84d0 + + + !!! Notice !!! + + "After the operating system requests a Microsoft OS String Descriptor from a device, it creates the following registry key: + + HLKM\SYSTEM\CurrentControlSet\Control\UsbFlags\vvvvpppprrrrr + + The operating system creates a registry entry, named osvc, under this registry key that indicates + whether the device supports Microsoft OS Descriptors. If the device does not provide a valid response + the first time that the operating system queries it for a Microsoft OS String Descriptor, + the operating system will make no further requests for that descriptor." + + If your firmware doesn't work please delete the registry key as stated above to retrigger a query from Windows. + + i.e. if your firmware has a device version of 0x07, 0x01 then there will be a registry key with the name : + + Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags\16C005DC0107 + */ From d5992627559eb3b77d5ddf6c252a5569248442ad Mon Sep 17 00:00:00 2001 From: "Dimitrios Chr. Ioannidis" Date: Sun, 21 Mar 2021 17:04:29 +0200 Subject: [PATCH 07/10] Comment forgotten debug code ... --- firmware/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/main.c b/firmware/main.c index 824efbf..5a823ec 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -179,7 +179,7 @@ PROGMEM const char OS_STRING_DESCRIPTOR[18] = { usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { - DBG1(0xEE, &rq->wValue.bytes[0], 2); + // DBG1(0xEE, &rq->wValue.bytes[0], 2); /* string (3) request at index 0xEE, is an OS string descriptor request */ if ((rq->wValue.bytes[1] == 3) && (rq->wValue.bytes[0] == 0xEE)) { From a1ed02fbab01938bf291361119151bd0247e5e2e Mon Sep 17 00:00:00 2001 From: "Dimitrios Chr. Ioannidis" Date: Sun, 21 Mar 2021 17:05:49 +0200 Subject: [PATCH 08/10] Upload main_winusb.hex firmware for atmega8 with winusb changes for people to test . --- firmware/main_winusb.hex | 256 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 firmware/main_winusb.hex diff --git a/firmware/main_winusb.hex b/firmware/main_winusb.hex new file mode 100644 index 0000000..7b8065e --- /dev/null +++ b/firmware/main_winusb.hex @@ -0,0 +1,256 @@ +:1000000044C09BC15DC05CC05BC05AC059C058C0F1 +:1000100057C056C055C054C053C052C051C050C044 +:100020004FC04EC04DC009021200010100A01909C5 +:1000300004000000000000000E03550053004200C1 +:100040006100730070001C037700770077002E00BA +:10005000660069007300630068006C002E00640095 +:1000600065000403090412034D00530046005400C8 +:100070003100300030005D0012010002FF00000876 +:10008000C016DC0507010102030111241FBECFE5E4 +:10009000D4E0DEBFCDBF10E0A0E6B0E0ECEBFFE0C7 +:1000A00002C005900D92AA38B107D9F720E0AAE85E +:1000B000B0E001C01D92A03DB207E1F771D77CC747 +:1000C0009FCFCF93DF936091B000635067FDA8C0CE +:1000D0008091AD00CCE0D0E0C81BD109CC54DF4FFB +:1000E0008091AC008D3209F08AC0683009F096C06A +:1000F00083EC80939F008AE5809361001092AB00AF +:100100008881807619F0CE01BED466C08A811092B3 +:10011000A8009981911106C01092A90028EA30E048 +:1001200082E055C0953019F48093B10042C09630FA +:10013000D1F59B81913019F488E790E004C09230AA +:1001400041F486E290E09093AF008093AE0082E1AC +:1001500026C0933001F5811108C082E690E09093AB +:10016000AF008093AE0084E01AC0813041F486E491 +:1001700090E09093AF008093AE008CE110C082308D +:1001800041F488E390E09093AF008093AE008EE05E +:1001900006C0833019F0CE0165D401C080E090E440 +:1001A0009093AB0019C0983079F0993031F4809376 +:1001B000B30028EA30E080E00AC081E09A3009F01C +:1001C00080E028EA30E003C023EB30E081E03093A8 +:1001D000AF002093AE0009C08F3F39F4988197FD9E +:1001E0008E8190E89093AB0007C09F81911104C06D +:1001F0009E81981708F4892F809360000FC080912A +:10020000AB0087FF0BC0CE010AD68F3F21F48EE1F1 +:100210008093610003C08111109260001092B000C1 +:100220008091610084FF55C0809160008F3F09F488 +:1002300050C0C82F893008F0C8E08C1B8093600044 +:1002400090919F0088E8892780939F00CC2309F430 +:100250004BC02091AB0027FF08C06C2F80EA90E0D4 +:1002600072D5C82F893078F523C08091AE00909167 +:10027000AF0026FF0AC0A0EAB0E0FC012C2F3491A9 +:100280003D9331962150D9F708C0DC01E0EAF0E057 +:100290002C2F3D9131932150E1F72FEF2C0F30E0BF +:1002A0002F5F3F4F820F931F9093AF008093AE005C +:1002B0006C2F80EA90E03DD0CC5FCC3041F08FEFE6 +:1002C0008093600004C08FEF80936000CEE1C09304 +:1002D000610084E196B3937069F48150D9F710926C +:1002E000B1001092AA0006C060E080EA90E021D040 +:1002F000C4E0E5CFDF91CF91089585B7836085BFD6 +:100300008BB780648BBF0895A82FB92F80E090E051 +:1003100041E050EA609530E009C02D918227979521 +:10032000879510F084279527305EC8F36F5FA8F398 +:100330000895EADF8D939D930895CF93CFB7CF9320 +:10034000C395B09BE9F7B09B09C0B09B07C0B09BB9 +:1003500005C0B09B03C0B09B01C0A1C0DF93C0919A +:10036000AD00DD27CC54DF4FB09B02C0DF91EBCF57 +:100370002F930F931F9306B32FEF00FB20F94F939A +:100380003F9316B34FEF012700FB21F93BE031C04B +:100390004E7F012F16B3216028C0102F4D7F2260A1 +:1003A000000006B329C04B7F2460012F000016B364 +:1003B0002BC016B3477F28602AC04F7E06B320614A +:1003C0002CC04F7D16B320622FC04F7B06B3206434 +:1003D00032C0422706B349934FEF0000102710FBAD +:1003E00020F916B31370C9F1297F91F2012700FBA0 +:1003F00021F906B3237F89F2315058F1102710FB01 +:1004000022F916B3277E79F2012700FB23F92F7C0E +:1004100081F206B3102710FB24F92F7971F200C086 +:1004200016B3012700FB25F92F7359F200C006B35C +:10043000102710FB26F9223040F200C016B3012726 +:1004400000FB27F9243028F64F77206816B3000008 +:10045000F9CF10E41ABF002717C03B503195C31BDA +:10046000D04010E41ABF0881033CE9F00B34D9F006 +:100470002091AA001981110F1213EDCF093641F115 +:100480000D3211F0013E39F70093B2003F914F91C8 +:100490001F910F912F91DF91CAB7C6FD51CFCF9118 +:1004A000CFBFCF9118952091B200222379F31091FC +:1004B000B000112311F5343012F13093B0002093C5 +:1004C000AC001091AD003BE0311B3093AD0017C084 +:1004D0000091B00001308CF40AE53091610034FDE8 +:1004E00010C000936100CFE9D0E00FC02795A8F4B9 +:1004F0005150A9F4220F0000F9CF4AE503C042EDA4 +:1005000001C0432FC4E1D0E032E017B31360C09ABA +:1005100017BB08B320E413E05F93012756E008BB44 +:10052000279520F4515021F4220FF9CF012756E0EE +:1005300000003B5A08BBD0F2279528F4515029F40B +:10054000220F0000F9CF012756E0279508BB20F4C1 +:10055000515021F4220FF9CF012756E0299133237E +:1005600008BB21F60C7F1091B100110FC651D0408D +:1005700008BB11F01093AA0010E41ABF016017B372 +:100580001C7F402F4C7F5F9100C000C008BB17BB91 +:1005900048BB7CCF8FB9779BFECF8FB10895DC012C +:1005A000CB0121E1B695A795979587952A95D1F727 +:1005B0002091CC002817D9F08093CC00E091CA009C +:1005C000F091CB008DE40995E091CA00F091CB0049 +:1005D00080E00995E091CA00F091CB008091CC00B9 +:1005E0000995E091CA00F091CB0080E0099408954C +:1005F000882319F0883020F101C08CE02AEC32E029 +:100600003093CB002093CA001EB891E09093CD00A8 +:100610008A3081F028F4883081F0893061F006C09A +:100620008B3031F08D3011F41DB8089581E08EB912 +:1006300081E004C09EB982E001C083E08DB90895D5 +:100640002AE333E03093CB002093CA0027E030E068 +:10065000281B310983E001C0880F2A95EAF78093AF +:10066000CD00089522B79091CD0082B7821B8917E3 +:10067000E0F308951F93CF93DF93182FD8E0C0E0E5 +:1006800017FF02C0C39A01C0C398110FCC0FB499D1 +:10069000CF5FC59AE7DFC598E5DFD15089F78C2F8A +:1006A000DF91CF911F910895BD9ABB9ABA9AC49ACF +:1006B000C29A81E066D1C2988FEF8093CC000895F2 +:1006C00087B3837D87BBC498C3981DB810928A00F6 +:1006D00008950F931F93CF93DF9380918A00811128 +:1006E0002EC08CE080938A002AC0C091CA00D091AD +:1006F000CB0082E0CA3CD80719F48DB180658DB972 +:1007000013E0C29A81E03DD1C2988EE33AD18CEADF +:10071000FE01099583E5FE01099580E0FE0109953A +:10072000082F80E0FE010995033579F0115049F753 +:100730001DB880918A00815080938A0059DF809192 +:100740008A008111D2CF81E001C080E0DF91CF919A +:100750001F910F910895CF92DF92EF92FF926B015C +:100760007C011DDF8C2D8170880F880F880FE09130 +:10077000CA00F091CB0080620995D701C60129E03B +:10078000B695A795979587952A95D1F7E091CA00D8 +:10079000F091CB000995D701C601B695A79597951D +:1007A0008795E091CA00F091CB000995E091CA00CD +:1007B000F091CB0080E0FF90EF90DF90CF90099414 +:1007C000CF92DF92EF92FF92CF93DF936B017C0188 +:1007D000C42FD22FE4DE8C2D8170880F880F880FF4 +:1007E000E091CA00F091CB0080640995D701C60161 +:1007F00029E0B695A795979587952A95D1F7E09129 +:10080000CA00F091CB000995D701C601B695A7950E +:1008100097958795E091CA00F091CB000995E091FA +:10082000CA00F091CB008C2F0995DD2321F0CF3742 +:1008300021F48FE0A6D080E00FC0D2B7CEE1C7018F +:10084000B60189DF8F37B9F782B78D1B8D33B8F3C7 +:10085000D2B7C150A1F781E0DF91CF91FF90EF9027 +:10086000DF90CF900895CF92DF92EF92FF92CF93D7 +:10087000DF936B017C01C42F92DEE091CA00F091FE +:10088000CB008CE40995D701C60129E0B695A79560 +:10089000979587952A95D1F7E091CA00F091CB0002 +:1008A0000995D701C601B695A79597958795E091CB +:1008B000CA00F091CB000995E091CA00F091CB00FD +:1008C00080E00995CF3F19F48FE05BD010C0D2B71C +:1008D000CEE1C701B6013FDF8F3F49F482B78D1BE0 +:1008E0008D33B8F3D2B7C150A1F781E001C080E0E9 +:1008F000DF91CF91FF90EF90DF90CF900895CF934D +:10090000DF93EC01E091CA00F091CB0080EA0995F9 +:10091000E091CA00F091CB008D2F0995E091CA00BB +:10092000F091CB008C2F0995E091CA00F091CB009B +:1009300080E0DF91CF9109941F93CF93DF93D82F5D +:10094000192FC62FE091CA00F091CB0080EC0995D9 +:10095000E091CA00F091CB00812F0995E091CA0087 +:10096000F091CB008D2F0995E091CA00F091CB005A +:100970008C2F09958EE105D080E0DF91CF911F91FA +:10098000089522B792B7921B9C33E0F38150C9F7C8 +:100990000895BD9ABB98C39A50E217D05A95E9F7CB +:1009A0000895AC0188E605D0842F03D089E601D0F4 +:1009B000852F0FD028E030E0382780FB869506D0C1 +:1009C0002A95D1F730FB02D000D06894BB98C39A27 +:1009D00016F0C398BB9AE091CE00F091CF0031970A +:1009E000F0F7C59AE6B3E3FBE091CE00F091CF00BB +:1009F0003197F0F7C598089520ECE7DF46F42A9583 +:100A0000E1F780E02AE1E5DF2A95E9F7DECF28E08B +:100A100030E0DBDF869587F938272A95D1F7D5DFD7 +:100A200027F9322772F3D1DFD0CFDB01742FB9DF82 +:100A300084E2BFDFE1DF8D937A95D1F70895DB0182 +:100A4000742FAFDF83EFB5DF8DE1B3DF84E6B1DF75 +:100A50008D91AFDF82E7ADDFCFDF8078D9F77A9570 +:100A600089F70895FC012381233059F482818E3E59 +:100A700041F486E690E09093AF008093AE0082E16F +:100A8000089580E00895CF93DF93EC018981813050 +:100A900041F480918A00ACDD10929500A19A04DEA9 +:100AA00046C1823011F40CDEF3C0833011F5E091C1 +:100AB000CA00F091CB008A81099580939700E0915C +:100AC000CA00F091CB008B81099580939800E0914A +:100AD000CA00F091CB008C81099580939900E09138 +:100AE000CA00F091CB008D81099580939A0084E033 +:100AF0001FC18430D1F48091950081110EC08A818C +:100B00009B81092E000CAA0BBB0B80939100909344 +:100B10009200A0939300B09394008E819F81909354 +:100B2000900080938F0082E0F0C08730D1F48091F4 +:100B3000950081110EC08A819B81092E000CAA0BA1 +:100B4000BB0B8093910090939200A0939300B0937D +:100B500094008E819F819093900080938F0083E01A +:100B6000D4C0853011F4B5DD98C0863079F5809118 +:100B7000950081110EC08A819B81092E000CAA0B61 +:100B8000BB0B8093910090939200A0939300B0933D +:100B900094003C812D81822F8F7080938C00822F56 +:100BA000807F40E1849FC0011124830F911D9093A9 +:100BB0008E0080938D0020FD80938B008E819F811D +:100BC0009093900080938F0081E09FC0883001F562 +:100BD0008091950081110EC08A819B81092E000CA5 +:100BE000AA0BBB0B8093910090939200A09393006B +:100BF000B093940010928E0010928D0010928C0091 +:100C00008E819F819093900080938F0084E07DC0BF +:100C1000893081F481E0809395008A819B81AC8149 +:100C2000BD818093910090939200A0939300B09324 +:100C300094007DC08A3031F48A8180938A001092BA +:100C400097002DC08B3081F48A819B819093CF00D7 +:100C50008093CE00C29ABA9A83E093DEC298A19A9A +:100C600080E18FDE96DE63C08C30A1F480ECA1DEE3 +:100C700080E09FDE8AE085DEC29A85E082DEC2984F +:100C800085E07FDE87B3837D87BB88B3837D88BBA8 +:100C9000A1984DC08D3029F4AFDE8093970081E09C +:100CA00047C08E3019F48A8184DE41C08F30B1F4A0 +:100CB0008A819B81092E000CAA0BBB0B80939100AB +:100CC00090939200A0939300B09394008E819F81A3 +:100CD0009093900080938F0085E017C08031C9F415 +:100CE0008A819B81092E000CAA0BBB0B809391007B +:100CF00090939200A0939300B09394008E819F8173 +:100D00009093900080938F0086E0809396008FEF01 +:100D10000FC08D3561F48C819D81049781F482E64A +:100D200090E09093AF008093AE0088E209C080E02D +:100D300027E930E03093AF002093AE0001C080E09F +:100D4000DF91CF910895EF92FF920F931F93CF936E +:100D5000C62F209196003EEF320F323028F48C01DE +:100D60007C01E60EF11C43C0253009F04FC0462F30 +:100D7000BC01809191009091920057DE809191008A +:100D800090919200A0919300B09194008C0F911DCE +:100D9000A11DB11D8093910090939200A0939300A8 +:100DA000B093940035C080919600823021F5609117 +:100DB0009100709192008091930090919400CBDC0F +:100DC000F80180838091910090919200A09193000E +:100DD000B09194000196A11DB11D80939100909354 +:100DE0009200A0939300B09394000F5F1F4F0E15D5 +:100DF0001F05C9F606C080919100909192007FDD99 +:100E0000DFCFC83028F41092960002C08FEF01C0E7 +:100E10008C2FCF911F910F91FF90EF900895EF923B +:100E2000FF921F93CF93DF93162F209196002130CE +:100E300031F4EC017C01E10EF11C10E066C02430BD +:100E4000C1F3263009F0A3C0462FBC018091910068 +:100E500090919200F4DD8091910090919200A09188 +:100E60009300B0919400810F911DA11DB11D80933D +:100E7000910090939200A0939300B093940080917E +:100E80008F0090919000811B910990939000809326 +:100E90008F00892B09F07DC01092960081E07AC006 +:100EA00080919600813009F04DC020918D003091E5 +:100EB0008E006091910070919200809193009091CA +:100EC0009400232B31F521E048817ADC80918F005A +:100ED0009091900001979093900080938F00892BC0 +:100EE000C1F18091910090919200A0919300B091F6 +:100EF00094000196A11DB11D8093910090939200E2 +:100F0000A0939300B09394002196CE15DF0541F68F +:100F10003CC020E0488154DC80918B00815080935C +:100F20008B008111D3CF60919100709192008091DC +:100F3000930090919400488196DC80918D0080937D +:100F40008B00C4CF68818091910090919200F4DC75 +:100F5000BDCF1092960080918C0081FF14C08091CB +:100F60008B0090E020918D0030918E0082179307C6 +:100F700051F0609191007091920080919300909156 +:100F80009400488170DC11E0ACCF812F03C08FEF5B +:100F900001C080E0DF91CF911F91FF90EF90089505 +:100FA00083E083BF8FEF87BB8FE1EBDC17BAA09A9A +:0C0FB000A4D9789486D8FECFF894FFCF27 +:100FBC00FF5A28000000000104000100000000009E +:100FCC000000000157494E5553420000000000003C +:0A0FDC00000000000000000000000B +:00000001FF From 42b96eb825e9bbe977c1e3ee57842284d1fbb5cb Mon Sep 17 00:00:00 2001 From: "Dimitrios Chr. Ioannidis" Date: Tue, 23 Mar 2021 02:39:56 +0200 Subject: [PATCH 09/10] Fix warnings mentioned in https://github.com/nerdralph/usbasp/pull/5#issuecomment-804491552 --- firmware/main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/firmware/main.c b/firmware/main.c index 5a823ec..c215abc 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -43,7 +43,7 @@ static uchar prog_pagecounter; To avoid using driver installation (Zadig, libusb) on Windows and use by default the winusb default driver for USBasp, we need to use OS feature descriptors. - All USB 2.0 devices ,when they are enumerated for the first time, Windows asks if + All USB 2.0 devices, when they are enumerated for the first time, Windows asks if there is an OS feature descriptor by sending a specific standard GET_DESCRIPTOR request with the format : @@ -159,11 +159,12 @@ typedef struct static const usbExtCompatDescriptor_t msExtCompatDescriptor = { - { sizeof(usbExtCompatDescriptor_t), 0x0100, 0x0004, 1 }, + { sizeof(usbExtCompatDescriptor_t), 0x0100, 0x0004, 1, {0} }, 0, 1, "WINUSB", - "" + "", + {0} }; #define MS_VENDOR_CODE 0x5D From a2ab97ed8fa731bff5670d4ec282a804b057dacc Mon Sep 17 00:00:00 2001 From: "Dimitrios Chr. Ioannidis" Date: Tue, 23 Mar 2021 15:16:48 +0200 Subject: [PATCH 10/10] Move the OS Extended Compat ID feature descriptor to flash from ram mentioned in https://github.com/nerdralph/usbasp/pull/5#issuecomment-804469404 . Rebuild the atmega8 firmware. --- firmware/main.c | 51 ++-- firmware/main_winusb.hex | 503 ++++++++++++++++++++------------------- 2 files changed, 270 insertions(+), 284 deletions(-) diff --git a/firmware/main.c b/firmware/main.c index c215abc..d1e2a0d 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -135,41 +135,26 @@ PROGMEM const char usbDescriptorDevice[18] = { /* USB device descriptor */ 1, /* number of configurations */ }; - -/* TODO: Change them to progmem consts */ - -typedef struct -{ - uint32_t dwLength; - uint16_t bcdVersion; - uint16_t wIndex; - uint8_t bCount; - uint8_t reserved[7]; -} usbExtCompatHeader_t; - -typedef struct -{ - usbExtCompatHeader_t header; - uint8_t bFirstInterfaceNumber; - uint8_t reserved1; - char compatibleID[8]; - char subCompatibleID[8]; - uint8_t reserved2[6]; -} usbExtCompatDescriptor_t; - -static const usbExtCompatDescriptor_t msExtCompatDescriptor = -{ - { sizeof(usbExtCompatDescriptor_t), 0x0100, 0x0004, 1, {0} }, - 0, - 1, - "WINUSB", - "", - {0} +/* OS Extended Compat ID feature descriptor */ + +PROGMEM const char OS_EXTENDED_COMPAT_ID[37] = { + /* Header */ + 0x25, /* OS Extended Compat ID feature descriptor length */ + 0x01, 0x00, /* OS Extended Compat ID version */ + 0x00, 0x04, /* Index */ + 0x01, /* Configurations count */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Reserved */ + /* Configuration */ + 0x00, /* First Interface Number */ + 0x01, /* Reserved */ + 'W','I','N','U','S','B', 0x00, 0x00, /* Windows string Compatible ID */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Windows string SubCompatible ID */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* Reserved */ }; #define MS_VENDOR_CODE 0x5D PROGMEM const char OS_STRING_DESCRIPTOR[18] = { - 0x12, /* Length: An unsigned byte and MUST be set to 0x12. */ + 0x12, /* Length: An unsigned byte and MUST be set to 0x12. */ /* https://docs.microsoft.com/en-us/windows-hardware/drivers/network/mb-interface-model-supplement */ 0x03, /* Type: An unsigned byte and MUST be set to 0x03. */ 'M',0,'S',0,'F',0,'T',0,'1',0,'0',0,'0',0, /* Signature: A Unicode string and MUST be set to "MSFT100". */ @@ -347,8 +332,8 @@ uchar usbFunctionSetup(uchar data[8]) { { /* Send the Extended Compat ID OS feature descriptor, requesting to load the default winusb driver for us */ - usbMsgPtr = (usbMsgPtr_t)&msExtCompatDescriptor; - return sizeof(msExtCompatDescriptor); + usbMsgPtr = (usbMsgPtr_t)&OS_EXTENDED_COMPAT_ID; + return sizeof(OS_EXTENDED_COMPAT_ID); } return 0; diff --git a/firmware/main_winusb.hex b/firmware/main_winusb.hex index 7b8065e..a2dc531 100644 --- a/firmware/main_winusb.hex +++ b/firmware/main_winusb.hex @@ -1,256 +1,257 @@ -:1000000044C09BC15DC05CC05BC05AC059C058C0F1 -:1000100057C056C055C054C053C052C051C050C044 -:100020004FC04EC04DC009021200010100A01909C5 +:1000000057C0AEC170C06FC06EC06DC06CC06BC059 +:100010006AC069C068C067C066C065C064C063C0AC +:1000200062C061C060C009021200010100A019098C :1000300004000000000000000E03550053004200C1 :100040006100730070001C037700770077002E00BA :10005000660069007300630068006C002E00640095 :1000600065000403090412034D00530046005400C8 -:100070003100300030005D0012010002FF00000876 -:10008000C016DC0507010102030111241FBECFE5E4 -:10009000D4E0DEBFCDBF10E0A0E6B0E0ECEBFFE0C7 -:1000A00002C005900D92AA38B107D9F720E0AAE85E -:1000B000B0E001C01D92A03DB207E1F771D77CC747 -:1000C0009FCFCF93DF936091B000635067FDA8C0CE -:1000D0008091AD00CCE0D0E0C81BD109CC54DF4FFB -:1000E0008091AC008D3209F08AC0683009F096C06A -:1000F00083EC80939F008AE5809361001092AB00AF -:100100008881807619F0CE01BED466C08A811092B3 -:10011000A8009981911106C01092A90028EA30E048 -:1001200082E055C0953019F48093B10042C09630FA -:10013000D1F59B81913019F488E790E004C09230AA -:1001400041F486E290E09093AF008093AE0082E1AC -:1001500026C0933001F5811108C082E690E09093AB -:10016000AF008093AE0084E01AC0813041F486E491 -:1001700090E09093AF008093AE008CE110C082308D -:1001800041F488E390E09093AF008093AE008EE05E -:1001900006C0833019F0CE0165D401C080E090E440 -:1001A0009093AB0019C0983079F0993031F4809376 -:1001B000B30028EA30E080E00AC081E09A3009F01C -:1001C00080E028EA30E003C023EB30E081E03093A8 -:1001D000AF002093AE0009C08F3F39F4988197FD9E -:1001E0008E8190E89093AB0007C09F81911104C06D -:1001F0009E81981708F4892F809360000FC080912A -:10020000AB0087FF0BC0CE010AD68F3F21F48EE1F1 -:100210008093610003C08111109260001092B000C1 -:100220008091610084FF55C0809160008F3F09F488 -:1002300050C0C82F893008F0C8E08C1B8093600044 -:1002400090919F0088E8892780939F00CC2309F430 -:100250004BC02091AB0027FF08C06C2F80EA90E0D4 -:1002600072D5C82F893078F523C08091AE00909167 -:10027000AF0026FF0AC0A0EAB0E0FC012C2F3491A9 -:100280003D9331962150D9F708C0DC01E0EAF0E057 -:100290002C2F3D9131932150E1F72FEF2C0F30E0BF -:1002A0002F5F3F4F820F931F9093AF008093AE005C -:1002B0006C2F80EA90E03DD0CC5FCC3041F08FEFE6 -:1002C0008093600004C08FEF80936000CEE1C09304 -:1002D000610084E196B3937069F48150D9F710926C -:1002E000B1001092AA0006C060E080EA90E021D040 -:1002F000C4E0E5CFDF91CF91089585B7836085BFD6 -:100300008BB780648BBF0895A82FB92F80E090E051 -:1003100041E050EA609530E009C02D918227979521 -:10032000879510F084279527305EC8F36F5FA8F398 -:100330000895EADF8D939D930895CF93CFB7CF9320 -:10034000C395B09BE9F7B09B09C0B09B07C0B09BB9 -:1003500005C0B09B03C0B09B01C0A1C0DF93C0919A -:10036000AD00DD27CC54DF4FB09B02C0DF91EBCF57 -:100370002F930F931F9306B32FEF00FB20F94F939A -:100380003F9316B34FEF012700FB21F93BE031C04B -:100390004E7F012F16B3216028C0102F4D7F2260A1 -:1003A000000006B329C04B7F2460012F000016B364 -:1003B0002BC016B3477F28602AC04F7E06B320614A -:1003C0002CC04F7D16B320622FC04F7B06B3206434 -:1003D00032C0422706B349934FEF0000102710FBAD -:1003E00020F916B31370C9F1297F91F2012700FBA0 -:1003F00021F906B3237F89F2315058F1102710FB01 -:1004000022F916B3277E79F2012700FB23F92F7C0E -:1004100081F206B3102710FB24F92F7971F200C086 -:1004200016B3012700FB25F92F7359F200C006B35C -:10043000102710FB26F9223040F200C016B3012726 -:1004400000FB27F9243028F64F77206816B3000008 -:10045000F9CF10E41ABF002717C03B503195C31BDA -:10046000D04010E41ABF0881033CE9F00B34D9F006 -:100470002091AA001981110F1213EDCF093641F115 -:100480000D3211F0013E39F70093B2003F914F91C8 -:100490001F910F912F91DF91CAB7C6FD51CFCF9118 -:1004A000CFBFCF9118952091B200222379F31091FC -:1004B000B000112311F5343012F13093B0002093C5 -:1004C000AC001091AD003BE0311B3093AD0017C084 -:1004D0000091B00001308CF40AE53091610034FDE8 -:1004E00010C000936100CFE9D0E00FC02795A8F4B9 -:1004F0005150A9F4220F0000F9CF4AE503C042EDA4 -:1005000001C0432FC4E1D0E032E017B31360C09ABA -:1005100017BB08B320E413E05F93012756E008BB44 -:10052000279520F4515021F4220FF9CF012756E0EE -:1005300000003B5A08BBD0F2279528F4515029F40B -:10054000220F0000F9CF012756E0279508BB20F4C1 -:10055000515021F4220FF9CF012756E0299133237E -:1005600008BB21F60C7F1091B100110FC651D0408D -:1005700008BB11F01093AA0010E41ABF016017B372 -:100580001C7F402F4C7F5F9100C000C008BB17BB91 -:1005900048BB7CCF8FB9779BFECF8FB10895DC012C -:1005A000CB0121E1B695A795979587952A95D1F727 -:1005B0002091CC002817D9F08093CC00E091CA009C -:1005C000F091CB008DE40995E091CA00F091CB0049 -:1005D00080E00995E091CA00F091CB008091CC00B9 -:1005E0000995E091CA00F091CB0080E0099408954C -:1005F000882319F0883020F101C08CE02AEC32E029 -:100600003093CB002093CA001EB891E09093CD00A8 -:100610008A3081F028F4883081F0893061F006C09A -:100620008B3031F08D3011F41DB8089581E08EB912 -:1006300081E004C09EB982E001C083E08DB90895D5 -:100640002AE333E03093CB002093CA0027E030E068 -:10065000281B310983E001C0880F2A95EAF78093AF -:10066000CD00089522B79091CD0082B7821B8917E3 -:10067000E0F308951F93CF93DF93182FD8E0C0E0E5 -:1006800017FF02C0C39A01C0C398110FCC0FB499D1 -:10069000CF5FC59AE7DFC598E5DFD15089F78C2F8A -:1006A000DF91CF911F910895BD9ABB9ABA9AC49ACF -:1006B000C29A81E066D1C2988FEF8093CC000895F2 -:1006C00087B3837D87BBC498C3981DB810928A00F6 -:1006D00008950F931F93CF93DF9380918A00811128 -:1006E0002EC08CE080938A002AC0C091CA00D091AD -:1006F000CB0082E0CA3CD80719F48DB180658DB972 -:1007000013E0C29A81E03DD1C2988EE33AD18CEADF -:10071000FE01099583E5FE01099580E0FE0109953A -:10072000082F80E0FE010995033579F0115049F753 -:100730001DB880918A00815080938A0059DF809192 -:100740008A008111D2CF81E001C080E0DF91CF919A -:100750001F910F910895CF92DF92EF92FF926B015C -:100760007C011DDF8C2D8170880F880F880FE09130 -:10077000CA00F091CB0080620995D701C60129E03B -:10078000B695A795979587952A95D1F7E091CA00D8 -:10079000F091CB000995D701C601B695A79597951D -:1007A0008795E091CA00F091CB000995E091CA00CD -:1007B000F091CB0080E0FF90EF90DF90CF90099414 -:1007C000CF92DF92EF92FF92CF93DF936B017C0188 -:1007D000C42FD22FE4DE8C2D8170880F880F880FF4 -:1007E000E091CA00F091CB0080640995D701C60161 -:1007F00029E0B695A795979587952A95D1F7E09129 -:10080000CA00F091CB000995D701C601B695A7950E -:1008100097958795E091CA00F091CB000995E091FA -:10082000CA00F091CB008C2F0995DD2321F0CF3742 -:1008300021F48FE0A6D080E00FC0D2B7CEE1C7018F -:10084000B60189DF8F37B9F782B78D1B8D33B8F3C7 -:10085000D2B7C150A1F781E0DF91CF91FF90EF9027 -:10086000DF90CF900895CF92DF92EF92FF92CF93D7 -:10087000DF936B017C01C42F92DEE091CA00F091FE -:10088000CB008CE40995D701C60129E0B695A79560 -:10089000979587952A95D1F7E091CA00F091CB0002 -:1008A0000995D701C601B695A79597958795E091CB -:1008B000CA00F091CB000995E091CA00F091CB00FD -:1008C00080E00995CF3F19F48FE05BD010C0D2B71C -:1008D000CEE1C701B6013FDF8F3F49F482B78D1BE0 -:1008E0008D33B8F3D2B7C150A1F781E001C080E0E9 -:1008F000DF91CF91FF90EF90DF90CF900895CF934D -:10090000DF93EC01E091CA00F091CB0080EA0995F9 -:10091000E091CA00F091CB008D2F0995E091CA00BB -:10092000F091CB008C2F0995E091CA00F091CB009B -:1009300080E0DF91CF9109941F93CF93DF93D82F5D -:10094000192FC62FE091CA00F091CB0080EC0995D9 -:10095000E091CA00F091CB00812F0995E091CA0087 -:10096000F091CB008D2F0995E091CA00F091CB005A -:100970008C2F09958EE105D080E0DF91CF911F91FA -:10098000089522B792B7921B9C33E0F38150C9F7C8 -:100990000895BD9ABB98C39A50E217D05A95E9F7CB -:1009A0000895AC0188E605D0842F03D089E601D0F4 -:1009B000852F0FD028E030E0382780FB869506D0C1 -:1009C0002A95D1F730FB02D000D06894BB98C39A27 -:1009D00016F0C398BB9AE091CE00F091CF0031970A -:1009E000F0F7C59AE6B3E3FBE091CE00F091CF00BB -:1009F0003197F0F7C598089520ECE7DF46F42A9583 -:100A0000E1F780E02AE1E5DF2A95E9F7DECF28E08B -:100A100030E0DBDF869587F938272A95D1F7D5DFD7 -:100A200027F9322772F3D1DFD0CFDB01742FB9DF82 -:100A300084E2BFDFE1DF8D937A95D1F70895DB0182 -:100A4000742FAFDF83EFB5DF8DE1B3DF84E6B1DF75 -:100A50008D91AFDF82E7ADDFCFDF8078D9F77A9570 -:100A600089F70895FC012381233059F482818E3E59 -:100A700041F486E690E09093AF008093AE0082E16F -:100A8000089580E00895CF93DF93EC018981813050 -:100A900041F480918A00ACDD10929500A19A04DEA9 -:100AA00046C1823011F40CDEF3C0833011F5E091C1 -:100AB000CA00F091CB008A81099580939700E0915C -:100AC000CA00F091CB008B81099580939800E0914A -:100AD000CA00F091CB008C81099580939900E09138 -:100AE000CA00F091CB008D81099580939A0084E033 -:100AF0001FC18430D1F48091950081110EC08A818C -:100B00009B81092E000CAA0BBB0B80939100909344 -:100B10009200A0939300B09394008E819F81909354 -:100B2000900080938F0082E0F0C08730D1F48091F4 -:100B3000950081110EC08A819B81092E000CAA0BA1 -:100B4000BB0B8093910090939200A0939300B0937D -:100B500094008E819F819093900080938F0083E01A -:100B6000D4C0853011F4B5DD98C0863079F5809118 -:100B7000950081110EC08A819B81092E000CAA0B61 -:100B8000BB0B8093910090939200A0939300B0933D -:100B900094003C812D81822F8F7080938C00822F56 -:100BA000807F40E1849FC0011124830F911D9093A9 -:100BB0008E0080938D0020FD80938B008E819F811D -:100BC0009093900080938F0081E09FC0883001F562 -:100BD0008091950081110EC08A819B81092E000CA5 -:100BE000AA0BBB0B8093910090939200A09393006B -:100BF000B093940010928E0010928D0010928C0091 -:100C00008E819F819093900080938F0084E07DC0BF -:100C1000893081F481E0809395008A819B81AC8149 -:100C2000BD818093910090939200A0939300B09324 -:100C300094007DC08A3031F48A8180938A001092BA -:100C400097002DC08B3081F48A819B819093CF00D7 -:100C50008093CE00C29ABA9A83E093DEC298A19A9A -:100C600080E18FDE96DE63C08C30A1F480ECA1DEE3 -:100C700080E09FDE8AE085DEC29A85E082DEC2984F -:100C800085E07FDE87B3837D87BB88B3837D88BBA8 -:100C9000A1984DC08D3029F4AFDE8093970081E09C -:100CA00047C08E3019F48A8184DE41C08F30B1F4A0 -:100CB0008A819B81092E000CAA0BBB0B80939100AB -:100CC00090939200A0939300B09394008E819F81A3 -:100CD0009093900080938F0085E017C08031C9F415 -:100CE0008A819B81092E000CAA0BBB0B809391007B -:100CF00090939200A0939300B09394008E819F8173 -:100D00009093900080938F0086E0809396008FEF01 -:100D10000FC08D3561F48C819D81049781F482E64A -:100D200090E09093AF008093AE0088E209C080E02D -:100D300027E930E03093AF002093AE0001C080E09F -:100D4000DF91CF910895EF92FF920F931F93CF936E -:100D5000C62F209196003EEF320F323028F48C01DE -:100D60007C01E60EF11C43C0253009F04FC0462F30 -:100D7000BC01809191009091920057DE809191008A -:100D800090919200A0919300B09194008C0F911DCE -:100D9000A11DB11D8093910090939200A0939300A8 -:100DA000B093940035C080919600823021F5609117 -:100DB0009100709192008091930090919400CBDC0F -:100DC000F80180838091910090919200A09193000E -:100DD000B09194000196A11DB11D80939100909354 -:100DE0009200A0939300B09394000F5F1F4F0E15D5 -:100DF0001F05C9F606C080919100909192007FDD99 -:100E0000DFCFC83028F41092960002C08FEF01C0E7 -:100E10008C2FCF911F910F91FF90EF900895EF923B -:100E2000FF921F93CF93DF93162F209196002130CE -:100E300031F4EC017C01E10EF11C10E066C02430BD -:100E4000C1F3263009F0A3C0462FBC018091910068 -:100E500090919200F4DD8091910090919200A09188 -:100E60009300B0919400810F911DA11DB11D80933D -:100E7000910090939200A0939300B093940080917E -:100E80008F0090919000811B910990939000809326 -:100E90008F00892B09F07DC01092960081E07AC006 -:100EA00080919600813009F04DC020918D003091E5 -:100EB0008E006091910070919200809193009091CA -:100EC0009400232B31F521E048817ADC80918F005A -:100ED0009091900001979093900080938F00892BC0 -:100EE000C1F18091910090919200A0919300B091F6 -:100EF00094000196A11DB11D8093910090939200E2 -:100F0000A0939300B09394002196CE15DF0541F68F -:100F10003CC020E0488154DC80918B00815080935C -:100F20008B008111D3CF60919100709192008091DC -:100F3000930090919400488196DC80918D0080937D -:100F40008B00C4CF68818091910090919200F4DC75 -:100F5000BDCF1092960080918C0081FF14C08091CB -:100F60008B0090E020918D0030918E0082179307C6 -:100F700051F0609191007091920080919300909156 -:100F80009400488170DC11E0ACCF812F03C08FEF5B -:100F900001C080E0DF91CF911F91FF90EF90089505 -:100FA00083E083BF8FEF87BB8FE1EBDC17BAA09A9A -:0C0FB000A4D9789486D8FECFF894FFCF27 -:100FBC00FF5A28000000000104000100000000009E -:100FCC000000000157494E5553420000000000003C -:0A0FDC00000000000000000000000B +:100070003100300030005D00250100000401000067 +:100080000000000000000157494E55534200000097 +:10009000000000000000000000000000001201004D +:1000A00002FF000008C016DC050701010203010081 +:1000B00011241FBECFE5D4E0DEBFCDBF10E0A0E627 +:1000C000B0E0E2EEFFE002C005900D92A236B1076B +:1000D000D9F720E0A2E6B0E001C01D92A83AB2072D +:1000E000E1F771D77CC78CCFCF93DF936091880005 +:1000F000635067FDA8C080918500CCE0D0E0C81BAC +:10010000D109C457DF4F809184008D3209F08AC035 +:10011000683009F096C083EC809377008AE580937D +:100120006100109283008881807619F0CE01BED4E0 +:1001300066C08A81109280009981911106C0109248 +:10014000810020E830E082E055C0953019F48093BA +:10015000890042C09630D1F59B81913019F48DE928 +:1001600090E004C0923041F486E290E090938700E2 +:100170008093860082E126C0933001F5811108C08A +:1001800082E690E0909387008093860084E01AC016 +:10019000813041F486E490E090938700809386005C +:1001A0008CE110C0823041F488E390E090938700A6 +:1001B000809386008EE006C0833019F0CE0165D4AE +:1001C00001C080E090E49093830019C0983079F0EA +:1001D000993031F480938B0020E830E080E00AC051 +:1001E00081E09A3009F080E020E830E003C02BE89D +:1001F00030E081E0309387002093860009C08F3F74 +:1002000039F4988197FD8E8190E89093830007C020 +:100210009F81911104C09E81981708F4892F8093C3 +:1002200060000FC08091830087FF0BC0CE010AD60B +:100230008F3F21F48EE18093610003C08111109201 +:100240006000109288008091610084FF55C0809109 +:1002500060008F3F09F450C0C82F893008F0C8E013 +:100260008C1B809360009091770088E889278093A9 +:100270007700CC2309F44BC02091830027FF08C0EE +:100280006C2F88E790E072D5C82F893078F523C0AD +:10029000809186009091870026FF0AC0A8E7B0E011 +:1002A000FC012C2F34913D9331962150D9F708C091 +:1002B000DC01E8E7F0E02C2F3D9131932150E1F78C +:1002C0002FEF2C0F30E02F5F3F4F820F931F909343 +:1002D0008700809386006C2F88E790E03DD0CC5F4C +:1002E000CC3041F08FEF8093600004C08FEF80939B +:1002F0006000CEE1C093610084E196B3937069F42D +:100300008150D9F7109289001092820006C060E0F7 +:1003100088E790E021D0C4E0E5CFDF91CF91089548 +:1003200085B7836085BF8BB780648BBF0895A82F86 +:10033000B92F80E090E041E050EA609530E009C0DC +:100340002D9182279795879510F084279527305E09 +:10035000C8F36F5FA8F30895EADF8D939D93089526 +:10036000CF93CFB7CF93C395B09BE9F7B09B09C0AC +:10037000B09B07C0B09B05C0B09B03C0B09B01C041 +:10038000A1C0DF93C0918500DD27C457DF4FB09B2C +:1003900002C0DF91EBCF2F930F931F9306B32FEF84 +:1003A00000FB20F94F933F9316B34FEF012700FB5B +:1003B00021F93BE031C04E7F012F16B3216028C0E8 +:1003C000102F4D7F2260000006B329C04B7F2460B0 +:1003D000012F000016B32BC016B3477F28602AC038 +:1003E0004F7E06B320612CC04F7D16B320622FC014 +:1003F0004F7B06B3206432C0422706B349934FEFC8 +:100400000000102710FB20F916B31370C9F1297FE3 +:1004100091F2012700FB21F906B3237F89F23150C5 +:1004200058F1102710FB22F916B3277E79F2012725 +:1004300000FB23F92F7C81F206B3102710FB24F96F +:100440002F7971F200C016B3012700FB25F92F7335 +:1004500059F200C006B3102710FB26F9223040F2F3 +:1004600000C016B3012700FB27F9243028F64F7788 +:10047000206816B30000F9CF10E41ABF002717C098 +:100480003B503195C31BD04010E41ABF0881033C98 +:10049000E9F00B34D9F0209182001981110F121369 +:1004A000EDCF093641F10D3211F0013E39F70093DD +:1004B0008A003F914F911F910F912F91DF91CAB701 +:1004C000C6FD51CFCF91CFBFCF91189520918A0013 +:1004D000222379F310918800112311F5343012F1A1 +:1004E0003093880020938400109185003BE0311BFD +:1004F0003093850017C00091880001308CF40AE524 +:100500003091610034FD10C000936100C7E7D0E076 +:100510000FC02795A8F45150A9F4220F0000F9CF7D +:100520004AE503C042ED01C0432FC4E1D0E032E010 +:1005300017B31360C09A17BB08B320E413E05F93AE +:10054000012756E008BB279520F4515021F4220FD3 +:10055000F9CF012756E000003B5A08BBD0F227959F +:1005600028F4515029F4220F0000F9CF012756E05A +:10057000279508BB20F4515021F4220FF9CF012711 +:1005800056E02991332308BB21F60C7F1091890096 +:10059000110FC651D04008BB11F01093820010E437 +:1005A0001ABF016017B31C7F402F4C7F5F9100C0C2 +:1005B00000C008BB17BB48BB7CCF8FB9779BFECF71 +:1005C0008FB10895DC01CB0121E1B695A7959795F0 +:1005D00087952A95D1F72091A4002817D9F0809308 +:1005E000A400E091A200F091A3008DE40995E091B0 +:1005F000A200F091A30080E00995E091A200F091A3 +:10060000A3008091A4000995E091A200F091A300BD +:1006100080E009940895882319F0883020F101C002 +:100620008CE02DED32E03093A3002093A2001EB8A1 +:1006300091E09093A5008A3081F028F4883081F011 +:10064000893061F006C08B3031F08D3011F41DB867 +:10065000089581E08EB981E004C09EB982E001C0B6 +:1006600083E08DB908952DE433E03093A300209307 +:10067000A20027E030E0281B310983E001C0880F89 +:100680002A95EAF78093A500089522B79091A500D6 +:1006900082B7821B8917E0F308951F93CF93DF93EE +:1006A000182FD8E0C0E017FF02C0C39A01C0C3985A +:1006B000110FCC0FB499CF5FC59AE7DFC598E5DF7E +:1006C000D15089F78C2FDF91CF911F910895BD9A5A +:1006D000BB9ABA9AC49AC29A81E066D1C2988FEF47 +:1006E0008093A400089587B3837D87BBC498C39883 +:1006F0001DB81092620008950F931F93CF93DF935C +:100700008091620081112EC08CE0809362002AC02B +:10071000C091A200D091A30082E0CD3DD80719F48A +:100720008DB180658DB913E0C29A81E03DD1C29848 +:100730008EE33AD18CEAFE01099583E5FE01099525 +:1007400080E0FE010995082F80E0FE010995033540 +:1007500079F0115049F71DB8809162008150809363 +:10076000620059DF809162008111D2CF81E001C027 +:1007700080E0DF91CF911F910F910895CF92DF928A +:10078000EF92FF926B017C011DDF8C2D8170880F31 +:10079000880F880FE091A200F091A3008062099574 +:1007A000D701C60129E0B695A795979587952A9513 +:1007B000D1F7E091A200F091A3000995D701C601FD +:1007C000B695A79597958795E091A200F091A30023 +:1007D0000995E091A200F091A30080E0FF90EF90D6 +:1007E000DF90CF900994CF92DF92EF92FF92CF9358 +:1007F000DF936B017C01C42FD22FE4DE8C2D81703E +:10080000880F880F880FE091A200F091A300806408 +:100810000995D701C60129E0B695A79597958795C3 +:100820002A95D1F7E091A200F091A3000995D70194 +:10083000C601B695A79597958795E091A200F0918E +:10084000A3000995E091A200F091A3008C2F0995D7 +:10085000DD2321F0CF3721F48FE0A6D080E00FC058 +:10086000D2B7CEE1C701B60189DF8F37B9F782B7BA +:100870008D1B8D33B8F3D2B7C150A1F781E0DF9162 +:10088000CF91FF90EF90DF90CF900895CF92DF92BD +:10089000EF92FF92CF93DF936B017C01C42F92DE26 +:1008A000E091A200F091A3008CE40995D701C60164 +:1008B00029E0B695A795979587952A95D1F7E09168 +:1008C000A200F091A3000995D701C601B695A7959E +:1008D00097958795E091A200F091A3000995E0918A +:1008E000A200F091A30080E00995CF3F19F48FE0BA +:1008F0005BD010C0D2B7CEE1C701B6013FDF8F3F5A +:1009000049F482B78D1B8D33B8F3D2B7C150A1F72C +:1009100081E001C080E0DF91CF91FF90EF90DF9008 +:10092000CF900895CF93DF93EC01E091A200F09176 +:10093000A30080EA0995E091A200F091A3008D2F19 +:100940000995E091A200F091A3008C2F0995E09108 +:10095000A200F091A30080E0DF91CF9109941F9352 +:10096000CF93DF93D82F192FC62FE091A200F091DB +:10097000A30080EC0995E091A200F091A300812FE3 +:100980000995E091A200F091A3008D2F0995E091C7 +:10099000A200F091A3008C2F09958EE105D080E094 +:1009A000DF91CF911F91089522B792B7921B9C338C +:1009B000E0F38150C9F70895BD9ABB98C39A50E2FD +:1009C00017D05A95E9F70895AC0188E605D0842F31 +:1009D00003D089E601D0852F0FD028E030E03827FA +:1009E00080FB869506D02A95D1F730FB02D000D047 +:1009F0006894BB98C39A16F0C398BB9AE091A6007E +:100A0000F091A7003197F0F7C59AE6B3E3FBE091C8 +:100A1000A600F091A7003197F0F7C598089520EC53 +:100A2000E7DF46F42A95E1F780E02AE1E5DF2A9541 +:100A3000E9F7DECF28E030E0DBDF869587F938275D +:100A40002A95D1F7D5DF27F9322772F3D1DFD0CF3E +:100A5000DB01742FB9DF84E2BFDFE1DF8D937A958C +:100A6000D1F70895DB01742FAFDF83EFB5DF8DE1A0 +:100A7000B3DF84E6B1DF8D91AFDF82E7ADDFCFDF9B +:100A80008078D9F77A9589F70895FC01238123307E +:100A900059F482818E3E41F486E690E0909387007F +:100AA0008093860082E1089580E00895CF93DF93DC +:100AB000EC018981813041F480916200ACDD1092BB +:100AC0006D00A19A04DE46C1823011F40CDEF3C041 +:100AD000833011F5E091A200F091A3008A8109957D +:100AE00080936F00E091A200F091A3008B810995A3 +:100AF00080937000E091A200F091A3008C81099591 +:100B000080937100E091A200F091A3008D8109957E +:100B10008093720084E01FC18430D1F480916D0015 +:100B200081110EC08A819B81092E000CAA0BBB0B80 +:100B30008093690090936A00A0936B00B0936C005F +:100B40008E819F81909368008093670082E0F0C05F +:100B50008730D1F480916D0081110EC08A819B8114 +:100B6000092E000CAA0BBB0B8093690090936A00BE +:100B7000A0936B00B0936C008E819F81909368006E +:100B80008093670083E0D4C0853011F4B5DD98C050 +:100B9000863079F580916D0081110EC08A819B812C +:100BA000092E000CAA0BBB0B8093690090936A007E +:100BB000A0936B00B0936C003C812D81822F8F70CD +:100BC00080936400822F807F40E1849FC0011124C4 +:100BD000830F911D909366008093650020FD8093A4 +:100BE00063008E819F81909368008093670081E00D +:100BF0009FC0883001F580916D0081110EC08A81FF +:100C00009B81092E000CAA0BBB0B8093690090936B +:100C10006A00A0936B00B0936C0010926600109273 +:100C20006500109264008E819F819093680080938C +:100C3000670084E07DC0893081F481E080936D009D +:100C40008A819B81AC81BD818093690090936A0009 +:100C5000A0936B00B0936C007DC08A3031F48A8120 +:100C60008093620010926F002DC08B3081F48A81D6 +:100C70009B819093A7008093A600C29ABA9A83E0C2 +:100C800093DEC298A19A80E18FDE96DE63C08C303D +:100C9000A1F480ECA1DE80E09FDE8AE085DEC29ACE +:100CA00085E082DEC29885E07FDE87B3837D87BBE7 +:100CB00088B3837D88BBA1984DC08D3029F4AFDE09 +:100CC00080936F0081E047C08E3019F48A8184DE02 +:100CD00041C08F30B1F48A819B81092E000CAA0B90 +:100CE000BB0B8093690090936A00A0936B00B09354 +:100CF0006C008E819F81909368008093670085E0EF +:100D000017C08031C9F48A819B81092E000CAA0B7F +:100D1000BB0B8093690090936A00A0936B00B09323 +:100D20006C008E819F81909368008093670086E0BD +:100D300080936E008FEF0FC08D3561F48C819D81A3 +:100D4000049781F488E790E0909387008093860071 +:100D500085E209C080E02FE630E0309387002093E1 +:100D6000860001C080E0DF91CF910895EF92FF925D +:100D70000F931F93CF93C62F20916E003EEF320F3B +:100D8000323028F48C017C01E60EF11C43C0253082 +:100D900009F04FC0462FBC018091690090916A0014 +:100DA00057DE8091690090916A00A0916B00B0912C +:100DB0006C008C0F911DA11DB11D80936900909353 +:100DC0006A00A0936B00B0936C0035C080916E00F8 +:100DD000823021F56091690070916A0080916B000A +:100DE00090916C00CBDCF801808380916900909138 +:100DF0006A00A0916B00B0916C000196A11DB11D1D +:100E00008093690090936A00A0936B00B0936C008C +:100E10000F5F1F4F0E151F05C9F606C080916900B0 +:100E200090916A007FDDDFCFC83028F410926E0009 +:100E300002C08FEF01C08C2FCF911F910F91FF90B7 +:100E4000EF900895EF92FF921F93CF93DF93162FA9 +:100E500020916E00213031F4EC017C01E10EF11C97 +:100E600010E066C02430C1F3263009F0A3C0462F3D +:100E7000BC018091690090916A00F4DD8091690065 +:100E800090916A00A0916B00B0916C00810F911D50 +:100E9000A11DB11D8093690090936A00A0936B001F +:100EA000B0936C008091670090916800811B91095C +:100EB0009093680080936700892B09F07DC01092A1 +:100EC0006E0081E07AC080916E00813009F04DC0E3 +:100ED00020916500309166006091690070916A0010 +:100EE00080916B0090916C00232B31F521E04881BB +:100EF0007ADC809167009091680001979093680078 +:100F000080936700892BC1F18091690090916A00FC +:100F1000A0916B00B0916C000196A11DB11D809352 +:100F2000690090936A00A0936B00B0936C002196C7 +:100F3000CE15DF0541F63CC020E0488154DC8091AD +:100F400063008150809363008111D3CF6091690069 +:100F500070916A0080916B0090916C00488196DCE2 +:100F60008091650080936300C4CF6881809169009F +:100F700090916A00F4DCBDCF10926E008091640005 +:100F800081FF14C08091630090E020916500309152 +:100F900066008217930751F06091690070916A00B2 +:100FA00080916B0090916C00488170DC11E0ACCFB7 +:100FB000812F03C08FEF01C080E0DF91CF911F919F +:100FC000FF90EF90089583E083BF8FEF87BB8FE1A1 +:100FD000EBDC17BAA09AA4D9789486D8FECFF894FF +:020FE000FFCF41 +:020FE200FF5AB4 :00000001FF