Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Pershendetje te gjitheve

Sot, Viktor Antipov dhe Ilya Aleshin do të ndajnë përvojat tona duke punuar me pajisjet USB nëpërmjet Python PyUSB dhe pak rreth inxhinierisë së kundërt.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

parahistorinë

Në vitin 2019, hyri në fuqi Rezoluta e Qeverisë Ruse nr. 224 "Për miratimin e Rregullave për shënimin e produkteve të duhanit me mjete identifikimi dhe specifikat e zbatimit të një sistemi shtetëror informacioni për monitorimin e qarkullimit të mallrave që i nënshtrohen shënimit të detyrueshëm me mjete identifikimi në lidhje me produktet e duhanit".
Dokumenti shpjegon se, që nga 1 korriku 2019, prodhuesit janë të detyruar të etiketojnë çdo pako duhani. Shpërndarësit e drejtpërdrejtë duhet t'i marrin këto produkte me një dokument universal transferimi (UTD). Dyqanet, nga ana tjetër, duhet të regjistrojnë shitjen e produkteve të etiketuara në arkë.

Gjithashtu, që nga 1 korriku 2020, qarkullimi i produkteve të duhanit pa etiketa është i ndaluar. Kjo do të thotë që të gjitha paketat e cigareve duhet të shënohen me një barkod të veçantë Datamatrix. Është e rëndësishme të theksohet se Datamatrix nuk do të jetë një barkod standard, por një i anasjelltë. Domethënë, jo një kod i zi mbi një të bardhë, por e kundërta.

Ne testuam skanerët tanë dhe doli që shumica e tyre duheshin riprogramuar ose ritrajnuar, përndryshe thjesht nuk do të funksiononin siç duhet me këtë barkod. Ky kthesë e ngjarjeve na garantoi një dhimbje koke të madhe, pasi kompania jonë ka një numër të madh dyqanesh të shpërndara në një territor të gjerë. Dhjetëra mijëra arka - dhe shumë pak kohë.

Çfarë duhet të bëjmë? Ekzistojnë dy mundësi. Së pari, inxhinierët në vend i ripërpunojnë dhe i rregullojnë manualisht skanerët. Së dyti, ne punojmë nga distanca dhe, idealisht, mbulojmë skanerë të shumtë në një përsëritje të vetme.

Opsioni i parë ishte padyshim i papërshtatshëm për ne: do të na duhej të shpenzonim para për vizitat e inxhinierëve dhe do të kishte qenë e vështirë të monitoronim dhe koordinonim procesin. Por më e rëndësishmja, do të kishte përfshirë njerëz, që do të thotë se do të kishim hasur gabime të shumta dhe me shumë mundësi do të kishim humbur afatin.

Opsioni i dytë do të kishte qenë perfekt, përveç një problemi. Disa shitës nuk kishin mjetet e instalimit në distancë që na nevojiteshin për të gjitha sistemet operative të kërkuara. Dhe meqenëse afatet ishin të shkurtra, na u desh ta zgjidhnim vetë.

Më pas, do t'ju tregojmë se si kemi zhvilluar mjete për skanerët portativë që përdorin Debian 9.x (të gjitha arkëtimet tona janë në Debian).

Zgjidh enigmën: si të ndezësh një skaner

Viktor Antipov tregon historinë.

Programi zyrtar i ofruar nga shitësi funksionon në Windows, por vetëm me Internet Explorer. Mund të instalojë dhe konfigurojë skanerin.

Meqenëse sistemi ynë i synuar është Debian, ne instaluam serverin USB-redirector në Debian dhe klientin USB-redirector në Windows. Duke përdorur shërbimet USB-redirector, ne e ridrejtuam skanerin nga makina Linux në makinën Windows.

Programi i Windows i shitësit e zbuloi skanerin dhe madje e instaloi me sukses. Pra, përfundimi ynë i parë: sistemi operativ nuk ka të bëjë fare me të; problemi qëndron në protokollin e instalimit.

Në rregull. Ne filluam përditësimin e firmware-it në makinën Windows dhe morëm një dump në makinën Linux.

E futëm skedarin në WireShark dhe... u trishtuam (do të anashkaloj disa nga detajet e skedarit, nuk kanë asnjë interes).

