diff for duplicates of <1541687328.2091.2.camel@analog.com> diff --git a/a/1.txt b/N1/1.txt index 9e68d56..abd7e31 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,477 +1,881 @@ -T24gU2IsIDIwMTgtMTEtMDMgYXQgMTI6MTYgKzAwMDAsIEpvbmF0aGFuIENhbWVyb24gd3JvdGU6 -DQo+IE9uIE1vbiwgMjkgT2N0IDIwMTggMTg6Mzg6MzEgKzAyMDANCj4gU3RlZmFuIFBvcGEgPHN0 -ZWZhbi5wb3BhQGFuYWxvZy5jb20+IHdyb3RlOg0KPiANCj4gPiANCj4gPiBUaGUgYWQ3MTI0LTQg -YW5kIGFkNzEyNC04IGFyZSBhIGZhbWlseSBvZiA0IGFuZCA4IGNoYW5uZWwgc2lnbWEtZGVsdGEN -Cj4gPiBBRENzDQo+ID4gd2l0aCAyNC1iaXQgcHJlY2lzaW9uIGFuZCByZWZlcmVuY2UuDQo+ID4g -DQo+ID4gVGhyZWUgcG93ZXIgbW9kZXMgYXJlIGF2YWlsYWJsZSB3aGljaCBpbiB0dXJuIGFmZmVj -dCB0aGUgb3V0cHV0IGRhdGENCj4gPiByYXRlOg0KPiA+IMKgKiBGdWxsIHBvd2VyOiA5LjM4IFNQ -UyB0byAxOSwyMDAgU1BTDQo+ID4gwqAqIE1pZCBwb3dlcjogMi4zNCBTUFMgdG8gNDgwMCBTUFMN -Cj4gPiDCoCogTG93IHBvd2VyOiAxLjE3IFNQUyB0byAyNDAwIFNQUw0KPiA+IA0KPiA+IFRoZSBh -ZDcxMjQtNCBjYW4gYmUgY29uZmlndXJlZCB0byBoYXZlIGZvdXIgZGlmZmVyZW50aWFsIGlucHV0 -cywgd2hpbGUNCj4gPiBhZDcxMjQtOCBjYW4gaGF2ZSA4LiBNb3Jlb3ZlciwgYWQ3MTI0IGFsc28g -c3VwcG9ydHMgcGVyIGNoYW5uZWwNCj4gPiBjb25maWd1cmF0aW9uLiBFYWNoIGNvbmZpZ3VyYXRp -b24gY29uc2lzdHMgb2YgZ2FpbiwgcmVmZXJlbmNlIHNvdXJjZSwNCj4gPiBvdXRwdXQgZGF0YSBy -YXRlIGFuZCBiaXBvbGFyL3VuaXBvbGFyIGNvbmZpZ3VyYXRpb24uDQo+ID4gDQo+ID4gRGF0YXNo -ZWV0czoNCj4gPiBMaW5rOiBodHRwOi8vd3d3LmFuYWxvZy5jb20vbWVkaWEvZW4vdGVjaG5pY2Fs -LWRvY3VtZW50YXRpb24vZGF0YS1zaGVldA0KPiA+IHMvQUQ3MTI0LTQucGRmDQo+ID4gTGluazog -aHR0cDovL3d3dy5hbmFsb2cuY29tL21lZGlhL2VuL3RlY2huaWNhbC1kb2N1bWVudGF0aW9uL2Rh -dGEtc2hlZXQNCj4gPiBzL2FkNzEyNC04LnBkZg0KPiA+IA0KPiA+IFNpZ25lZC1vZmYtYnk6IFN0 -ZWZhbiBQb3BhIDxzdGVmYW4ucG9wYUBhbmFsb2cuY29tPg0KPiBIaSBTdGVmYW4sDQo+IA0KPiBU -aGUgZGlzY3Vzc2lvbiBhcm91bmQgdGhlIERUIGJpbmRpbmcgaGFzIGdvdHRlbiBtZSBsb29raW5n -IGF0IGJpdA0KPiBtb3JlIGNsb3NlbHkgYXQgdGhhdCBmb3IgdGhpcyB2ZXJzaW9uLg0KPiANCj4g -U29tZSBtb3N0IGNvbW1lbnRzIGluIHRoYXQgc2VjdGlvbi7CoMKgQWxzbyBhIHJlYWxseSBtaW5v -ciBvcmRlcmluZyBpc3N1ZQ0KPiBpbg0KPiByZW1vdmUgd2hpY2ggSSdkIGp1c3QgaGF2ZSBmaXhl -ZCBpZiB3ZSB3ZXJlbid0IGdvaW5nIGFyb3VuZCBhZ2FpbiBmb3INCj4gdGhlIGJpbmRpbmcuDQo+ -IA0KPiBNYWluIGJpbmRpbmcgdGhpbmcgaXMgSSBkb24ndCB0aGluayB0aGUgb2RyIHZhbHVlIGJl -bG9uZ3MgaW4gRFQuDQo+IEdhaW4gaXMgbW9yZSBtYXJnaW5hbCAodW5sZXNzIHRoZSBwYXJ0IGNh -biBhY3R1YWxseSBiZSBkYW1hZ2VkIGJ5DQo+IGEgd3JvbmcgdmFsdWUgLSB3aGljaCBJIGhvcGUg -aXQgY2FuJ3QhKS7CoMKgSSdtIG5vdCB0aGF0IGZ1c3NlZA0KPiBhcyB0aGVyZSBhcmUgZGVmaW5p -dGVseSByZWFzb25zIHRvIHNwZWNpZnkgYSBkZWZhdWx0IHNjYWxlIHRvDQo+IGNvdmVyIHRoZSBy -ZWFzb25hYmxlIHJhbmdlIG9uIGEgcGluLg0KPiANCj4gVGhhbmtzLA0KPiANCj4gSm9uYXRoYW4N -Cg0KSGkgSm9uYXRoYW4sDQoNClRoYW5rIHlvdSBmb3IgdGhlIHJldmlldyEgU28sIGhvdyBzaG91 -bGQgSSBwcm9jZWVkPw0KDQpGaXJzdCwgd2UgbmVlZCBhbiBhZGMudHh0IGZpbGUgd2hlcmUgImJp -cG9sYXIiIGFuZCBzb21ldGhpbmcgbGlrZSAiZGlmZi0NCmNoYW5uZWxzIiBzaG91bGQgYmUgZG9j -dW1lbnRlZC4gU2hvdWxkIHRoZSBmaWxlIGJlIHBsYWNlZCB1bmRlcg0KRG9jdW1lbnRhdGlvbi9k -ZXZpY2V0cmVlL2JpbmRpbmdzL2lpby9hZGM/DQoNClJlZ2FyZGluZyB0aGUgIm9kci1oeiIgcHJv -cGVydHksIGl0IHRvdGFsbHkgbWFrZXMgc2Vuc2UgdG8gcmVtb3ZlIGl0IGZyb20NCnRoZSBEVC4g -SG93IGFib3V0IHRoZSAiZ2FpbiI/IFNob3VsZCB3ZSBsZWF2ZSBpdCBpbiB0aGUgRFQgYW5kIGFs -c28gYWRkIHRoZQ0KcG9zc2liaWxpdHkgdG8gYmUgY29uZmlndXJlZCBmcm9tIHVzZXIgc3BhY2U/ -DQoNClJlZ2FyZHMsDQotU3RlZmFuDQo+ID4gDQo+ID4gLS0tDQo+ID4gQ2hhbmdlcyBpbiB2MjoN -Cj4gPiAJLSBBZGRlZCB0aGlzIGNvbW1pdC4NCj4gPiBDaGFuZ2VzIGluIHYzOg0KPiA+IAktIFJl -bW92ZWQgY2hhbm5lbCwgYWRkcmVzcywgc2Nhbl9pbmRleCBhbmQgc2hpZnQgZmllbGRzIGZyb20N -Cj4gPiAJwqDCoGFkNzEyNF9jaGFubmVsX3RlbXBsYXRlLg0KPiA+IAktIEFkZGVkIGEgc2FuaXR5 -IGNoZWNrIGZvciB2YWwyIGluIGFkNzEyNF93cml0ZV9yYXcoKS4NCj4gPiAJLSBVc2VkIHRoZSAi -cmVnIiBwcm9wZXJ0eSB0byBnZXQgdGhlIGNoYW5uZWwgYWRkcmVzcyBhbmQgImFkaSxkaWZmLQ0K -PiA+IGNoYW5uZWxzIg0KPiA+IAnCoMKgZm9yIHRoZSBkaWZmZXJlbnRpYWwgcGlucy4gVGhlICJh -ZGksY2hhbm5lbC1udW1iZXIiIHByb3BlcnR5IHdhcw0KPiA+IHJlbW92ZWQuDQo+ID4gCS0gV2hl -biBjYWxsaW5nIHJlZ3VsYXRvcl9nZXRfb3B0aW9uYWwsIHRoZSBwcm9iZSBpcyBnaXZlbiB1cCBp -bg0KPiA+IGNhc2Ugb2YgZXJyb3IsDQo+ID4gCcKgwqBidXQgY29udGludWVzIGluIGNhc2Ugb2Yg -LUVOT0RFVi4NCj4gPiAJLSBjbGtfZGlzYWJsZV91bnByZXBhcmUoKSBpcyBjYWxsZWQgYmVmb3Jl -DQo+ID4gYWRfc2RfY2xlYW51cF9idWZmZXJfYW5kX3RyaWdnZXINCj4gPiAJwqDCoGluIGFkNzEy -NF9yZW1vdmUoKS4NCj4gPiANCj4gPiDCoE1BSU5UQUlORVJTwqDCoMKgwqDCoMKgwqDCoMKgwqDC -oMKgwqDCoHzCoMKgwqA3ICsNCj4gPiDCoGRyaXZlcnMvaWlvL2FkYy9LY29uZmlnwqDCoHzCoMKg -MTEgKw0KPiA+IMKgZHJpdmVycy9paW8vYWRjL01ha2VmaWxlIHzCoMKgwqAxICsNCj4gPiDCoGRy -aXZlcnMvaWlvL2FkYy9hZDcxMjQuYyB8IDY0OA0KPiA+ICsrKysrKysrKysrKysrKysrKysrKysr -KysrKysrKysrKysrKysrKysrKysrKysrDQo+ID4gwqA0IGZpbGVzIGNoYW5nZWQsIDY2NyBpbnNl -cnRpb25zKCspDQo+ID4gwqBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9paW8vYWRjL2FkNzEy -NC5jDQo+ID4gDQo+ID4gZGlmZiAtLWdpdCBhL01BSU5UQUlORVJTIGIvTUFJTlRBSU5FUlMNCj4g -PiBpbmRleCBmNjQyMDQ0Li4zYTFiZmNiIDEwMDY0NA0KPiA+IC0tLSBhL01BSU5UQUlORVJTDQo+ -ID4gKysrIGIvTUFJTlRBSU5FUlMNCj4gPiBAQCAtODM5LDYgKzgzOSwxMyBAQCBTOglTdXBwb3J0 -ZWQNCj4gPiDCoEY6CWRyaXZlcnMvaWlvL2RhYy9hZDU3NTguYw0KPiA+IMKgRjoJRG9jdW1lbnRh -dGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2lpby9kYWMvYWQ1NzU4LnR4dA0KPiA+IMKgDQo+ID4g -K0FOQUxPRyBERVZJQ0VTIElOQyBBRDcxMjQgRFJJVkVSDQo+ID4gK006CVN0ZWZhbiBQb3BhIDxz -dGVmYW4ucG9wYUBhbmFsb2cuY29tPg0KPiA+ICtMOglsaW51eC1paW9Admdlci5rZXJuZWwub3Jn -DQo+ID4gK1c6CWh0dHA6Ly9lei5hbmFsb2cuY29tL2NvbW11bml0eS9saW51eC1kZXZpY2UtZHJp -dmVycw0KPiA+ICtTOglTdXBwb3J0ZWQNCj4gPiArRjoJZHJpdmVycy9paW8vYWRjL2FkNzEyNC5j -DQo+ID4gKw0KPiA+IMKgQU5BTE9HIERFVklDRVMgSU5DIEFEOTM4OUIgRFJJVkVSDQo+ID4gwqBN -OglIYW5zIFZlcmt1aWwgPGhhbnMudmVya3VpbEBjaXNjby5jb20+DQo+ID4gwqBMOglsaW51eC1t -ZWRpYUB2Z2VyLmtlcm5lbC5vcmcNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9paW8vYWRjL0tj -b25maWcgYi9kcml2ZXJzL2lpby9hZGMvS2NvbmZpZw0KPiA+IGluZGV4IGE1MmZlYTguLjE0OGEx -MGYgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9paW8vYWRjL0tjb25maWcNCj4gPiArKysgYi9k -cml2ZXJzL2lpby9hZGMvS2NvbmZpZw0KPiA+IEBAIC0xMCw2ICsxMCwxNyBAQCBjb25maWcgQURf -U0lHTUFfREVMVEENCj4gPiDCoAlzZWxlY3QgSUlPX0JVRkZFUg0KPiA+IMKgCXNlbGVjdCBJSU9f -VFJJR0dFUkVEX0JVRkZFUg0KPiA+IMKgDQo+ID4gK2NvbmZpZyBBRDcxMjQNCj4gPiArCXRyaXN0 -YXRlICJBbmFsb2cgRGV2aWNlcyBBRDcxMjQgYW5kIHNpbWlsYXIgc2lnbWEtZGVsdGEgQURDcw0K -PiA+IGRyaXZlciINCj4gPiArCWRlcGVuZHMgb24gU1BJX01BU1RFUg0KPiA+ICsJc2VsZWN0IEFE -X1NJR01BX0RFTFRBDQo+ID4gKwloZWxwDQo+ID4gKwnCoMKgU2F5IHllcyBoZXJlIHRvIGJ1aWxk -IHN1cHBvcnQgZm9yIEFuYWxvZyBEZXZpY2VzIEFENzEyNC00DQo+ID4gYW5kIEFENzEyNC04DQo+ -ID4gKwnCoMKgU1BJIGFuYWxvZyB0byBkaWdpdGFsIGNvbnZlcnRlcnMgKEFEQykuDQo+ID4gKw0K -PiA+ICsJwqDCoFRvIGNvbXBpbGUgdGhpcyBkcml2ZXIgYXMgYSBtb2R1bGUsIGNob29zZSBNIGhl -cmU6IHRoZQ0KPiA+IG1vZHVsZSB3aWxsIGJlDQo+ID4gKwnCoMKgY2FsbGVkIGFkNzEyNC4NCj4g -PiArDQo+ID4gwqBjb25maWcgQUQ3MjY2DQo+ID4gwqAJdHJpc3RhdGUgIkFuYWxvZyBEZXZpY2Vz -IEFENzI2NS9BRDcyNjYgQURDIGRyaXZlciINCj4gPiDCoAlkZXBlbmRzIG9uIFNQSV9NQVNURVIN -Cj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9paW8vYWRjL01ha2VmaWxlIGIvZHJpdmVycy9paW8v -YWRjL01ha2VmaWxlDQo+ID4gaW5kZXggYTZlNmEwYi4uNzYxNjhiMiAxMDA2NDQNCj4gPiAtLS0g -YS9kcml2ZXJzL2lpby9hZGMvTWFrZWZpbGUNCj4gPiArKysgYi9kcml2ZXJzL2lpby9hZGMvTWFr -ZWZpbGUNCj4gPiBAQCAtNSw2ICs1LDcgQEANCj4gPiDCoA0KPiA+IMKgIyBXaGVuIGFkZGluZyBu -ZXcgZW50cmllcyBrZWVwIHRoZSBsaXN0IGluIGFscGhhYmV0aWNhbCBvcmRlcg0KPiA+IMKgb2Jq -LSQoQ09ORklHX0FEX1NJR01BX0RFTFRBKSArPSBhZF9zaWdtYV9kZWx0YS5vDQo+ID4gK29iai0k -KENPTkZJR19BRDcxMjQpICs9IGFkNzEyNC5vDQo+ID4gwqBvYmotJChDT05GSUdfQUQ3MjY2KSAr -PSBhZDcyNjYubw0KPiA+IMKgb2JqLSQoQ09ORklHX0FENzI5MSkgKz0gYWQ3MjkxLm8NCj4gPiDC -oG9iai0kKENPTkZJR19BRDcyOTgpICs9IGFkNzI5OC5vDQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZl -cnMvaWlvL2FkYy9hZDcxMjQuYyBiL2RyaXZlcnMvaWlvL2FkYy9hZDcxMjQuYw0KPiA+IG5ldyBm -aWxlIG1vZGUgMTAwNjQ0DQo+ID4gaW5kZXggMDAwMDAwMC4uMDY2MDEzNQ0KPiA+IC0tLSAvZGV2 -L251bGwNCj4gPiArKysgYi9kcml2ZXJzL2lpby9hZGMvYWQ3MTI0LmMNCj4gPiBAQCAtMCwwICsx -LDY0OCBAQA0KPiA+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCsNCj4gPiAr -LyoNCj4gPiArICogQUQ3MTI0IFNQSSBBREMgZHJpdmVyDQo+ID4gKyAqDQo+ID4gKyAqIENvcHly -aWdodCAyMDE4IEFuYWxvZyBEZXZpY2VzIEluYy4NCj4gPiArICovDQo+ID4gKyNpbmNsdWRlIDxs -aW51eC9iaXRmaWVsZC5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvY2xrLmg+DQo+ID4gKyNpbmNs -dWRlIDxsaW51eC9kZWxheS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+DQo+ID4g -KyNpbmNsdWRlIDxsaW51eC9lcnIuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPg0K -PiA+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9yZWd1 -bGF0b3IvY29uc3VtZXIuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3NwaS9zcGkuaD4NCj4gPiAr -DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9paW8vaWlvLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9p -aW8vYWRjL2FkX3NpZ21hX2RlbHRhLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9paW8vc3lzZnMu -aD4NCj4gPiArDQo+ID4gKy8qIEFENzEyNCByZWdpc3RlcnMgKi8NCj4gPiArI2RlZmluZSBBRDcx -MjRfQ09NTVMJCQkweDAwDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X1NUQVRVUwkJCTB4MDANCj4gPiAr -I2RlZmluZSBBRDcxMjRfQURDX0NPTlRST0wJCTB4MDENCj4gPiArI2RlZmluZSBBRDcxMjRfREFU -QQkJCTB4MDINCj4gPiArI2RlZmluZSBBRDcxMjRfSU9fQ09OVFJPTF8xCQkweDAzDQo+ID4gKyNk -ZWZpbmUgQUQ3MTI0X0lPX0NPTlRST0xfMgkJMHgwNA0KPiA+ICsjZGVmaW5lIEFENzEyNF9JRAkJ -CTB4MDUNCj4gPiArI2RlZmluZSBBRDcxMjRfRVJST1IJCQkweDA2DQo+ID4gKyNkZWZpbmUgQUQ3 -MTI0X0VSUk9SX0VOCQkweDA3DQo+ID4gKyNkZWZpbmUgQUQ3MTI0X01DTEtfQ09VTlQJCTB4MDgN -Cj4gPiArI2RlZmluZSBBRDcxMjRfQ0hBTk5FTCh4KQkJKDB4MDkgKyAoeCkpDQo+ID4gKyNkZWZp -bmUgQUQ3MTI0X0NPTkZJRyh4KQkJKDB4MTkgKyAoeCkpDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0ZJ -TFRFUih4KQkJKDB4MjEgKyAoeCkpDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X09GRlNFVCh4KQkJKDB4 -MjkgKyAoeCkpDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0dBSU4oeCkJCQkoMHgzMSArICh4KSkNCj4g -PiArDQo+ID4gKy8qIEFENzEyNF9TVEFUVVMgKi8NCj4gPiArI2RlZmluZSBBRDcxMjRfU1RBVFVT -X1BPUl9GTEFHX01TSwlCSVQoNCkNCj4gPiArDQo+ID4gKy8qIEFENzEyNF9BRENfQ09OVFJPTCAq -Lw0KPiA+ICsjZGVmaW5lIEFENzEyNF9BRENfQ1RSTF9QV1JfTVNLCUdFTk1BU0soNywgNikNCj4g -PiArI2RlZmluZSBBRDcxMjRfQURDX0NUUkxfUFdSKHgpCQlGSUVMRF9QUkVQKEFENzEyNF9BRENf -Q1QNCj4gPiBSTF9QV1JfTVNLLCB4KQ0KPiA+ICsjZGVmaW5lIEFENzEyNF9BRENfQ1RSTF9NT0RF -X01TSwlHRU5NQVNLKDUsIDIpDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0FEQ19DVFJMX01PREUoeCkJ -RklFTERfUFJFUChBRDcxMjRfQURDX0NUUkxfTU9ERQ0KPiA+IF9NU0ssIHgpDQo+ID4gKw0KPiA+ -ICsvKiBBRDcxMjRfQ0hBTk5FTF9YICovDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0NIQU5ORUxfRU5f -TVNLCQlCSVQoMTUpDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0NIQU5ORUxfRU4oeCkJCUZJRUxEX1BS -RVAoQUQ3MTI0X0NIQU5ORUxfDQo+ID4gRU5fTVNLLCB4KQ0KPiA+ICsjZGVmaW5lIEFENzEyNF9D -SEFOTkVMX1NFVFVQX01TSwlHRU5NQVNLKDE0LCAxMikNCj4gPiArI2RlZmluZSBBRDcxMjRfQ0hB -Tk5FTF9TRVRVUCh4KQlGSUVMRF9QUkVQKEFENzEyNF9DSEFOTkVMX1NFVFVQDQo+ID4gX01TSywg -eCkNCj4gPiArI2RlZmluZSBBRDcxMjRfQ0hBTk5FTF9BSU5QX01TSwlHRU5NQVNLKDksIDUpDQo+ -ID4gKyNkZWZpbmUgQUQ3MTI0X0NIQU5ORUxfQUlOUCh4KQkJRklFTERfUFJFUChBRDcxMjRfQ0hB -Tk5FDQo+ID4gTF9BSU5QX01TSywgeCkNCj4gPiArI2RlZmluZSBBRDcxMjRfQ0hBTk5FTF9BSU5N -X01TSwlHRU5NQVNLKDQsIDApDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0NIQU5ORUxfQUlOTSh4KQkJ -RklFTERfUFJFUChBRDcxMjRfQ0hBTk5FDQo+ID4gTF9BSU5NX01TSywgeCkNCj4gPiArDQo+ID4g -Ky8qIEFENzEyNF9DT05GSUdfWCAqLw0KPiA+ICsjZGVmaW5lIEFENzEyNF9DT05GSUdfQklQT0xB -Ul9NU0sJQklUKDExKQ0KPiA+ICsjZGVmaW5lIEFENzEyNF9DT05GSUdfQklQT0xBUih4KQlGSUVM -RF9QUkVQKEFENzEyNF9DT05GSUdfQklQT0wNCj4gPiBBUl9NU0ssIHgpDQo+ID4gKyNkZWZpbmUg -QUQ3MTI0X0NPTkZJR19SRUZfU0VMX01TSwlHRU5NQVNLKDQsIDMpDQo+ID4gKyNkZWZpbmUgQUQ3 -MTI0X0NPTkZJR19SRUZfU0VMKHgpCUZJRUxEX1BSRVAoQUQ3MTI0X0NPTkZJR19SRUZfUw0KPiA+ -IEVMX01TSywgeCkNCj4gPiArI2RlZmluZSBBRDcxMjRfQ09ORklHX1BHQV9NU0sJCUdFTk1BU0so -MiwgMCkNCj4gPiArI2RlZmluZSBBRDcxMjRfQ09ORklHX1BHQSh4KQkJRklFTERfUFJFUChBRDcx -MjRfQ09ORklHX1ANCj4gPiBHQV9NU0ssIHgpDQo+ID4gKw0KPiA+ICsvKiBBRDcxMjRfRklMVEVS -X1ggKi8NCj4gPiArI2RlZmluZSBBRDcxMjRfRklMVEVSX0ZTX01TSwkJR0VOTUFTSygxMCwgMCkN -Cj4gPiArI2RlZmluZSBBRDcxMjRfRklMVEVSX0ZTKHgpCQlGSUVMRF9QUkVQKEFENzEyNF9GSUxU -RVJfRlMNCj4gPiBfTVNLLCB4KQ0KPiA+ICsNCj4gPiArZW51bSBhZDcxMjRfaWRzIHsNCj4gPiAr -CUlEX0FENzEyNF80LA0KPiA+ICsJSURfQUQ3MTI0XzgsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtl -bnVtIGFkNzEyNF9yZWZfc2VsIHsNCj4gPiArCUFENzEyNF9SRUZJTjEsDQo+ID4gKwlBRDcxMjRf -UkVGSU4yLA0KPiA+ICsJQUQ3MTI0X0lOVF9SRUYsDQo+ID4gKwlBRDcxMjRfQVZERF9SRUYsDQo+ -ID4gK307DQo+ID4gKw0KPiA+ICtlbnVtIGFkNzEyNF9wb3dlcl9tb2RlIHsNCj4gPiArCUFENzEy -NF9MT1dfUE9XRVIsDQo+ID4gKwlBRDcxMjRfTUlEX1BPV0VSLA0KPiA+ICsJQUQ3MTI0X0ZVTExf -UE9XRVIsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3QgdW5zaWduZWQgaW50IGFk -NzEyNF9nYWluWzhdID0gew0KPiA+ICsJMSwgMiwgNCwgOCwgMTYsIDMyLCA2NCwgMTI4DQo+ID4g -K307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3QgaW50IGFkNzEyNF9tYXN0ZXJfY2xrX2ZyZXFf -aHpbM10gPSB7DQo+ID4gKwlbQUQ3MTI0X0xPV19QT1dFUl0gPSA3NjgwMCwNCj4gPiArCVtBRDcx -MjRfTUlEX1BPV0VSXSA9IDE1MzYwMCwNCj4gPiArCVtBRDcxMjRfRlVMTF9QT1dFUl0gPSA2MTQ0 -MDAsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3QgY2hhciAqIGNvbnN0IGFkNzEy -NF9yZWZfbmFtZXNbXSA9IHsNCj4gPiArCVtBRDcxMjRfUkVGSU4xXSA9ICJyZWZpbjEiLA0KPiA+ -ICsJW0FENzEyNF9SRUZJTjJdID0gInJlZmluMiIsDQo+ID4gKwlbQUQ3MTI0X0lOVF9SRUZdID0g -ImludCIsDQo+ID4gKwlbQUQ3MTI0X0FWRERfUkVGXSA9ICJhdmRkIiwNCj4gPiArfTsNCj4gPiAr -DQo+ID4gK3N0cnVjdCBhZDcxMjRfY2hpcF9pbmZvIHsNCj4gPiArCXVuc2lnbmVkIGludCBudW1f -aW5wdXRzOw0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RydWN0IGFkNzEyNF9jaGFubmVsX2NvbmZp -ZyB7DQo+ID4gKwllbnVtIGFkNzEyNF9yZWZfc2VsIHJlZnNlbDsNCj4gPiArCWJvb2wgYmlwb2xh -cjsNCj4gPiArCXVuc2lnbmVkIGludCBhaW47DQo+ID4gKwl1bnNpZ25lZCBpbnQgdnJlZl9tdjsN -Cj4gPiArCXVuc2lnbmVkIGludCBwZ2FfYml0czsNCj4gPiArCXVuc2lnbmVkIGludCBvZHI7DQo+ -ID4gK307DQo+ID4gKw0KPiA+ICtzdHJ1Y3QgYWQ3MTI0X3N0YXRlIHsNCj4gPiArCWNvbnN0IHN0 -cnVjdCBhZDcxMjRfY2hpcF9pbmZvICpjaGlwX2luZm87DQo+ID4gKwlzdHJ1Y3QgYWRfc2lnbWFf -ZGVsdGEgc2Q7DQo+ID4gKwlzdHJ1Y3QgYWQ3MTI0X2NoYW5uZWxfY29uZmlnIGNoYW5uZWxfY29u -ZmlnWzRdOw0KPiA+ICsJc3RydWN0IHJlZ3VsYXRvciAqdnJlZls0XTsNCj4gPiArCXN0cnVjdCBj -bGsgKm1jbGs7DQo+ID4gKwl1bnNpZ25lZCBpbnQgYWRjX2NvbnRyb2w7DQo+ID4gKwl1bnNpZ25l -ZCBpbnQgbnVtX2NoYW5uZWxzOw0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0 -cnVjdCBpaW9fY2hhbl9zcGVjIGFkNzEyNF9jaGFubmVsX3RlbXBsYXRlID0gew0KPiA+ICsJLnR5 -cGUgPSBJSU9fVk9MVEFHRSwNCj4gPiArCS5pbmRleGVkID0gMSwNCj4gPiArCS5kaWZmZXJlbnRp -YWwgPSAxLA0KPiA+ICsJLmluZm9fbWFza19zZXBhcmF0ZSA9IEJJVChJSU9fQ0hBTl9JTkZPX1JB -VykgfA0KPiA+ICsJCUJJVChJSU9fQ0hBTl9JTkZPX1NDQUxFKSB8DQo+ID4gKwkJQklUKElJT19D -SEFOX0lORk9fT0ZGU0VUKSB8DQo+ID4gKwkJQklUKElJT19DSEFOX0lORk9fU0FNUF9GUkVRKSwN -Cj4gPiArCS5zY2FuX3R5cGUgPSB7DQo+ID4gKwkJLnNpZ24gPSAndScsDQo+ID4gKwkJLnJlYWxi -aXRzID0gMjQsDQo+ID4gKwkJLnN0b3JhZ2ViaXRzID0gMzIsDQo+ID4gKwl9LA0KPiA+ICt9Ow0K -PiA+ICsNCj4gPiArc3RhdGljIHN0cnVjdCBhZDcxMjRfY2hpcF9pbmZvIGFkNzEyNF9jaGlwX2lu -Zm9fdGJsW10gPSB7DQo+ID4gKwlbSURfQUQ3MTI0XzRdID0gew0KPiA+ICsJCS5udW1faW5wdXRz -ID0gOCwNCj4gPiArCX0sDQo+ID4gKwlbSURfQUQ3MTI0XzhdID0gew0KPiA+ICsJCS5udW1faW5w -dXRzID0gMTYsDQo+ID4gKwl9LA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGludCBhZDcx -MjRfZmluZF9jbG9zZXN0X21hdGNoKGNvbnN0IGludCAqYXJyYXksDQo+ID4gKwkJCQnCoMKgwqDC -oMKgdW5zaWduZWQgaW50IHNpemUsIGludCB2YWwpDQo+ID4gK3sNCj4gPiArCWludCBpOw0KPiA+ -ICsNCj4gPiArCWZvciAoaSA9IDA7IGkgPCBzaXplOyBpKyspIHsNCj4gPiArCQlpZiAodmFsIDw9 -IGFycmF5W2ldKQ0KPiA+ICsJCQlyZXR1cm4gaTsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlyZXR1 -cm4gc2l6ZSAtIDE7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgYWQ3MTI0X3NwaV93 -cml0ZV9tYXNrKHN0cnVjdCBhZDcxMjRfc3RhdGUgKnN0LA0KPiA+ICsJCQkJwqB1bnNpZ25lZCBp -bnQgYWRkciwNCj4gPiArCQkJCcKgdW5zaWduZWQgbG9uZyBtYXNrLA0KPiA+ICsJCQkJwqB1bnNp -Z25lZCBpbnQgdmFsLA0KPiA+ICsJCQkJwqB1bnNpZ25lZCBpbnQgYnl0ZXMpDQo+ID4gK3sNCj4g -PiArCXVuc2lnbmVkIGludCByZWFkdmFsOw0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ID4gKwly -ZXQgPSBhZF9zZF9yZWFkX3JlZygmc3QtPnNkLCBhZGRyLCBieXRlcywgJnJlYWR2YWwpOw0KPiA+ -ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArDQo+ID4gKwlyZWFkdmFs -ICY9IH5tYXNrOw0KPiA+ICsJcmVhZHZhbCB8PSB2YWw7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIGFk -X3NkX3dyaXRlX3JlZygmc3QtPnNkLCBhZGRyLCBieXRlcywgcmVhZHZhbCk7DQo+ID4gK30NCj4g -PiArDQo+ID4gK3N0YXRpYyBpbnQgYWQ3MTI0X3NldF9tb2RlKHN0cnVjdCBhZF9zaWdtYV9kZWx0 -YSAqc2QsDQo+ID4gKwkJCcKgwqDCoGVudW0gYWRfc2lnbWFfZGVsdGFfbW9kZSBtb2RlKQ0KPiA+ -ICt7DQo+ID4gKwlzdHJ1Y3QgYWQ3MTI0X3N0YXRlICpzdCA9IGNvbnRhaW5lcl9vZihzZCwgc3Ry -dWN0DQo+ID4gYWQ3MTI0X3N0YXRlLCBzZCk7DQo+ID4gKw0KPiA+ICsJc3QtPmFkY19jb250cm9s -ICY9IH5BRDcxMjRfQURDX0NUUkxfTU9ERV9NU0s7DQo+ID4gKwlzdC0+YWRjX2NvbnRyb2wgfD0g -QUQ3MTI0X0FEQ19DVFJMX01PREUobW9kZSk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIGFkX3NkX3dy -aXRlX3JlZygmc3QtPnNkLCBBRDcxMjRfQURDX0NPTlRST0wsIDIsIHN0LQ0KPiA+ID5hZGNfY29u -dHJvbCk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgYWQ3MTI0X3NldF9jaGFubmVs -KHN0cnVjdCBhZF9zaWdtYV9kZWx0YSAqc2QsIHVuc2lnbmVkIGludA0KPiA+IGNoYW5uZWwpDQo+ -ID4gK3sNCj4gPiArCXN0cnVjdCBhZDcxMjRfc3RhdGUgKnN0ID0gY29udGFpbmVyX29mKHNkLCBz -dHJ1Y3QNCj4gPiBhZDcxMjRfc3RhdGUsIHNkKTsNCj4gPiArCXVuc2lnbmVkIGludCB2YWw7DQo+ -ID4gKw0KPiA+ICsJdmFsID0gc3QtPmNoYW5uZWxfY29uZmlnW2NoYW5uZWxdLmFpbiB8IEFENzEy -NF9DSEFOTkVMX0VOKDEpIHwNCj4gPiArCcKgwqDCoMKgwqDCoEFENzEyNF9DSEFOTkVMX1NFVFVQ -KGNoYW5uZWwpOw0KPiA+ICsNCj4gPiArCXJldHVybiBhZF9zZF93cml0ZV9yZWcoJnN0LT5zZCwg -QUQ3MTI0X0NIQU5ORUwoY2hhbm5lbCksIDIsDQo+ID4gdmFsKTsNCj4gPiArfQ0KPiA+ICsNCj4g -PiArc3RhdGljIGNvbnN0IHN0cnVjdCBhZF9zaWdtYV9kZWx0YV9pbmZvIGFkNzEyNF9zaWdtYV9k -ZWx0YV9pbmZvID0gew0KPiA+ICsJLnNldF9jaGFubmVsID0gYWQ3MTI0X3NldF9jaGFubmVsLA0K -PiA+ICsJLnNldF9tb2RlID0gYWQ3MTI0X3NldF9tb2RlLA0KPiA+ICsJLmhhc19yZWdpc3RlcnMg -PSB0cnVlLA0KPiA+ICsJLmFkZHJfc2hpZnQgPSAwLA0KPiA+ICsJLnJlYWRfbWFzayA9IEJJVCg2 -KSwNCj4gPiArCS5kYXRhX3JlZyA9IEFENzEyNF9EQVRBLA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiAr -c3RhdGljIGludCBhZDcxMjRfc2V0X2NoYW5uZWxfb2RyKHN0cnVjdCBhZDcxMjRfc3RhdGUgKnN0 -LA0KPiA+ICsJCQkJwqDCoHVuc2lnbmVkIGludCBjaGFubmVsLA0KPiA+ICsJCQkJwqDCoHVuc2ln -bmVkIGludCBvZHIpDQo+ID4gK3sNCj4gPiArCXVuc2lnbmVkIGludCBmY2xrLCBvZHJfc2VsX2Jp -dHM7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCWZjbGsgPSBjbGtfZ2V0X3JhdGUoc3Qt -Pm1jbGspOw0KPiA+ICsJLyoNCj4gPiArCcKgKiBGU1sxMDowXSA9IGZDTEsgLyAoZkFEQyB4IDMy -KSB3aGVyZToNCj4gPiArCcKgKiBmQURDIGlzIHRoZSBvdXRwdXQgZGF0YSByYXRlDQo+ID4gKwnC -oCogZkNMSyBpcyB0aGUgbWFzdGVyIGNsb2NrIGZyZXF1ZW5jeQ0KPiA+ICsJwqAqIEZTWzEwOjBd -IGFyZSB0aGUgYml0cyBpbiB0aGUgZmlsdGVyIHJlZ2lzdGVyDQo+ID4gKwnCoCogRlNbMTA6MF0g -Y2FuIGhhdmUgYSB2YWx1ZSBmcm9tIDEgdG8gMjA0Nw0KPiA+ICsJwqAqLw0KPiA+ICsJb2RyX3Nl -bF9iaXRzID0gRElWX1JPVU5EX0NMT1NFU1QoZmNsaywgb2RyICogMzIpOw0KPiA+ICsJaWYgKG9k -cl9zZWxfYml0cyA8IDEpDQo+ID4gKwkJb2RyX3NlbF9iaXRzID0gMTsNCj4gPiArCWVsc2UgaWYg -KG9kcl9zZWxfYml0cyA+IDIwNDcpDQo+ID4gKwkJb2RyX3NlbF9iaXRzID0gMjA0NzsNCj4gPiAr -DQo+ID4gKwlyZXQgPSBhZDcxMjRfc3BpX3dyaXRlX21hc2soc3QsIEFENzEyNF9GSUxURVIoY2hh -bm5lbCksDQo+ID4gKwkJCQnCoMKgwqDCoEFENzEyNF9GSUxURVJfRlNfTVNLLA0KPiA+ICsJCQkJ -wqDCoMKgwqBBRDcxMjRfRklMVEVSX0ZTKG9kcl9zZWxfYml0cyksDQo+ID4gMyk7DQo+ID4gKwlp -ZiAocmV0IDwgMCkNCj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsJLyogZkFEQyA9IGZDTEsgLyAo -RlNbMTA6MF0geCAzMikgKi8NCj4gPiArCXN0LT5jaGFubmVsX2NvbmZpZ1tjaGFubmVsXS5vZHIg -PQ0KPiA+ICsJCURJVl9ST1VORF9DTE9TRVNUKGZjbGssIG9kcl9zZWxfYml0cyAqIDMyKTsNCj4g -PiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBhZDcx -MjRfcmVhZF9yYXcoc3RydWN0IGlpb19kZXYgKmluZGlvX2RldiwNCj4gPiArCQkJwqDCoMKgc3Ry -dWN0IGlpb19jaGFuX3NwZWMgY29uc3QgKmNoYW4sDQo+ID4gKwkJCcKgwqDCoGludCAqdmFsLCBp -bnQgKnZhbDIsIGxvbmcgaW5mbykNCj4gPiArew0KPiA+ICsJc3RydWN0IGFkNzEyNF9zdGF0ZSAq -c3QgPSBpaW9fcHJpdihpbmRpb19kZXYpOw0KPiA+ICsJaW50IGlkeCwgcmV0Ow0KPiA+ICsNCj4g -PiArCXN3aXRjaCAoaW5mbykgew0KPiA+ICsJY2FzZSBJSU9fQ0hBTl9JTkZPX1JBVzoNCj4gPiAr -CQlyZXQgPSBhZF9zaWdtYV9kZWx0YV9zaW5nbGVfY29udmVyc2lvbihpbmRpb19kZXYsDQo+ID4g -Y2hhbiwgdmFsKTsNCj4gPiArCQlpZiAocmV0IDwgMCkNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4g -PiArDQo+ID4gKwkJLyogQWZ0ZXIgdGhlIGNvbnZlcnNpb24gaXMgcGVyZm9ybWVkLCBkaXNhYmxl -IHRoZQ0KPiA+IGNoYW5uZWwgKi8NCj4gPiArCQlyZXQgPSBhZF9zZF93cml0ZV9yZWcoJnN0LT5z -ZCwNCj4gPiArCQkJCcKgwqDCoMKgwqDCoEFENzEyNF9DSEFOTkVMKGNoYW4tPmFkZHJlc3MpLA0K -PiA+IDIsDQo+ID4gKwkJCQnCoMKgwqDCoMKgwqBzdC0+Y2hhbm5lbF9jb25maWdbY2hhbi0NCj4g -PiA+YWRkcmVzc10uYWluIHwNCj4gPiArCQkJCcKgwqDCoMKgwqDCoEFENzEyNF9DSEFOTkVMX0VO -KDApKTsNCj4gPiArCQlpZiAocmV0IDwgMCkNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4gPiArDQo+ -ID4gKwkJcmV0dXJuIElJT19WQUxfSU5UOw0KPiA+ICsJY2FzZSBJSU9fQ0hBTl9JTkZPX1NDQUxF -Og0KPiA+ICsJCWlkeCA9IHN0LT5jaGFubmVsX2NvbmZpZ1tjaGFuLT5hZGRyZXNzXS5wZ2FfYml0 -czsNCj4gPiArCQkqdmFsID0gc3QtPmNoYW5uZWxfY29uZmlnW2NoYW4tPmFkZHJlc3NdLnZyZWZf -bXYgLw0KPiA+ICsJCQlhZDcxMjRfZ2FpbltpZHhdOw0KPiA+ICsJCWlmIChzdC0+Y2hhbm5lbF9j -b25maWdbY2hhbi0+YWRkcmVzc10uYmlwb2xhcikNCj4gPiArCQkJKnZhbDIgPSBjaGFuLT5zY2Fu -X3R5cGUucmVhbGJpdHMgLSAxOw0KPiA+ICsJCWVsc2UNCj4gPiArCQkJKnZhbDIgPSBjaGFuLT5z -Y2FuX3R5cGUucmVhbGJpdHM7DQo+ID4gKw0KPiA+ICsJCXJldHVybiBJSU9fVkFMX0ZSQUNUSU9O -QUxfTE9HMjsNCj4gPiArCWNhc2UgSUlPX0NIQU5fSU5GT19PRkZTRVQ6DQo+ID4gKwkJaWYgKHN0 -LT5jaGFubmVsX2NvbmZpZ1tjaGFuLT5hZGRyZXNzXS5iaXBvbGFyKSB7DQo+ID4gKwkJCS8qIENv -ZGUgPSAyXihuIOKIkiAxKSDDlyAoKEFpbiDDlyBHYWluIC8gVnJlZikgKw0KPiA+IDEpICovDQo+ -ID4gKwkJCWlkeCA9IHN0LT5jaGFubmVsX2NvbmZpZ1tjaGFuLQ0KPiA+ID5hZGRyZXNzXS5wZ2Ff -Yml0czsNCj4gPiArCQkJKnZhbCA9IC0oc3QtPmNoYW5uZWxfY29uZmlnW2NoYW4tDQo+ID4gPmFk -ZHJlc3NdLnZyZWZfbXYgLw0KPiA+ICsJCQkJwqBhZDcxMjRfZ2FpbltpZHhdKTsNCj4gPiArCQl9 -IGVsc2Ugew0KPiA+ICsJCQkqdmFsID0gMDsNCj4gPiArCQl9DQo+ID4gKw0KPiA+ICsJCXJldHVy -biBJSU9fVkFMX0lOVDsNCj4gPiArCWNhc2UgSUlPX0NIQU5fSU5GT19TQU1QX0ZSRVE6DQo+ID4g -KwkJKnZhbCA9IHN0LT5jaGFubmVsX2NvbmZpZ1tjaGFuLT5hZGRyZXNzXS5vZHI7DQo+ID4gKw0K -PiA+ICsJCXJldHVybiBJSU9fVkFMX0lOVDsNCj4gPiArCWRlZmF1bHQ6DQo+ID4gKwkJcmV0dXJu -IC1FSU5WQUw7DQo+ID4gKwl9DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgYWQ3MTI0 -X3dyaXRlX3JhdyhzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LA0KPiA+ICsJCQnCoMKgwqDCoHN0 -cnVjdCBpaW9fY2hhbl9zcGVjIGNvbnN0ICpjaGFuLA0KPiA+ICsJCQnCoMKgwqDCoGludCB2YWws -IGludCB2YWwyLCBsb25nIGluZm8pDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBhZDcxMjRfc3RhdGUg -KnN0ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4gPiArDQo+ID4gKwlzd2l0Y2ggKGluZm8pIHsN -Cj4gPiArCWNhc2UgSUlPX0NIQU5fSU5GT19TQU1QX0ZSRVE6DQo+ID4gKwkJaWYgKHZhbDIgIT0g -MCkNCj4gPiArCQkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gKw0KPiA+ICsJCXJldHVybiBhZDcxMjRf -c2V0X2NoYW5uZWxfb2RyKHN0LCBjaGFuLT5hZGRyZXNzLCB2YWwpOw0KPiA+ICsJZGVmYXVsdDoN -Cj4gPiArCQlyZXR1cm4gLUVJTlZBTDsNCj4gPiArCX0NCj4gPiArfQ0KPiA+ICsNCj4gPiArc3Rh -dGljIGNvbnN0IHN0cnVjdCBpaW9faW5mbyBhZDcxMjRfaW5mbyA9IHsNCj4gPiArCS5yZWFkX3Jh -dyA9IGFkNzEyNF9yZWFkX3JhdywNCj4gPiArCS53cml0ZV9yYXcgPSBhZDcxMjRfd3JpdGVfcmF3 -LA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGludCBhZDcxMjRfc29mdF9yZXNldChzdHJ1 -Y3QgYWQ3MTI0X3N0YXRlICpzdCkNCj4gPiArew0KPiA+ICsJdW5zaWduZWQgaW50IHJlYWR2YWws -IHRpbWVvdXQ7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCXJldCA9IGFkX3NkX3Jlc2V0 -KCZzdC0+c2QsIDY0KTsNCj4gPiArCWlmIChyZXQgPCAwKQ0KPiA+ICsJCXJldHVybiByZXQ7DQo+ -ID4gKw0KPiA+ICsJdGltZW91dCA9IDEwMDsNCj4gPiArCWRvIHsNCj4gPiArCQlyZXQgPSBhZF9z -ZF9yZWFkX3JlZygmc3QtPnNkLCBBRDcxMjRfU1RBVFVTLCAxLA0KPiA+ICZyZWFkdmFsKTsNCj4g -PiArCQlpZiAocmV0IDwgMCkNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4gPiArDQo+ID4gKwkJaWYg -KCEocmVhZHZhbCAmIEFENzEyNF9TVEFUVVNfUE9SX0ZMQUdfTVNLKSkNCj4gPiArCQkJcmV0dXJu -IDA7DQo+ID4gKw0KPiA+ICsJCS8qIFRoZSBBRDcxMjQgcmVxdWlyZXMgdHlwaWNhbGx5IDJtcyB0 -byBwb3dlciB1cCBhbmQNCj4gPiBzZXR0bGUgKi8NCj4gPiArCQl1c2xlZXBfcmFuZ2UoMTAwLCAy -MDAwKTsNCj4gPiArCX0gd2hpbGUgKC0tdGltZW91dCk7DQo+ID4gKw0KPiA+ICsJZGV2X2Vycigm -c3QtPnNkLnNwaS0+ZGV2LCAiU29mdCByZXNldCBmYWlsZWRcbiIpOw0KPiA+ICsNCj4gPiArCXJl -dHVybiAtRUlPOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGFkNzEyNF9pbml0X2No -YW5uZWxfdnJlZihzdHJ1Y3QgYWQ3MTI0X3N0YXRlICpzdCwNCj4gPiArCQkJCcKgwqDCoMKgdW5z -aWduZWQgaW50IGNoYW5uZWxfbnVtYmVyKQ0KPiA+ICt7DQo+ID4gKwl1bnNpZ25lZCBpbnQgcmVm -c2VsID0gc3QtDQo+ID4gPmNoYW5uZWxfY29uZmlnW2NoYW5uZWxfbnVtYmVyXS5yZWZzZWw7DQo+ -ID4gKw0KPiA+ICsJc3dpdGNoIChyZWZzZWwpIHsNCj4gPiArCWNhc2UgQUQ3MTI0X1JFRklOMToN -Cj4gPiArCWNhc2UgQUQ3MTI0X1JFRklOMjoNCj4gPiArCWNhc2UgQUQ3MTI0X0FWRERfUkVGOg0K -PiA+ICsJCWlmIChJU19FUlIoc3QtPnZyZWZbcmVmc2VsXSkpIHsNCj4gPiArCQkJZGV2X2Vycigm -c3QtPnNkLnNwaS0+ZGV2LA0KPiA+ICsJCQkJIkVycm9yLCB0cnlpbmcgdG8gdXNlIGV4dGVybmFs -IHZvbHRhZ2UNCj4gPiByZWZlcmVuY2Ugd2l0aG91dCBhICVzIHJlZ3VsYXRvci4iLA0KPiA+ICsJ -CQkJYWQ3MTI0X3JlZl9uYW1lc1tyZWZzZWxdKTsNCj4gPiArCQkJCXJldHVybiBQVFJfRVJSKHN0 -LT52cmVmW3JlZnNlbF0pOw0KPiA+ICsJCX0NCj4gPiArCQlzdC0+Y2hhbm5lbF9jb25maWdbY2hh -bm5lbF9udW1iZXJdLnZyZWZfbXYgPQ0KPiA+ICsJCQlyZWd1bGF0b3JfZ2V0X3ZvbHRhZ2Uoc3Qt -PnZyZWZbcmVmc2VsXSk7DQo+ID4gKwkJLyogQ29udmVyc2lvbiBmcm9tIHVWIHRvIG1WICovDQo+ -ID4gKwkJc3QtPmNoYW5uZWxfY29uZmlnW2NoYW5uZWxfbnVtYmVyXS52cmVmX212IC89IDEwMDA7 -DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwljYXNlIEFENzEyNF9JTlRfUkVGOg0KPiA+ICsJCXN0LT5j -aGFubmVsX2NvbmZpZ1tjaGFubmVsX251bWJlcl0udnJlZl9tdiA9IDI1MDA7DQo+ID4gKwkJYnJl -YWs7DQo+ID4gKwlkZWZhdWx0Og0KPiA+ICsJCWRldl9lcnIoJnN0LT5zZC5zcGktPmRldiwgIklu -dmFsaWQgcmVmZXJlbmNlICVkXG4iLA0KPiA+IHJlZnNlbCk7DQo+ID4gKwkJcmV0dXJuIC1FSU5W -QUw7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4g -K3N0YXRpYyBpbnQgYWQ3MTI0X29mX3BhcnNlX2NoYW5uZWxfY29uZmlnKHN0cnVjdCBpaW9fZGV2 -ICppbmRpb19kZXYsDQo+ID4gKwkJCQkJwqDCoHN0cnVjdCBkZXZpY2Vfbm9kZSAqbnApDQo+ID4g -K3sNCj4gPiArCXN0cnVjdCBhZDcxMjRfc3RhdGUgKnN0ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsN -Cj4gPiArCXN0cnVjdCBkZXZpY2Vfbm9kZSAqY2hpbGQ7DQo+ID4gKwlzdHJ1Y3QgaWlvX2NoYW5f -c3BlYyAqY2hhbjsNCj4gPiArCXVuc2lnbmVkIGludCBhaW5bMl0sIGNoYW5uZWwgPSAwLCB0bXA7 -DQo+ID4gKwlpbnQgcmV0LCByZXM7DQo+ID4gKw0KPiA+ICsJc3QtPm51bV9jaGFubmVscyA9IG9m -X2dldF9hdmFpbGFibGVfY2hpbGRfY291bnQobnApOw0KPiA+ICsJaWYgKCFzdC0+bnVtX2NoYW5u -ZWxzKSB7DQo+ID4gKwkJZGV2X2VycihpbmRpb19kZXYtPmRldi5wYXJlbnQsICJubyBjaGFubmVs -DQo+ID4gY2hpbGRyZW5cbiIpOw0KPiA+ICsJCXJldHVybiAtRU5PREVWOw0KPiA+ICsJfQ0KPiA+ -ICsNCj4gPiArCWNoYW4gPSBkZXZtX2tjYWxsb2MoaW5kaW9fZGV2LT5kZXYucGFyZW50LCBzdC0+ -bnVtX2NoYW5uZWxzLA0KPiA+ICsJCQnCoMKgwqDCoHNpemVvZigqY2hhbiksIEdGUF9LRVJORUwp -Ow0KPiA+ICsJaWYgKCFjaGFuKQ0KPiA+ICsJCXJldHVybiAtRU5PTUVNOw0KPiA+ICsNCj4gPiAr -CWluZGlvX2Rldi0+Y2hhbm5lbHMgPSBjaGFuOw0KPiA+ICsJaW5kaW9fZGV2LT5udW1fY2hhbm5l -bHMgPSBzdC0+bnVtX2NoYW5uZWxzOw0KPiA+ICsNCj4gPiArCWZvcl9lYWNoX2F2YWlsYWJsZV9j -aGlsZF9vZl9ub2RlKG5wLCBjaGlsZCkgew0KPiA+ICsJCXJldCA9IG9mX3Byb3BlcnR5X3JlYWRf -dTMyKGNoaWxkLCAicmVnIiwgJmNoYW5uZWwpOw0KPiA+ICsJCWlmIChyZXQpDQo+ID4gKwkJCWdv -dG8gZXJyOw0KPiA+ICsNCj4gPiArCQlyZXQgPSBvZl9wcm9wZXJ0eV9yZWFkX3UzMl9hcnJheShj -aGlsZCwgImFkaSxkaWZmLQ0KPiA+IGNoYW5uZWxzIiwNCj4gPiArCQkJCQkJwqBhaW4sIDIpOw0K -PiBUaGlzIGFjdHVhbGx5IGZlZWxzIGxpa2Ugc29tZXRoaW5nIHdlIGNvdWxkIHN0YW5kYXJkaXpl -IGFzIHdlbGwgYXMNCj4gYmlwb2xhci4NCj4gSW4gdGhlIG9sZGVzdCBkcml2ZXJzIHdlIGFjdHVh -bGx5IGxldCB1c2Vyc3BhY2UgY29uZmlndXJlIGFsbCBvZiB0aGlzLA0KPiBidXQNCj4gSSBjYW4g -dW5kZXJzdGFuZCB0aGF0IG9ubHkgc29tZSBjb21iaW5hdGlvbnMgbWFrZSBzZW5zZSBvbiBhIGdp -dmVuIGJvYXJkDQo+IHNvIGl0IGFyZ3VhYmx5IG1ha2VzIHNlbnNlIHRvIG9ubHkgZW5hYmxlIHRo -b3NlLCBwYXJ0aWN1bGFybHkgd2hlbiB0aGVyZQ0KPiBpcyBhIHJlZmVyZW5jZSBzZWxlY3QgdGhh -dCBoYXMgdG8gYmUgcGFpcmVkIHdpdGggY2hhbm5lbCBjaG9pY2UuDQo+IA0KPiA+IA0KPiA+ICsJ -CWlmIChyZXQpDQo+ID4gKwkJCWdvdG8gZXJyOw0KPiA+ICsNCj4gPiArCQlpZiAoYWluWzBdID49 -IHN0LT5jaGlwX2luZm8tPm51bV9pbnB1dHMgfHwNCj4gPiArCQnCoMKgwqDCoGFpblsxXSA+PSBz -dC0+Y2hpcF9pbmZvLT5udW1faW5wdXRzKSB7DQo+ID4gKwkJCWRldl9lcnIoaW5kaW9fZGV2LT5k -ZXYucGFyZW50LA0KPiA+ICsJCQkJIklucHV0IHBpbiBudW1iZXIgb3V0IG9mIHJhbmdlLlxuIik7 -DQo+ID4gKwkJCXJldCA9IC1FSU5WQUw7DQo+ID4gKwkJCWdvdG8gZXJyOw0KPiA+ICsJCX0NCj4g -PiArCQlzdC0+Y2hhbm5lbF9jb25maWdbY2hhbm5lbF0uYWluID0NCj4gPiBBRDcxMjRfQ0hBTk5F -TF9BSU5QKGFpblswXSkgfA0KPiA+ICsJCQkJCQnCoMKgQUQ3MTI0X0NIQU5ORUxfQUlOTSgNCj4g -PiBhaW5bMV0pOw0KPiA+ICsJCXN0LT5jaGFubmVsX2NvbmZpZ1tjaGFubmVsXS5iaXBvbGFyID0N -Cj4gPiArCQkJb2ZfcHJvcGVydHlfcmVhZF9ib29sKGNoaWxkLCAiYWRpLGJpcG9sYXIiKTsNCj4g -PiArDQo+ID4gKwkJcmV0ID0gb2ZfcHJvcGVydHlfcmVhZF91MzIoY2hpbGQsICJhZGkscmVmZXJl -bmNlLQ0KPiA+IHNlbGVjdCIsICZ0bXApOw0KPiA+ICsJCWlmIChyZXQpDQo+ID4gKwkJCXN0LT5j -aGFubmVsX2NvbmZpZ1tjaGFubmVsXS5yZWZzZWwgPQ0KPiA+IEFENzEyNF9JTlRfUkVGOw0KPiA+ -ICsJCWVsc2UNCj4gPiArCQkJc3QtPmNoYW5uZWxfY29uZmlnW2NoYW5uZWxdLnJlZnNlbCA9IHRt -cDsNCj4gPiArDQo+ID4gKwkJcmV0ID0gb2ZfcHJvcGVydHlfcmVhZF91MzIoY2hpbGQsICJhZGks -Z2FpbiIsICZ0bXApOw0KPiA+ICsJCWlmIChyZXQpIHsNCj4gPiArCQkJc3QtPmNoYW5uZWxfY29u -ZmlnW2NoYW5uZWxdLnBnYV9iaXRzID0gMDsNCj4gPiArCQl9IGVsc2Ugew0KPiA+ICsJCQlyZXMg -PSBhZDcxMjRfZmluZF9jbG9zZXN0X21hdGNoKGFkNzEyNF9nYWluLA0KPiA+ICsJCQkJCQlBUlJB -WV9TSVpFKGFkNzEyNF9nYWluDQo+ID4gKSwgdG1wKTsNCj4gPiArCQkJc3QtPmNoYW5uZWxfY29u -ZmlnW2NoYW5uZWxdLnBnYV9iaXRzID0gcmVzOw0KPiBIbW0uIFRoZSBvbGQgcXVlc3Rpb24gb2Yg -d2hhdCB0byBwdXQgaW4gRFQgYXMgaXQgcmVmbGVjdHMgd2lyaW5nIGFuZA0KPiB3aGF0IHRvIGxl -YXZlIHRvIHVzZXJzcGFjZS4gR2FpbiBpcyB0cmlja3kgYXMgb25seSBzb21lIHZhbHVlcyBtYWtl -IHNlbnNlDQo+IGZvciBhIGdpdmVuIHN5c3RlbSwgYnV0IHRoZXJlIGNhbiBiZSBtb3JlIHRoYW4g -b25lIHRoYXQgZG9lcy4uLg0KPiBUaGlzIGlzIHByb2JhYmx5IHJlYXNvbmFibGUgYXMgaXQgY2Fu -IGJlIGNvbnNpZGVyZWQgYXMgc2V0dGluZyB0aGUNCj4gZGVmYXVsdA0KPiB0aGF0IG1ha2VzIHNl -bnNlIGZvciB3aGF0IGlzIHdpcmVkLsKgwqBQb3RlbnRpYWxseSB1c2VyIHNwYWNlIGNvdWxkDQo+ -IG92ZXJyaWRlDQo+IGl0IGxhdGVyIGlmIGl0IHdhbnRlZCB0by4NCj4gDQo+ID4gDQo+ID4gKwkJ -fQ0KPiA+ICsNCj4gPiArCQlyZXQgPSBvZl9wcm9wZXJ0eV9yZWFkX3UzMihjaGlsZCwgImFkaSxv -ZHItaHoiLCAmdG1wKTsNCj4gV2h5IGlzIHRoaXMgaW4gRFQuIFRoaXMgb25lIGZlZWxzIGxpa2Ug -YSB1c2Vyc3BhY2UgY2hvaWNlIHRvIG1lLiBJdCdzDQo+IG9ubHkgdGFuZ2VudGlhbGx5IGNvbm5l -Y3RlZCB0byBob3cgdGhpbmdzIGFyZSBjb25uZWN0ZWQgb24gdGhlIGJvYXJkLg0KPiBZb3UgYWxz -byBzdXBwb3J0IGNvbnRyb2wgZnJvbSB1c2Vyc3BhY2UuwqDCoEkgd291bGQgcGljayBhIHNlbnNp -YmxlDQo+IGdlbmVyYWwgZGVmYXVsdCBhbmQgdGhlbiBkcm9wIHRoaXMgZnJvbSB0aGUgRFQgYmlu -ZGluZy4gSXQncyBvcHRpb25hbA0KPiBhbnl3YXkuDQo+IA0KPiA+IA0KPiA+ICsJCWlmIChyZXQp -DQo+ID4gKwkJCS8qDQo+ID4gKwkJCcKgKiA5IFNQUyBpcyB0aGUgbWluaW11bSBvdXRwdXQgZGF0 -YSByYXRlDQo+ID4gc3VwcG9ydGVkDQo+ID4gKwkJCcKgKiByZWdhcmRsZXNzIG9mIHRoZSBzZWxl -Y3RlZCBwb3dlciBtb2RlLg0KPiA+ICsJCQnCoCovDQo+ID4gKwkJCXN0LT5jaGFubmVsX2NvbmZp -Z1tjaGFubmVsXS5vZHIgPSA5Ow0KPiA+ICsJCWVsc2UNCj4gPiArCQkJc3QtPmNoYW5uZWxfY29u -ZmlnW2NoYW5uZWxdLm9kciA9IHRtcDsNCj4gPiArDQo+ID4gKwkJKmNoYW4gPSBhZDcxMjRfY2hh -bm5lbF90ZW1wbGF0ZTsNCj4gPiArCQljaGFuLT5hZGRyZXNzID0gY2hhbm5lbDsNCj4gPiArCQlj -aGFuLT5zY2FuX2luZGV4ID0gY2hhbm5lbDsNCj4gPiArCQljaGFuLT5jaGFubmVsID0gYWluWzBd -Ow0KPiA+ICsJCWNoYW4tPmNoYW5uZWwyID0gYWluWzFdOw0KPiA+ICsNCj4gPiArCQljaGFuKys7 -DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK2VycjoNCj4gPiArCW9mX25v -ZGVfcHV0KGNoaWxkKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gcmV0Ow0KPiA+ICt9DQo+ID4gKw0K -PiA+ICtzdGF0aWMgaW50IGFkNzEyNF9zZXR1cChzdHJ1Y3QgYWQ3MTI0X3N0YXRlICpzdCkNCj4g -PiArew0KPiA+ICsJdW5zaWduZWQgaW50IHZhbCwgZmNsaywgcG93ZXJfbW9kZTsNCj4gPiArCWlu -dCBpLCByZXQ7DQo+ID4gKw0KPiA+ICsJZmNsayA9IGNsa19nZXRfcmF0ZShzdC0+bWNsayk7DQo+ -ID4gKwlpZiAoIWZjbGspDQo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gKw0KPiA+ICsJLyog -VGhlIHBvd2VyIG1vZGUgY2hhbmdlcyB0aGUgbWFzdGVyIGNsb2NrIGZyZXF1ZW5jeSAqLw0KPiA+ -ICsJcG93ZXJfbW9kZSA9DQo+ID4gYWQ3MTI0X2ZpbmRfY2xvc2VzdF9tYXRjaChhZDcxMjRfbWFz -dGVyX2Nsa19mcmVxX2h6LA0KPiA+ICsJCQkJCUFSUkFZX1NJWkUoYWQ3MTI0X21hc3Rlcl9jbGtf -Zg0KPiA+IHJlcV9oeiksDQo+ID4gKwkJCQkJZmNsayk7DQo+ID4gKwlpZiAoZmNsayAhPSBhZDcx -MjRfbWFzdGVyX2Nsa19mcmVxX2h6W3Bvd2VyX21vZGVdKSB7DQo+ID4gKwkJcmV0ID0gY2xrX3Nl -dF9yYXRlKHN0LT5tY2xrLCBmY2xrKTsNCj4gPiArCQlpZiAocmV0KQ0KPiA+ICsJCQlyZXR1cm4g -cmV0Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCS8qIFNldCB0aGUgcG93ZXIgbW9kZSAqLw0KPiA+ -ICsJc3QtPmFkY19jb250cm9sICY9IH5BRDcxMjRfQURDX0NUUkxfUFdSX01TSzsNCj4gPiArCXN0 -LT5hZGNfY29udHJvbCB8PSBBRDcxMjRfQURDX0NUUkxfUFdSKHBvd2VyX21vZGUpOw0KPiA+ICsJ -cmV0ID0gYWRfc2Rfd3JpdGVfcmVnKCZzdC0+c2QsIEFENzEyNF9BRENfQ09OVFJPTCwgMiwgc3Qt -DQo+ID4gPmFkY19jb250cm9sKTsNCj4gPiArCWlmIChyZXQgPCAwKQ0KPiA+ICsJCXJldHVybiBy -ZXQ7DQo+ID4gKw0KPiA+ICsJZm9yIChpID0gMDsgaSA8IHN0LT5udW1fY2hhbm5lbHM7IGkrKykg -ew0KPiA+ICsJCXZhbCA9IHN0LT5jaGFubmVsX2NvbmZpZ1tpXS5haW4gfA0KPiA+IEFENzEyNF9D -SEFOTkVMX1NFVFVQKGkpOw0KPiA+ICsJCXJldCA9IGFkX3NkX3dyaXRlX3JlZygmc3QtPnNkLCBB -RDcxMjRfQ0hBTk5FTChpKSwgMiwNCj4gPiB2YWwpOw0KPiA+ICsJCWlmIChyZXQgPCAwKQ0KPiA+ -ICsJCQlyZXR1cm4gcmV0Ow0KPiA+ICsNCj4gPiArCQlyZXQgPSBhZDcxMjRfaW5pdF9jaGFubmVs -X3ZyZWYoc3QsIGkpOw0KPiA+ICsJCWlmIChyZXQgPCAwKQ0KPiA+ICsJCQlyZXR1cm4gcmV0Ow0K -PiA+ICsNCj4gPiArCQl2YWwgPSBBRDcxMjRfQ09ORklHX0JJUE9MQVIoc3QtDQo+ID4gPmNoYW5u -ZWxfY29uZmlnW2ldLmJpcG9sYXIpIHwNCj4gPiArCQnCoMKgwqDCoMKgwqBBRDcxMjRfQ09ORklH -X1JFRl9TRUwoc3QtDQo+ID4gPmNoYW5uZWxfY29uZmlnW2ldLnJlZnNlbCkgfA0KPiA+ICsJCcKg -wqDCoMKgwqDCoEFENzEyNF9DT05GSUdfUEdBKHN0LQ0KPiA+ID5jaGFubmVsX2NvbmZpZ1tpXS5w -Z2FfYml0cyk7DQo+ID4gKwkJcmV0ID0gYWRfc2Rfd3JpdGVfcmVnKCZzdC0+c2QsIEFENzEyNF9D -T05GSUcoaSksIDIsDQo+ID4gdmFsKTsNCj4gPiArCQlpZiAocmV0IDwgMCkNCj4gPiArCQkJcmV0 -dXJuIHJldDsNCj4gPiArDQo+ID4gKwkJcmV0ID0gYWQ3MTI0X3NldF9jaGFubmVsX29kcihzdCwg -aSwgc3QtDQo+ID4gPmNoYW5uZWxfY29uZmlnW2ldLm9kcik7DQo+ID4gKwkJaWYgKHJldCA8IDAp -DQo+ID4gKwkJCXJldHVybiByZXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIHJldDsN -Cj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBhZDcxMjRfcHJvYmUoc3RydWN0IHNwaV9k -ZXZpY2UgKnNwaSkNCj4gPiArew0KPiA+ICsJY29uc3Qgc3RydWN0IHNwaV9kZXZpY2VfaWQgKmlk -Ow0KPiA+ICsJc3RydWN0IGFkNzEyNF9zdGF0ZSAqc3Q7DQo+ID4gKwlzdHJ1Y3QgaWlvX2RldiAq -aW5kaW9fZGV2Ow0KPiA+ICsJaW50IGksIHJldDsNCj4gPiArDQo+ID4gKwlpbmRpb19kZXYgPSBk -ZXZtX2lpb19kZXZpY2VfYWxsb2MoJnNwaS0+ZGV2LCBzaXplb2YoKnN0KSk7DQo+ID4gKwlpZiAo -IWluZGlvX2RldikNCj4gPiArCQlyZXR1cm4gLUVOT01FTTsNCj4gPiArDQo+ID4gKwlzdCA9IGlp -b19wcml2KGluZGlvX2Rldik7DQo+ID4gKw0KPiA+ICsJaWQgPSBzcGlfZ2V0X2RldmljZV9pZChz -cGkpOw0KPiA+ICsJc3QtPmNoaXBfaW5mbyA9ICZhZDcxMjRfY2hpcF9pbmZvX3RibFtpZC0+ZHJp -dmVyX2RhdGFdOw0KPiA+ICsNCj4gPiArCWFkX3NkX2luaXQoJnN0LT5zZCwgaW5kaW9fZGV2LCBz -cGksICZhZDcxMjRfc2lnbWFfZGVsdGFfaW5mbyk7DQo+ID4gKw0KPiA+ICsJc3BpX3NldF9kcnZk -YXRhKHNwaSwgaW5kaW9fZGV2KTsNCj4gPiArDQo+ID4gKwlpbmRpb19kZXYtPmRldi5wYXJlbnQg -PSAmc3BpLT5kZXY7DQo+ID4gKwlpbmRpb19kZXYtPm5hbWUgPSBzcGlfZ2V0X2RldmljZV9pZChz -cGkpLT5uYW1lOw0KPiA+ICsJaW5kaW9fZGV2LT5tb2RlcyA9IElORElPX0RJUkVDVF9NT0RFOw0K -PiA+ICsJaW5kaW9fZGV2LT5pbmZvID0gJmFkNzEyNF9pbmZvOw0KPiA+ICsNCj4gPiArCXJldCA9 -IGFkNzEyNF9vZl9wYXJzZV9jaGFubmVsX2NvbmZpZyhpbmRpb19kZXYsIHNwaS0NCj4gPiA+ZGV2 -Lm9mX25vZGUpOw0KPiA+ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiAr -DQo+ID4gKwlmb3IgKGkgPSAwOyBpIDwgQVJSQVlfU0laRShzdC0+dnJlZik7IGkrKykgew0KPiA+ -ICsJCWlmIChpICE9IEFENzEyNF9JTlRfUkVGKSB7DQo+ID4gKwkJCXN0LT52cmVmW2ldID0NCj4g -PiBkZXZtX3JlZ3VsYXRvcl9nZXRfb3B0aW9uYWwoJnNwaS0+ZGV2LA0KPiA+ICsJCQkJCQkJYWQ3 -MTI0X3JlZl9uYW0NCj4gPiBlc1tpXSk7DQo+ID4gKwkJCWlmIChQVFJfRVJSKHN0LT52cmVmW2ld -KSA9PSAtRU5PREVWKQ0KPiA+ICsJCQkJY29udGludWU7DQo+ID4gKwkJCWVsc2UgaWYgKElTX0VS -UihzdC0+dnJlZltpXSkpDQo+ID4gKwkJCQlyZXR1cm4gUFRSX0VSUihzdC0+dnJlZltpXSk7DQo+ -ID4gKw0KPiA+ICsJCQlyZXQgPSByZWd1bGF0b3JfZW5hYmxlKHN0LT52cmVmW2ldKTsNCj4gPiAr -CQkJaWYgKHJldCkNCj4gPiArCQkJCXJldHVybiByZXQ7DQo+ID4gKwkJfQ0KPiA+ICsJfQ0KPiA+ -ICsNCj4gPiArCXN0LT5tY2xrID0gZGV2bV9jbGtfZ2V0KCZzcGktPmRldiwgIm1jbGsiKTsNCj4g -PiArCWlmIChJU19FUlIoc3QtPm1jbGspKSB7DQo+ID4gKwkJcmV0ID0gUFRSX0VSUihzdC0+bWNs -ayk7DQo+ID4gKwkJZ290byBlcnJvcl9yZWd1bGF0b3JfZGlzYWJsZTsNCj4gPiArCX0NCj4gPiAr -DQo+ID4gKwlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoc3QtPm1jbGspOw0KPiA+ICsJaWYgKHJl -dCA8IDApDQo+ID4gKwkJZ290byBlcnJvcl9yZWd1bGF0b3JfZGlzYWJsZTsNCj4gPiArDQo+ID4g -KwlyZXQgPSBhZDcxMjRfc29mdF9yZXNldChzdCk7DQo+ID4gKwlpZiAocmV0IDwgMCkNCj4gPiAr -CQlnb3RvIGVycm9yX2Nsa19kaXNhYmxlX3VucHJlcGFyZTsNCj4gPiArDQo+ID4gKwlyZXQgPSBh -ZDcxMjRfc2V0dXAoc3QpOw0KPiA+ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJZ290byBlcnJvcl9j -bGtfZGlzYWJsZV91bnByZXBhcmU7DQo+ID4gKw0KPiA+ICsJcmV0ID0gYWRfc2Rfc2V0dXBfYnVm -ZmVyX2FuZF90cmlnZ2VyKGluZGlvX2Rldik7DQo+ID4gKwlpZiAocmV0IDwgMCkNCj4gPiArCQln -b3RvIGVycm9yX2Nsa19kaXNhYmxlX3VucHJlcGFyZTsNCj4gPiArDQo+ID4gKwlyZXQgPSBpaW9f -ZGV2aWNlX3JlZ2lzdGVyKGluZGlvX2Rldik7DQo+ID4gKwlpZiAocmV0IDwgMCkgew0KPiA+ICsJ -CWRldl9lcnIoJnNwaS0+ZGV2LCAiRmFpbGVkIHRvIHJlZ2lzdGVyIGlpbyBkZXZpY2VcbiIpOw0K -PiA+ICsJCWdvdG8gZXJyb3JfcmVtb3ZlX3RyaWdnZXI7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJ -cmV0dXJuIDA7DQo+ID4gKw0KPiA+ICtlcnJvcl9yZW1vdmVfdHJpZ2dlcjoNCj4gPiArCWFkX3Nk -X2NsZWFudXBfYnVmZmVyX2FuZF90cmlnZ2VyKGluZGlvX2Rldik7DQo+ID4gK2Vycm9yX2Nsa19k -aXNhYmxlX3VucHJlcGFyZToNCj4gPiArCWNsa19kaXNhYmxlX3VucHJlcGFyZShzdC0+bWNsayk7 -DQo+ID4gK2Vycm9yX3JlZ3VsYXRvcl9kaXNhYmxlOg0KPiA+ICsJZm9yIChpID0gQVJSQVlfU0la -RShzdC0+dnJlZikgLSAxOyBpID49IDA7IGktLSkgew0KPiA+ICsJCWlmICghSVNfRVJSX09SX05V -TEwoc3QtPnZyZWZbaV0pKQ0KPiA+ICsJCQlyZWd1bGF0b3JfZGlzYWJsZShzdC0+dnJlZltpXSk7 -DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiAr -c3RhdGljIGludCBhZDcxMjRfcmVtb3ZlKHN0cnVjdCBzcGlfZGV2aWNlICpzcGkpDQo+ID4gK3sN -Cj4gPiArCXN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYgPSBzcGlfZ2V0X2RydmRhdGEoc3BpKTsN -Cj4gPiArCXN0cnVjdCBhZDcxMjRfc3RhdGUgKnN0ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4g -PiArCWludCBpOw0KPiA+ICsNCj4gPiArCWlpb19kZXZpY2VfdW5yZWdpc3RlcihpbmRpb19kZXYp -Ow0KPiA+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKHN0LT5tY2xrKTsNCj4gPiArCWFkX3NkX2Ns -ZWFudXBfYnVmZmVyX2FuZF90cmlnZ2VyKGluZGlvX2Rldik7DQo+IFRoZSBvcmRlcmluZyBoZXJl -IHNob3VsZCBtYXRjaCB0aGF0IGluIHRoZSBlcnJvciBwYXRoIGFib3ZlLg0KPiAoc28gdGhlIHR3 -byB0aGluZ3MgaGVyZSBzaG91bGQgYmUgcmV2ZXJzZWQpLg0KPiBJdCdzIGluIHRoZSBjYXRlZ29y -eSBvZiBtYWtpbmcgdGhpbmdzIG9idmlvdXNseSBzYWZlIHJhdGhlciB0aGFuIGFuDQo+IGFjdHVh -bCBpc3N1ZS4NCj4gSSBsaWtlIHRvIGJlIGFibGUgdG8gY2hlY2sgdGhlIG9yZGVyaW5nIG9ubHkg -b25jZSByYXRoZXIgdGhhbiB0d2ljZQ0KPiB3aGVuIHJldmlld2luZyBzbyB3aWxsIGFsd2F5cyBj -b25maXJtIHRoZXkgbWF0Y2guDQo+IA0KPiA+IA0KPiA+ICsNCj4gPiArCWZvciAoaSA9IEFSUkFZ -X1NJWkUoc3QtPnZyZWYpIC0gMTsgaSA+PSAwOyBpLS0pIHsNCj4gPiArCQlpZiAoIUlTX0VSUl9P -Ul9OVUxMKHN0LT52cmVmW2ldKSkNCj4gPiArCQkJcmVndWxhdG9yX2Rpc2FibGUoc3QtPnZyZWZb -aV0pOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ -ICtzdGF0aWMgY29uc3Qgc3RydWN0IHNwaV9kZXZpY2VfaWQgYWQ3MTI0X2lkX3RhYmxlW10gPSB7 -DQo+ID4gKwl7ICJhZDcxMjQtNCIsIElEX0FENzEyNF80IH0sDQo+ID4gKwl7ICJhZDcxMjQtOCIs -IElEX0FENzEyNF84IH0sDQo+ID4gKwl7fQ0KPiA+ICt9Ow0KPiA+ICtNT0RVTEVfREVWSUNFX1RB -QkxFKHNwaSwgYWQ3MTI0X2lkX3RhYmxlKTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1 -Y3Qgb2ZfZGV2aWNlX2lkIGFkNzEyNF9vZl9tYXRjaFtdID0gew0KPiA+ICsJeyAuY29tcGF0aWJs -ZSA9ICJhZGksYWQ3MTI0LTQiIH0sDQo+ID4gKwl7IC5jb21wYXRpYmxlID0gImFkaSxhZDcxMjQt -OCIgfSwNCj4gPiArCXsgfSwNCj4gPiArfTsNCj4gPiArTU9EVUxFX0RFVklDRV9UQUJMRShvZiwg -YWQ3MTI0X29mX21hdGNoKTsNCj4gPiArDQo+ID4gK3N0YXRpYyBzdHJ1Y3Qgc3BpX2RyaXZlciBh -ZDcxMTI0X2RyaXZlciA9IHsNCj4gPiArCS5kcml2ZXIgPSB7DQo+ID4gKwkJLm5hbWUgPSAiYWQ3 -MTI0IiwNCj4gPiArCQkub2ZfbWF0Y2hfdGFibGUgPSBhZDcxMjRfb2ZfbWF0Y2gsDQo+ID4gKwl9 -LA0KPiA+ICsJLnByb2JlID0gYWQ3MTI0X3Byb2JlLA0KPiA+ICsJLnJlbW92ZQk9IGFkNzEyNF9y -ZW1vdmUsDQo+ID4gKwkuaWRfdGFibGUgPSBhZDcxMjRfaWRfdGFibGUsDQo+ID4gK307DQo+ID4g -K21vZHVsZV9zcGlfZHJpdmVyKGFkNzExMjRfZHJpdmVyKTsNCj4gPiArDQo+ID4gK01PRFVMRV9B -VVRIT1IoIlN0ZWZhbiBQb3BhIDxzdGVmYW4ucG9wYUBhbmFsb2cuY29tPiIpOw0KPiA+ICtNT0RV -TEVfREVTQ1JJUFRJT04oIkFuYWxvZyBEZXZpY2VzIEFENzEyNCBTUEkgZHJpdmVyIik7DQo+ID4g -K01PRFVMRV9MSUNFTlNFKCJHUEwiKTsNCj4g +On Sb, 2018-11-03 at 12:16 +0000, Jonathan Cameron wrote: +> On Mon, 29 Oct 2018 18:38:31 +0200 +> Stefan Popa <stefan.popa@analog.com> wrote: +> +> > +> > The ad7124-4 and ad7124-8 are a family of 4 and 8 channel sigma-delta +> > ADCs +> > with 24-bit precision and reference. +> > +> > Three power modes are available which in turn affect the output data +> > rate: +> > * Full power: 9.38 SPS to 19,200 SPS +> > * Mid power: 2.34 SPS to 4800 SPS +> > * Low power: 1.17 SPS to 2400 SPS +> > +> > The ad7124-4 can be configured to have four differential inputs, while +> > ad7124-8 can have 8. Moreover, ad7124 also supports per channel +> > configuration. Each configuration consists of gain, reference source, +> > output data rate and bipolar/unipolar configuration. +> > +> > Datasheets: +> > Link: http://www.analog.com/media/en/technical-documentation/data-sheet +> > s/AD7124-4.pdf +> > Link: http://www.analog.com/media/en/technical-documentation/data-sheet +> > s/ad7124-8.pdf +> > +> > Signed-off-by: Stefan Popa <stefan.popa@analog.com> +> Hi Stefan, +> +> The discussion around the DT binding has gotten me looking at bit +> more closely at that for this version. +> +> Some most comments in that section. Also a really minor ordering issue +> in +> remove which I'd just have fixed if we weren't going around again for +> the binding. +> +> Main binding thing is I don't think the odr value belongs in DT. +> Gain is more marginal (unless the part can actually be damaged by +> a wrong value - which I hope it can't!). I'm not that fussed +> as there are definitely reasons to specify a default scale to +> cover the reasonable range on a pin. +> +> Thanks, +> +> Jonathan + +Hi Jonathan, + +Thank you for the review! So, how should I proceed? + +First, we need an adc.txt file where "bipolar" and something like "diff- +channels" should be documented. Should the file be placed under +Documentation/devicetree/bindings/iio/adc? + +Regarding the "odr-hz" property, it totally makes sense to remove it from +the DT. How about the "gain"? Should we leave it in the DT and also add the +possibility to be configured from user space? + +Regards, +-Stefan +> > +> > --- +> > Changes in v2: +> > - Added this commit. +> > Changes in v3: +> > - Removed channel, address, scan_index and shift fields from +> > ad7124_channel_template. +> > - Added a sanity check for val2 in ad7124_write_raw(). +> > - Used the "reg" property to get the channel address and "adi,diff- +> > channels" +> > for the differential pins. The "adi,channel-number" property was +> > removed. +> > - When calling regulator_get_optional, the probe is given up in +> > case of error, +> > but continues in case of -ENODEV. +> > - clk_disable_unprepare() is called before +> > ad_sd_cleanup_buffer_and_trigger +> > in ad7124_remove(). +> > +> > MAINTAINERS | 7 + +> > drivers/iio/adc/Kconfig | 11 + +> > drivers/iio/adc/Makefile | 1 + +> > drivers/iio/adc/ad7124.c | 648 +> > +++++++++++++++++++++++++++++++++++++++++++++++ +> > 4 files changed, 667 insertions(+) +> > create mode 100644 drivers/iio/adc/ad7124.c +> > +> > diff --git a/MAINTAINERS b/MAINTAINERS +> > index f642044..3a1bfcb 100644 +> > --- a/MAINTAINERS +> > +++ b/MAINTAINERS +> > @@ -839,6 +839,13 @@ S: Supported +> > F: drivers/iio/dac/ad5758.c +> > F: Documentation/devicetree/bindings/iio/dac/ad5758.txt +> > +> > +ANALOG DEVICES INC AD7124 DRIVER +> > +M: Stefan Popa <stefan.popa@analog.com> +> > +L: linux-iio@vger.kernel.org +> > +W: http://ez.analog.com/community/linux-device-drivers +> > +S: Supported +> > +F: drivers/iio/adc/ad7124.c +> > + +> > ANALOG DEVICES INC AD9389B DRIVER +> > M: Hans Verkuil <hans.verkuil@cisco.com> +> > L: linux-media@vger.kernel.org +> > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig +> > index a52fea8..148a10f 100644 +> > --- a/drivers/iio/adc/Kconfig +> > +++ b/drivers/iio/adc/Kconfig +> > @@ -10,6 +10,17 @@ config AD_SIGMA_DELTA +> > select IIO_BUFFER +> > select IIO_TRIGGERED_BUFFER +> > +> > +config AD7124 +> > + tristate "Analog Devices AD7124 and similar sigma-delta ADCs +> > driver" +> > + depends on SPI_MASTER +> > + select AD_SIGMA_DELTA +> > + help +> > + Say yes here to build support for Analog Devices AD7124-4 +> > and AD7124-8 +> > + SPI analog to digital converters (ADC). +> > + +> > + To compile this driver as a module, choose M here: the +> > module will be +> > + called ad7124. +> > + +> > config AD7266 +> > tristate "Analog Devices AD7265/AD7266 ADC driver" +> > depends on SPI_MASTER +> > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile +> > index a6e6a0b..76168b2 100644 +> > --- a/drivers/iio/adc/Makefile +> > +++ b/drivers/iio/adc/Makefile +> > @@ -5,6 +5,7 @@ +> > +> > # When adding new entries keep the list in alphabetical order +> > obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o +> > +obj-$(CONFIG_AD7124) += ad7124.o +> > obj-$(CONFIG_AD7266) += ad7266.o +> > obj-$(CONFIG_AD7291) += ad7291.o +> > obj-$(CONFIG_AD7298) += ad7298.o +> > diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c +> > new file mode 100644 +> > index 0000000..0660135 +> > --- /dev/null +> > +++ b/drivers/iio/adc/ad7124.c +> > @@ -0,0 +1,648 @@ +> > +// SPDX-License-Identifier: GPL-2.0+ +> > +/* +> > + * AD7124 SPI ADC driver +> > + * +> > + * Copyright 2018 Analog Devices Inc. +> > + */ +> > +#include <linux/bitfield.h> +> > +#include <linux/clk.h> +> > +#include <linux/delay.h> +> > +#include <linux/device.h> +> > +#include <linux/err.h> +> > +#include <linux/kernel.h> +> > +#include <linux/module.h> +> > +#include <linux/regulator/consumer.h> +> > +#include <linux/spi/spi.h> +> > + +> > +#include <linux/iio/iio.h> +> > +#include <linux/iio/adc/ad_sigma_delta.h> +> > +#include <linux/iio/sysfs.h> +> > + +> > +/* AD7124 registers */ +> > +#define AD7124_COMMS 0x00 +> > +#define AD7124_STATUS 0x00 +> > +#define AD7124_ADC_CONTROL 0x01 +> > +#define AD7124_DATA 0x02 +> > +#define AD7124_IO_CONTROL_1 0x03 +> > +#define AD7124_IO_CONTROL_2 0x04 +> > +#define AD7124_ID 0x05 +> > +#define AD7124_ERROR 0x06 +> > +#define AD7124_ERROR_EN 0x07 +> > +#define AD7124_MCLK_COUNT 0x08 +> > +#define AD7124_CHANNEL(x) (0x09 + (x)) +> > +#define AD7124_CONFIG(x) (0x19 + (x)) +> > +#define AD7124_FILTER(x) (0x21 + (x)) +> > +#define AD7124_OFFSET(x) (0x29 + (x)) +> > +#define AD7124_GAIN(x) (0x31 + (x)) +> > + +> > +/* AD7124_STATUS */ +> > +#define AD7124_STATUS_POR_FLAG_MSK BIT(4) +> > + +> > +/* AD7124_ADC_CONTROL */ +> > +#define AD7124_ADC_CTRL_PWR_MSK GENMASK(7, 6) +> > +#define AD7124_ADC_CTRL_PWR(x) FIELD_PREP(AD7124_ADC_CT +> > RL_PWR_MSK, x) +> > +#define AD7124_ADC_CTRL_MODE_MSK GENMASK(5, 2) +> > +#define AD7124_ADC_CTRL_MODE(x) FIELD_PREP(AD7124_ADC_CTRL_MODE +> > _MSK, x) +> > + +> > +/* AD7124_CHANNEL_X */ +> > +#define AD7124_CHANNEL_EN_MSK BIT(15) +> > +#define AD7124_CHANNEL_EN(x) FIELD_PREP(AD7124_CHANNEL_ +> > EN_MSK, x) +> > +#define AD7124_CHANNEL_SETUP_MSK GENMASK(14, 12) +> > +#define AD7124_CHANNEL_SETUP(x) FIELD_PREP(AD7124_CHANNEL_SETUP +> > _MSK, x) +> > +#define AD7124_CHANNEL_AINP_MSK GENMASK(9, 5) +> > +#define AD7124_CHANNEL_AINP(x) FIELD_PREP(AD7124_CHANNE +> > L_AINP_MSK, x) +> > +#define AD7124_CHANNEL_AINM_MSK GENMASK(4, 0) +> > +#define AD7124_CHANNEL_AINM(x) FIELD_PREP(AD7124_CHANNE +> > L_AINM_MSK, x) +> > + +> > +/* AD7124_CONFIG_X */ +> > +#define AD7124_CONFIG_BIPOLAR_MSK BIT(11) +> > +#define AD7124_CONFIG_BIPOLAR(x) FIELD_PREP(AD7124_CONFIG_BIPOL +> > AR_MSK, x) +> > +#define AD7124_CONFIG_REF_SEL_MSK GENMASK(4, 3) +> > +#define AD7124_CONFIG_REF_SEL(x) FIELD_PREP(AD7124_CONFIG_REF_S +> > EL_MSK, x) +> > +#define AD7124_CONFIG_PGA_MSK GENMASK(2, 0) +> > +#define AD7124_CONFIG_PGA(x) FIELD_PREP(AD7124_CONFIG_P +> > GA_MSK, x) +> > + +> > +/* AD7124_FILTER_X */ +> > +#define AD7124_FILTER_FS_MSK GENMASK(10, 0) +> > +#define AD7124_FILTER_FS(x) FIELD_PREP(AD7124_FILTER_FS +> > _MSK, x) +> > + +> > +enum ad7124_ids { +> > + ID_AD7124_4, +> > + ID_AD7124_8, +> > +}; +> > + +> > +enum ad7124_ref_sel { +> > + AD7124_REFIN1, +> > + AD7124_REFIN2, +> > + AD7124_INT_REF, +> > + AD7124_AVDD_REF, +> > +}; +> > + +> > +enum ad7124_power_mode { +> > + AD7124_LOW_POWER, +> > + AD7124_MID_POWER, +> > + AD7124_FULL_POWER, +> > +}; +> > + +> > +static const unsigned int ad7124_gain[8] = { +> > + 1, 2, 4, 8, 16, 32, 64, 128 +> > +}; +> > + +> > +static const int ad7124_master_clk_freq_hz[3] = { +> > + [AD7124_LOW_POWER] = 76800, +> > + [AD7124_MID_POWER] = 153600, +> > + [AD7124_FULL_POWER] = 614400, +> > +}; +> > + +> > +static const char * const ad7124_ref_names[] = { +> > + [AD7124_REFIN1] = "refin1", +> > + [AD7124_REFIN2] = "refin2", +> > + [AD7124_INT_REF] = "int", +> > + [AD7124_AVDD_REF] = "avdd", +> > +}; +> > + +> > +struct ad7124_chip_info { +> > + unsigned int num_inputs; +> > +}; +> > + +> > +struct ad7124_channel_config { +> > + enum ad7124_ref_sel refsel; +> > + bool bipolar; +> > + unsigned int ain; +> > + unsigned int vref_mv; +> > + unsigned int pga_bits; +> > + unsigned int odr; +> > +}; +> > + +> > +struct ad7124_state { +> > + const struct ad7124_chip_info *chip_info; +> > + struct ad_sigma_delta sd; +> > + struct ad7124_channel_config channel_config[4]; +> > + struct regulator *vref[4]; +> > + struct clk *mclk; +> > + unsigned int adc_control; +> > + unsigned int num_channels; +> > +}; +> > + +> > +static const struct iio_chan_spec ad7124_channel_template = { +> > + .type = IIO_VOLTAGE, +> > + .indexed = 1, +> > + .differential = 1, +> > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | +> > + BIT(IIO_CHAN_INFO_SCALE) | +> > + BIT(IIO_CHAN_INFO_OFFSET) | +> > + BIT(IIO_CHAN_INFO_SAMP_FREQ), +> > + .scan_type = { +> > + .sign = 'u', +> > + .realbits = 24, +> > + .storagebits = 32, +> > + }, +> > +}; +> > + +> > +static struct ad7124_chip_info ad7124_chip_info_tbl[] = { +> > + [ID_AD7124_4] = { +> > + .num_inputs = 8, +> > + }, +> > + [ID_AD7124_8] = { +> > + .num_inputs = 16, +> > + }, +> > +}; +> > + +> > +static int ad7124_find_closest_match(const int *array, +> > + unsigned int size, int val) +> > +{ +> > + int i; +> > + +> > + for (i = 0; i < size; i++) { +> > + if (val <= array[i]) +> > + return i; +> > + } +> > + +> > + return size - 1; +> > +} +> > + +> > +static int ad7124_spi_write_mask(struct ad7124_state *st, +> > + unsigned int addr, +> > + unsigned long mask, +> > + unsigned int val, +> > + unsigned int bytes) +> > +{ +> > + unsigned int readval; +> > + int ret; +> > + +> > + ret = ad_sd_read_reg(&st->sd, addr, bytes, &readval); +> > + if (ret < 0) +> > + return ret; +> > + +> > + readval &= ~mask; +> > + readval |= val; +> > + +> > + return ad_sd_write_reg(&st->sd, addr, bytes, readval); +> > +} +> > + +> > +static int ad7124_set_mode(struct ad_sigma_delta *sd, +> > + enum ad_sigma_delta_mode mode) +> > +{ +> > + struct ad7124_state *st = container_of(sd, struct +> > ad7124_state, sd); +> > + +> > + st->adc_control &= ~AD7124_ADC_CTRL_MODE_MSK; +> > + st->adc_control |= AD7124_ADC_CTRL_MODE(mode); +> > + +> > + return ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, st- +> > >adc_control); +> > +} +> > + +> > +static int ad7124_set_channel(struct ad_sigma_delta *sd, unsigned int +> > channel) +> > +{ +> > + struct ad7124_state *st = container_of(sd, struct +> > ad7124_state, sd); +> > + unsigned int val; +> > + +> > + val = st->channel_config[channel].ain | AD7124_CHANNEL_EN(1) | +> > + AD7124_CHANNEL_SETUP(channel); +> > + +> > + return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(channel), 2, +> > val); +> > +} +> > + +> > +static const struct ad_sigma_delta_info ad7124_sigma_delta_info = { +> > + .set_channel = ad7124_set_channel, +> > + .set_mode = ad7124_set_mode, +> > + .has_registers = true, +> > + .addr_shift = 0, +> > + .read_mask = BIT(6), +> > + .data_reg = AD7124_DATA, +> > +}; +> > + +> > +static int ad7124_set_channel_odr(struct ad7124_state *st, +> > + unsigned int channel, +> > + unsigned int odr) +> > +{ +> > + unsigned int fclk, odr_sel_bits; +> > + int ret; +> > + +> > + fclk = clk_get_rate(st->mclk); +> > + /* +> > + * FS[10:0] = fCLK / (fADC x 32) where: +> > + * fADC is the output data rate +> > + * fCLK is the master clock frequency +> > + * FS[10:0] are the bits in the filter register +> > + * FS[10:0] can have a value from 1 to 2047 +> > + */ +> > + odr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * 32); +> > + if (odr_sel_bits < 1) +> > + odr_sel_bits = 1; +> > + else if (odr_sel_bits > 2047) +> > + odr_sel_bits = 2047; +> > + +> > + ret = ad7124_spi_write_mask(st, AD7124_FILTER(channel), +> > + AD7124_FILTER_FS_MSK, +> > + AD7124_FILTER_FS(odr_sel_bits), +> > 3); +> > + if (ret < 0) +> > + return ret; +> > + /* fADC = fCLK / (FS[10:0] x 32) */ +> > + st->channel_config[channel].odr = +> > + DIV_ROUND_CLOSEST(fclk, odr_sel_bits * 32); +> > + +> > + return 0; +> > +} +> > + +> > +static int ad7124_read_raw(struct iio_dev *indio_dev, +> > + struct iio_chan_spec const *chan, +> > + int *val, int *val2, long info) +> > +{ +> > + struct ad7124_state *st = iio_priv(indio_dev); +> > + int idx, ret; +> > + +> > + switch (info) { +> > + case IIO_CHAN_INFO_RAW: +> > + ret = ad_sigma_delta_single_conversion(indio_dev, +> > chan, val); +> > + if (ret < 0) +> > + return ret; +> > + +> > + /* After the conversion is performed, disable the +> > channel */ +> > + ret = ad_sd_write_reg(&st->sd, +> > + AD7124_CHANNEL(chan->address), +> > 2, +> > + st->channel_config[chan- +> > >address].ain | +> > + AD7124_CHANNEL_EN(0)); +> > + if (ret < 0) +> > + return ret; +> > + +> > + return IIO_VAL_INT; +> > + case IIO_CHAN_INFO_SCALE: +> > + idx = st->channel_config[chan->address].pga_bits; +> > + *val = st->channel_config[chan->address].vref_mv / +> > + ad7124_gain[idx]; +> > + if (st->channel_config[chan->address].bipolar) +> > + *val2 = chan->scan_type.realbits - 1; +> > + else +> > + *val2 = chan->scan_type.realbits; +> > + +> > + return IIO_VAL_FRACTIONAL_LOG2; +> > + case IIO_CHAN_INFO_OFFSET: +> > + if (st->channel_config[chan->address].bipolar) { +> > + /* Code = 2^(n − 1) × ((Ain × Gain / Vref) + +> > 1) */ +> > + idx = st->channel_config[chan- +> > >address].pga_bits; +> > + *val = -(st->channel_config[chan- +> > >address].vref_mv / +> > + ad7124_gain[idx]); +> > + } else { +> > + *val = 0; +> > + } +> > + +> > + return IIO_VAL_INT; +> > + case IIO_CHAN_INFO_SAMP_FREQ: +> > + *val = st->channel_config[chan->address].odr; +> > + +> > + return IIO_VAL_INT; +> > + default: +> > + return -EINVAL; +> > + } +> > +} +> > + +> > +static int ad7124_write_raw(struct iio_dev *indio_dev, +> > + struct iio_chan_spec const *chan, +> > + int val, int val2, long info) +> > +{ +> > + struct ad7124_state *st = iio_priv(indio_dev); +> > + +> > + switch (info) { +> > + case IIO_CHAN_INFO_SAMP_FREQ: +> > + if (val2 != 0) +> > + return -EINVAL; +> > + +> > + return ad7124_set_channel_odr(st, chan->address, val); +> > + default: +> > + return -EINVAL; +> > + } +> > +} +> > + +> > +static const struct iio_info ad7124_info = { +> > + .read_raw = ad7124_read_raw, +> > + .write_raw = ad7124_write_raw, +> > +}; +> > + +> > +static int ad7124_soft_reset(struct ad7124_state *st) +> > +{ +> > + unsigned int readval, timeout; +> > + int ret; +> > + +> > + ret = ad_sd_reset(&st->sd, 64); +> > + if (ret < 0) +> > + return ret; +> > + +> > + timeout = 100; +> > + do { +> > + ret = ad_sd_read_reg(&st->sd, AD7124_STATUS, 1, +> > &readval); +> > + if (ret < 0) +> > + return ret; +> > + +> > + if (!(readval & AD7124_STATUS_POR_FLAG_MSK)) +> > + return 0; +> > + +> > + /* The AD7124 requires typically 2ms to power up and +> > settle */ +> > + usleep_range(100, 2000); +> > + } while (--timeout); +> > + +> > + dev_err(&st->sd.spi->dev, "Soft reset failed\n"); +> > + +> > + return -EIO; +> > +} +> > + +> > +static int ad7124_init_channel_vref(struct ad7124_state *st, +> > + unsigned int channel_number) +> > +{ +> > + unsigned int refsel = st- +> > >channel_config[channel_number].refsel; +> > + +> > + switch (refsel) { +> > + case AD7124_REFIN1: +> > + case AD7124_REFIN2: +> > + case AD7124_AVDD_REF: +> > + if (IS_ERR(st->vref[refsel])) { +> > + dev_err(&st->sd.spi->dev, +> > + "Error, trying to use external voltage +> > reference without a %s regulator.", +> > + ad7124_ref_names[refsel]); +> > + return PTR_ERR(st->vref[refsel]); +> > + } +> > + st->channel_config[channel_number].vref_mv = +> > + regulator_get_voltage(st->vref[refsel]); +> > + /* Conversion from uV to mV */ +> > + st->channel_config[channel_number].vref_mv /= 1000; +> > + break; +> > + case AD7124_INT_REF: +> > + st->channel_config[channel_number].vref_mv = 2500; +> > + break; +> > + default: +> > + dev_err(&st->sd.spi->dev, "Invalid reference %d\n", +> > refsel); +> > + return -EINVAL; +> > + } +> > + +> > + return 0; +> > +} +> > + +> > +static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev, +> > + struct device_node *np) +> > +{ +> > + struct ad7124_state *st = iio_priv(indio_dev); +> > + struct device_node *child; +> > + struct iio_chan_spec *chan; +> > + unsigned int ain[2], channel = 0, tmp; +> > + int ret, res; +> > + +> > + st->num_channels = of_get_available_child_count(np); +> > + if (!st->num_channels) { +> > + dev_err(indio_dev->dev.parent, "no channel +> > children\n"); +> > + return -ENODEV; +> > + } +> > + +> > + chan = devm_kcalloc(indio_dev->dev.parent, st->num_channels, +> > + sizeof(*chan), GFP_KERNEL); +> > + if (!chan) +> > + return -ENOMEM; +> > + +> > + indio_dev->channels = chan; +> > + indio_dev->num_channels = st->num_channels; +> > + +> > + for_each_available_child_of_node(np, child) { +> > + ret = of_property_read_u32(child, "reg", &channel); +> > + if (ret) +> > + goto err; +> > + +> > + ret = of_property_read_u32_array(child, "adi,diff- +> > channels", +> > + ain, 2); +> This actually feels like something we could standardize as well as +> bipolar. +> In the oldest drivers we actually let userspace configure all of this, +> but +> I can understand that only some combinations make sense on a given board +> so it arguably makes sense to only enable those, particularly when there +> is a reference select that has to be paired with channel choice. +> +> > +> > + if (ret) +> > + goto err; +> > + +> > + if (ain[0] >= st->chip_info->num_inputs || +> > + ain[1] >= st->chip_info->num_inputs) { +> > + dev_err(indio_dev->dev.parent, +> > + "Input pin number out of range.\n"); +> > + ret = -EINVAL; +> > + goto err; +> > + } +> > + st->channel_config[channel].ain = +> > AD7124_CHANNEL_AINP(ain[0]) | +> > + AD7124_CHANNEL_AINM( +> > ain[1]); +> > + st->channel_config[channel].bipolar = +> > + of_property_read_bool(child, "adi,bipolar"); +> > + +> > + ret = of_property_read_u32(child, "adi,reference- +> > select", &tmp); +> > + if (ret) +> > + st->channel_config[channel].refsel = +> > AD7124_INT_REF; +> > + else +> > + st->channel_config[channel].refsel = tmp; +> > + +> > + ret = of_property_read_u32(child, "adi,gain", &tmp); +> > + if (ret) { +> > + st->channel_config[channel].pga_bits = 0; +> > + } else { +> > + res = ad7124_find_closest_match(ad7124_gain, +> > + ARRAY_SIZE(ad7124_gain +> > ), tmp); +> > + st->channel_config[channel].pga_bits = res; +> Hmm. The old question of what to put in DT as it reflects wiring and +> what to leave to userspace. Gain is tricky as only some values make sense +> for a given system, but there can be more than one that does... +> This is probably reasonable as it can be considered as setting the +> default +> that makes sense for what is wired. Potentially user space could +> override +> it later if it wanted to. +> +> > +> > + } +> > + +> > + ret = of_property_read_u32(child, "adi,odr-hz", &tmp); +> Why is this in DT. This one feels like a userspace choice to me. It's +> only tangentially connected to how things are connected on the board. +> You also support control from userspace. I would pick a sensible +> general default and then drop this from the DT binding. It's optional +> anyway. +> +> > +> > + if (ret) +> > + /* +> > + * 9 SPS is the minimum output data rate +> > supported +> > + * regardless of the selected power mode. +> > + */ +> > + st->channel_config[channel].odr = 9; +> > + else +> > + st->channel_config[channel].odr = tmp; +> > + +> > + *chan = ad7124_channel_template; +> > + chan->address = channel; +> > + chan->scan_index = channel; +> > + chan->channel = ain[0]; +> > + chan->channel2 = ain[1]; +> > + +> > + chan++; +> > + } +> > + +> > + return 0; +> > +err: +> > + of_node_put(child); +> > + +> > + return ret; +> > +} +> > + +> > +static int ad7124_setup(struct ad7124_state *st) +> > +{ +> > + unsigned int val, fclk, power_mode; +> > + int i, ret; +> > + +> > + fclk = clk_get_rate(st->mclk); +> > + if (!fclk) +> > + return -EINVAL; +> > + +> > + /* The power mode changes the master clock frequency */ +> > + power_mode = +> > ad7124_find_closest_match(ad7124_master_clk_freq_hz, +> > + ARRAY_SIZE(ad7124_master_clk_f +> > req_hz), +> > + fclk); +> > + if (fclk != ad7124_master_clk_freq_hz[power_mode]) { +> > + ret = clk_set_rate(st->mclk, fclk); +> > + if (ret) +> > + return ret; +> > + } +> > + +> > + /* Set the power mode */ +> > + st->adc_control &= ~AD7124_ADC_CTRL_PWR_MSK; +> > + st->adc_control |= AD7124_ADC_CTRL_PWR(power_mode); +> > + ret = ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, st- +> > >adc_control); +> > + if (ret < 0) +> > + return ret; +> > + +> > + for (i = 0; i < st->num_channels; i++) { +> > + val = st->channel_config[i].ain | +> > AD7124_CHANNEL_SETUP(i); +> > + ret = ad_sd_write_reg(&st->sd, AD7124_CHANNEL(i), 2, +> > val); +> > + if (ret < 0) +> > + return ret; +> > + +> > + ret = ad7124_init_channel_vref(st, i); +> > + if (ret < 0) +> > + return ret; +> > + +> > + val = AD7124_CONFIG_BIPOLAR(st- +> > >channel_config[i].bipolar) | +> > + AD7124_CONFIG_REF_SEL(st- +> > >channel_config[i].refsel) | +> > + AD7124_CONFIG_PGA(st- +> > >channel_config[i].pga_bits); +> > + ret = ad_sd_write_reg(&st->sd, AD7124_CONFIG(i), 2, +> > val); +> > + if (ret < 0) +> > + return ret; +> > + +> > + ret = ad7124_set_channel_odr(st, i, st- +> > >channel_config[i].odr); +> > + if (ret < 0) +> > + return ret; +> > + } +> > + +> > + return ret; +> > +} +> > + +> > +static int ad7124_probe(struct spi_device *spi) +> > +{ +> > + const struct spi_device_id *id; +> > + struct ad7124_state *st; +> > + struct iio_dev *indio_dev; +> > + int i, ret; +> > + +> > + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); +> > + if (!indio_dev) +> > + return -ENOMEM; +> > + +> > + st = iio_priv(indio_dev); +> > + +> > + id = spi_get_device_id(spi); +> > + st->chip_info = &ad7124_chip_info_tbl[id->driver_data]; +> > + +> > + ad_sd_init(&st->sd, indio_dev, spi, &ad7124_sigma_delta_info); +> > + +> > + spi_set_drvdata(spi, indio_dev); +> > + +> > + indio_dev->dev.parent = &spi->dev; +> > + indio_dev->name = spi_get_device_id(spi)->name; +> > + indio_dev->modes = INDIO_DIRECT_MODE; +> > + indio_dev->info = &ad7124_info; +> > + +> > + ret = ad7124_of_parse_channel_config(indio_dev, spi- +> > >dev.of_node); +> > + if (ret < 0) +> > + return ret; +> > + +> > + for (i = 0; i < ARRAY_SIZE(st->vref); i++) { +> > + if (i != AD7124_INT_REF) { +> > + st->vref[i] = +> > devm_regulator_get_optional(&spi->dev, +> > + ad7124_ref_nam +> > es[i]); +> > + if (PTR_ERR(st->vref[i]) == -ENODEV) +> > + continue; +> > + else if (IS_ERR(st->vref[i])) +> > + return PTR_ERR(st->vref[i]); +> > + +> > + ret = regulator_enable(st->vref[i]); +> > + if (ret) +> > + return ret; +> > + } +> > + } +> > + +> > + st->mclk = devm_clk_get(&spi->dev, "mclk"); +> > + if (IS_ERR(st->mclk)) { +> > + ret = PTR_ERR(st->mclk); +> > + goto error_regulator_disable; +> > + } +> > + +> > + ret = clk_prepare_enable(st->mclk); +> > + if (ret < 0) +> > + goto error_regulator_disable; +> > + +> > + ret = ad7124_soft_reset(st); +> > + if (ret < 0) +> > + goto error_clk_disable_unprepare; +> > + +> > + ret = ad7124_setup(st); +> > + if (ret < 0) +> > + goto error_clk_disable_unprepare; +> > + +> > + ret = ad_sd_setup_buffer_and_trigger(indio_dev); +> > + if (ret < 0) +> > + goto error_clk_disable_unprepare; +> > + +> > + ret = iio_device_register(indio_dev); +> > + if (ret < 0) { +> > + dev_err(&spi->dev, "Failed to register iio device\n"); +> > + goto error_remove_trigger; +> > + } +> > + +> > + return 0; +> > + +> > +error_remove_trigger: +> > + ad_sd_cleanup_buffer_and_trigger(indio_dev); +> > +error_clk_disable_unprepare: +> > + clk_disable_unprepare(st->mclk); +> > +error_regulator_disable: +> > + for (i = ARRAY_SIZE(st->vref) - 1; i >= 0; i--) { +> > + if (!IS_ERR_OR_NULL(st->vref[i])) +> > + regulator_disable(st->vref[i]); +> > + } +> > + +> > + return ret; +> > +} +> > + +> > +static int ad7124_remove(struct spi_device *spi) +> > +{ +> > + struct iio_dev *indio_dev = spi_get_drvdata(spi); +> > + struct ad7124_state *st = iio_priv(indio_dev); +> > + int i; +> > + +> > + iio_device_unregister(indio_dev); +> > + clk_disable_unprepare(st->mclk); +> > + ad_sd_cleanup_buffer_and_trigger(indio_dev); +> The ordering here should match that in the error path above. +> (so the two things here should be reversed). +> It's in the category of making things obviously safe rather than an +> actual issue. +> I like to be able to check the ordering only once rather than twice +> when reviewing so will always confirm they match. +> +> > +> > + +> > + for (i = ARRAY_SIZE(st->vref) - 1; i >= 0; i--) { +> > + if (!IS_ERR_OR_NULL(st->vref[i])) +> > + regulator_disable(st->vref[i]); +> > + } +> > + +> > + return 0; +> > +} +> > + +> > +static const struct spi_device_id ad7124_id_table[] = { +> > + { "ad7124-4", ID_AD7124_4 }, +> > + { "ad7124-8", ID_AD7124_8 }, +> > + {} +> > +}; +> > +MODULE_DEVICE_TABLE(spi, ad7124_id_table); +> > + +> > +static const struct of_device_id ad7124_of_match[] = { +> > + { .compatible = "adi,ad7124-4" }, +> > + { .compatible = "adi,ad7124-8" }, +> > + { }, +> > +}; +> > +MODULE_DEVICE_TABLE(of, ad7124_of_match); +> > + +> > +static struct spi_driver ad71124_driver = { +> > + .driver = { +> > + .name = "ad7124", +> > + .of_match_table = ad7124_of_match, +> > + }, +> > + .probe = ad7124_probe, +> > + .remove = ad7124_remove, +> > + .id_table = ad7124_id_table, +> > +}; +> > +module_spi_driver(ad71124_driver); +> > + +> > +MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>"); +> > +MODULE_DESCRIPTION("Analog Devices AD7124 SPI driver"); +> > +MODULE_LICENSE("GPL"); +> diff --git a/a/content_digest b/N1/content_digest index 3c26bbc..9e5a56d 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -15,482 +15,886 @@ " linux-kernel@vger.kernel.org <linux-kernel@vger.kernel.org>\0" "\00:1\0" "b\0" - "T24gU2IsIDIwMTgtMTEtMDMgYXQgMTI6MTYgKzAwMDAsIEpvbmF0aGFuIENhbWVyb24gd3JvdGU6\n" - "DQo+IE9uIE1vbiwgMjkgT2N0IDIwMTggMTg6Mzg6MzEgKzAyMDANCj4gU3RlZmFuIFBvcGEgPHN0\n" - "ZWZhbi5wb3BhQGFuYWxvZy5jb20+IHdyb3RlOg0KPiANCj4gPiANCj4gPiBUaGUgYWQ3MTI0LTQg\n" - "YW5kIGFkNzEyNC04IGFyZSBhIGZhbWlseSBvZiA0IGFuZCA4IGNoYW5uZWwgc2lnbWEtZGVsdGEN\n" - "Cj4gPiBBRENzDQo+ID4gd2l0aCAyNC1iaXQgcHJlY2lzaW9uIGFuZCByZWZlcmVuY2UuDQo+ID4g\n" - "DQo+ID4gVGhyZWUgcG93ZXIgbW9kZXMgYXJlIGF2YWlsYWJsZSB3aGljaCBpbiB0dXJuIGFmZmVj\n" - "dCB0aGUgb3V0cHV0IGRhdGENCj4gPiByYXRlOg0KPiA+IMKgKiBGdWxsIHBvd2VyOiA5LjM4IFNQ\n" - "UyB0byAxOSwyMDAgU1BTDQo+ID4gwqAqIE1pZCBwb3dlcjogMi4zNCBTUFMgdG8gNDgwMCBTUFMN\n" - "Cj4gPiDCoCogTG93IHBvd2VyOiAxLjE3IFNQUyB0byAyNDAwIFNQUw0KPiA+IA0KPiA+IFRoZSBh\n" - "ZDcxMjQtNCBjYW4gYmUgY29uZmlndXJlZCB0byBoYXZlIGZvdXIgZGlmZmVyZW50aWFsIGlucHV0\n" - "cywgd2hpbGUNCj4gPiBhZDcxMjQtOCBjYW4gaGF2ZSA4LiBNb3Jlb3ZlciwgYWQ3MTI0IGFsc28g\n" - "c3VwcG9ydHMgcGVyIGNoYW5uZWwNCj4gPiBjb25maWd1cmF0aW9uLiBFYWNoIGNvbmZpZ3VyYXRp\n" - "b24gY29uc2lzdHMgb2YgZ2FpbiwgcmVmZXJlbmNlIHNvdXJjZSwNCj4gPiBvdXRwdXQgZGF0YSBy\n" - "YXRlIGFuZCBiaXBvbGFyL3VuaXBvbGFyIGNvbmZpZ3VyYXRpb24uDQo+ID4gDQo+ID4gRGF0YXNo\n" - "ZWV0czoNCj4gPiBMaW5rOiBodHRwOi8vd3d3LmFuYWxvZy5jb20vbWVkaWEvZW4vdGVjaG5pY2Fs\n" - "LWRvY3VtZW50YXRpb24vZGF0YS1zaGVldA0KPiA+IHMvQUQ3MTI0LTQucGRmDQo+ID4gTGluazog\n" - "aHR0cDovL3d3dy5hbmFsb2cuY29tL21lZGlhL2VuL3RlY2huaWNhbC1kb2N1bWVudGF0aW9uL2Rh\n" - "dGEtc2hlZXQNCj4gPiBzL2FkNzEyNC04LnBkZg0KPiA+IA0KPiA+IFNpZ25lZC1vZmYtYnk6IFN0\n" - "ZWZhbiBQb3BhIDxzdGVmYW4ucG9wYUBhbmFsb2cuY29tPg0KPiBIaSBTdGVmYW4sDQo+IA0KPiBU\n" - "aGUgZGlzY3Vzc2lvbiBhcm91bmQgdGhlIERUIGJpbmRpbmcgaGFzIGdvdHRlbiBtZSBsb29raW5n\n" - "IGF0IGJpdA0KPiBtb3JlIGNsb3NlbHkgYXQgdGhhdCBmb3IgdGhpcyB2ZXJzaW9uLg0KPiANCj4g\n" - "U29tZSBtb3N0IGNvbW1lbnRzIGluIHRoYXQgc2VjdGlvbi7CoMKgQWxzbyBhIHJlYWxseSBtaW5v\n" - "ciBvcmRlcmluZyBpc3N1ZQ0KPiBpbg0KPiByZW1vdmUgd2hpY2ggSSdkIGp1c3QgaGF2ZSBmaXhl\n" - "ZCBpZiB3ZSB3ZXJlbid0IGdvaW5nIGFyb3VuZCBhZ2FpbiBmb3INCj4gdGhlIGJpbmRpbmcuDQo+\n" - "IA0KPiBNYWluIGJpbmRpbmcgdGhpbmcgaXMgSSBkb24ndCB0aGluayB0aGUgb2RyIHZhbHVlIGJl\n" - "bG9uZ3MgaW4gRFQuDQo+IEdhaW4gaXMgbW9yZSBtYXJnaW5hbCAodW5sZXNzIHRoZSBwYXJ0IGNh\n" - "biBhY3R1YWxseSBiZSBkYW1hZ2VkIGJ5DQo+IGEgd3JvbmcgdmFsdWUgLSB3aGljaCBJIGhvcGUg\n" - "aXQgY2FuJ3QhKS7CoMKgSSdtIG5vdCB0aGF0IGZ1c3NlZA0KPiBhcyB0aGVyZSBhcmUgZGVmaW5p\n" - "dGVseSByZWFzb25zIHRvIHNwZWNpZnkgYSBkZWZhdWx0IHNjYWxlIHRvDQo+IGNvdmVyIHRoZSBy\n" - "ZWFzb25hYmxlIHJhbmdlIG9uIGEgcGluLg0KPiANCj4gVGhhbmtzLA0KPiANCj4gSm9uYXRoYW4N\n" - "Cg0KSGkgSm9uYXRoYW4sDQoNClRoYW5rIHlvdSBmb3IgdGhlIHJldmlldyEgU28sIGhvdyBzaG91\n" - "bGQgSSBwcm9jZWVkPw0KDQpGaXJzdCwgd2UgbmVlZCBhbiBhZGMudHh0IGZpbGUgd2hlcmUgImJp\n" - "cG9sYXIiIGFuZCBzb21ldGhpbmcgbGlrZSAiZGlmZi0NCmNoYW5uZWxzIiBzaG91bGQgYmUgZG9j\n" - "dW1lbnRlZC4gU2hvdWxkIHRoZSBmaWxlIGJlIHBsYWNlZCB1bmRlcg0KRG9jdW1lbnRhdGlvbi9k\n" - "ZXZpY2V0cmVlL2JpbmRpbmdzL2lpby9hZGM/DQoNClJlZ2FyZGluZyB0aGUgIm9kci1oeiIgcHJv\n" - "cGVydHksIGl0IHRvdGFsbHkgbWFrZXMgc2Vuc2UgdG8gcmVtb3ZlIGl0IGZyb20NCnRoZSBEVC4g\n" - "SG93IGFib3V0IHRoZSAiZ2FpbiI/IFNob3VsZCB3ZSBsZWF2ZSBpdCBpbiB0aGUgRFQgYW5kIGFs\n" - "c28gYWRkIHRoZQ0KcG9zc2liaWxpdHkgdG8gYmUgY29uZmlndXJlZCBmcm9tIHVzZXIgc3BhY2U/\n" - "DQoNClJlZ2FyZHMsDQotU3RlZmFuDQo+ID4gDQo+ID4gLS0tDQo+ID4gQ2hhbmdlcyBpbiB2MjoN\n" - "Cj4gPiAJLSBBZGRlZCB0aGlzIGNvbW1pdC4NCj4gPiBDaGFuZ2VzIGluIHYzOg0KPiA+IAktIFJl\n" - "bW92ZWQgY2hhbm5lbCwgYWRkcmVzcywgc2Nhbl9pbmRleCBhbmQgc2hpZnQgZmllbGRzIGZyb20N\n" - "Cj4gPiAJwqDCoGFkNzEyNF9jaGFubmVsX3RlbXBsYXRlLg0KPiA+IAktIEFkZGVkIGEgc2FuaXR5\n" - "IGNoZWNrIGZvciB2YWwyIGluIGFkNzEyNF93cml0ZV9yYXcoKS4NCj4gPiAJLSBVc2VkIHRoZSAi\n" - "cmVnIiBwcm9wZXJ0eSB0byBnZXQgdGhlIGNoYW5uZWwgYWRkcmVzcyBhbmQgImFkaSxkaWZmLQ0K\n" - "PiA+IGNoYW5uZWxzIg0KPiA+IAnCoMKgZm9yIHRoZSBkaWZmZXJlbnRpYWwgcGlucy4gVGhlICJh\n" - "ZGksY2hhbm5lbC1udW1iZXIiIHByb3BlcnR5IHdhcw0KPiA+IHJlbW92ZWQuDQo+ID4gCS0gV2hl\n" - "biBjYWxsaW5nIHJlZ3VsYXRvcl9nZXRfb3B0aW9uYWwsIHRoZSBwcm9iZSBpcyBnaXZlbiB1cCBp\n" - "bg0KPiA+IGNhc2Ugb2YgZXJyb3IsDQo+ID4gCcKgwqBidXQgY29udGludWVzIGluIGNhc2Ugb2Yg\n" - "LUVOT0RFVi4NCj4gPiAJLSBjbGtfZGlzYWJsZV91bnByZXBhcmUoKSBpcyBjYWxsZWQgYmVmb3Jl\n" - "DQo+ID4gYWRfc2RfY2xlYW51cF9idWZmZXJfYW5kX3RyaWdnZXINCj4gPiAJwqDCoGluIGFkNzEy\n" - "NF9yZW1vdmUoKS4NCj4gPiANCj4gPiDCoE1BSU5UQUlORVJTwqDCoMKgwqDCoMKgwqDCoMKgwqDC\n" - "oMKgwqDCoHzCoMKgwqA3ICsNCj4gPiDCoGRyaXZlcnMvaWlvL2FkYy9LY29uZmlnwqDCoHzCoMKg\n" - "MTEgKw0KPiA+IMKgZHJpdmVycy9paW8vYWRjL01ha2VmaWxlIHzCoMKgwqAxICsNCj4gPiDCoGRy\n" - "aXZlcnMvaWlvL2FkYy9hZDcxMjQuYyB8IDY0OA0KPiA+ICsrKysrKysrKysrKysrKysrKysrKysr\n" - "KysrKysrKysrKysrKysrKysrKysrKysrDQo+ID4gwqA0IGZpbGVzIGNoYW5nZWQsIDY2NyBpbnNl\n" - "cnRpb25zKCspDQo+ID4gwqBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9paW8vYWRjL2FkNzEy\n" - "NC5jDQo+ID4gDQo+ID4gZGlmZiAtLWdpdCBhL01BSU5UQUlORVJTIGIvTUFJTlRBSU5FUlMNCj4g\n" - "PiBpbmRleCBmNjQyMDQ0Li4zYTFiZmNiIDEwMDY0NA0KPiA+IC0tLSBhL01BSU5UQUlORVJTDQo+\n" - "ID4gKysrIGIvTUFJTlRBSU5FUlMNCj4gPiBAQCAtODM5LDYgKzgzOSwxMyBAQCBTOglTdXBwb3J0\n" - "ZWQNCj4gPiDCoEY6CWRyaXZlcnMvaWlvL2RhYy9hZDU3NTguYw0KPiA+IMKgRjoJRG9jdW1lbnRh\n" - "dGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2lpby9kYWMvYWQ1NzU4LnR4dA0KPiA+IMKgDQo+ID4g\n" - "K0FOQUxPRyBERVZJQ0VTIElOQyBBRDcxMjQgRFJJVkVSDQo+ID4gK006CVN0ZWZhbiBQb3BhIDxz\n" - "dGVmYW4ucG9wYUBhbmFsb2cuY29tPg0KPiA+ICtMOglsaW51eC1paW9Admdlci5rZXJuZWwub3Jn\n" - "DQo+ID4gK1c6CWh0dHA6Ly9lei5hbmFsb2cuY29tL2NvbW11bml0eS9saW51eC1kZXZpY2UtZHJp\n" - "dmVycw0KPiA+ICtTOglTdXBwb3J0ZWQNCj4gPiArRjoJZHJpdmVycy9paW8vYWRjL2FkNzEyNC5j\n" - "DQo+ID4gKw0KPiA+IMKgQU5BTE9HIERFVklDRVMgSU5DIEFEOTM4OUIgRFJJVkVSDQo+ID4gwqBN\n" - "OglIYW5zIFZlcmt1aWwgPGhhbnMudmVya3VpbEBjaXNjby5jb20+DQo+ID4gwqBMOglsaW51eC1t\n" - "ZWRpYUB2Z2VyLmtlcm5lbC5vcmcNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9paW8vYWRjL0tj\n" - "b25maWcgYi9kcml2ZXJzL2lpby9hZGMvS2NvbmZpZw0KPiA+IGluZGV4IGE1MmZlYTguLjE0OGEx\n" - "MGYgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9paW8vYWRjL0tjb25maWcNCj4gPiArKysgYi9k\n" - "cml2ZXJzL2lpby9hZGMvS2NvbmZpZw0KPiA+IEBAIC0xMCw2ICsxMCwxNyBAQCBjb25maWcgQURf\n" - "U0lHTUFfREVMVEENCj4gPiDCoAlzZWxlY3QgSUlPX0JVRkZFUg0KPiA+IMKgCXNlbGVjdCBJSU9f\n" - "VFJJR0dFUkVEX0JVRkZFUg0KPiA+IMKgDQo+ID4gK2NvbmZpZyBBRDcxMjQNCj4gPiArCXRyaXN0\n" - "YXRlICJBbmFsb2cgRGV2aWNlcyBBRDcxMjQgYW5kIHNpbWlsYXIgc2lnbWEtZGVsdGEgQURDcw0K\n" - "PiA+IGRyaXZlciINCj4gPiArCWRlcGVuZHMgb24gU1BJX01BU1RFUg0KPiA+ICsJc2VsZWN0IEFE\n" - "X1NJR01BX0RFTFRBDQo+ID4gKwloZWxwDQo+ID4gKwnCoMKgU2F5IHllcyBoZXJlIHRvIGJ1aWxk\n" - "IHN1cHBvcnQgZm9yIEFuYWxvZyBEZXZpY2VzIEFENzEyNC00DQo+ID4gYW5kIEFENzEyNC04DQo+\n" - "ID4gKwnCoMKgU1BJIGFuYWxvZyB0byBkaWdpdGFsIGNvbnZlcnRlcnMgKEFEQykuDQo+ID4gKw0K\n" - "PiA+ICsJwqDCoFRvIGNvbXBpbGUgdGhpcyBkcml2ZXIgYXMgYSBtb2R1bGUsIGNob29zZSBNIGhl\n" - "cmU6IHRoZQ0KPiA+IG1vZHVsZSB3aWxsIGJlDQo+ID4gKwnCoMKgY2FsbGVkIGFkNzEyNC4NCj4g\n" - "PiArDQo+ID4gwqBjb25maWcgQUQ3MjY2DQo+ID4gwqAJdHJpc3RhdGUgIkFuYWxvZyBEZXZpY2Vz\n" - "IEFENzI2NS9BRDcyNjYgQURDIGRyaXZlciINCj4gPiDCoAlkZXBlbmRzIG9uIFNQSV9NQVNURVIN\n" - "Cj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9paW8vYWRjL01ha2VmaWxlIGIvZHJpdmVycy9paW8v\n" - "YWRjL01ha2VmaWxlDQo+ID4gaW5kZXggYTZlNmEwYi4uNzYxNjhiMiAxMDA2NDQNCj4gPiAtLS0g\n" - "YS9kcml2ZXJzL2lpby9hZGMvTWFrZWZpbGUNCj4gPiArKysgYi9kcml2ZXJzL2lpby9hZGMvTWFr\n" - "ZWZpbGUNCj4gPiBAQCAtNSw2ICs1LDcgQEANCj4gPiDCoA0KPiA+IMKgIyBXaGVuIGFkZGluZyBu\n" - "ZXcgZW50cmllcyBrZWVwIHRoZSBsaXN0IGluIGFscGhhYmV0aWNhbCBvcmRlcg0KPiA+IMKgb2Jq\n" - "LSQoQ09ORklHX0FEX1NJR01BX0RFTFRBKSArPSBhZF9zaWdtYV9kZWx0YS5vDQo+ID4gK29iai0k\n" - "KENPTkZJR19BRDcxMjQpICs9IGFkNzEyNC5vDQo+ID4gwqBvYmotJChDT05GSUdfQUQ3MjY2KSAr\n" - "PSBhZDcyNjYubw0KPiA+IMKgb2JqLSQoQ09ORklHX0FENzI5MSkgKz0gYWQ3MjkxLm8NCj4gPiDC\n" - "oG9iai0kKENPTkZJR19BRDcyOTgpICs9IGFkNzI5OC5vDQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZl\n" - "cnMvaWlvL2FkYy9hZDcxMjQuYyBiL2RyaXZlcnMvaWlvL2FkYy9hZDcxMjQuYw0KPiA+IG5ldyBm\n" - "aWxlIG1vZGUgMTAwNjQ0DQo+ID4gaW5kZXggMDAwMDAwMC4uMDY2MDEzNQ0KPiA+IC0tLSAvZGV2\n" - "L251bGwNCj4gPiArKysgYi9kcml2ZXJzL2lpby9hZGMvYWQ3MTI0LmMNCj4gPiBAQCAtMCwwICsx\n" - "LDY0OCBAQA0KPiA+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCsNCj4gPiAr\n" - "LyoNCj4gPiArICogQUQ3MTI0IFNQSSBBREMgZHJpdmVyDQo+ID4gKyAqDQo+ID4gKyAqIENvcHly\n" - "aWdodCAyMDE4IEFuYWxvZyBEZXZpY2VzIEluYy4NCj4gPiArICovDQo+ID4gKyNpbmNsdWRlIDxs\n" - "aW51eC9iaXRmaWVsZC5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvY2xrLmg+DQo+ID4gKyNpbmNs\n" - "dWRlIDxsaW51eC9kZWxheS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+DQo+ID4g\n" - "KyNpbmNsdWRlIDxsaW51eC9lcnIuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPg0K\n" - "PiA+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9yZWd1\n" - "bGF0b3IvY29uc3VtZXIuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3NwaS9zcGkuaD4NCj4gPiAr\n" - "DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9paW8vaWlvLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9p\n" - "aW8vYWRjL2FkX3NpZ21hX2RlbHRhLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9paW8vc3lzZnMu\n" - "aD4NCj4gPiArDQo+ID4gKy8qIEFENzEyNCByZWdpc3RlcnMgKi8NCj4gPiArI2RlZmluZSBBRDcx\n" - "MjRfQ09NTVMJCQkweDAwDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X1NUQVRVUwkJCTB4MDANCj4gPiAr\n" - "I2RlZmluZSBBRDcxMjRfQURDX0NPTlRST0wJCTB4MDENCj4gPiArI2RlZmluZSBBRDcxMjRfREFU\n" - "QQkJCTB4MDINCj4gPiArI2RlZmluZSBBRDcxMjRfSU9fQ09OVFJPTF8xCQkweDAzDQo+ID4gKyNk\n" - "ZWZpbmUgQUQ3MTI0X0lPX0NPTlRST0xfMgkJMHgwNA0KPiA+ICsjZGVmaW5lIEFENzEyNF9JRAkJ\n" - "CTB4MDUNCj4gPiArI2RlZmluZSBBRDcxMjRfRVJST1IJCQkweDA2DQo+ID4gKyNkZWZpbmUgQUQ3\n" - "MTI0X0VSUk9SX0VOCQkweDA3DQo+ID4gKyNkZWZpbmUgQUQ3MTI0X01DTEtfQ09VTlQJCTB4MDgN\n" - "Cj4gPiArI2RlZmluZSBBRDcxMjRfQ0hBTk5FTCh4KQkJKDB4MDkgKyAoeCkpDQo+ID4gKyNkZWZp\n" - "bmUgQUQ3MTI0X0NPTkZJRyh4KQkJKDB4MTkgKyAoeCkpDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0ZJ\n" - "TFRFUih4KQkJKDB4MjEgKyAoeCkpDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X09GRlNFVCh4KQkJKDB4\n" - "MjkgKyAoeCkpDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0dBSU4oeCkJCQkoMHgzMSArICh4KSkNCj4g\n" - "PiArDQo+ID4gKy8qIEFENzEyNF9TVEFUVVMgKi8NCj4gPiArI2RlZmluZSBBRDcxMjRfU1RBVFVT\n" - "X1BPUl9GTEFHX01TSwlCSVQoNCkNCj4gPiArDQo+ID4gKy8qIEFENzEyNF9BRENfQ09OVFJPTCAq\n" - "Lw0KPiA+ICsjZGVmaW5lIEFENzEyNF9BRENfQ1RSTF9QV1JfTVNLCUdFTk1BU0soNywgNikNCj4g\n" - "PiArI2RlZmluZSBBRDcxMjRfQURDX0NUUkxfUFdSKHgpCQlGSUVMRF9QUkVQKEFENzEyNF9BRENf\n" - "Q1QNCj4gPiBSTF9QV1JfTVNLLCB4KQ0KPiA+ICsjZGVmaW5lIEFENzEyNF9BRENfQ1RSTF9NT0RF\n" - "X01TSwlHRU5NQVNLKDUsIDIpDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0FEQ19DVFJMX01PREUoeCkJ\n" - "RklFTERfUFJFUChBRDcxMjRfQURDX0NUUkxfTU9ERQ0KPiA+IF9NU0ssIHgpDQo+ID4gKw0KPiA+\n" - "ICsvKiBBRDcxMjRfQ0hBTk5FTF9YICovDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0NIQU5ORUxfRU5f\n" - "TVNLCQlCSVQoMTUpDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0NIQU5ORUxfRU4oeCkJCUZJRUxEX1BS\n" - "RVAoQUQ3MTI0X0NIQU5ORUxfDQo+ID4gRU5fTVNLLCB4KQ0KPiA+ICsjZGVmaW5lIEFENzEyNF9D\n" - "SEFOTkVMX1NFVFVQX01TSwlHRU5NQVNLKDE0LCAxMikNCj4gPiArI2RlZmluZSBBRDcxMjRfQ0hB\n" - "Tk5FTF9TRVRVUCh4KQlGSUVMRF9QUkVQKEFENzEyNF9DSEFOTkVMX1NFVFVQDQo+ID4gX01TSywg\n" - "eCkNCj4gPiArI2RlZmluZSBBRDcxMjRfQ0hBTk5FTF9BSU5QX01TSwlHRU5NQVNLKDksIDUpDQo+\n" - "ID4gKyNkZWZpbmUgQUQ3MTI0X0NIQU5ORUxfQUlOUCh4KQkJRklFTERfUFJFUChBRDcxMjRfQ0hB\n" - "Tk5FDQo+ID4gTF9BSU5QX01TSywgeCkNCj4gPiArI2RlZmluZSBBRDcxMjRfQ0hBTk5FTF9BSU5N\n" - "X01TSwlHRU5NQVNLKDQsIDApDQo+ID4gKyNkZWZpbmUgQUQ3MTI0X0NIQU5ORUxfQUlOTSh4KQkJ\n" - "RklFTERfUFJFUChBRDcxMjRfQ0hBTk5FDQo+ID4gTF9BSU5NX01TSywgeCkNCj4gPiArDQo+ID4g\n" - "Ky8qIEFENzEyNF9DT05GSUdfWCAqLw0KPiA+ICsjZGVmaW5lIEFENzEyNF9DT05GSUdfQklQT0xB\n" - "Ul9NU0sJQklUKDExKQ0KPiA+ICsjZGVmaW5lIEFENzEyNF9DT05GSUdfQklQT0xBUih4KQlGSUVM\n" - "RF9QUkVQKEFENzEyNF9DT05GSUdfQklQT0wNCj4gPiBBUl9NU0ssIHgpDQo+ID4gKyNkZWZpbmUg\n" - "QUQ3MTI0X0NPTkZJR19SRUZfU0VMX01TSwlHRU5NQVNLKDQsIDMpDQo+ID4gKyNkZWZpbmUgQUQ3\n" - "MTI0X0NPTkZJR19SRUZfU0VMKHgpCUZJRUxEX1BSRVAoQUQ3MTI0X0NPTkZJR19SRUZfUw0KPiA+\n" - "IEVMX01TSywgeCkNCj4gPiArI2RlZmluZSBBRDcxMjRfQ09ORklHX1BHQV9NU0sJCUdFTk1BU0so\n" - "MiwgMCkNCj4gPiArI2RlZmluZSBBRDcxMjRfQ09ORklHX1BHQSh4KQkJRklFTERfUFJFUChBRDcx\n" - "MjRfQ09ORklHX1ANCj4gPiBHQV9NU0ssIHgpDQo+ID4gKw0KPiA+ICsvKiBBRDcxMjRfRklMVEVS\n" - "X1ggKi8NCj4gPiArI2RlZmluZSBBRDcxMjRfRklMVEVSX0ZTX01TSwkJR0VOTUFTSygxMCwgMCkN\n" - "Cj4gPiArI2RlZmluZSBBRDcxMjRfRklMVEVSX0ZTKHgpCQlGSUVMRF9QUkVQKEFENzEyNF9GSUxU\n" - "RVJfRlMNCj4gPiBfTVNLLCB4KQ0KPiA+ICsNCj4gPiArZW51bSBhZDcxMjRfaWRzIHsNCj4gPiAr\n" - "CUlEX0FENzEyNF80LA0KPiA+ICsJSURfQUQ3MTI0XzgsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtl\n" - "bnVtIGFkNzEyNF9yZWZfc2VsIHsNCj4gPiArCUFENzEyNF9SRUZJTjEsDQo+ID4gKwlBRDcxMjRf\n" - "UkVGSU4yLA0KPiA+ICsJQUQ3MTI0X0lOVF9SRUYsDQo+ID4gKwlBRDcxMjRfQVZERF9SRUYsDQo+\n" - "ID4gK307DQo+ID4gKw0KPiA+ICtlbnVtIGFkNzEyNF9wb3dlcl9tb2RlIHsNCj4gPiArCUFENzEy\n" - "NF9MT1dfUE9XRVIsDQo+ID4gKwlBRDcxMjRfTUlEX1BPV0VSLA0KPiA+ICsJQUQ3MTI0X0ZVTExf\n" - "UE9XRVIsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3QgdW5zaWduZWQgaW50IGFk\n" - "NzEyNF9nYWluWzhdID0gew0KPiA+ICsJMSwgMiwgNCwgOCwgMTYsIDMyLCA2NCwgMTI4DQo+ID4g\n" - "K307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3QgaW50IGFkNzEyNF9tYXN0ZXJfY2xrX2ZyZXFf\n" - "aHpbM10gPSB7DQo+ID4gKwlbQUQ3MTI0X0xPV19QT1dFUl0gPSA3NjgwMCwNCj4gPiArCVtBRDcx\n" - "MjRfTUlEX1BPV0VSXSA9IDE1MzYwMCwNCj4gPiArCVtBRDcxMjRfRlVMTF9QT1dFUl0gPSA2MTQ0\n" - "MDAsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3QgY2hhciAqIGNvbnN0IGFkNzEy\n" - "NF9yZWZfbmFtZXNbXSA9IHsNCj4gPiArCVtBRDcxMjRfUkVGSU4xXSA9ICJyZWZpbjEiLA0KPiA+\n" - "ICsJW0FENzEyNF9SRUZJTjJdID0gInJlZmluMiIsDQo+ID4gKwlbQUQ3MTI0X0lOVF9SRUZdID0g\n" - "ImludCIsDQo+ID4gKwlbQUQ3MTI0X0FWRERfUkVGXSA9ICJhdmRkIiwNCj4gPiArfTsNCj4gPiAr\n" - "DQo+ID4gK3N0cnVjdCBhZDcxMjRfY2hpcF9pbmZvIHsNCj4gPiArCXVuc2lnbmVkIGludCBudW1f\n" - "aW5wdXRzOw0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RydWN0IGFkNzEyNF9jaGFubmVsX2NvbmZp\n" - "ZyB7DQo+ID4gKwllbnVtIGFkNzEyNF9yZWZfc2VsIHJlZnNlbDsNCj4gPiArCWJvb2wgYmlwb2xh\n" - "cjsNCj4gPiArCXVuc2lnbmVkIGludCBhaW47DQo+ID4gKwl1bnNpZ25lZCBpbnQgdnJlZl9tdjsN\n" - "Cj4gPiArCXVuc2lnbmVkIGludCBwZ2FfYml0czsNCj4gPiArCXVuc2lnbmVkIGludCBvZHI7DQo+\n" - "ID4gK307DQo+ID4gKw0KPiA+ICtzdHJ1Y3QgYWQ3MTI0X3N0YXRlIHsNCj4gPiArCWNvbnN0IHN0\n" - "cnVjdCBhZDcxMjRfY2hpcF9pbmZvICpjaGlwX2luZm87DQo+ID4gKwlzdHJ1Y3QgYWRfc2lnbWFf\n" - "ZGVsdGEgc2Q7DQo+ID4gKwlzdHJ1Y3QgYWQ3MTI0X2NoYW5uZWxfY29uZmlnIGNoYW5uZWxfY29u\n" - "ZmlnWzRdOw0KPiA+ICsJc3RydWN0IHJlZ3VsYXRvciAqdnJlZls0XTsNCj4gPiArCXN0cnVjdCBj\n" - "bGsgKm1jbGs7DQo+ID4gKwl1bnNpZ25lZCBpbnQgYWRjX2NvbnRyb2w7DQo+ID4gKwl1bnNpZ25l\n" - "ZCBpbnQgbnVtX2NoYW5uZWxzOw0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0\n" - "cnVjdCBpaW9fY2hhbl9zcGVjIGFkNzEyNF9jaGFubmVsX3RlbXBsYXRlID0gew0KPiA+ICsJLnR5\n" - "cGUgPSBJSU9fVk9MVEFHRSwNCj4gPiArCS5pbmRleGVkID0gMSwNCj4gPiArCS5kaWZmZXJlbnRp\n" - "YWwgPSAxLA0KPiA+ICsJLmluZm9fbWFza19zZXBhcmF0ZSA9IEJJVChJSU9fQ0hBTl9JTkZPX1JB\n" - "VykgfA0KPiA+ICsJCUJJVChJSU9fQ0hBTl9JTkZPX1NDQUxFKSB8DQo+ID4gKwkJQklUKElJT19D\n" - "SEFOX0lORk9fT0ZGU0VUKSB8DQo+ID4gKwkJQklUKElJT19DSEFOX0lORk9fU0FNUF9GUkVRKSwN\n" - "Cj4gPiArCS5zY2FuX3R5cGUgPSB7DQo+ID4gKwkJLnNpZ24gPSAndScsDQo+ID4gKwkJLnJlYWxi\n" - "aXRzID0gMjQsDQo+ID4gKwkJLnN0b3JhZ2ViaXRzID0gMzIsDQo+ID4gKwl9LA0KPiA+ICt9Ow0K\n" - "PiA+ICsNCj4gPiArc3RhdGljIHN0cnVjdCBhZDcxMjRfY2hpcF9pbmZvIGFkNzEyNF9jaGlwX2lu\n" - "Zm9fdGJsW10gPSB7DQo+ID4gKwlbSURfQUQ3MTI0XzRdID0gew0KPiA+ICsJCS5udW1faW5wdXRz\n" - "ID0gOCwNCj4gPiArCX0sDQo+ID4gKwlbSURfQUQ3MTI0XzhdID0gew0KPiA+ICsJCS5udW1faW5w\n" - "dXRzID0gMTYsDQo+ID4gKwl9LA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGludCBhZDcx\n" - "MjRfZmluZF9jbG9zZXN0X21hdGNoKGNvbnN0IGludCAqYXJyYXksDQo+ID4gKwkJCQnCoMKgwqDC\n" - "oMKgdW5zaWduZWQgaW50IHNpemUsIGludCB2YWwpDQo+ID4gK3sNCj4gPiArCWludCBpOw0KPiA+\n" - "ICsNCj4gPiArCWZvciAoaSA9IDA7IGkgPCBzaXplOyBpKyspIHsNCj4gPiArCQlpZiAodmFsIDw9\n" - "IGFycmF5W2ldKQ0KPiA+ICsJCQlyZXR1cm4gaTsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlyZXR1\n" - "cm4gc2l6ZSAtIDE7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgYWQ3MTI0X3NwaV93\n" - "cml0ZV9tYXNrKHN0cnVjdCBhZDcxMjRfc3RhdGUgKnN0LA0KPiA+ICsJCQkJwqB1bnNpZ25lZCBp\n" - "bnQgYWRkciwNCj4gPiArCQkJCcKgdW5zaWduZWQgbG9uZyBtYXNrLA0KPiA+ICsJCQkJwqB1bnNp\n" - "Z25lZCBpbnQgdmFsLA0KPiA+ICsJCQkJwqB1bnNpZ25lZCBpbnQgYnl0ZXMpDQo+ID4gK3sNCj4g\n" - "PiArCXVuc2lnbmVkIGludCByZWFkdmFsOw0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ID4gKwly\n" - "ZXQgPSBhZF9zZF9yZWFkX3JlZygmc3QtPnNkLCBhZGRyLCBieXRlcywgJnJlYWR2YWwpOw0KPiA+\n" - "ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArDQo+ID4gKwlyZWFkdmFs\n" - "ICY9IH5tYXNrOw0KPiA+ICsJcmVhZHZhbCB8PSB2YWw7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIGFk\n" - "X3NkX3dyaXRlX3JlZygmc3QtPnNkLCBhZGRyLCBieXRlcywgcmVhZHZhbCk7DQo+ID4gK30NCj4g\n" - "PiArDQo+ID4gK3N0YXRpYyBpbnQgYWQ3MTI0X3NldF9tb2RlKHN0cnVjdCBhZF9zaWdtYV9kZWx0\n" - "YSAqc2QsDQo+ID4gKwkJCcKgwqDCoGVudW0gYWRfc2lnbWFfZGVsdGFfbW9kZSBtb2RlKQ0KPiA+\n" - "ICt7DQo+ID4gKwlzdHJ1Y3QgYWQ3MTI0X3N0YXRlICpzdCA9IGNvbnRhaW5lcl9vZihzZCwgc3Ry\n" - "dWN0DQo+ID4gYWQ3MTI0X3N0YXRlLCBzZCk7DQo+ID4gKw0KPiA+ICsJc3QtPmFkY19jb250cm9s\n" - "ICY9IH5BRDcxMjRfQURDX0NUUkxfTU9ERV9NU0s7DQo+ID4gKwlzdC0+YWRjX2NvbnRyb2wgfD0g\n" - "QUQ3MTI0X0FEQ19DVFJMX01PREUobW9kZSk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIGFkX3NkX3dy\n" - "aXRlX3JlZygmc3QtPnNkLCBBRDcxMjRfQURDX0NPTlRST0wsIDIsIHN0LQ0KPiA+ID5hZGNfY29u\n" - "dHJvbCk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgYWQ3MTI0X3NldF9jaGFubmVs\n" - "KHN0cnVjdCBhZF9zaWdtYV9kZWx0YSAqc2QsIHVuc2lnbmVkIGludA0KPiA+IGNoYW5uZWwpDQo+\n" - "ID4gK3sNCj4gPiArCXN0cnVjdCBhZDcxMjRfc3RhdGUgKnN0ID0gY29udGFpbmVyX29mKHNkLCBz\n" - "dHJ1Y3QNCj4gPiBhZDcxMjRfc3RhdGUsIHNkKTsNCj4gPiArCXVuc2lnbmVkIGludCB2YWw7DQo+\n" - "ID4gKw0KPiA+ICsJdmFsID0gc3QtPmNoYW5uZWxfY29uZmlnW2NoYW5uZWxdLmFpbiB8IEFENzEy\n" - "NF9DSEFOTkVMX0VOKDEpIHwNCj4gPiArCcKgwqDCoMKgwqDCoEFENzEyNF9DSEFOTkVMX1NFVFVQ\n" - "KGNoYW5uZWwpOw0KPiA+ICsNCj4gPiArCXJldHVybiBhZF9zZF93cml0ZV9yZWcoJnN0LT5zZCwg\n" - "QUQ3MTI0X0NIQU5ORUwoY2hhbm5lbCksIDIsDQo+ID4gdmFsKTsNCj4gPiArfQ0KPiA+ICsNCj4g\n" - "PiArc3RhdGljIGNvbnN0IHN0cnVjdCBhZF9zaWdtYV9kZWx0YV9pbmZvIGFkNzEyNF9zaWdtYV9k\n" - "ZWx0YV9pbmZvID0gew0KPiA+ICsJLnNldF9jaGFubmVsID0gYWQ3MTI0X3NldF9jaGFubmVsLA0K\n" - "PiA+ICsJLnNldF9tb2RlID0gYWQ3MTI0X3NldF9tb2RlLA0KPiA+ICsJLmhhc19yZWdpc3RlcnMg\n" - "PSB0cnVlLA0KPiA+ICsJLmFkZHJfc2hpZnQgPSAwLA0KPiA+ICsJLnJlYWRfbWFzayA9IEJJVCg2\n" - "KSwNCj4gPiArCS5kYXRhX3JlZyA9IEFENzEyNF9EQVRBLA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiAr\n" - "c3RhdGljIGludCBhZDcxMjRfc2V0X2NoYW5uZWxfb2RyKHN0cnVjdCBhZDcxMjRfc3RhdGUgKnN0\n" - "LA0KPiA+ICsJCQkJwqDCoHVuc2lnbmVkIGludCBjaGFubmVsLA0KPiA+ICsJCQkJwqDCoHVuc2ln\n" - "bmVkIGludCBvZHIpDQo+ID4gK3sNCj4gPiArCXVuc2lnbmVkIGludCBmY2xrLCBvZHJfc2VsX2Jp\n" - "dHM7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCWZjbGsgPSBjbGtfZ2V0X3JhdGUoc3Qt\n" - "Pm1jbGspOw0KPiA+ICsJLyoNCj4gPiArCcKgKiBGU1sxMDowXSA9IGZDTEsgLyAoZkFEQyB4IDMy\n" - "KSB3aGVyZToNCj4gPiArCcKgKiBmQURDIGlzIHRoZSBvdXRwdXQgZGF0YSByYXRlDQo+ID4gKwnC\n" - "oCogZkNMSyBpcyB0aGUgbWFzdGVyIGNsb2NrIGZyZXF1ZW5jeQ0KPiA+ICsJwqAqIEZTWzEwOjBd\n" - "IGFyZSB0aGUgYml0cyBpbiB0aGUgZmlsdGVyIHJlZ2lzdGVyDQo+ID4gKwnCoCogRlNbMTA6MF0g\n" - "Y2FuIGhhdmUgYSB2YWx1ZSBmcm9tIDEgdG8gMjA0Nw0KPiA+ICsJwqAqLw0KPiA+ICsJb2RyX3Nl\n" - "bF9iaXRzID0gRElWX1JPVU5EX0NMT1NFU1QoZmNsaywgb2RyICogMzIpOw0KPiA+ICsJaWYgKG9k\n" - "cl9zZWxfYml0cyA8IDEpDQo+ID4gKwkJb2RyX3NlbF9iaXRzID0gMTsNCj4gPiArCWVsc2UgaWYg\n" - "KG9kcl9zZWxfYml0cyA+IDIwNDcpDQo+ID4gKwkJb2RyX3NlbF9iaXRzID0gMjA0NzsNCj4gPiAr\n" - "DQo+ID4gKwlyZXQgPSBhZDcxMjRfc3BpX3dyaXRlX21hc2soc3QsIEFENzEyNF9GSUxURVIoY2hh\n" - "bm5lbCksDQo+ID4gKwkJCQnCoMKgwqDCoEFENzEyNF9GSUxURVJfRlNfTVNLLA0KPiA+ICsJCQkJ\n" - "wqDCoMKgwqBBRDcxMjRfRklMVEVSX0ZTKG9kcl9zZWxfYml0cyksDQo+ID4gMyk7DQo+ID4gKwlp\n" - "ZiAocmV0IDwgMCkNCj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsJLyogZkFEQyA9IGZDTEsgLyAo\n" - "RlNbMTA6MF0geCAzMikgKi8NCj4gPiArCXN0LT5jaGFubmVsX2NvbmZpZ1tjaGFubmVsXS5vZHIg\n" - "PQ0KPiA+ICsJCURJVl9ST1VORF9DTE9TRVNUKGZjbGssIG9kcl9zZWxfYml0cyAqIDMyKTsNCj4g\n" - "PiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBhZDcx\n" - "MjRfcmVhZF9yYXcoc3RydWN0IGlpb19kZXYgKmluZGlvX2RldiwNCj4gPiArCQkJwqDCoMKgc3Ry\n" - "dWN0IGlpb19jaGFuX3NwZWMgY29uc3QgKmNoYW4sDQo+ID4gKwkJCcKgwqDCoGludCAqdmFsLCBp\n" - "bnQgKnZhbDIsIGxvbmcgaW5mbykNCj4gPiArew0KPiA+ICsJc3RydWN0IGFkNzEyNF9zdGF0ZSAq\n" - "c3QgPSBpaW9fcHJpdihpbmRpb19kZXYpOw0KPiA+ICsJaW50IGlkeCwgcmV0Ow0KPiA+ICsNCj4g\n" - "PiArCXN3aXRjaCAoaW5mbykgew0KPiA+ICsJY2FzZSBJSU9fQ0hBTl9JTkZPX1JBVzoNCj4gPiAr\n" - "CQlyZXQgPSBhZF9zaWdtYV9kZWx0YV9zaW5nbGVfY29udmVyc2lvbihpbmRpb19kZXYsDQo+ID4g\n" - "Y2hhbiwgdmFsKTsNCj4gPiArCQlpZiAocmV0IDwgMCkNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4g\n" - "PiArDQo+ID4gKwkJLyogQWZ0ZXIgdGhlIGNvbnZlcnNpb24gaXMgcGVyZm9ybWVkLCBkaXNhYmxl\n" - "IHRoZQ0KPiA+IGNoYW5uZWwgKi8NCj4gPiArCQlyZXQgPSBhZF9zZF93cml0ZV9yZWcoJnN0LT5z\n" - "ZCwNCj4gPiArCQkJCcKgwqDCoMKgwqDCoEFENzEyNF9DSEFOTkVMKGNoYW4tPmFkZHJlc3MpLA0K\n" - "PiA+IDIsDQo+ID4gKwkJCQnCoMKgwqDCoMKgwqBzdC0+Y2hhbm5lbF9jb25maWdbY2hhbi0NCj4g\n" - "PiA+YWRkcmVzc10uYWluIHwNCj4gPiArCQkJCcKgwqDCoMKgwqDCoEFENzEyNF9DSEFOTkVMX0VO\n" - "KDApKTsNCj4gPiArCQlpZiAocmV0IDwgMCkNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4gPiArDQo+\n" - "ID4gKwkJcmV0dXJuIElJT19WQUxfSU5UOw0KPiA+ICsJY2FzZSBJSU9fQ0hBTl9JTkZPX1NDQUxF\n" - "Og0KPiA+ICsJCWlkeCA9IHN0LT5jaGFubmVsX2NvbmZpZ1tjaGFuLT5hZGRyZXNzXS5wZ2FfYml0\n" - "czsNCj4gPiArCQkqdmFsID0gc3QtPmNoYW5uZWxfY29uZmlnW2NoYW4tPmFkZHJlc3NdLnZyZWZf\n" - "bXYgLw0KPiA+ICsJCQlhZDcxMjRfZ2FpbltpZHhdOw0KPiA+ICsJCWlmIChzdC0+Y2hhbm5lbF9j\n" - "b25maWdbY2hhbi0+YWRkcmVzc10uYmlwb2xhcikNCj4gPiArCQkJKnZhbDIgPSBjaGFuLT5zY2Fu\n" - "X3R5cGUucmVhbGJpdHMgLSAxOw0KPiA+ICsJCWVsc2UNCj4gPiArCQkJKnZhbDIgPSBjaGFuLT5z\n" - "Y2FuX3R5cGUucmVhbGJpdHM7DQo+ID4gKw0KPiA+ICsJCXJldHVybiBJSU9fVkFMX0ZSQUNUSU9O\n" - "QUxfTE9HMjsNCj4gPiArCWNhc2UgSUlPX0NIQU5fSU5GT19PRkZTRVQ6DQo+ID4gKwkJaWYgKHN0\n" - "LT5jaGFubmVsX2NvbmZpZ1tjaGFuLT5hZGRyZXNzXS5iaXBvbGFyKSB7DQo+ID4gKwkJCS8qIENv\n" - "ZGUgPSAyXihuIOKIkiAxKSDDlyAoKEFpbiDDlyBHYWluIC8gVnJlZikgKw0KPiA+IDEpICovDQo+\n" - "ID4gKwkJCWlkeCA9IHN0LT5jaGFubmVsX2NvbmZpZ1tjaGFuLQ0KPiA+ID5hZGRyZXNzXS5wZ2Ff\n" - "Yml0czsNCj4gPiArCQkJKnZhbCA9IC0oc3QtPmNoYW5uZWxfY29uZmlnW2NoYW4tDQo+ID4gPmFk\n" - "ZHJlc3NdLnZyZWZfbXYgLw0KPiA+ICsJCQkJwqBhZDcxMjRfZ2FpbltpZHhdKTsNCj4gPiArCQl9\n" - "IGVsc2Ugew0KPiA+ICsJCQkqdmFsID0gMDsNCj4gPiArCQl9DQo+ID4gKw0KPiA+ICsJCXJldHVy\n" - "biBJSU9fVkFMX0lOVDsNCj4gPiArCWNhc2UgSUlPX0NIQU5fSU5GT19TQU1QX0ZSRVE6DQo+ID4g\n" - "KwkJKnZhbCA9IHN0LT5jaGFubmVsX2NvbmZpZ1tjaGFuLT5hZGRyZXNzXS5vZHI7DQo+ID4gKw0K\n" - "PiA+ICsJCXJldHVybiBJSU9fVkFMX0lOVDsNCj4gPiArCWRlZmF1bHQ6DQo+ID4gKwkJcmV0dXJu\n" - "IC1FSU5WQUw7DQo+ID4gKwl9DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgYWQ3MTI0\n" - "X3dyaXRlX3JhdyhzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LA0KPiA+ICsJCQnCoMKgwqDCoHN0\n" - "cnVjdCBpaW9fY2hhbl9zcGVjIGNvbnN0ICpjaGFuLA0KPiA+ICsJCQnCoMKgwqDCoGludCB2YWws\n" - "IGludCB2YWwyLCBsb25nIGluZm8pDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBhZDcxMjRfc3RhdGUg\n" - "KnN0ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4gPiArDQo+ID4gKwlzd2l0Y2ggKGluZm8pIHsN\n" - "Cj4gPiArCWNhc2UgSUlPX0NIQU5fSU5GT19TQU1QX0ZSRVE6DQo+ID4gKwkJaWYgKHZhbDIgIT0g\n" - "MCkNCj4gPiArCQkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gKw0KPiA+ICsJCXJldHVybiBhZDcxMjRf\n" - "c2V0X2NoYW5uZWxfb2RyKHN0LCBjaGFuLT5hZGRyZXNzLCB2YWwpOw0KPiA+ICsJZGVmYXVsdDoN\n" - "Cj4gPiArCQlyZXR1cm4gLUVJTlZBTDsNCj4gPiArCX0NCj4gPiArfQ0KPiA+ICsNCj4gPiArc3Rh\n" - "dGljIGNvbnN0IHN0cnVjdCBpaW9faW5mbyBhZDcxMjRfaW5mbyA9IHsNCj4gPiArCS5yZWFkX3Jh\n" - "dyA9IGFkNzEyNF9yZWFkX3JhdywNCj4gPiArCS53cml0ZV9yYXcgPSBhZDcxMjRfd3JpdGVfcmF3\n" - "LA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGludCBhZDcxMjRfc29mdF9yZXNldChzdHJ1\n" - "Y3QgYWQ3MTI0X3N0YXRlICpzdCkNCj4gPiArew0KPiA+ICsJdW5zaWduZWQgaW50IHJlYWR2YWws\n" - "IHRpbWVvdXQ7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCXJldCA9IGFkX3NkX3Jlc2V0\n" - "KCZzdC0+c2QsIDY0KTsNCj4gPiArCWlmIChyZXQgPCAwKQ0KPiA+ICsJCXJldHVybiByZXQ7DQo+\n" - "ID4gKw0KPiA+ICsJdGltZW91dCA9IDEwMDsNCj4gPiArCWRvIHsNCj4gPiArCQlyZXQgPSBhZF9z\n" - "ZF9yZWFkX3JlZygmc3QtPnNkLCBBRDcxMjRfU1RBVFVTLCAxLA0KPiA+ICZyZWFkdmFsKTsNCj4g\n" - "PiArCQlpZiAocmV0IDwgMCkNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4gPiArDQo+ID4gKwkJaWYg\n" - "KCEocmVhZHZhbCAmIEFENzEyNF9TVEFUVVNfUE9SX0ZMQUdfTVNLKSkNCj4gPiArCQkJcmV0dXJu\n" - "IDA7DQo+ID4gKw0KPiA+ICsJCS8qIFRoZSBBRDcxMjQgcmVxdWlyZXMgdHlwaWNhbGx5IDJtcyB0\n" - "byBwb3dlciB1cCBhbmQNCj4gPiBzZXR0bGUgKi8NCj4gPiArCQl1c2xlZXBfcmFuZ2UoMTAwLCAy\n" - "MDAwKTsNCj4gPiArCX0gd2hpbGUgKC0tdGltZW91dCk7DQo+ID4gKw0KPiA+ICsJZGV2X2Vycigm\n" - "c3QtPnNkLnNwaS0+ZGV2LCAiU29mdCByZXNldCBmYWlsZWRcbiIpOw0KPiA+ICsNCj4gPiArCXJl\n" - "dHVybiAtRUlPOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGFkNzEyNF9pbml0X2No\n" - "YW5uZWxfdnJlZihzdHJ1Y3QgYWQ3MTI0X3N0YXRlICpzdCwNCj4gPiArCQkJCcKgwqDCoMKgdW5z\n" - "aWduZWQgaW50IGNoYW5uZWxfbnVtYmVyKQ0KPiA+ICt7DQo+ID4gKwl1bnNpZ25lZCBpbnQgcmVm\n" - "c2VsID0gc3QtDQo+ID4gPmNoYW5uZWxfY29uZmlnW2NoYW5uZWxfbnVtYmVyXS5yZWZzZWw7DQo+\n" - "ID4gKw0KPiA+ICsJc3dpdGNoIChyZWZzZWwpIHsNCj4gPiArCWNhc2UgQUQ3MTI0X1JFRklOMToN\n" - "Cj4gPiArCWNhc2UgQUQ3MTI0X1JFRklOMjoNCj4gPiArCWNhc2UgQUQ3MTI0X0FWRERfUkVGOg0K\n" - "PiA+ICsJCWlmIChJU19FUlIoc3QtPnZyZWZbcmVmc2VsXSkpIHsNCj4gPiArCQkJZGV2X2Vycigm\n" - "c3QtPnNkLnNwaS0+ZGV2LA0KPiA+ICsJCQkJIkVycm9yLCB0cnlpbmcgdG8gdXNlIGV4dGVybmFs\n" - "IHZvbHRhZ2UNCj4gPiByZWZlcmVuY2Ugd2l0aG91dCBhICVzIHJlZ3VsYXRvci4iLA0KPiA+ICsJ\n" - "CQkJYWQ3MTI0X3JlZl9uYW1lc1tyZWZzZWxdKTsNCj4gPiArCQkJCXJldHVybiBQVFJfRVJSKHN0\n" - "LT52cmVmW3JlZnNlbF0pOw0KPiA+ICsJCX0NCj4gPiArCQlzdC0+Y2hhbm5lbF9jb25maWdbY2hh\n" - "bm5lbF9udW1iZXJdLnZyZWZfbXYgPQ0KPiA+ICsJCQlyZWd1bGF0b3JfZ2V0X3ZvbHRhZ2Uoc3Qt\n" - "PnZyZWZbcmVmc2VsXSk7DQo+ID4gKwkJLyogQ29udmVyc2lvbiBmcm9tIHVWIHRvIG1WICovDQo+\n" - "ID4gKwkJc3QtPmNoYW5uZWxfY29uZmlnW2NoYW5uZWxfbnVtYmVyXS52cmVmX212IC89IDEwMDA7\n" - "DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwljYXNlIEFENzEyNF9JTlRfUkVGOg0KPiA+ICsJCXN0LT5j\n" - "aGFubmVsX2NvbmZpZ1tjaGFubmVsX251bWJlcl0udnJlZl9tdiA9IDI1MDA7DQo+ID4gKwkJYnJl\n" - "YWs7DQo+ID4gKwlkZWZhdWx0Og0KPiA+ICsJCWRldl9lcnIoJnN0LT5zZC5zcGktPmRldiwgIklu\n" - "dmFsaWQgcmVmZXJlbmNlICVkXG4iLA0KPiA+IHJlZnNlbCk7DQo+ID4gKwkJcmV0dXJuIC1FSU5W\n" - "QUw7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4g\n" - "K3N0YXRpYyBpbnQgYWQ3MTI0X29mX3BhcnNlX2NoYW5uZWxfY29uZmlnKHN0cnVjdCBpaW9fZGV2\n" - "ICppbmRpb19kZXYsDQo+ID4gKwkJCQkJwqDCoHN0cnVjdCBkZXZpY2Vfbm9kZSAqbnApDQo+ID4g\n" - "K3sNCj4gPiArCXN0cnVjdCBhZDcxMjRfc3RhdGUgKnN0ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsN\n" - "Cj4gPiArCXN0cnVjdCBkZXZpY2Vfbm9kZSAqY2hpbGQ7DQo+ID4gKwlzdHJ1Y3QgaWlvX2NoYW5f\n" - "c3BlYyAqY2hhbjsNCj4gPiArCXVuc2lnbmVkIGludCBhaW5bMl0sIGNoYW5uZWwgPSAwLCB0bXA7\n" - "DQo+ID4gKwlpbnQgcmV0LCByZXM7DQo+ID4gKw0KPiA+ICsJc3QtPm51bV9jaGFubmVscyA9IG9m\n" - "X2dldF9hdmFpbGFibGVfY2hpbGRfY291bnQobnApOw0KPiA+ICsJaWYgKCFzdC0+bnVtX2NoYW5u\n" - "ZWxzKSB7DQo+ID4gKwkJZGV2X2VycihpbmRpb19kZXYtPmRldi5wYXJlbnQsICJubyBjaGFubmVs\n" - "DQo+ID4gY2hpbGRyZW5cbiIpOw0KPiA+ICsJCXJldHVybiAtRU5PREVWOw0KPiA+ICsJfQ0KPiA+\n" - "ICsNCj4gPiArCWNoYW4gPSBkZXZtX2tjYWxsb2MoaW5kaW9fZGV2LT5kZXYucGFyZW50LCBzdC0+\n" - "bnVtX2NoYW5uZWxzLA0KPiA+ICsJCQnCoMKgwqDCoHNpemVvZigqY2hhbiksIEdGUF9LRVJORUwp\n" - "Ow0KPiA+ICsJaWYgKCFjaGFuKQ0KPiA+ICsJCXJldHVybiAtRU5PTUVNOw0KPiA+ICsNCj4gPiAr\n" - "CWluZGlvX2Rldi0+Y2hhbm5lbHMgPSBjaGFuOw0KPiA+ICsJaW5kaW9fZGV2LT5udW1fY2hhbm5l\n" - "bHMgPSBzdC0+bnVtX2NoYW5uZWxzOw0KPiA+ICsNCj4gPiArCWZvcl9lYWNoX2F2YWlsYWJsZV9j\n" - "aGlsZF9vZl9ub2RlKG5wLCBjaGlsZCkgew0KPiA+ICsJCXJldCA9IG9mX3Byb3BlcnR5X3JlYWRf\n" - "dTMyKGNoaWxkLCAicmVnIiwgJmNoYW5uZWwpOw0KPiA+ICsJCWlmIChyZXQpDQo+ID4gKwkJCWdv\n" - "dG8gZXJyOw0KPiA+ICsNCj4gPiArCQlyZXQgPSBvZl9wcm9wZXJ0eV9yZWFkX3UzMl9hcnJheShj\n" - "aGlsZCwgImFkaSxkaWZmLQ0KPiA+IGNoYW5uZWxzIiwNCj4gPiArCQkJCQkJwqBhaW4sIDIpOw0K\n" - "PiBUaGlzIGFjdHVhbGx5IGZlZWxzIGxpa2Ugc29tZXRoaW5nIHdlIGNvdWxkIHN0YW5kYXJkaXpl\n" - "IGFzIHdlbGwgYXMNCj4gYmlwb2xhci4NCj4gSW4gdGhlIG9sZGVzdCBkcml2ZXJzIHdlIGFjdHVh\n" - "bGx5IGxldCB1c2Vyc3BhY2UgY29uZmlndXJlIGFsbCBvZiB0aGlzLA0KPiBidXQNCj4gSSBjYW4g\n" - "dW5kZXJzdGFuZCB0aGF0IG9ubHkgc29tZSBjb21iaW5hdGlvbnMgbWFrZSBzZW5zZSBvbiBhIGdp\n" - "dmVuIGJvYXJkDQo+IHNvIGl0IGFyZ3VhYmx5IG1ha2VzIHNlbnNlIHRvIG9ubHkgZW5hYmxlIHRo\n" - "b3NlLCBwYXJ0aWN1bGFybHkgd2hlbiB0aGVyZQ0KPiBpcyBhIHJlZmVyZW5jZSBzZWxlY3QgdGhh\n" - "dCBoYXMgdG8gYmUgcGFpcmVkIHdpdGggY2hhbm5lbCBjaG9pY2UuDQo+IA0KPiA+IA0KPiA+ICsJ\n" - "CWlmIChyZXQpDQo+ID4gKwkJCWdvdG8gZXJyOw0KPiA+ICsNCj4gPiArCQlpZiAoYWluWzBdID49\n" - "IHN0LT5jaGlwX2luZm8tPm51bV9pbnB1dHMgfHwNCj4gPiArCQnCoMKgwqDCoGFpblsxXSA+PSBz\n" - "dC0+Y2hpcF9pbmZvLT5udW1faW5wdXRzKSB7DQo+ID4gKwkJCWRldl9lcnIoaW5kaW9fZGV2LT5k\n" - "ZXYucGFyZW50LA0KPiA+ICsJCQkJIklucHV0IHBpbiBudW1iZXIgb3V0IG9mIHJhbmdlLlxuIik7\n" - "DQo+ID4gKwkJCXJldCA9IC1FSU5WQUw7DQo+ID4gKwkJCWdvdG8gZXJyOw0KPiA+ICsJCX0NCj4g\n" - "PiArCQlzdC0+Y2hhbm5lbF9jb25maWdbY2hhbm5lbF0uYWluID0NCj4gPiBBRDcxMjRfQ0hBTk5F\n" - "TF9BSU5QKGFpblswXSkgfA0KPiA+ICsJCQkJCQnCoMKgQUQ3MTI0X0NIQU5ORUxfQUlOTSgNCj4g\n" - "PiBhaW5bMV0pOw0KPiA+ICsJCXN0LT5jaGFubmVsX2NvbmZpZ1tjaGFubmVsXS5iaXBvbGFyID0N\n" - "Cj4gPiArCQkJb2ZfcHJvcGVydHlfcmVhZF9ib29sKGNoaWxkLCAiYWRpLGJpcG9sYXIiKTsNCj4g\n" - "PiArDQo+ID4gKwkJcmV0ID0gb2ZfcHJvcGVydHlfcmVhZF91MzIoY2hpbGQsICJhZGkscmVmZXJl\n" - "bmNlLQ0KPiA+IHNlbGVjdCIsICZ0bXApOw0KPiA+ICsJCWlmIChyZXQpDQo+ID4gKwkJCXN0LT5j\n" - "aGFubmVsX2NvbmZpZ1tjaGFubmVsXS5yZWZzZWwgPQ0KPiA+IEFENzEyNF9JTlRfUkVGOw0KPiA+\n" - "ICsJCWVsc2UNCj4gPiArCQkJc3QtPmNoYW5uZWxfY29uZmlnW2NoYW5uZWxdLnJlZnNlbCA9IHRt\n" - "cDsNCj4gPiArDQo+ID4gKwkJcmV0ID0gb2ZfcHJvcGVydHlfcmVhZF91MzIoY2hpbGQsICJhZGks\n" - "Z2FpbiIsICZ0bXApOw0KPiA+ICsJCWlmIChyZXQpIHsNCj4gPiArCQkJc3QtPmNoYW5uZWxfY29u\n" - "ZmlnW2NoYW5uZWxdLnBnYV9iaXRzID0gMDsNCj4gPiArCQl9IGVsc2Ugew0KPiA+ICsJCQlyZXMg\n" - "PSBhZDcxMjRfZmluZF9jbG9zZXN0X21hdGNoKGFkNzEyNF9nYWluLA0KPiA+ICsJCQkJCQlBUlJB\n" - "WV9TSVpFKGFkNzEyNF9nYWluDQo+ID4gKSwgdG1wKTsNCj4gPiArCQkJc3QtPmNoYW5uZWxfY29u\n" - "ZmlnW2NoYW5uZWxdLnBnYV9iaXRzID0gcmVzOw0KPiBIbW0uIFRoZSBvbGQgcXVlc3Rpb24gb2Yg\n" - "d2hhdCB0byBwdXQgaW4gRFQgYXMgaXQgcmVmbGVjdHMgd2lyaW5nIGFuZA0KPiB3aGF0IHRvIGxl\n" - "YXZlIHRvIHVzZXJzcGFjZS4gR2FpbiBpcyB0cmlja3kgYXMgb25seSBzb21lIHZhbHVlcyBtYWtl\n" - "IHNlbnNlDQo+IGZvciBhIGdpdmVuIHN5c3RlbSwgYnV0IHRoZXJlIGNhbiBiZSBtb3JlIHRoYW4g\n" - "b25lIHRoYXQgZG9lcy4uLg0KPiBUaGlzIGlzIHByb2JhYmx5IHJlYXNvbmFibGUgYXMgaXQgY2Fu\n" - "IGJlIGNvbnNpZGVyZWQgYXMgc2V0dGluZyB0aGUNCj4gZGVmYXVsdA0KPiB0aGF0IG1ha2VzIHNl\n" - "bnNlIGZvciB3aGF0IGlzIHdpcmVkLsKgwqBQb3RlbnRpYWxseSB1c2VyIHNwYWNlIGNvdWxkDQo+\n" - "IG92ZXJyaWRlDQo+IGl0IGxhdGVyIGlmIGl0IHdhbnRlZCB0by4NCj4gDQo+ID4gDQo+ID4gKwkJ\n" - "fQ0KPiA+ICsNCj4gPiArCQlyZXQgPSBvZl9wcm9wZXJ0eV9yZWFkX3UzMihjaGlsZCwgImFkaSxv\n" - "ZHItaHoiLCAmdG1wKTsNCj4gV2h5IGlzIHRoaXMgaW4gRFQuIFRoaXMgb25lIGZlZWxzIGxpa2Ug\n" - "YSB1c2Vyc3BhY2UgY2hvaWNlIHRvIG1lLiBJdCdzDQo+IG9ubHkgdGFuZ2VudGlhbGx5IGNvbm5l\n" - "Y3RlZCB0byBob3cgdGhpbmdzIGFyZSBjb25uZWN0ZWQgb24gdGhlIGJvYXJkLg0KPiBZb3UgYWxz\n" - "byBzdXBwb3J0IGNvbnRyb2wgZnJvbSB1c2Vyc3BhY2UuwqDCoEkgd291bGQgcGljayBhIHNlbnNp\n" - "YmxlDQo+IGdlbmVyYWwgZGVmYXVsdCBhbmQgdGhlbiBkcm9wIHRoaXMgZnJvbSB0aGUgRFQgYmlu\n" - "ZGluZy4gSXQncyBvcHRpb25hbA0KPiBhbnl3YXkuDQo+IA0KPiA+IA0KPiA+ICsJCWlmIChyZXQp\n" - "DQo+ID4gKwkJCS8qDQo+ID4gKwkJCcKgKiA5IFNQUyBpcyB0aGUgbWluaW11bSBvdXRwdXQgZGF0\n" - "YSByYXRlDQo+ID4gc3VwcG9ydGVkDQo+ID4gKwkJCcKgKiByZWdhcmRsZXNzIG9mIHRoZSBzZWxl\n" - "Y3RlZCBwb3dlciBtb2RlLg0KPiA+ICsJCQnCoCovDQo+ID4gKwkJCXN0LT5jaGFubmVsX2NvbmZp\n" - "Z1tjaGFubmVsXS5vZHIgPSA5Ow0KPiA+ICsJCWVsc2UNCj4gPiArCQkJc3QtPmNoYW5uZWxfY29u\n" - "ZmlnW2NoYW5uZWxdLm9kciA9IHRtcDsNCj4gPiArDQo+ID4gKwkJKmNoYW4gPSBhZDcxMjRfY2hh\n" - "bm5lbF90ZW1wbGF0ZTsNCj4gPiArCQljaGFuLT5hZGRyZXNzID0gY2hhbm5lbDsNCj4gPiArCQlj\n" - "aGFuLT5zY2FuX2luZGV4ID0gY2hhbm5lbDsNCj4gPiArCQljaGFuLT5jaGFubmVsID0gYWluWzBd\n" - "Ow0KPiA+ICsJCWNoYW4tPmNoYW5uZWwyID0gYWluWzFdOw0KPiA+ICsNCj4gPiArCQljaGFuKys7\n" - "DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK2VycjoNCj4gPiArCW9mX25v\n" - "ZGVfcHV0KGNoaWxkKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gcmV0Ow0KPiA+ICt9DQo+ID4gKw0K\n" - "PiA+ICtzdGF0aWMgaW50IGFkNzEyNF9zZXR1cChzdHJ1Y3QgYWQ3MTI0X3N0YXRlICpzdCkNCj4g\n" - "PiArew0KPiA+ICsJdW5zaWduZWQgaW50IHZhbCwgZmNsaywgcG93ZXJfbW9kZTsNCj4gPiArCWlu\n" - "dCBpLCByZXQ7DQo+ID4gKw0KPiA+ICsJZmNsayA9IGNsa19nZXRfcmF0ZShzdC0+bWNsayk7DQo+\n" - "ID4gKwlpZiAoIWZjbGspDQo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gKw0KPiA+ICsJLyog\n" - "VGhlIHBvd2VyIG1vZGUgY2hhbmdlcyB0aGUgbWFzdGVyIGNsb2NrIGZyZXF1ZW5jeSAqLw0KPiA+\n" - "ICsJcG93ZXJfbW9kZSA9DQo+ID4gYWQ3MTI0X2ZpbmRfY2xvc2VzdF9tYXRjaChhZDcxMjRfbWFz\n" - "dGVyX2Nsa19mcmVxX2h6LA0KPiA+ICsJCQkJCUFSUkFZX1NJWkUoYWQ3MTI0X21hc3Rlcl9jbGtf\n" - "Zg0KPiA+IHJlcV9oeiksDQo+ID4gKwkJCQkJZmNsayk7DQo+ID4gKwlpZiAoZmNsayAhPSBhZDcx\n" - "MjRfbWFzdGVyX2Nsa19mcmVxX2h6W3Bvd2VyX21vZGVdKSB7DQo+ID4gKwkJcmV0ID0gY2xrX3Nl\n" - "dF9yYXRlKHN0LT5tY2xrLCBmY2xrKTsNCj4gPiArCQlpZiAocmV0KQ0KPiA+ICsJCQlyZXR1cm4g\n" - "cmV0Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCS8qIFNldCB0aGUgcG93ZXIgbW9kZSAqLw0KPiA+\n" - "ICsJc3QtPmFkY19jb250cm9sICY9IH5BRDcxMjRfQURDX0NUUkxfUFdSX01TSzsNCj4gPiArCXN0\n" - "LT5hZGNfY29udHJvbCB8PSBBRDcxMjRfQURDX0NUUkxfUFdSKHBvd2VyX21vZGUpOw0KPiA+ICsJ\n" - "cmV0ID0gYWRfc2Rfd3JpdGVfcmVnKCZzdC0+c2QsIEFENzEyNF9BRENfQ09OVFJPTCwgMiwgc3Qt\n" - "DQo+ID4gPmFkY19jb250cm9sKTsNCj4gPiArCWlmIChyZXQgPCAwKQ0KPiA+ICsJCXJldHVybiBy\n" - "ZXQ7DQo+ID4gKw0KPiA+ICsJZm9yIChpID0gMDsgaSA8IHN0LT5udW1fY2hhbm5lbHM7IGkrKykg\n" - "ew0KPiA+ICsJCXZhbCA9IHN0LT5jaGFubmVsX2NvbmZpZ1tpXS5haW4gfA0KPiA+IEFENzEyNF9D\n" - "SEFOTkVMX1NFVFVQKGkpOw0KPiA+ICsJCXJldCA9IGFkX3NkX3dyaXRlX3JlZygmc3QtPnNkLCBB\n" - "RDcxMjRfQ0hBTk5FTChpKSwgMiwNCj4gPiB2YWwpOw0KPiA+ICsJCWlmIChyZXQgPCAwKQ0KPiA+\n" - "ICsJCQlyZXR1cm4gcmV0Ow0KPiA+ICsNCj4gPiArCQlyZXQgPSBhZDcxMjRfaW5pdF9jaGFubmVs\n" - "X3ZyZWYoc3QsIGkpOw0KPiA+ICsJCWlmIChyZXQgPCAwKQ0KPiA+ICsJCQlyZXR1cm4gcmV0Ow0K\n" - "PiA+ICsNCj4gPiArCQl2YWwgPSBBRDcxMjRfQ09ORklHX0JJUE9MQVIoc3QtDQo+ID4gPmNoYW5u\n" - "ZWxfY29uZmlnW2ldLmJpcG9sYXIpIHwNCj4gPiArCQnCoMKgwqDCoMKgwqBBRDcxMjRfQ09ORklH\n" - "X1JFRl9TRUwoc3QtDQo+ID4gPmNoYW5uZWxfY29uZmlnW2ldLnJlZnNlbCkgfA0KPiA+ICsJCcKg\n" - "wqDCoMKgwqDCoEFENzEyNF9DT05GSUdfUEdBKHN0LQ0KPiA+ID5jaGFubmVsX2NvbmZpZ1tpXS5w\n" - "Z2FfYml0cyk7DQo+ID4gKwkJcmV0ID0gYWRfc2Rfd3JpdGVfcmVnKCZzdC0+c2QsIEFENzEyNF9D\n" - "T05GSUcoaSksIDIsDQo+ID4gdmFsKTsNCj4gPiArCQlpZiAocmV0IDwgMCkNCj4gPiArCQkJcmV0\n" - "dXJuIHJldDsNCj4gPiArDQo+ID4gKwkJcmV0ID0gYWQ3MTI0X3NldF9jaGFubmVsX29kcihzdCwg\n" - "aSwgc3QtDQo+ID4gPmNoYW5uZWxfY29uZmlnW2ldLm9kcik7DQo+ID4gKwkJaWYgKHJldCA8IDAp\n" - "DQo+ID4gKwkJCXJldHVybiByZXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIHJldDsN\n" - "Cj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBhZDcxMjRfcHJvYmUoc3RydWN0IHNwaV9k\n" - "ZXZpY2UgKnNwaSkNCj4gPiArew0KPiA+ICsJY29uc3Qgc3RydWN0IHNwaV9kZXZpY2VfaWQgKmlk\n" - "Ow0KPiA+ICsJc3RydWN0IGFkNzEyNF9zdGF0ZSAqc3Q7DQo+ID4gKwlzdHJ1Y3QgaWlvX2RldiAq\n" - "aW5kaW9fZGV2Ow0KPiA+ICsJaW50IGksIHJldDsNCj4gPiArDQo+ID4gKwlpbmRpb19kZXYgPSBk\n" - "ZXZtX2lpb19kZXZpY2VfYWxsb2MoJnNwaS0+ZGV2LCBzaXplb2YoKnN0KSk7DQo+ID4gKwlpZiAo\n" - "IWluZGlvX2RldikNCj4gPiArCQlyZXR1cm4gLUVOT01FTTsNCj4gPiArDQo+ID4gKwlzdCA9IGlp\n" - "b19wcml2KGluZGlvX2Rldik7DQo+ID4gKw0KPiA+ICsJaWQgPSBzcGlfZ2V0X2RldmljZV9pZChz\n" - "cGkpOw0KPiA+ICsJc3QtPmNoaXBfaW5mbyA9ICZhZDcxMjRfY2hpcF9pbmZvX3RibFtpZC0+ZHJp\n" - "dmVyX2RhdGFdOw0KPiA+ICsNCj4gPiArCWFkX3NkX2luaXQoJnN0LT5zZCwgaW5kaW9fZGV2LCBz\n" - "cGksICZhZDcxMjRfc2lnbWFfZGVsdGFfaW5mbyk7DQo+ID4gKw0KPiA+ICsJc3BpX3NldF9kcnZk\n" - "YXRhKHNwaSwgaW5kaW9fZGV2KTsNCj4gPiArDQo+ID4gKwlpbmRpb19kZXYtPmRldi5wYXJlbnQg\n" - "PSAmc3BpLT5kZXY7DQo+ID4gKwlpbmRpb19kZXYtPm5hbWUgPSBzcGlfZ2V0X2RldmljZV9pZChz\n" - "cGkpLT5uYW1lOw0KPiA+ICsJaW5kaW9fZGV2LT5tb2RlcyA9IElORElPX0RJUkVDVF9NT0RFOw0K\n" - "PiA+ICsJaW5kaW9fZGV2LT5pbmZvID0gJmFkNzEyNF9pbmZvOw0KPiA+ICsNCj4gPiArCXJldCA9\n" - "IGFkNzEyNF9vZl9wYXJzZV9jaGFubmVsX2NvbmZpZyhpbmRpb19kZXYsIHNwaS0NCj4gPiA+ZGV2\n" - "Lm9mX25vZGUpOw0KPiA+ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiAr\n" - "DQo+ID4gKwlmb3IgKGkgPSAwOyBpIDwgQVJSQVlfU0laRShzdC0+dnJlZik7IGkrKykgew0KPiA+\n" - "ICsJCWlmIChpICE9IEFENzEyNF9JTlRfUkVGKSB7DQo+ID4gKwkJCXN0LT52cmVmW2ldID0NCj4g\n" - "PiBkZXZtX3JlZ3VsYXRvcl9nZXRfb3B0aW9uYWwoJnNwaS0+ZGV2LA0KPiA+ICsJCQkJCQkJYWQ3\n" - "MTI0X3JlZl9uYW0NCj4gPiBlc1tpXSk7DQo+ID4gKwkJCWlmIChQVFJfRVJSKHN0LT52cmVmW2ld\n" - "KSA9PSAtRU5PREVWKQ0KPiA+ICsJCQkJY29udGludWU7DQo+ID4gKwkJCWVsc2UgaWYgKElTX0VS\n" - "UihzdC0+dnJlZltpXSkpDQo+ID4gKwkJCQlyZXR1cm4gUFRSX0VSUihzdC0+dnJlZltpXSk7DQo+\n" - "ID4gKw0KPiA+ICsJCQlyZXQgPSByZWd1bGF0b3JfZW5hYmxlKHN0LT52cmVmW2ldKTsNCj4gPiAr\n" - "CQkJaWYgKHJldCkNCj4gPiArCQkJCXJldHVybiByZXQ7DQo+ID4gKwkJfQ0KPiA+ICsJfQ0KPiA+\n" - "ICsNCj4gPiArCXN0LT5tY2xrID0gZGV2bV9jbGtfZ2V0KCZzcGktPmRldiwgIm1jbGsiKTsNCj4g\n" - "PiArCWlmIChJU19FUlIoc3QtPm1jbGspKSB7DQo+ID4gKwkJcmV0ID0gUFRSX0VSUihzdC0+bWNs\n" - "ayk7DQo+ID4gKwkJZ290byBlcnJvcl9yZWd1bGF0b3JfZGlzYWJsZTsNCj4gPiArCX0NCj4gPiAr\n" - "DQo+ID4gKwlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoc3QtPm1jbGspOw0KPiA+ICsJaWYgKHJl\n" - "dCA8IDApDQo+ID4gKwkJZ290byBlcnJvcl9yZWd1bGF0b3JfZGlzYWJsZTsNCj4gPiArDQo+ID4g\n" - "KwlyZXQgPSBhZDcxMjRfc29mdF9yZXNldChzdCk7DQo+ID4gKwlpZiAocmV0IDwgMCkNCj4gPiAr\n" - "CQlnb3RvIGVycm9yX2Nsa19kaXNhYmxlX3VucHJlcGFyZTsNCj4gPiArDQo+ID4gKwlyZXQgPSBh\n" - "ZDcxMjRfc2V0dXAoc3QpOw0KPiA+ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJZ290byBlcnJvcl9j\n" - "bGtfZGlzYWJsZV91bnByZXBhcmU7DQo+ID4gKw0KPiA+ICsJcmV0ID0gYWRfc2Rfc2V0dXBfYnVm\n" - "ZmVyX2FuZF90cmlnZ2VyKGluZGlvX2Rldik7DQo+ID4gKwlpZiAocmV0IDwgMCkNCj4gPiArCQln\n" - "b3RvIGVycm9yX2Nsa19kaXNhYmxlX3VucHJlcGFyZTsNCj4gPiArDQo+ID4gKwlyZXQgPSBpaW9f\n" - "ZGV2aWNlX3JlZ2lzdGVyKGluZGlvX2Rldik7DQo+ID4gKwlpZiAocmV0IDwgMCkgew0KPiA+ICsJ\n" - "CWRldl9lcnIoJnNwaS0+ZGV2LCAiRmFpbGVkIHRvIHJlZ2lzdGVyIGlpbyBkZXZpY2VcbiIpOw0K\n" - "PiA+ICsJCWdvdG8gZXJyb3JfcmVtb3ZlX3RyaWdnZXI7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJ\n" - "cmV0dXJuIDA7DQo+ID4gKw0KPiA+ICtlcnJvcl9yZW1vdmVfdHJpZ2dlcjoNCj4gPiArCWFkX3Nk\n" - "X2NsZWFudXBfYnVmZmVyX2FuZF90cmlnZ2VyKGluZGlvX2Rldik7DQo+ID4gK2Vycm9yX2Nsa19k\n" - "aXNhYmxlX3VucHJlcGFyZToNCj4gPiArCWNsa19kaXNhYmxlX3VucHJlcGFyZShzdC0+bWNsayk7\n" - "DQo+ID4gK2Vycm9yX3JlZ3VsYXRvcl9kaXNhYmxlOg0KPiA+ICsJZm9yIChpID0gQVJSQVlfU0la\n" - "RShzdC0+dnJlZikgLSAxOyBpID49IDA7IGktLSkgew0KPiA+ICsJCWlmICghSVNfRVJSX09SX05V\n" - "TEwoc3QtPnZyZWZbaV0pKQ0KPiA+ICsJCQlyZWd1bGF0b3JfZGlzYWJsZShzdC0+dnJlZltpXSk7\n" - "DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiAr\n" - "c3RhdGljIGludCBhZDcxMjRfcmVtb3ZlKHN0cnVjdCBzcGlfZGV2aWNlICpzcGkpDQo+ID4gK3sN\n" - "Cj4gPiArCXN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYgPSBzcGlfZ2V0X2RydmRhdGEoc3BpKTsN\n" - "Cj4gPiArCXN0cnVjdCBhZDcxMjRfc3RhdGUgKnN0ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4g\n" - "PiArCWludCBpOw0KPiA+ICsNCj4gPiArCWlpb19kZXZpY2VfdW5yZWdpc3RlcihpbmRpb19kZXYp\n" - "Ow0KPiA+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKHN0LT5tY2xrKTsNCj4gPiArCWFkX3NkX2Ns\n" - "ZWFudXBfYnVmZmVyX2FuZF90cmlnZ2VyKGluZGlvX2Rldik7DQo+IFRoZSBvcmRlcmluZyBoZXJl\n" - "IHNob3VsZCBtYXRjaCB0aGF0IGluIHRoZSBlcnJvciBwYXRoIGFib3ZlLg0KPiAoc28gdGhlIHR3\n" - "byB0aGluZ3MgaGVyZSBzaG91bGQgYmUgcmV2ZXJzZWQpLg0KPiBJdCdzIGluIHRoZSBjYXRlZ29y\n" - "eSBvZiBtYWtpbmcgdGhpbmdzIG9idmlvdXNseSBzYWZlIHJhdGhlciB0aGFuIGFuDQo+IGFjdHVh\n" - "bCBpc3N1ZS4NCj4gSSBsaWtlIHRvIGJlIGFibGUgdG8gY2hlY2sgdGhlIG9yZGVyaW5nIG9ubHkg\n" - "b25jZSByYXRoZXIgdGhhbiB0d2ljZQ0KPiB3aGVuIHJldmlld2luZyBzbyB3aWxsIGFsd2F5cyBj\n" - "b25maXJtIHRoZXkgbWF0Y2guDQo+IA0KPiA+IA0KPiA+ICsNCj4gPiArCWZvciAoaSA9IEFSUkFZ\n" - "X1NJWkUoc3QtPnZyZWYpIC0gMTsgaSA+PSAwOyBpLS0pIHsNCj4gPiArCQlpZiAoIUlTX0VSUl9P\n" - "Ul9OVUxMKHN0LT52cmVmW2ldKSkNCj4gPiArCQkJcmVndWxhdG9yX2Rpc2FibGUoc3QtPnZyZWZb\n" - "aV0pOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+\n" - "ICtzdGF0aWMgY29uc3Qgc3RydWN0IHNwaV9kZXZpY2VfaWQgYWQ3MTI0X2lkX3RhYmxlW10gPSB7\n" - "DQo+ID4gKwl7ICJhZDcxMjQtNCIsIElEX0FENzEyNF80IH0sDQo+ID4gKwl7ICJhZDcxMjQtOCIs\n" - "IElEX0FENzEyNF84IH0sDQo+ID4gKwl7fQ0KPiA+ICt9Ow0KPiA+ICtNT0RVTEVfREVWSUNFX1RB\n" - "QkxFKHNwaSwgYWQ3MTI0X2lkX3RhYmxlKTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1\n" - "Y3Qgb2ZfZGV2aWNlX2lkIGFkNzEyNF9vZl9tYXRjaFtdID0gew0KPiA+ICsJeyAuY29tcGF0aWJs\n" - "ZSA9ICJhZGksYWQ3MTI0LTQiIH0sDQo+ID4gKwl7IC5jb21wYXRpYmxlID0gImFkaSxhZDcxMjQt\n" - "OCIgfSwNCj4gPiArCXsgfSwNCj4gPiArfTsNCj4gPiArTU9EVUxFX0RFVklDRV9UQUJMRShvZiwg\n" - "YWQ3MTI0X29mX21hdGNoKTsNCj4gPiArDQo+ID4gK3N0YXRpYyBzdHJ1Y3Qgc3BpX2RyaXZlciBh\n" - "ZDcxMTI0X2RyaXZlciA9IHsNCj4gPiArCS5kcml2ZXIgPSB7DQo+ID4gKwkJLm5hbWUgPSAiYWQ3\n" - "MTI0IiwNCj4gPiArCQkub2ZfbWF0Y2hfdGFibGUgPSBhZDcxMjRfb2ZfbWF0Y2gsDQo+ID4gKwl9\n" - "LA0KPiA+ICsJLnByb2JlID0gYWQ3MTI0X3Byb2JlLA0KPiA+ICsJLnJlbW92ZQk9IGFkNzEyNF9y\n" - "ZW1vdmUsDQo+ID4gKwkuaWRfdGFibGUgPSBhZDcxMjRfaWRfdGFibGUsDQo+ID4gK307DQo+ID4g\n" - "K21vZHVsZV9zcGlfZHJpdmVyKGFkNzExMjRfZHJpdmVyKTsNCj4gPiArDQo+ID4gK01PRFVMRV9B\n" - "VVRIT1IoIlN0ZWZhbiBQb3BhIDxzdGVmYW4ucG9wYUBhbmFsb2cuY29tPiIpOw0KPiA+ICtNT0RV\n" - "TEVfREVTQ1JJUFRJT04oIkFuYWxvZyBEZXZpY2VzIEFENzEyNCBTUEkgZHJpdmVyIik7DQo+ID4g\n" - K01PRFVMRV9MSUNFTlNFKCJHUEwiKTsNCj4g + "On Sb, 2018-11-03 at 12:16 +0000, Jonathan Cameron wrote:\n" + "> On Mon, 29 Oct 2018 18:38:31 +0200\n" + "> Stefan Popa <stefan.popa@analog.com> wrote:\n" + "> \n" + "> > \n" + "> > The ad7124-4 and ad7124-8 are a family of 4 and 8 channel sigma-delta\n" + "> > ADCs\n" + "> > with 24-bit precision and reference.\n" + "> > \n" + "> > Three power modes are available which in turn affect the output data\n" + "> > rate:\n" + "> > \302\240* Full power: 9.38 SPS to 19,200 SPS\n" + "> > \302\240* Mid power: 2.34 SPS to 4800 SPS\n" + "> > \302\240* Low power: 1.17 SPS to 2400 SPS\n" + "> > \n" + "> > The ad7124-4 can be configured to have four differential inputs, while\n" + "> > ad7124-8 can have 8. Moreover, ad7124 also supports per channel\n" + "> > configuration. Each configuration consists of gain, reference source,\n" + "> > output data rate and bipolar/unipolar configuration.\n" + "> > \n" + "> > Datasheets:\n" + "> > Link: http://www.analog.com/media/en/technical-documentation/data-sheet\n" + "> > s/AD7124-4.pdf\n" + "> > Link: http://www.analog.com/media/en/technical-documentation/data-sheet\n" + "> > s/ad7124-8.pdf\n" + "> > \n" + "> > Signed-off-by: Stefan Popa <stefan.popa@analog.com>\n" + "> Hi Stefan,\n" + "> \n" + "> The discussion around the DT binding has gotten me looking at bit\n" + "> more closely at that for this version.\n" + "> \n" + "> Some most comments in that section.\302\240\302\240Also a really minor ordering issue\n" + "> in\n" + "> remove which I'd just have fixed if we weren't going around again for\n" + "> the binding.\n" + "> \n" + "> Main binding thing is I don't think the odr value belongs in DT.\n" + "> Gain is more marginal (unless the part can actually be damaged by\n" + "> a wrong value - which I hope it can't!).\302\240\302\240I'm not that fussed\n" + "> as there are definitely reasons to specify a default scale to\n" + "> cover the reasonable range on a pin.\n" + "> \n" + "> Thanks,\n" + "> \n" + "> Jonathan\n" + "\n" + "Hi Jonathan,\n" + "\n" + "Thank you for the review! So, how should I proceed?\n" + "\n" + "First, we need an adc.txt file where \"bipolar\" and something like \"diff-\n" + "channels\" should be documented. Should the file be placed under\n" + "Documentation/devicetree/bindings/iio/adc?\n" + "\n" + "Regarding the \"odr-hz\" property, it totally makes sense to remove it from\n" + "the DT. How about the \"gain\"? Should we leave it in the DT and also add the\n" + "possibility to be configured from user space?\n" + "\n" + "Regards,\n" + "-Stefan\n" + "> > \n" + "> > ---\n" + "> > Changes in v2:\n" + "> > \t- Added this commit.\n" + "> > Changes in v3:\n" + "> > \t- Removed channel, address, scan_index and shift fields from\n" + "> > \t\302\240\302\240ad7124_channel_template.\n" + "> > \t- Added a sanity check for val2 in ad7124_write_raw().\n" + "> > \t- Used the \"reg\" property to get the channel address and \"adi,diff-\n" + "> > channels\"\n" + "> > \t\302\240\302\240for the differential pins. The \"adi,channel-number\" property was\n" + "> > removed.\n" + "> > \t- When calling regulator_get_optional, the probe is given up in\n" + "> > case of error,\n" + "> > \t\302\240\302\240but continues in case of -ENODEV.\n" + "> > \t- clk_disable_unprepare() is called before\n" + "> > ad_sd_cleanup_buffer_and_trigger\n" + "> > \t\302\240\302\240in ad7124_remove().\n" + "> > \n" + "> > \302\240MAINTAINERS\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240|\302\240\302\240\302\2407 +\n" + "> > \302\240drivers/iio/adc/Kconfig\302\240\302\240|\302\240\302\24011 +\n" + "> > \302\240drivers/iio/adc/Makefile |\302\240\302\240\302\2401 +\n" + "> > \302\240drivers/iio/adc/ad7124.c | 648\n" + "> > +++++++++++++++++++++++++++++++++++++++++++++++\n" + "> > \302\2404 files changed, 667 insertions(+)\n" + "> > \302\240create mode 100644 drivers/iio/adc/ad7124.c\n" + "> > \n" + "> > diff --git a/MAINTAINERS b/MAINTAINERS\n" + "> > index f642044..3a1bfcb 100644\n" + "> > --- a/MAINTAINERS\n" + "> > +++ b/MAINTAINERS\n" + "> > @@ -839,6 +839,13 @@ S:\tSupported\n" + "> > \302\240F:\tdrivers/iio/dac/ad5758.c\n" + "> > \302\240F:\tDocumentation/devicetree/bindings/iio/dac/ad5758.txt\n" + "> > \302\240\n" + "> > +ANALOG DEVICES INC AD7124 DRIVER\n" + "> > +M:\tStefan Popa <stefan.popa@analog.com>\n" + "> > +L:\tlinux-iio@vger.kernel.org\n" + "> > +W:\thttp://ez.analog.com/community/linux-device-drivers\n" + "> > +S:\tSupported\n" + "> > +F:\tdrivers/iio/adc/ad7124.c\n" + "> > +\n" + "> > \302\240ANALOG DEVICES INC AD9389B DRIVER\n" + "> > \302\240M:\tHans Verkuil <hans.verkuil@cisco.com>\n" + "> > \302\240L:\tlinux-media@vger.kernel.org\n" + "> > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig\n" + "> > index a52fea8..148a10f 100644\n" + "> > --- a/drivers/iio/adc/Kconfig\n" + "> > +++ b/drivers/iio/adc/Kconfig\n" + "> > @@ -10,6 +10,17 @@ config AD_SIGMA_DELTA\n" + "> > \302\240\tselect IIO_BUFFER\n" + "> > \302\240\tselect IIO_TRIGGERED_BUFFER\n" + "> > \302\240\n" + "> > +config AD7124\n" + "> > +\ttristate \"Analog Devices AD7124 and similar sigma-delta ADCs\n" + "> > driver\"\n" + "> > +\tdepends on SPI_MASTER\n" + "> > +\tselect AD_SIGMA_DELTA\n" + "> > +\thelp\n" + "> > +\t\302\240\302\240Say yes here to build support for Analog Devices AD7124-4\n" + "> > and AD7124-8\n" + "> > +\t\302\240\302\240SPI analog to digital converters (ADC).\n" + "> > +\n" + "> > +\t\302\240\302\240To compile this driver as a module, choose M here: the\n" + "> > module will be\n" + "> > +\t\302\240\302\240called ad7124.\n" + "> > +\n" + "> > \302\240config AD7266\n" + "> > \302\240\ttristate \"Analog Devices AD7265/AD7266 ADC driver\"\n" + "> > \302\240\tdepends on SPI_MASTER\n" + "> > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile\n" + "> > index a6e6a0b..76168b2 100644\n" + "> > --- a/drivers/iio/adc/Makefile\n" + "> > +++ b/drivers/iio/adc/Makefile\n" + "> > @@ -5,6 +5,7 @@\n" + "> > \302\240\n" + "> > \302\240# When adding new entries keep the list in alphabetical order\n" + "> > \302\240obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o\n" + "> > +obj-$(CONFIG_AD7124) += ad7124.o\n" + "> > \302\240obj-$(CONFIG_AD7266) += ad7266.o\n" + "> > \302\240obj-$(CONFIG_AD7291) += ad7291.o\n" + "> > \302\240obj-$(CONFIG_AD7298) += ad7298.o\n" + "> > diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c\n" + "> > new file mode 100644\n" + "> > index 0000000..0660135\n" + "> > --- /dev/null\n" + "> > +++ b/drivers/iio/adc/ad7124.c\n" + "> > @@ -0,0 +1,648 @@\n" + "> > +// SPDX-License-Identifier: GPL-2.0+\n" + "> > +/*\n" + "> > + * AD7124 SPI ADC driver\n" + "> > + *\n" + "> > + * Copyright 2018 Analog Devices Inc.\n" + "> > + */\n" + "> > +#include <linux/bitfield.h>\n" + "> > +#include <linux/clk.h>\n" + "> > +#include <linux/delay.h>\n" + "> > +#include <linux/device.h>\n" + "> > +#include <linux/err.h>\n" + "> > +#include <linux/kernel.h>\n" + "> > +#include <linux/module.h>\n" + "> > +#include <linux/regulator/consumer.h>\n" + "> > +#include <linux/spi/spi.h>\n" + "> > +\n" + "> > +#include <linux/iio/iio.h>\n" + "> > +#include <linux/iio/adc/ad_sigma_delta.h>\n" + "> > +#include <linux/iio/sysfs.h>\n" + "> > +\n" + "> > +/* AD7124 registers */\n" + "> > +#define AD7124_COMMS\t\t\t0x00\n" + "> > +#define AD7124_STATUS\t\t\t0x00\n" + "> > +#define AD7124_ADC_CONTROL\t\t0x01\n" + "> > +#define AD7124_DATA\t\t\t0x02\n" + "> > +#define AD7124_IO_CONTROL_1\t\t0x03\n" + "> > +#define AD7124_IO_CONTROL_2\t\t0x04\n" + "> > +#define AD7124_ID\t\t\t0x05\n" + "> > +#define AD7124_ERROR\t\t\t0x06\n" + "> > +#define AD7124_ERROR_EN\t\t0x07\n" + "> > +#define AD7124_MCLK_COUNT\t\t0x08\n" + "> > +#define AD7124_CHANNEL(x)\t\t(0x09 + (x))\n" + "> > +#define AD7124_CONFIG(x)\t\t(0x19 + (x))\n" + "> > +#define AD7124_FILTER(x)\t\t(0x21 + (x))\n" + "> > +#define AD7124_OFFSET(x)\t\t(0x29 + (x))\n" + "> > +#define AD7124_GAIN(x)\t\t\t(0x31 + (x))\n" + "> > +\n" + "> > +/* AD7124_STATUS */\n" + "> > +#define AD7124_STATUS_POR_FLAG_MSK\tBIT(4)\n" + "> > +\n" + "> > +/* AD7124_ADC_CONTROL */\n" + "> > +#define AD7124_ADC_CTRL_PWR_MSK\tGENMASK(7, 6)\n" + "> > +#define AD7124_ADC_CTRL_PWR(x)\t\tFIELD_PREP(AD7124_ADC_CT\n" + "> > RL_PWR_MSK, x)\n" + "> > +#define AD7124_ADC_CTRL_MODE_MSK\tGENMASK(5, 2)\n" + "> > +#define AD7124_ADC_CTRL_MODE(x)\tFIELD_PREP(AD7124_ADC_CTRL_MODE\n" + "> > _MSK, x)\n" + "> > +\n" + "> > +/* AD7124_CHANNEL_X */\n" + "> > +#define AD7124_CHANNEL_EN_MSK\t\tBIT(15)\n" + "> > +#define AD7124_CHANNEL_EN(x)\t\tFIELD_PREP(AD7124_CHANNEL_\n" + "> > EN_MSK, x)\n" + "> > +#define AD7124_CHANNEL_SETUP_MSK\tGENMASK(14, 12)\n" + "> > +#define AD7124_CHANNEL_SETUP(x)\tFIELD_PREP(AD7124_CHANNEL_SETUP\n" + "> > _MSK, x)\n" + "> > +#define AD7124_CHANNEL_AINP_MSK\tGENMASK(9, 5)\n" + "> > +#define AD7124_CHANNEL_AINP(x)\t\tFIELD_PREP(AD7124_CHANNE\n" + "> > L_AINP_MSK, x)\n" + "> > +#define AD7124_CHANNEL_AINM_MSK\tGENMASK(4, 0)\n" + "> > +#define AD7124_CHANNEL_AINM(x)\t\tFIELD_PREP(AD7124_CHANNE\n" + "> > L_AINM_MSK, x)\n" + "> > +\n" + "> > +/* AD7124_CONFIG_X */\n" + "> > +#define AD7124_CONFIG_BIPOLAR_MSK\tBIT(11)\n" + "> > +#define AD7124_CONFIG_BIPOLAR(x)\tFIELD_PREP(AD7124_CONFIG_BIPOL\n" + "> > AR_MSK, x)\n" + "> > +#define AD7124_CONFIG_REF_SEL_MSK\tGENMASK(4, 3)\n" + "> > +#define AD7124_CONFIG_REF_SEL(x)\tFIELD_PREP(AD7124_CONFIG_REF_S\n" + "> > EL_MSK, x)\n" + "> > +#define AD7124_CONFIG_PGA_MSK\t\tGENMASK(2, 0)\n" + "> > +#define AD7124_CONFIG_PGA(x)\t\tFIELD_PREP(AD7124_CONFIG_P\n" + "> > GA_MSK, x)\n" + "> > +\n" + "> > +/* AD7124_FILTER_X */\n" + "> > +#define AD7124_FILTER_FS_MSK\t\tGENMASK(10, 0)\n" + "> > +#define AD7124_FILTER_FS(x)\t\tFIELD_PREP(AD7124_FILTER_FS\n" + "> > _MSK, x)\n" + "> > +\n" + "> > +enum ad7124_ids {\n" + "> > +\tID_AD7124_4,\n" + "> > +\tID_AD7124_8,\n" + "> > +};\n" + "> > +\n" + "> > +enum ad7124_ref_sel {\n" + "> > +\tAD7124_REFIN1,\n" + "> > +\tAD7124_REFIN2,\n" + "> > +\tAD7124_INT_REF,\n" + "> > +\tAD7124_AVDD_REF,\n" + "> > +};\n" + "> > +\n" + "> > +enum ad7124_power_mode {\n" + "> > +\tAD7124_LOW_POWER,\n" + "> > +\tAD7124_MID_POWER,\n" + "> > +\tAD7124_FULL_POWER,\n" + "> > +};\n" + "> > +\n" + "> > +static const unsigned int ad7124_gain[8] = {\n" + "> > +\t1, 2, 4, 8, 16, 32, 64, 128\n" + "> > +};\n" + "> > +\n" + "> > +static const int ad7124_master_clk_freq_hz[3] = {\n" + "> > +\t[AD7124_LOW_POWER] = 76800,\n" + "> > +\t[AD7124_MID_POWER] = 153600,\n" + "> > +\t[AD7124_FULL_POWER] = 614400,\n" + "> > +};\n" + "> > +\n" + "> > +static const char * const ad7124_ref_names[] = {\n" + "> > +\t[AD7124_REFIN1] = \"refin1\",\n" + "> > +\t[AD7124_REFIN2] = \"refin2\",\n" + "> > +\t[AD7124_INT_REF] = \"int\",\n" + "> > +\t[AD7124_AVDD_REF] = \"avdd\",\n" + "> > +};\n" + "> > +\n" + "> > +struct ad7124_chip_info {\n" + "> > +\tunsigned int num_inputs;\n" + "> > +};\n" + "> > +\n" + "> > +struct ad7124_channel_config {\n" + "> > +\tenum ad7124_ref_sel refsel;\n" + "> > +\tbool bipolar;\n" + "> > +\tunsigned int ain;\n" + "> > +\tunsigned int vref_mv;\n" + "> > +\tunsigned int pga_bits;\n" + "> > +\tunsigned int odr;\n" + "> > +};\n" + "> > +\n" + "> > +struct ad7124_state {\n" + "> > +\tconst struct ad7124_chip_info *chip_info;\n" + "> > +\tstruct ad_sigma_delta sd;\n" + "> > +\tstruct ad7124_channel_config channel_config[4];\n" + "> > +\tstruct regulator *vref[4];\n" + "> > +\tstruct clk *mclk;\n" + "> > +\tunsigned int adc_control;\n" + "> > +\tunsigned int num_channels;\n" + "> > +};\n" + "> > +\n" + "> > +static const struct iio_chan_spec ad7124_channel_template = {\n" + "> > +\t.type = IIO_VOLTAGE,\n" + "> > +\t.indexed = 1,\n" + "> > +\t.differential = 1,\n" + "> > +\t.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |\n" + "> > +\t\tBIT(IIO_CHAN_INFO_SCALE) |\n" + "> > +\t\tBIT(IIO_CHAN_INFO_OFFSET) |\n" + "> > +\t\tBIT(IIO_CHAN_INFO_SAMP_FREQ),\n" + "> > +\t.scan_type = {\n" + "> > +\t\t.sign = 'u',\n" + "> > +\t\t.realbits = 24,\n" + "> > +\t\t.storagebits = 32,\n" + "> > +\t},\n" + "> > +};\n" + "> > +\n" + "> > +static struct ad7124_chip_info ad7124_chip_info_tbl[] = {\n" + "> > +\t[ID_AD7124_4] = {\n" + "> > +\t\t.num_inputs = 8,\n" + "> > +\t},\n" + "> > +\t[ID_AD7124_8] = {\n" + "> > +\t\t.num_inputs = 16,\n" + "> > +\t},\n" + "> > +};\n" + "> > +\n" + "> > +static int ad7124_find_closest_match(const int *array,\n" + "> > +\t\t\t\t\302\240\302\240\302\240\302\240\302\240unsigned int size, int val)\n" + "> > +{\n" + "> > +\tint i;\n" + "> > +\n" + "> > +\tfor (i = 0; i < size; i++) {\n" + "> > +\t\tif (val <= array[i])\n" + "> > +\t\t\treturn i;\n" + "> > +\t}\n" + "> > +\n" + "> > +\treturn size - 1;\n" + "> > +}\n" + "> > +\n" + "> > +static int ad7124_spi_write_mask(struct ad7124_state *st,\n" + "> > +\t\t\t\t\302\240unsigned int addr,\n" + "> > +\t\t\t\t\302\240unsigned long mask,\n" + "> > +\t\t\t\t\302\240unsigned int val,\n" + "> > +\t\t\t\t\302\240unsigned int bytes)\n" + "> > +{\n" + "> > +\tunsigned int readval;\n" + "> > +\tint ret;\n" + "> > +\n" + "> > +\tret = ad_sd_read_reg(&st->sd, addr, bytes, &readval);\n" + "> > +\tif (ret < 0)\n" + "> > +\t\treturn ret;\n" + "> > +\n" + "> > +\treadval &= ~mask;\n" + "> > +\treadval |= val;\n" + "> > +\n" + "> > +\treturn ad_sd_write_reg(&st->sd, addr, bytes, readval);\n" + "> > +}\n" + "> > +\n" + "> > +static int ad7124_set_mode(struct ad_sigma_delta *sd,\n" + "> > +\t\t\t\302\240\302\240\302\240enum ad_sigma_delta_mode mode)\n" + "> > +{\n" + "> > +\tstruct ad7124_state *st = container_of(sd, struct\n" + "> > ad7124_state, sd);\n" + "> > +\n" + "> > +\tst->adc_control &= ~AD7124_ADC_CTRL_MODE_MSK;\n" + "> > +\tst->adc_control |= AD7124_ADC_CTRL_MODE(mode);\n" + "> > +\n" + "> > +\treturn ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, st-\n" + "> > >adc_control);\n" + "> > +}\n" + "> > +\n" + "> > +static int ad7124_set_channel(struct ad_sigma_delta *sd, unsigned int\n" + "> > channel)\n" + "> > +{\n" + "> > +\tstruct ad7124_state *st = container_of(sd, struct\n" + "> > ad7124_state, sd);\n" + "> > +\tunsigned int val;\n" + "> > +\n" + "> > +\tval = st->channel_config[channel].ain | AD7124_CHANNEL_EN(1) |\n" + "> > +\t\302\240\302\240\302\240\302\240\302\240\302\240AD7124_CHANNEL_SETUP(channel);\n" + "> > +\n" + "> > +\treturn ad_sd_write_reg(&st->sd, AD7124_CHANNEL(channel), 2,\n" + "> > val);\n" + "> > +}\n" + "> > +\n" + "> > +static const struct ad_sigma_delta_info ad7124_sigma_delta_info = {\n" + "> > +\t.set_channel = ad7124_set_channel,\n" + "> > +\t.set_mode = ad7124_set_mode,\n" + "> > +\t.has_registers = true,\n" + "> > +\t.addr_shift = 0,\n" + "> > +\t.read_mask = BIT(6),\n" + "> > +\t.data_reg = AD7124_DATA,\n" + "> > +};\n" + "> > +\n" + "> > +static int ad7124_set_channel_odr(struct ad7124_state *st,\n" + "> > +\t\t\t\t\302\240\302\240unsigned int channel,\n" + "> > +\t\t\t\t\302\240\302\240unsigned int odr)\n" + "> > +{\n" + "> > +\tunsigned int fclk, odr_sel_bits;\n" + "> > +\tint ret;\n" + "> > +\n" + "> > +\tfclk = clk_get_rate(st->mclk);\n" + "> > +\t/*\n" + "> > +\t\302\240* FS[10:0] = fCLK / (fADC x 32) where:\n" + "> > +\t\302\240* fADC is the output data rate\n" + "> > +\t\302\240* fCLK is the master clock frequency\n" + "> > +\t\302\240* FS[10:0] are the bits in the filter register\n" + "> > +\t\302\240* FS[10:0] can have a value from 1 to 2047\n" + "> > +\t\302\240*/\n" + "> > +\todr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * 32);\n" + "> > +\tif (odr_sel_bits < 1)\n" + "> > +\t\todr_sel_bits = 1;\n" + "> > +\telse if (odr_sel_bits > 2047)\n" + "> > +\t\todr_sel_bits = 2047;\n" + "> > +\n" + "> > +\tret = ad7124_spi_write_mask(st, AD7124_FILTER(channel),\n" + "> > +\t\t\t\t\302\240\302\240\302\240\302\240AD7124_FILTER_FS_MSK,\n" + "> > +\t\t\t\t\302\240\302\240\302\240\302\240AD7124_FILTER_FS(odr_sel_bits),\n" + "> > 3);\n" + "> > +\tif (ret < 0)\n" + "> > +\t\treturn ret;\n" + "> > +\t/* fADC = fCLK / (FS[10:0] x 32) */\n" + "> > +\tst->channel_config[channel].odr =\n" + "> > +\t\tDIV_ROUND_CLOSEST(fclk, odr_sel_bits * 32);\n" + "> > +\n" + "> > +\treturn 0;\n" + "> > +}\n" + "> > +\n" + "> > +static int ad7124_read_raw(struct iio_dev *indio_dev,\n" + "> > +\t\t\t\302\240\302\240\302\240struct iio_chan_spec const *chan,\n" + "> > +\t\t\t\302\240\302\240\302\240int *val, int *val2, long info)\n" + "> > +{\n" + "> > +\tstruct ad7124_state *st = iio_priv(indio_dev);\n" + "> > +\tint idx, ret;\n" + "> > +\n" + "> > +\tswitch (info) {\n" + "> > +\tcase IIO_CHAN_INFO_RAW:\n" + "> > +\t\tret = ad_sigma_delta_single_conversion(indio_dev,\n" + "> > chan, val);\n" + "> > +\t\tif (ret < 0)\n" + "> > +\t\t\treturn ret;\n" + "> > +\n" + "> > +\t\t/* After the conversion is performed, disable the\n" + "> > channel */\n" + "> > +\t\tret = ad_sd_write_reg(&st->sd,\n" + "> > +\t\t\t\t\302\240\302\240\302\240\302\240\302\240\302\240AD7124_CHANNEL(chan->address),\n" + "> > 2,\n" + "> > +\t\t\t\t\302\240\302\240\302\240\302\240\302\240\302\240st->channel_config[chan-\n" + "> > >address].ain |\n" + "> > +\t\t\t\t\302\240\302\240\302\240\302\240\302\240\302\240AD7124_CHANNEL_EN(0));\n" + "> > +\t\tif (ret < 0)\n" + "> > +\t\t\treturn ret;\n" + "> > +\n" + "> > +\t\treturn IIO_VAL_INT;\n" + "> > +\tcase IIO_CHAN_INFO_SCALE:\n" + "> > +\t\tidx = st->channel_config[chan->address].pga_bits;\n" + "> > +\t\t*val = st->channel_config[chan->address].vref_mv /\n" + "> > +\t\t\tad7124_gain[idx];\n" + "> > +\t\tif (st->channel_config[chan->address].bipolar)\n" + "> > +\t\t\t*val2 = chan->scan_type.realbits - 1;\n" + "> > +\t\telse\n" + "> > +\t\t\t*val2 = chan->scan_type.realbits;\n" + "> > +\n" + "> > +\t\treturn IIO_VAL_FRACTIONAL_LOG2;\n" + "> > +\tcase IIO_CHAN_INFO_OFFSET:\n" + "> > +\t\tif (st->channel_config[chan->address].bipolar) {\n" + "> > +\t\t\t/* Code = 2^(n \342\210\222 1) \303\227 ((Ain \303\227 Gain / Vref) +\n" + "> > 1) */\n" + "> > +\t\t\tidx = st->channel_config[chan-\n" + "> > >address].pga_bits;\n" + "> > +\t\t\t*val = -(st->channel_config[chan-\n" + "> > >address].vref_mv /\n" + "> > +\t\t\t\t\302\240ad7124_gain[idx]);\n" + "> > +\t\t} else {\n" + "> > +\t\t\t*val = 0;\n" + "> > +\t\t}\n" + "> > +\n" + "> > +\t\treturn IIO_VAL_INT;\n" + "> > +\tcase IIO_CHAN_INFO_SAMP_FREQ:\n" + "> > +\t\t*val = st->channel_config[chan->address].odr;\n" + "> > +\n" + "> > +\t\treturn IIO_VAL_INT;\n" + "> > +\tdefault:\n" + "> > +\t\treturn -EINVAL;\n" + "> > +\t}\n" + "> > +}\n" + "> > +\n" + "> > +static int ad7124_write_raw(struct iio_dev *indio_dev,\n" + "> > +\t\t\t\302\240\302\240\302\240\302\240struct iio_chan_spec const *chan,\n" + "> > +\t\t\t\302\240\302\240\302\240\302\240int val, int val2, long info)\n" + "> > +{\n" + "> > +\tstruct ad7124_state *st = iio_priv(indio_dev);\n" + "> > +\n" + "> > +\tswitch (info) {\n" + "> > +\tcase IIO_CHAN_INFO_SAMP_FREQ:\n" + "> > +\t\tif (val2 != 0)\n" + "> > +\t\t\treturn -EINVAL;\n" + "> > +\n" + "> > +\t\treturn ad7124_set_channel_odr(st, chan->address, val);\n" + "> > +\tdefault:\n" + "> > +\t\treturn -EINVAL;\n" + "> > +\t}\n" + "> > +}\n" + "> > +\n" + "> > +static const struct iio_info ad7124_info = {\n" + "> > +\t.read_raw = ad7124_read_raw,\n" + "> > +\t.write_raw = ad7124_write_raw,\n" + "> > +};\n" + "> > +\n" + "> > +static int ad7124_soft_reset(struct ad7124_state *st)\n" + "> > +{\n" + "> > +\tunsigned int readval, timeout;\n" + "> > +\tint ret;\n" + "> > +\n" + "> > +\tret = ad_sd_reset(&st->sd, 64);\n" + "> > +\tif (ret < 0)\n" + "> > +\t\treturn ret;\n" + "> > +\n" + "> > +\ttimeout = 100;\n" + "> > +\tdo {\n" + "> > +\t\tret = ad_sd_read_reg(&st->sd, AD7124_STATUS, 1,\n" + "> > &readval);\n" + "> > +\t\tif (ret < 0)\n" + "> > +\t\t\treturn ret;\n" + "> > +\n" + "> > +\t\tif (!(readval & AD7124_STATUS_POR_FLAG_MSK))\n" + "> > +\t\t\treturn 0;\n" + "> > +\n" + "> > +\t\t/* The AD7124 requires typically 2ms to power up and\n" + "> > settle */\n" + "> > +\t\tusleep_range(100, 2000);\n" + "> > +\t} while (--timeout);\n" + "> > +\n" + "> > +\tdev_err(&st->sd.spi->dev, \"Soft reset failed\\n\");\n" + "> > +\n" + "> > +\treturn -EIO;\n" + "> > +}\n" + "> > +\n" + "> > +static int ad7124_init_channel_vref(struct ad7124_state *st,\n" + "> > +\t\t\t\t\302\240\302\240\302\240\302\240unsigned int channel_number)\n" + "> > +{\n" + "> > +\tunsigned int refsel = st-\n" + "> > >channel_config[channel_number].refsel;\n" + "> > +\n" + "> > +\tswitch (refsel) {\n" + "> > +\tcase AD7124_REFIN1:\n" + "> > +\tcase AD7124_REFIN2:\n" + "> > +\tcase AD7124_AVDD_REF:\n" + "> > +\t\tif (IS_ERR(st->vref[refsel])) {\n" + "> > +\t\t\tdev_err(&st->sd.spi->dev,\n" + "> > +\t\t\t\t\"Error, trying to use external voltage\n" + "> > reference without a %s regulator.\",\n" + "> > +\t\t\t\tad7124_ref_names[refsel]);\n" + "> > +\t\t\t\treturn PTR_ERR(st->vref[refsel]);\n" + "> > +\t\t}\n" + "> > +\t\tst->channel_config[channel_number].vref_mv =\n" + "> > +\t\t\tregulator_get_voltage(st->vref[refsel]);\n" + "> > +\t\t/* Conversion from uV to mV */\n" + "> > +\t\tst->channel_config[channel_number].vref_mv /= 1000;\n" + "> > +\t\tbreak;\n" + "> > +\tcase AD7124_INT_REF:\n" + "> > +\t\tst->channel_config[channel_number].vref_mv = 2500;\n" + "> > +\t\tbreak;\n" + "> > +\tdefault:\n" + "> > +\t\tdev_err(&st->sd.spi->dev, \"Invalid reference %d\\n\",\n" + "> > refsel);\n" + "> > +\t\treturn -EINVAL;\n" + "> > +\t}\n" + "> > +\n" + "> > +\treturn 0;\n" + "> > +}\n" + "> > +\n" + "> > +static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev,\n" + "> > +\t\t\t\t\t\302\240\302\240struct device_node *np)\n" + "> > +{\n" + "> > +\tstruct ad7124_state *st = iio_priv(indio_dev);\n" + "> > +\tstruct device_node *child;\n" + "> > +\tstruct iio_chan_spec *chan;\n" + "> > +\tunsigned int ain[2], channel = 0, tmp;\n" + "> > +\tint ret, res;\n" + "> > +\n" + "> > +\tst->num_channels = of_get_available_child_count(np);\n" + "> > +\tif (!st->num_channels) {\n" + "> > +\t\tdev_err(indio_dev->dev.parent, \"no channel\n" + "> > children\\n\");\n" + "> > +\t\treturn -ENODEV;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tchan = devm_kcalloc(indio_dev->dev.parent, st->num_channels,\n" + "> > +\t\t\t\302\240\302\240\302\240\302\240sizeof(*chan), GFP_KERNEL);\n" + "> > +\tif (!chan)\n" + "> > +\t\treturn -ENOMEM;\n" + "> > +\n" + "> > +\tindio_dev->channels = chan;\n" + "> > +\tindio_dev->num_channels = st->num_channels;\n" + "> > +\n" + "> > +\tfor_each_available_child_of_node(np, child) {\n" + "> > +\t\tret = of_property_read_u32(child, \"reg\", &channel);\n" + "> > +\t\tif (ret)\n" + "> > +\t\t\tgoto err;\n" + "> > +\n" + "> > +\t\tret = of_property_read_u32_array(child, \"adi,diff-\n" + "> > channels\",\n" + "> > +\t\t\t\t\t\t\302\240ain, 2);\n" + "> This actually feels like something we could standardize as well as\n" + "> bipolar.\n" + "> In the oldest drivers we actually let userspace configure all of this,\n" + "> but\n" + "> I can understand that only some combinations make sense on a given board\n" + "> so it arguably makes sense to only enable those, particularly when there\n" + "> is a reference select that has to be paired with channel choice.\n" + "> \n" + "> > \n" + "> > +\t\tif (ret)\n" + "> > +\t\t\tgoto err;\n" + "> > +\n" + "> > +\t\tif (ain[0] >= st->chip_info->num_inputs ||\n" + "> > +\t\t\302\240\302\240\302\240\302\240ain[1] >= st->chip_info->num_inputs) {\n" + "> > +\t\t\tdev_err(indio_dev->dev.parent,\n" + "> > +\t\t\t\t\"Input pin number out of range.\\n\");\n" + "> > +\t\t\tret = -EINVAL;\n" + "> > +\t\t\tgoto err;\n" + "> > +\t\t}\n" + "> > +\t\tst->channel_config[channel].ain =\n" + "> > AD7124_CHANNEL_AINP(ain[0]) |\n" + "> > +\t\t\t\t\t\t\302\240\302\240AD7124_CHANNEL_AINM(\n" + "> > ain[1]);\n" + "> > +\t\tst->channel_config[channel].bipolar =\n" + "> > +\t\t\tof_property_read_bool(child, \"adi,bipolar\");\n" + "> > +\n" + "> > +\t\tret = of_property_read_u32(child, \"adi,reference-\n" + "> > select\", &tmp);\n" + "> > +\t\tif (ret)\n" + "> > +\t\t\tst->channel_config[channel].refsel =\n" + "> > AD7124_INT_REF;\n" + "> > +\t\telse\n" + "> > +\t\t\tst->channel_config[channel].refsel = tmp;\n" + "> > +\n" + "> > +\t\tret = of_property_read_u32(child, \"adi,gain\", &tmp);\n" + "> > +\t\tif (ret) {\n" + "> > +\t\t\tst->channel_config[channel].pga_bits = 0;\n" + "> > +\t\t} else {\n" + "> > +\t\t\tres = ad7124_find_closest_match(ad7124_gain,\n" + "> > +\t\t\t\t\t\tARRAY_SIZE(ad7124_gain\n" + "> > ), tmp);\n" + "> > +\t\t\tst->channel_config[channel].pga_bits = res;\n" + "> Hmm. The old question of what to put in DT as it reflects wiring and\n" + "> what to leave to userspace. Gain is tricky as only some values make sense\n" + "> for a given system, but there can be more than one that does...\n" + "> This is probably reasonable as it can be considered as setting the\n" + "> default\n" + "> that makes sense for what is wired.\302\240\302\240Potentially user space could\n" + "> override\n" + "> it later if it wanted to.\n" + "> \n" + "> > \n" + "> > +\t\t}\n" + "> > +\n" + "> > +\t\tret = of_property_read_u32(child, \"adi,odr-hz\", &tmp);\n" + "> Why is this in DT. This one feels like a userspace choice to me. It's\n" + "> only tangentially connected to how things are connected on the board.\n" + "> You also support control from userspace.\302\240\302\240I would pick a sensible\n" + "> general default and then drop this from the DT binding. It's optional\n" + "> anyway.\n" + "> \n" + "> > \n" + "> > +\t\tif (ret)\n" + "> > +\t\t\t/*\n" + "> > +\t\t\t\302\240* 9 SPS is the minimum output data rate\n" + "> > supported\n" + "> > +\t\t\t\302\240* regardless of the selected power mode.\n" + "> > +\t\t\t\302\240*/\n" + "> > +\t\t\tst->channel_config[channel].odr = 9;\n" + "> > +\t\telse\n" + "> > +\t\t\tst->channel_config[channel].odr = tmp;\n" + "> > +\n" + "> > +\t\t*chan = ad7124_channel_template;\n" + "> > +\t\tchan->address = channel;\n" + "> > +\t\tchan->scan_index = channel;\n" + "> > +\t\tchan->channel = ain[0];\n" + "> > +\t\tchan->channel2 = ain[1];\n" + "> > +\n" + "> > +\t\tchan++;\n" + "> > +\t}\n" + "> > +\n" + "> > +\treturn 0;\n" + "> > +err:\n" + "> > +\tof_node_put(child);\n" + "> > +\n" + "> > +\treturn ret;\n" + "> > +}\n" + "> > +\n" + "> > +static int ad7124_setup(struct ad7124_state *st)\n" + "> > +{\n" + "> > +\tunsigned int val, fclk, power_mode;\n" + "> > +\tint i, ret;\n" + "> > +\n" + "> > +\tfclk = clk_get_rate(st->mclk);\n" + "> > +\tif (!fclk)\n" + "> > +\t\treturn -EINVAL;\n" + "> > +\n" + "> > +\t/* The power mode changes the master clock frequency */\n" + "> > +\tpower_mode =\n" + "> > ad7124_find_closest_match(ad7124_master_clk_freq_hz,\n" + "> > +\t\t\t\t\tARRAY_SIZE(ad7124_master_clk_f\n" + "> > req_hz),\n" + "> > +\t\t\t\t\tfclk);\n" + "> > +\tif (fclk != ad7124_master_clk_freq_hz[power_mode]) {\n" + "> > +\t\tret = clk_set_rate(st->mclk, fclk);\n" + "> > +\t\tif (ret)\n" + "> > +\t\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\t/* Set the power mode */\n" + "> > +\tst->adc_control &= ~AD7124_ADC_CTRL_PWR_MSK;\n" + "> > +\tst->adc_control |= AD7124_ADC_CTRL_PWR(power_mode);\n" + "> > +\tret = ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, st-\n" + "> > >adc_control);\n" + "> > +\tif (ret < 0)\n" + "> > +\t\treturn ret;\n" + "> > +\n" + "> > +\tfor (i = 0; i < st->num_channels; i++) {\n" + "> > +\t\tval = st->channel_config[i].ain |\n" + "> > AD7124_CHANNEL_SETUP(i);\n" + "> > +\t\tret = ad_sd_write_reg(&st->sd, AD7124_CHANNEL(i), 2,\n" + "> > val);\n" + "> > +\t\tif (ret < 0)\n" + "> > +\t\t\treturn ret;\n" + "> > +\n" + "> > +\t\tret = ad7124_init_channel_vref(st, i);\n" + "> > +\t\tif (ret < 0)\n" + "> > +\t\t\treturn ret;\n" + "> > +\n" + "> > +\t\tval = AD7124_CONFIG_BIPOLAR(st-\n" + "> > >channel_config[i].bipolar) |\n" + "> > +\t\t\302\240\302\240\302\240\302\240\302\240\302\240AD7124_CONFIG_REF_SEL(st-\n" + "> > >channel_config[i].refsel) |\n" + "> > +\t\t\302\240\302\240\302\240\302\240\302\240\302\240AD7124_CONFIG_PGA(st-\n" + "> > >channel_config[i].pga_bits);\n" + "> > +\t\tret = ad_sd_write_reg(&st->sd, AD7124_CONFIG(i), 2,\n" + "> > val);\n" + "> > +\t\tif (ret < 0)\n" + "> > +\t\t\treturn ret;\n" + "> > +\n" + "> > +\t\tret = ad7124_set_channel_odr(st, i, st-\n" + "> > >channel_config[i].odr);\n" + "> > +\t\tif (ret < 0)\n" + "> > +\t\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\treturn ret;\n" + "> > +}\n" + "> > +\n" + "> > +static int ad7124_probe(struct spi_device *spi)\n" + "> > +{\n" + "> > +\tconst struct spi_device_id *id;\n" + "> > +\tstruct ad7124_state *st;\n" + "> > +\tstruct iio_dev *indio_dev;\n" + "> > +\tint i, ret;\n" + "> > +\n" + "> > +\tindio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));\n" + "> > +\tif (!indio_dev)\n" + "> > +\t\treturn -ENOMEM;\n" + "> > +\n" + "> > +\tst = iio_priv(indio_dev);\n" + "> > +\n" + "> > +\tid = spi_get_device_id(spi);\n" + "> > +\tst->chip_info = &ad7124_chip_info_tbl[id->driver_data];\n" + "> > +\n" + "> > +\tad_sd_init(&st->sd, indio_dev, spi, &ad7124_sigma_delta_info);\n" + "> > +\n" + "> > +\tspi_set_drvdata(spi, indio_dev);\n" + "> > +\n" + "> > +\tindio_dev->dev.parent = &spi->dev;\n" + "> > +\tindio_dev->name = spi_get_device_id(spi)->name;\n" + "> > +\tindio_dev->modes = INDIO_DIRECT_MODE;\n" + "> > +\tindio_dev->info = &ad7124_info;\n" + "> > +\n" + "> > +\tret = ad7124_of_parse_channel_config(indio_dev, spi-\n" + "> > >dev.of_node);\n" + "> > +\tif (ret < 0)\n" + "> > +\t\treturn ret;\n" + "> > +\n" + "> > +\tfor (i = 0; i < ARRAY_SIZE(st->vref); i++) {\n" + "> > +\t\tif (i != AD7124_INT_REF) {\n" + "> > +\t\t\tst->vref[i] =\n" + "> > devm_regulator_get_optional(&spi->dev,\n" + "> > +\t\t\t\t\t\t\tad7124_ref_nam\n" + "> > es[i]);\n" + "> > +\t\t\tif (PTR_ERR(st->vref[i]) == -ENODEV)\n" + "> > +\t\t\t\tcontinue;\n" + "> > +\t\t\telse if (IS_ERR(st->vref[i]))\n" + "> > +\t\t\t\treturn PTR_ERR(st->vref[i]);\n" + "> > +\n" + "> > +\t\t\tret = regulator_enable(st->vref[i]);\n" + "> > +\t\t\tif (ret)\n" + "> > +\t\t\t\treturn ret;\n" + "> > +\t\t}\n" + "> > +\t}\n" + "> > +\n" + "> > +\tst->mclk = devm_clk_get(&spi->dev, \"mclk\");\n" + "> > +\tif (IS_ERR(st->mclk)) {\n" + "> > +\t\tret = PTR_ERR(st->mclk);\n" + "> > +\t\tgoto error_regulator_disable;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = clk_prepare_enable(st->mclk);\n" + "> > +\tif (ret < 0)\n" + "> > +\t\tgoto error_regulator_disable;\n" + "> > +\n" + "> > +\tret = ad7124_soft_reset(st);\n" + "> > +\tif (ret < 0)\n" + "> > +\t\tgoto error_clk_disable_unprepare;\n" + "> > +\n" + "> > +\tret = ad7124_setup(st);\n" + "> > +\tif (ret < 0)\n" + "> > +\t\tgoto error_clk_disable_unprepare;\n" + "> > +\n" + "> > +\tret = ad_sd_setup_buffer_and_trigger(indio_dev);\n" + "> > +\tif (ret < 0)\n" + "> > +\t\tgoto error_clk_disable_unprepare;\n" + "> > +\n" + "> > +\tret = iio_device_register(indio_dev);\n" + "> > +\tif (ret < 0) {\n" + "> > +\t\tdev_err(&spi->dev, \"Failed to register iio device\\n\");\n" + "> > +\t\tgoto error_remove_trigger;\n" + "> > +\t}\n" + "> > +\n" + "> > +\treturn 0;\n" + "> > +\n" + "> > +error_remove_trigger:\n" + "> > +\tad_sd_cleanup_buffer_and_trigger(indio_dev);\n" + "> > +error_clk_disable_unprepare:\n" + "> > +\tclk_disable_unprepare(st->mclk);\n" + "> > +error_regulator_disable:\n" + "> > +\tfor (i = ARRAY_SIZE(st->vref) - 1; i >= 0; i--) {\n" + "> > +\t\tif (!IS_ERR_OR_NULL(st->vref[i]))\n" + "> > +\t\t\tregulator_disable(st->vref[i]);\n" + "> > +\t}\n" + "> > +\n" + "> > +\treturn ret;\n" + "> > +}\n" + "> > +\n" + "> > +static int ad7124_remove(struct spi_device *spi)\n" + "> > +{\n" + "> > +\tstruct iio_dev *indio_dev = spi_get_drvdata(spi);\n" + "> > +\tstruct ad7124_state *st = iio_priv(indio_dev);\n" + "> > +\tint i;\n" + "> > +\n" + "> > +\tiio_device_unregister(indio_dev);\n" + "> > +\tclk_disable_unprepare(st->mclk);\n" + "> > +\tad_sd_cleanup_buffer_and_trigger(indio_dev);\n" + "> The ordering here should match that in the error path above.\n" + "> (so the two things here should be reversed).\n" + "> It's in the category of making things obviously safe rather than an\n" + "> actual issue.\n" + "> I like to be able to check the ordering only once rather than twice\n" + "> when reviewing so will always confirm they match.\n" + "> \n" + "> > \n" + "> > +\n" + "> > +\tfor (i = ARRAY_SIZE(st->vref) - 1; i >= 0; i--) {\n" + "> > +\t\tif (!IS_ERR_OR_NULL(st->vref[i]))\n" + "> > +\t\t\tregulator_disable(st->vref[i]);\n" + "> > +\t}\n" + "> > +\n" + "> > +\treturn 0;\n" + "> > +}\n" + "> > +\n" + "> > +static const struct spi_device_id ad7124_id_table[] = {\n" + "> > +\t{ \"ad7124-4\", ID_AD7124_4 },\n" + "> > +\t{ \"ad7124-8\", ID_AD7124_8 },\n" + "> > +\t{}\n" + "> > +};\n" + "> > +MODULE_DEVICE_TABLE(spi, ad7124_id_table);\n" + "> > +\n" + "> > +static const struct of_device_id ad7124_of_match[] = {\n" + "> > +\t{ .compatible = \"adi,ad7124-4\" },\n" + "> > +\t{ .compatible = \"adi,ad7124-8\" },\n" + "> > +\t{ },\n" + "> > +};\n" + "> > +MODULE_DEVICE_TABLE(of, ad7124_of_match);\n" + "> > +\n" + "> > +static struct spi_driver ad71124_driver = {\n" + "> > +\t.driver = {\n" + "> > +\t\t.name = \"ad7124\",\n" + "> > +\t\t.of_match_table = ad7124_of_match,\n" + "> > +\t},\n" + "> > +\t.probe = ad7124_probe,\n" + "> > +\t.remove\t= ad7124_remove,\n" + "> > +\t.id_table = ad7124_id_table,\n" + "> > +};\n" + "> > +module_spi_driver(ad71124_driver);\n" + "> > +\n" + "> > +MODULE_AUTHOR(\"Stefan Popa <stefan.popa@analog.com>\");\n" + "> > +MODULE_DESCRIPTION(\"Analog Devices AD7124 SPI driver\");\n" + "> > +MODULE_LICENSE(\"GPL\");\n" + > -e06a8a28b99ad60797454ff47de4aa7430450614fb1fd30876a70c59a62f08b0 +1bb1ae41f7659d5d3c19a90b240171e7b283545067f0a8af9a4961a232698c77
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.