From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755275Ab1I1XzR (ORCPT ); Wed, 28 Sep 2011 19:55:17 -0400 Received: from relay.ihostexchange.net ([66.46.182.51]:50088 "EHLO relay.ihostexchange.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753996Ab1I1XzP (ORCPT ); Wed, 28 Sep 2011 19:55:15 -0400 X-Greylist: delayed 305 seconds by postgrey-1.27 at vger.kernel.org; Wed, 28 Sep 2011 19:55:14 EDT From: Kevin McNeely To: Javier Martinez Canillas , Henrik Rydberg CC: Dmitry Torokhov , Greg Kroah-Hartman , "linux-input@vger.kernel.org" , "linux-kernel@vger.kernel.org" Date: Wed, 28 Sep 2011 19:50:05 -0400 Subject: RE: [PATCH V3 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Thread-Topic: [PATCH V3 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Thread-Index: Acx+NY3PJyDySSzZRLiZ7WYzz6MvfwAAyBiA Message-ID: <332E958ABC555E44B6FC413E3DFEAA3D3C2AD90A7C@VMBX131.ihostexchange.net> References: <1316311297-12765-1-git-send-email-martinez.javier@gmail.com> <1316311297-12765-2-git-send-email-martinez.javier@gmail.com> <20110927115207.GA3701@polaris.bitmath.org> In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by nfs id p8SNtik3002355 Hi Javier, Yes, the hardware reports touches in the range 1 to 14. Best regards, Kevin > -----Original Message----- > From: Javier Martinez Canillas [mailto:martinez.javier@gmail.com] > Sent: Wednesday, September 28, 2011 4:23 PM > To: Henrik Rydberg > Cc: Dmitry Torokhov; Greg Kroah-Hartman; linux-input@vger.kernel.org; > linux-kernel@vger.kernel.org; Kevin McNeely > Subject: Re: [PATCH V3 1/3] Input: cyttsp - Cypress TTSP capacitive multi- > touch screen support > > On Tue, Sep 27, 2011 at 1:52 PM, Henrik Rydberg > wrote: > > Hi Javier, > > > >> Cypress TrueTouch(tm) Standard Product controllers are found in a > >> wide range of embedded devices. This driver add support for a variety > >> of TTSP controllers. > > > > please find some comments below. > > > > Hello Henrik, > > Thanks a lot for the review > > >> +/* Slots management */ > >> +#define CY_MAX_FINGER 4 #define CY_UNUSED > >> +0 #define CY_USED 1 > > > > These two look like bool, please use as bool instead. > > > >> +#define CY_MAX_ID 15 > > > > Why not 16 here? > > > > Because as far as I know there are only 14 possible tracking ids (1-14), not 16. > 15 and 0 are not valid track ids. > > When a contact lifts off the hardware reports a magic number (15) for it. > Also, the sequence always start with 1 which is the track id that gets the first > contact reported by the touch. > > >> + > >> +/* TrueTouch Standard Product Gen3 interface definition */ struct > >> +cyttsp_xydata { > >> + u8 hst_mode; > >> + u8 tt_mode; > >> + u8 tt_stat; > >> + struct cyttsp_tch tch1; > >> + u8 touch12_id; > >> + struct cyttsp_tch tch2; > >> + u8 gest_cnt; > >> + u8 gest_id; > >> + struct cyttsp_tch tch3; > >> + u8 touch34_id; > >> + struct cyttsp_tch tch4; > >> + u8 tt_undef[3]; > >> + u8 act_dist; > >> + u8 tt_reserved; > >> +} __packed; > > > > Too bad the touches are not an array here... > > > > Yes, the problem is that the offset between touches is not uniform. > For tch1 and tch2 is only 8 bits but the offset between tch2 and tch3 is 16 (u8 > * 2) for example. > > >> + int slot_curr[CY_MAX_ID]; > >> + int slot_prev[CY_MAX_ID]; > > > > These two are not needed; the input core will take care of duplicates, > > so slot_prev can be removed. Also, the set of current slots can be > > tracked using a temporary bitmask, so slot_curr can be removed as well. > > Perfect, I'll remove both. I didn't know that the input core took care of > duplicates, sorry for not getting this from the docs. > > >> + > >> +static void cyttsp_get_tch(struct cyttsp_xydata *xy_data, int idx, > >> + struct cyttsp_tch **tch) { > >> + switch (idx) { > >> + case 0: > >> + *tch = &xy_data->tch1; > >> + break; > >> + case 1: > >> + *tch = &xy_data->tch2; > >> + break; > >> + case 2: > >> + *tch = &xy_data->tch3; > >> + break; > >> + case 3: > >> + *tch = &xy_data->tch4; > >> + break; > >> + } > >> +} > > > > How about returning a const struct cyttsp_tch* here instead. > > > > Ok, will return a struct pointer instead. > > >> + > >> + cyttsp_extract_track_ids(&xy_data, ids); > >> + > >> + for (i = 0; i < num_cur_tch; i++) { > >> + ts->slot_curr[ids[i] - 1] = CY_USED; > > > > Why the -1 here? Since the values are provably between 0 and 15, there > > is no need to change them further. > > As I told you before is a HW thing. I looked at the track ids reported by the > touchscreen and their values are always between 1 and 14. So I did the -1 to > avoid having and unused element in the array. (I don't have the HW > datasheet so maybe I'm wrong with this) > > Kevin? > > > > > Also, the above line could be replaced by "used |= 1 << ids[i]", for instance. > > > >> + > >> + cyttsp_get_tch(&xy_data, i, &tch); > >> + > >> + x = be16_to_cpu(tch->x); > >> + y = be16_to_cpu(tch->y); > >> + z = tch->z; > >> + > >> + cyttsp_report_slot(ts->input, ids[i] - 1, x, y, z); > > > > Ditto, -1. > > > >> + } > >> + > >> + for (i = 0; i < CY_MAX_ID; i++) { > >> + if (ts->slot_prev[i] == CY_USED && > >> + ts->slot_curr[i] == CY_UNUSED) > >> + cyttsp_report_slot_empty(ts->input, i); > >> + ts->slot_prev[i] = ts->slot_curr[i]; > >> + ts->slot_curr[i] = CY_UNUSED; > >> + } > > > > Input core handles duplicate calls, so the above could be simplified. > > > > Perfect, will clean this code. > > >> + > >> + for (i = 0; i < CY_MAX_ID; i++) { > >> + ts->slot_prev[i] = CY_UNUSED; > >> + ts->slot_curr[i] = CY_UNUSED; > >> + } > > > > Could be removed. > > > > Yes, I'll do that. > > > > > Thanks, > > Henrik > > > > Thanks for your comments, I will work on these issues and resubmit a new > version of the patch-set. > > Best regards, > > -- > Javier Martínez Canillas > (+34) 682 39 81 69 > Barcelona, Spain This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message. {.n++%ݶw{.n+{G{ayʇڙ,jfhz_(階ݢj"mG?&~iOzv^m ?I From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kevin McNeely Subject: RE: [PATCH V3 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Date: Wed, 28 Sep 2011 19:50:05 -0400 Message-ID: <332E958ABC555E44B6FC413E3DFEAA3D3C2AD90A7C@VMBX131.ihostexchange.net> References: <1316311297-12765-1-git-send-email-martinez.javier@gmail.com> <1316311297-12765-2-git-send-email-martinez.javier@gmail.com> <20110927115207.GA3701@polaris.bitmath.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from relay.ihostexchange.net ([66.46.182.51]:50088 "EHLO relay.ihostexchange.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753996Ab1I1XzP (ORCPT ); Wed, 28 Sep 2011 19:55:15 -0400 In-Reply-To: Content-Language: en-US Sender: linux-input-owner@vger.kernel.org List-Id: linux-input@vger.kernel.org To: Javier Martinez Canillas , Henrik Rydberg Cc: Dmitry Torokhov , Greg Kroah-Hartman , "linux-input@vger.kernel.org" , "linux-kernel@vger.kernel.org" SGkgSmF2aWVyLA0KDQpZZXMsIHRoZSBoYXJkd2FyZSByZXBvcnRzIHRvdWNoZXMgaW4gdGhlIHJh bmdlIDEgdG8gMTQuDQoNCkJlc3QgcmVnYXJkcywNCktldmluDQoNCg0KPiAtLS0tLU9yaWdpbmFs IE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBKYXZpZXIgTWFydGluZXogQ2FuaWxsYXMgW21haWx0bzpt YXJ0aW5lei5qYXZpZXJAZ21haWwuY29tXQ0KPiBTZW50OiBXZWRuZXNkYXksIFNlcHRlbWJlciAy OCwgMjAxMSA0OjIzIFBNDQo+IFRvOiBIZW5yaWsgUnlkYmVyZw0KPiBDYzogRG1pdHJ5IFRvcm9r aG92OyBHcmVnIEtyb2FoLUhhcnRtYW47IGxpbnV4LWlucHV0QHZnZXIua2VybmVsLm9yZzsNCj4g bGludXgta2VybmVsQHZnZXIua2VybmVsLm9yZzsgS2V2aW4gTWNOZWVseQ0KPiBTdWJqZWN0OiBS ZTogW1BBVENIIFYzIDEvM10gSW5wdXQ6IGN5dHRzcCAtIEN5cHJlc3MgVFRTUCBjYXBhY2l0aXZl IG11bHRpLQ0KPiB0b3VjaCBzY3JlZW4gc3VwcG9ydA0KPg0KPiBPbiBUdWUsIFNlcCAyNywgMjAx MSBhdCAxOjUyIFBNLCBIZW5yaWsgUnlkYmVyZyA8cnlkYmVyZ0BldXJvbWFpbC5zZT4NCj4gd3Jv dGU6DQo+ID4gSGkgSmF2aWVyLA0KPiA+DQo+ID4+IEN5cHJlc3MgVHJ1ZVRvdWNoKHRtKSBTdGFu ZGFyZCBQcm9kdWN0IGNvbnRyb2xsZXJzIGFyZSBmb3VuZCBpbiBhDQo+ID4+IHdpZGUgcmFuZ2Ug b2YgZW1iZWRkZWQgZGV2aWNlcy4gVGhpcyBkcml2ZXIgYWRkIHN1cHBvcnQgZm9yIGEgdmFyaWV0 eQ0KPiA+PiBvZiBUVFNQIGNvbnRyb2xsZXJzLg0KPiA+DQo+ID4gcGxlYXNlIGZpbmQgc29tZSBj b21tZW50cyBiZWxvdy4NCj4gPg0KPg0KPiBIZWxsbyBIZW5yaWssDQo+DQo+IFRoYW5rcyBhIGxv dCBmb3IgdGhlIHJldmlldw0KPg0KPiA+PiArLyogU2xvdHMgbWFuYWdlbWVudCAqLw0KPiA+PiAr I2RlZmluZSBDWV9NQVhfRklOR0VSICAgICAgICAgICAgICAgNCAjZGVmaW5lIENZX1VOVVNFRA0K PiA+PiArMCAjZGVmaW5lIENZX1VTRUQgICAgICAgICAgICAgICAgICAgICAxDQo+ID4NCj4gPiBU aGVzZSB0d28gbG9vayBsaWtlIGJvb2wsIHBsZWFzZSB1c2UgYXMgYm9vbCBpbnN0ZWFkLg0KPiA+ DQo+ID4+ICsjZGVmaW5lIENZX01BWF9JRCAgICAgICAgICAgICAgICAgICAxNQ0KPiA+DQo+ID4g V2h5IG5vdCAxNiBoZXJlPw0KPiA+DQo+DQo+IEJlY2F1c2UgYXMgZmFyIGFzIEkga25vdyB0aGVy ZSBhcmUgb25seSAxNCBwb3NzaWJsZSB0cmFja2luZyBpZHMgKDEtMTQpLCBub3QgMTYuDQo+IDE1 IGFuZCAwIGFyZSBub3QgdmFsaWQgdHJhY2sgaWRzLg0KPg0KPiBXaGVuIGEgY29udGFjdCBsaWZ0 cyBvZmYgdGhlIGhhcmR3YXJlIHJlcG9ydHMgYSBtYWdpYyBudW1iZXIgKDE1KSBmb3IgaXQuDQo+ IEFsc28sIHRoZSBzZXF1ZW5jZSBhbHdheXMgc3RhcnQgd2l0aCAxIHdoaWNoIGlzIHRoZSB0cmFj ayBpZCB0aGF0IGdldHMgdGhlIGZpcnN0DQo+IGNvbnRhY3QgcmVwb3J0ZWQgYnkgdGhlIHRvdWNo Lg0KPg0KPiA+PiArDQo+ID4+ICsvKiBUcnVlVG91Y2ggU3RhbmRhcmQgUHJvZHVjdCBHZW4zIGlu dGVyZmFjZSBkZWZpbml0aW9uICovIHN0cnVjdA0KPiA+PiArY3l0dHNwX3h5ZGF0YSB7DQo+ID4+ ICsgICAgIHU4IGhzdF9tb2RlOw0KPiA+PiArICAgICB1OCB0dF9tb2RlOw0KPiA+PiArICAgICB1 OCB0dF9zdGF0Ow0KPiA+PiArICAgICBzdHJ1Y3QgY3l0dHNwX3RjaCB0Y2gxOw0KPiA+PiArICAg ICB1OCB0b3VjaDEyX2lkOw0KPiA+PiArICAgICBzdHJ1Y3QgY3l0dHNwX3RjaCB0Y2gyOw0KPiA+ PiArICAgICB1OCBnZXN0X2NudDsNCj4gPj4gKyAgICAgdTggZ2VzdF9pZDsNCj4gPj4gKyAgICAg c3RydWN0IGN5dHRzcF90Y2ggdGNoMzsNCj4gPj4gKyAgICAgdTggdG91Y2gzNF9pZDsNCj4gPj4g KyAgICAgc3RydWN0IGN5dHRzcF90Y2ggdGNoNDsNCj4gPj4gKyAgICAgdTggdHRfdW5kZWZbM107 DQo+ID4+ICsgICAgIHU4IGFjdF9kaXN0Ow0KPiA+PiArICAgICB1OCB0dF9yZXNlcnZlZDsNCj4g Pj4gK30gX19wYWNrZWQ7DQo+ID4NCj4gPiBUb28gYmFkIHRoZSB0b3VjaGVzIGFyZSBub3QgYW4g YXJyYXkgaGVyZS4uLg0KPiA+DQo+DQo+IFllcywgdGhlIHByb2JsZW0gaXMgdGhhdCB0aGUgb2Zm c2V0IGJldHdlZW4gdG91Y2hlcyBpcyBub3QgdW5pZm9ybS4NCj4gRm9yIHRjaDEgYW5kIHRjaDIg aXMgb25seSA4IGJpdHMgYnV0IHRoZSBvZmZzZXQgYmV0d2VlbiB0Y2gyIGFuZCB0Y2gzIGlzIDE2 ICh1OA0KPiAqIDIpIGZvciBleGFtcGxlLg0KPg0KPiA+PiArICAgICBpbnQgc2xvdF9jdXJyW0NZ X01BWF9JRF07DQo+ID4+ICsgICAgIGludCBzbG90X3ByZXZbQ1lfTUFYX0lEXTsNCj4gPg0KPiA+ IFRoZXNlIHR3byBhcmUgbm90IG5lZWRlZDsgdGhlIGlucHV0IGNvcmUgd2lsbCB0YWtlIGNhcmUg b2YgZHVwbGljYXRlcywNCj4gPiBzbyBzbG90X3ByZXYgY2FuIGJlIHJlbW92ZWQuIEFsc28sIHRo ZSBzZXQgb2YgY3VycmVudCBzbG90cyBjYW4gYmUNCj4gPiB0cmFja2VkIHVzaW5nIGEgdGVtcG9y YXJ5IGJpdG1hc2ssIHNvIHNsb3RfY3VyciBjYW4gYmUgcmVtb3ZlZCBhcyB3ZWxsLg0KPg0KPiBQ ZXJmZWN0LCBJJ2xsIHJlbW92ZSBib3RoLiBJIGRpZG4ndCBrbm93IHRoYXQgdGhlIGlucHV0IGNv cmUgdG9vayBjYXJlIG9mDQo+IGR1cGxpY2F0ZXMsIHNvcnJ5IGZvciBub3QgZ2V0dGluZyB0aGlz IGZyb20gdGhlIGRvY3MuDQo+DQo+ID4+ICsNCj4gPj4gK3N0YXRpYyB2b2lkIGN5dHRzcF9nZXRf dGNoKHN0cnVjdCBjeXR0c3BfeHlkYXRhICp4eV9kYXRhLCBpbnQgaWR4LA0KPiA+PiArICAgICAg ICAgICAgICAgICAgICAgICAgc3RydWN0IGN5dHRzcF90Y2ggKip0Y2gpIHsNCj4gPj4gKyAgICAg c3dpdGNoIChpZHgpIHsNCj4gPj4gKyAgICAgY2FzZSAwOg0KPiA+PiArICAgICAgICAgICAgICp0 Y2ggPSAmeHlfZGF0YS0+dGNoMTsNCj4gPj4gKyAgICAgICAgICAgICBicmVhazsNCj4gPj4gKyAg ICAgY2FzZSAxOg0KPiA+PiArICAgICAgICAgICAgICp0Y2ggPSAmeHlfZGF0YS0+dGNoMjsNCj4g Pj4gKyAgICAgICAgICAgICBicmVhazsNCj4gPj4gKyAgICAgY2FzZSAyOg0KPiA+PiArICAgICAg ICAgICAgICp0Y2ggPSAmeHlfZGF0YS0+dGNoMzsNCj4gPj4gKyAgICAgICAgICAgICBicmVhazsN Cj4gPj4gKyAgICAgY2FzZSAzOg0KPiA+PiArICAgICAgICAgICAgICp0Y2ggPSAmeHlfZGF0YS0+ dGNoNDsNCj4gPj4gKyAgICAgICAgICAgICBicmVhazsNCj4gPj4gKyAgICAgfQ0KPiA+PiArfQ0K PiA+DQo+ID4gSG93IGFib3V0IHJldHVybmluZyBhIGNvbnN0IHN0cnVjdCBjeXR0c3BfdGNoKiBo ZXJlIGluc3RlYWQuDQo+ID4NCj4NCj4gT2ssIHdpbGwgcmV0dXJuIGEgc3RydWN0IHBvaW50ZXIg aW5zdGVhZC4NCj4NCj4gPj4gKw0KPiA+PiArICAgICBjeXR0c3BfZXh0cmFjdF90cmFja19pZHMo Jnh5X2RhdGEsIGlkcyk7DQo+ID4+ICsNCj4gPj4gKyAgICAgZm9yIChpID0gMDsgaSA8IG51bV9j dXJfdGNoOyBpKyspIHsNCj4gPj4gKyAgICAgICAgICAgICB0cy0+c2xvdF9jdXJyW2lkc1tpXSAt IDFdID0gQ1lfVVNFRDsNCj4gPg0KPiA+IFdoeSB0aGUgLTEgaGVyZT8gU2luY2UgdGhlIHZhbHVl cyBhcmUgcHJvdmFibHkgYmV0d2VlbiAwIGFuZCAxNSwgdGhlcmUNCj4gPiBpcyBubyBuZWVkIHRv IGNoYW5nZSB0aGVtIGZ1cnRoZXIuDQo+DQo+IEFzIEkgdG9sZCB5b3UgYmVmb3JlIGlzIGEgSFcg dGhpbmcuIEkgbG9va2VkIGF0IHRoZSB0cmFjayBpZHMgcmVwb3J0ZWQgYnkgdGhlDQo+IHRvdWNo c2NyZWVuIGFuZCB0aGVpciB2YWx1ZXMgYXJlIGFsd2F5cyBiZXR3ZWVuIDEgYW5kIDE0LiBTbyBJ IGRpZCB0aGUgLTEgdG8NCj4gYXZvaWQgaGF2aW5nIGFuZCB1bnVzZWQgZWxlbWVudCBpbiB0aGUg YXJyYXkuIChJIGRvbid0IGhhdmUgdGhlIEhXDQo+IGRhdGFzaGVldCBzbyBtYXliZSBJJ20gd3Jv bmcgd2l0aCB0aGlzKQ0KPg0KPiBLZXZpbj8NCj4NCj4gPg0KPiA+IEFsc28sIHRoZSBhYm92ZSBs aW5lIGNvdWxkIGJlIHJlcGxhY2VkIGJ5ICJ1c2VkIHw9IDEgPDwgaWRzW2ldIiwgZm9yIGluc3Rh bmNlLg0KPiA+DQo+ID4+ICsNCj4gPj4gKyAgICAgICAgICAgICBjeXR0c3BfZ2V0X3RjaCgmeHlf ZGF0YSwgaSwgJnRjaCk7DQo+ID4+ICsNCj4gPj4gKyAgICAgICAgICAgICB4ID0gYmUxNl90b19j cHUodGNoLT54KTsNCj4gPj4gKyAgICAgICAgICAgICB5ID0gYmUxNl90b19jcHUodGNoLT55KTsN Cj4gPj4gKyAgICAgICAgICAgICB6ID0gdGNoLT56Ow0KPiA+PiArDQo+ID4+ICsgICAgICAgICAg ICAgY3l0dHNwX3JlcG9ydF9zbG90KHRzLT5pbnB1dCwgaWRzW2ldIC0gMSwgeCwgeSwgeik7DQo+ ID4NCj4gPiBEaXR0bywgLTEuDQo+ID4NCj4gPj4gKyAgICAgfQ0KPiA+PiArDQo+ID4+ICsgICAg IGZvciAoaSA9IDA7IGkgPCBDWV9NQVhfSUQ7IGkrKykgew0KPiA+PiArICAgICAgICAgICAgIGlm ICh0cy0+c2xvdF9wcmV2W2ldID09IENZX1VTRUQgJiYNCj4gPj4gKyAgICAgICAgICAgICAgICAg dHMtPnNsb3RfY3VycltpXSA9PSBDWV9VTlVTRUQpDQo+ID4+ICsgICAgICAgICAgICAgICAgICAg ICBjeXR0c3BfcmVwb3J0X3Nsb3RfZW1wdHkodHMtPmlucHV0LCBpKTsNCj4gPj4gKyAgICAgICAg ICAgICB0cy0+c2xvdF9wcmV2W2ldID0gdHMtPnNsb3RfY3VycltpXTsNCj4gPj4gKyAgICAgICAg ICAgICB0cy0+c2xvdF9jdXJyW2ldID0gQ1lfVU5VU0VEOw0KPiA+PiArICAgICB9DQo+ID4NCj4g PiBJbnB1dCBjb3JlIGhhbmRsZXMgZHVwbGljYXRlIGNhbGxzLCBzbyB0aGUgYWJvdmUgY291bGQg YmUgc2ltcGxpZmllZC4NCj4gPg0KPg0KPiBQZXJmZWN0LCB3aWxsIGNsZWFuIHRoaXMgY29kZS4N Cj4NCj4gPj4gKw0KPiA+PiArICAgICBmb3IgKGkgPSAwOyBpIDwgQ1lfTUFYX0lEOyBpKyspIHsN Cj4gPj4gKyAgICAgICAgICAgICB0cy0+c2xvdF9wcmV2W2ldID0gQ1lfVU5VU0VEOw0KPiA+PiAr ICAgICAgICAgICAgIHRzLT5zbG90X2N1cnJbaV0gPSBDWV9VTlVTRUQ7DQo+ID4+ICsgICAgIH0N Cj4gPg0KPiA+IENvdWxkIGJlIHJlbW92ZWQuDQo+ID4NCj4NCj4gWWVzLCBJJ2xsIGRvIHRoYXQu DQo+DQo+ID4NCj4gPiBUaGFua3MsDQo+ID4gSGVucmlrDQo+ID4NCj4NCj4gVGhhbmtzIGZvciB5 b3VyIGNvbW1lbnRzLCBJIHdpbGwgd29yayBvbiB0aGVzZSBpc3N1ZXMgYW5kIHJlc3VibWl0IGEg bmV3DQo+IHZlcnNpb24gb2YgdGhlIHBhdGNoLXNldC4NCj4NCj4gQmVzdCByZWdhcmRzLA0KPg0K PiAtLQ0KPiBKYXZpZXIgTWFydMOtbmV6IENhbmlsbGFzDQo+ICgrMzQpIDY4MiAzOSA4MSA2OQ0K PiBCYXJjZWxvbmEsIFNwYWluDQoNClRoaXMgbWVzc2FnZSBhbmQgYW55IGF0dGFjaG1lbnRzIG1h eSBjb250YWluIEN5cHJlc3MgKG9yIGl0cyBzdWJzaWRpYXJpZXMpIGNvbmZpZGVudGlhbCBpbmZv cm1hdGlvbi4gSWYgaXQgaGFzIGJlZW4gcmVjZWl2ZWQgaW4gZXJyb3IsIHBsZWFzZSBhZHZpc2Ug dGhlIHNlbmRlciBhbmQgaW1tZWRpYXRlbHkgZGVsZXRlIHRoaXMgbWVzc2FnZS4NCg==