Çfarë na tregoi deponia:

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Adresat 0000-0030, sipas Wireshark, janë informacion mbi shërbimin USB.

Ne ishim të interesuar për pjesën 0040-0070.

Asgjë nuk ishte e qartë nga kuadri i vetëm i transmetimit përveç simboleve MOCFT. Këto simbole rezultuan të ishin nga skedari i firmware-it, ashtu si edhe pjesa tjetër e simboleve deri në fund të kuadrit (skedari i firmware-it është i theksuar):

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Personalisht, unë, ashtu si Ilya, nuk kisha idenë se çfarë domethënie kishin simbolet fd 3e 02 01 fe.

Shikova kornizën e mëposhtme (informacioni i shërbimit është hequr këtu, skedari i firmware-it është i theksuar):

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Çfarë u bë e qartë? Se dy bajtet e para janë një lloj konstante. Të gjitha blloqet pasuese e konfirmuan këtë, por jo deri në fund të bllokut të transmetimit:

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Ky kuadër më ngatërroi edhe mua, pasi konstantja (e theksuar) kishte ndryshuar dhe, çuditërisht, një pjesë e skedarit ishte e pranishme. Madhësia e bajteve të transferuara tregonte se ishin transferuar 1024 bajt. Çfarë domethënie kishin bajtet e mbetura—përsëri, nuk kisha ide.

Gjëja e parë që bëra, si një BBSer veteran, ishte të shqyrtoja protokollet standarde të transmetimit. Asnjëri prej tyre nuk mund të transmetonte 1024 bajt. Fillova të bëja kërkime për harduerin dhe hasa në protokollin 1K Xmodem. Ai lejonte 1024 bajt, por me një problem: fillimisht, vetëm 128, dhe vetëm nëse nuk kishte gabime protokolli do të rriste numrin e bajteve të transmetuar. Po transmetoja menjëherë 1024 bajt. Vendosa të studioja protokollet e transmetimit, konkretisht Xmodem.

Kishte dy variacione të modemit.

Së pari, formati i paketës XMODEM me mbështetje CRC8 (XMODEM origjinal):

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Së dyti, formati i paketës XMODEM me mbështetje CRC16 (XmodemCRC):

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Duket e ngjashme përveç SOH, numrit të paketës, CRC dhe gjatësisë së paketës.

Shikova fillimin e bllokut të dytë të transmetimit (dhe përsëri pashë skedarin e firmware-it, por me një indent prej 1024 bajtesh):

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Pashë një kokë të njohur, fd 3e 02, por dy bajtet e ardhshme kishin ndryshuar tashmë: ishte 01 fe, tani 02 fd. Pastaj vura re se blloku i dytë tani ishte numëruar 02, dhe kështu kuptova: ky ishte numërimi i një blloku transferimi. Transferimi i parë 1024 është 01, i dyti është 02, i treti është 03, e kështu me radhë (por në heksadecimal, sigurisht). Por çfarë do të thotë ndryshimi nga fe në fd? Sytë e mi panë një rënie prej 1, truri im më kujtoi se programuesit numërojnë nga 0, jo nga 1. Por atëherë pse blloku i parë është 1, jo 0? Nuk e gjeta kurrë përgjigjen e kësaj pyetjeje. Por e kuptova se si llogaritet blloku i dytë. Blloku i dytë nuk është gjë tjetër veçse FF - (minus) numri i bllokut të parë. Kështu, blloku i dytë u përcaktua si = 02 (FF-02) = 02 FD. Leximi pasues i dump-it konfirmoi hamendësimin tim.

Pastaj filloi të shfaqej fotografia e mëposhtme e transmetimit:

Fillimi i transmetimit
fd 3e 02 – Fillimi
01 FE – numërues transmetimi
Transmetimi (34 blloqe, 1024 bajt të transferuar)
fd 3e 1024 bajt të dhënash (të ndara në blloqe 30-bajtëshe).
Fundi i transmetimit
fd 25

Të dhënat mbeten për t'u përshtatur në 1024 bajt.

Si duket fundi i kornizës së transmetimit të bllokut:

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

fd 25 është sinjali për transmetimin e bllokut të fundit. Pastaj 2f 52 është pjesa e mbetur e skedarit deri në 1024 bajt. 2f 52, sipas protokollit, është shuma e kontrollit CRC 16-bit.

Nga zakoni, krijova një program në C që nxori 1024 bajt nga një skedar dhe llogariti CRC-në 16-bit. Ekzekutimi i programit zbuloi se nuk ishte një CRC 16-bit. Përsëri, mbeta i hutuar - për rreth tre ditë. Gjatë gjithë kësaj kohe, po përpiqesha të kuptoja se çfarë mund të ishte nëse jo një shumë kontrolli. Ndërsa kërkoja në faqet e internetit në gjuhën angleze, zbulova se X-modem përdor llogaritjen e vet të shumës së kontrollit - CRC-CCITT (XModem). Nuk munda të gjeja asnjë implementim C të kësaj llogaritjeje, por gjeta një faqe interneti që llogariste këtë shumë kontrolli në internet. Pasi ngarkova 1024 bajt të skedarit të saj në një faqe interneti, faqja e internetit më tregoi një shumë kontrolli që përputhej plotësisht me shumën e kontrollit nga skedari.

Ura! Enigma e fundit u zgjidh, tani duhej të krijoja firmware-in tim. Më pas, ia kalova njohuritë e mia (të cilat më mbetën vetëm në mendje) Ilya-s, i cili është i njohur me një set mjetesh të fuqishme - Python-in.

Krijimi i një programi

Ilya Aleshin tregon historinë.

Pasi mora udhëzimet përkatëse, u ndjeva shumë i “kënaqur”.

Nga t’ia fillojmë? Pikërisht, që nga fillimi.  Duke e çaktivizuar portën USB.

Hap USB-pcap https://desowin.org/usbpcap/tour.html

Zgjidhni portin me të cilin është lidhur pajisja dhe skedarin ku do ta ruajmë skedarin e hedhur.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Ne e lidhim skanerin me një makinë ku është instaluar softueri vendas EZConfigScanning për Windows.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Atje gjejmë opsionin për të dërguar komanda në pajisje. Po komandat? Ku mund t'i marr?
Kur programi fillon, pajisja pyetet automatikisht (do ta shohim këtë pak më vonë). Kishte edhe barkode trajnimi nga dokumentacioni zyrtar i pajisjes. DEFALT. Ky është ekipi ynë.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Të dhënat e nevojshme janë marrë. Hapni dump.pcap duke përdorur Wireshark.

Blloko kur fillon EZConfigScanning. Zonat që kërkojnë vëmendje janë të theksuara me të kuqe.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Duke i parë të gjitha këto për herë të parë, u dekurajova. Nuk ishte e qartë se ku të gërmoja më tej.

Pak shkëmbim idesh dhe... Aha! Në hale nga - kjo inDhe in это nga.

Kërkova në Google për URB_INTERRUPT dhe zbulova se është një metodë transferimi të dhënash. Ekzistojnë katër prej këtyre metodave: kontrolli, ndërprerja, izokrone dhe pjesa më e madhe. Mund të lexoni rreth tyre veçmas.

Dhe adresa e pikës fundore në ndërfaqen e pajisjes USB mund të merret ose përmes komandës "lsusb –v" ose duke përdorur pyusb.

Tani duhet të gjejmë të gjitha pajisjet me këtë VID. Mund të kërkoni specifikisht sipas VID:PID.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Duket kështu:

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Pra, kemi informacionin e nevojshëm: komandat P_INFO ose DEFALT, adresat ku duhet të shkruhen komandat (pika fundore=03) dhe ku duhet të merret përgjigja (pika fundore=86). E tëra çfarë mbetet është t'i konvertojmë komandat në heksadecimale.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Meqenëse e kemi gjetur tashmë pajisjen, le ta shkëputim atë nga bërthama...

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

...dhe shkruaj në pikën fundore me adresën 0x03,

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

... dhe pastaj lexojmë përgjigjen nga pika fundore me adresën 0x86.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Përgjigje e strukturuar:

P_INFOfmt: 1
mode: app
app-present: 1
boot-present: 1
hw-sn: 18072B44CA
hw-rev: 0x20
cbl: 4
app-sw-rev: CP000116BBA
boot-sw-rev: CP000014BAD
flash: 3
app-m_name: Voyager 1450g
boot-m_name: Voyager 1450g
app-p_name: 1450g
boot-p_name: 1450g
boot-time: 16:56:02
boot-date: Oct 16 2014
app-time: 08:49:30
app-date: Mar 25 2019
app-compat: 289
boot-compat: 288
csum: 0x6986

Ne i shohim këto të dhëna në dump.pcap.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Shkëlqyeshëm! Po i konvertojmë barkodet e sistemit në hekzagonale. Kaq ishte, funksionaliteti i trajnimit është gati.

Po firmware-i? Duket se është i njëjtë, por ka një nuancë.

Pasi kapëm një skedar të plotë të procesit të përditësimit të firmware-it, krijuam një ide të përafërt se me çfarë po merreshim. Ja një artikull rreth XMODEM, i cili na ndihmoi vërtet të kuptojmë se si funksionon ky komunikim, megjithëse në terma të përgjithshëm: http://microsin.net/adminstuff/others/xmodem-protocol-overview.html Unë rekomandoj ta lexoni.

Duke parë skedarin dump, mund të shihni se madhësia e kornizës është 1024, dhe madhësia e të dhënave URB është 64.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Prandaj – 1024/64 – marrim 16 rreshta në një bllok, lexojmë skedarin e firmware-it një nga një dhe formojmë bllokun. Shtojmë një rresht në bllok me karakteret speciale fd3e02 + numrin e bllokut.
Ne i plotësojmë 14 rreshtat e ardhshëm me fd25 +, duke përdorur XMODEM.calc_crc() llogarisim checksum-in e të gjithë bllokut (na u desh shumë kohë për të kuptuar se "FF – 1" është CSUM) dhe plotësojmë rreshtin e fundit, të 16-të, me fd3e.

Duket se kaq është: lexo skedarin e firmware-it, kliko te blloqet, shkëput skanerin nga bërthama dhe dërgoje atë te pajisja. Por nuk është kaq e thjeshtë. Skaneri duhet të vihet në modalitetin e firmware-it.
отправив ему NEWAPP = ‘\xfd\x0a\x16\x4e\x2c\x4e\x45\x57\x41\x50\x50\x0d’.
Nga vjen kjo komandë? Nga një skedar dump.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Por nuk mund ta dërgojmë të gjithë bllokun në skaner për shkak të kufizimit prej 64:

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Dhe skaneri nuk pranon heksadecam në modalitetin e ndezjes NEWAPP. Pra, do t'ju duhet të përktheni çdo rresht të bytes_array.

[253, 10, 22, 78, 44, 78, 69, 87, 65, 80, 80, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Dhe pastaj dërgoni këto të dhëna në skaner.

Ne marrim përgjigjen:

[2, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Nëse e kontrolloni artikullin rreth XMODEM, bëhet e qartë: të dhënat janë marrë.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Pasi të jenë transferuar të gjitha blloqet, ne e përfundojmë transferimin END_TRANSFER = 'xfdx01x04'.

Meqenëse këto blloqe nuk u japin asnjë informacion njerëzve të zakonshëm, ne do ta ekzekutojmë firmware-in në modalitetin e fshehtë si parazgjedhje. Dhe për çdo rast, do të konfigurojmë një shirit progresi duke përdorur tqdm.

Një detyrë për një zhvillues, ose si ne ndezëm skanerët e dorës pa një shitës

Tani, e tëra çfarë mbetet është të mbështillet zgjidhja në skripte për vendosje masive në një kohë të përcaktuar qartë, në mënyrë që të mos ngadalësohet procesi i arkëtimit, dhe të shtohet regjistrimi.

Total

Pasi investuam shumë kohë, përpjekje dhe mund, arritëm të zhvillonim zgjidhjet që na nevojiteshin dhe e përmbushëm afatin. Për më tepër, skanerët tani janë riprogramuar dhe ritrajnuar në mënyrë qendrore, duke na dhënë kontroll të saktë mbi të gjithë procesin. Kompania kurseu kohë dhe para, dhe ne fituam përvojë të paçmuar në inxhinierinë e kundërt të këtij lloji pajisjesh.

Burimi: www.habr.com