O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Buna ziua.

Noi, Victor Antipov și Ilya Aleshin, vom vorbi astăzi despre experiența noastră de lucru cu dispozitive USB prin Python PyUSB și puțin despre inginerie inversă.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

preistorie

În 2019, Decretul Guvernului Federației Ruse nr. 224 „Cu privire la aprobarea Regulilor de etichetare a produselor din tutun cu mijloace de identificare și caracteristici ale implementării unui sistem de informare de stat pentru monitorizarea circulației mărfurilor supuse etichetării obligatorii cu mijloace de identificare în legătură cu produsele din tutun” a intrat în vigoare.
Documentul explică că de la 1 iulie 2019 producătorii sunt obligați să eticheteze fiecare pachet de tutun. Iar distribuitorii direcți trebuie să primească aceste produse cu executarea unui document de transfer universal (UDD). Magazinele, la rândul lor, trebuie să înregistreze vânzarea produselor etichetate prin casa de marcat.

De asemenea, de la 1 iulie 2020, circulația produselor din tutun neetichetate este interzisă. Aceasta înseamnă că toate pachetele de țigări trebuie să fie marcate cu un cod de bare Datamatrix special. Mai mult, - un punct important - s-a dovedit că Datamatrix nu va fi obișnuit, ci invers. Adică nu cod negru pe alb, ci invers.

Ne-am testat scanerele și s-a dovedit că cele mai multe dintre ele trebuie să fie reflashate/reeducate, altfel pur și simplu nu pot funcționa normal cu acest cod de bare. Această întorsătură a evenimentelor ne-a garantat o mare bătaie de cap, deoarece compania noastră are o mulțime de magazine care sunt împrăștiate pe un teritoriu vast. Câteva zeci de mii de case de marcat – și foarte puțin timp.

Ce era de făcut? Există două opțiuni. În primul rând: inginerii de la fața locului reflashează manual și reglează scanerele. În al doilea rând: lucrăm de la distanță și, de preferință, acoperim mai multe scanere simultan într-o singură iterație.

Prima variantă, evident, nu era potrivită pentru noi: ar trebui să cheltuim bani pe vizitarea inginerilor, iar în acest caz ar fi dificil să controlăm și să coordonăm procesul. Dar cel mai important lucru este că oamenii ar lucra, adică am putea primi o mulțime de erori și, cel mai probabil, nu respectăm termenul.

A doua opțiune este bună pentru toată lumea, dacă nu pentru un singur lucru. Unii furnizori nu aveau instrumentele de intermitent la distanță de care aveam nevoie pentru toate sistemele de operare necesare. Și din moment ce termenele limită se scurgeau, a trebuit să mă gândesc cu capul meu.

În continuare, vă vom spune cum am dezvoltat instrumente pentru scanere portabile pentru sistemul de operare Debian 9.x (toate casele noastre de marcat sunt pe Debian).

Rezolvați ghicitoarea: cum să flashați un scaner

relatează Victor Antipov.

Utilitarul oficial furnizat de furnizor funcționează sub Windows și numai cu IE. Utilitarul poate flash și configura scanerul.

Deoarece sistemul nostru țintă este Debian, am instalat un server USB-redirector pe Debian și un client USB-redirector pe Windows. Folosind utilitare de redirecționare USB, am redirecționat scanerul de la o mașină Linux la o mașină Windows.

Un utilitar de la un furnizor de Windows a văzut scanerul și chiar l-a făcut flash în mod normal. Astfel, am făcut prima concluzie: nimic nu depinde de sistemul de operare, este o chestiune de protocol intermitent.

BINE. Am rulat intermiterea pe mașina Windows și am eliminat descărcarea de pe mașina Linux.

Am îndesat groapa în WireShark și... ne-am întristat (voi omite câteva dintre detaliile gropii, nu prezintă niciun interes).

Ce ne-a arătat groapa:

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Adresele 0000-0030, judecând după Wireshark, sunt informații de serviciu USB.

Ne-a interesat partea 0040-0070.

Nimic nu a fost clar dintr-un cadru de transmisie, cu excepția caracterelor MOCFT. Aceste caractere s-au dovedit a fi caractere din fișierul firmware, precum și caracterele rămase până la sfârșitul cadrului (fișierul firmware este evidențiat):

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Ce înseamnă simbolurile fd 3e 02 01 fe, eu personal, ca Ilya, habar n-aveam.

M-am uitat la următorul cadru (informațiile de service au fost eliminate aici, fișierul firmware a fost evidențiat):

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Ce a devenit clar? Că primii doi octeți sunt un fel de constantă. Toate blocurile ulterioare au confirmat acest lucru, dar înainte de sfârșitul blocului de transmisie:

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Acest cadru era, de asemenea, uluitor, deoarece constanta se schimbase (evidențiată) și, în mod ciudat, exista o parte din fișier. Mărimea octeților transferați ai fișierului a arătat că au fost transferați 1024 de octeți. Din nou nu știam ce înseamnă octeții rămași.

În primul rând, ca o poreclă BBS veche, am trecut în revistă protocoalele standard de transmisie. Niciun protocol nu a transmis 1024 de octeți. Am început să studiez hardware-ul și am dat peste protocolul 1K Xmodem. Permitea transmiterea a 1024, dar cu o avertizare: la început doar 128, și numai dacă nu existau erori, protocolul a crescut numărul de octeți transmisi. Am avut imediat un transfer de 1024 de octeți. Am decis să studiez protocoalele de transmisie și în special modemul X.

Au existat două variante ale modemului.

În primul rând, formatul de pachet XMODEM cu suport CRC8 (XMODEM original):

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

În al doilea rând, formatul de pachet XMODEM cu suport CRC16 (XmodemCRC):

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Arată similar, cu excepția SOH, numărul pachetului și CRC și lungimea pachetului.

M-am uitat la începutul celui de-al doilea bloc de transmisie (și am văzut din nou fișierul firmware, dar deja indentat cu 1024 de octeți):

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Am văzut antetul familiar fd 3e 02, dar următorii doi octeți se schimbaseră deja: era 01 fe și devenea 02 fd. Apoi am observat că al doilea bloc era acum numerotat 02 și astfel am înțeles: în fața mea era numerotarea blocului de transmisie. Prima viteză 1024 este 01, a doua este 02, a treia este 03 și așa mai departe (dar în hex, desigur). Dar ce înseamnă schimbarea de la fe la fd? Ochii au văzut o scădere cu 1, creierul a amintit că programatorii numără de la 0, nu de la 1. Dar atunci de ce primul bloc este 1 și nu 0? Inca nu am gasit raspunsul la aceasta intrebare. Dar am înțeles cum se numără al doilea bloc. Al doilea bloc nu este altceva decât FF – (minus) numărul primului bloc. Astfel, al doilea bloc a fost desemnat ca = 02 (FF-02) = 02 FD. Citirea ulterioară a gropii mi-a confirmat presupunerea.

Apoi a început să apară următoarea imagine a transmisiei:

Începutul transmisiei
fd 3e 02 – Start
01 FE – contor transmisii
Transfer (34 de blocuri, 1024 de octeți transferați)
fd 3e 1024 de octeți de date (împărțit în blocuri de 30 de octeți).
Sfârșitul transmisiei
fd 25

Datele rămase vor fi aliniate la 1024 de octeți.

Cum arată cadrul final al transmisiei blocului:

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

fd 25 – semnal pentru terminarea transmisiei blocului. Următorul 2f 52 – restul fișierului cu dimensiunea de până la 1024 de octeți. 2f 52, judecând după protocol, este o sumă de control CRC pe 16 biți.

De dragul vremurilor vechi, am făcut un program în C care a extras 1024 de octeți dintr-un fișier și a calculat un CRC de 16 biți. Lansarea programului a arătat că acesta nu este un CRC pe 16 biți. Stupor din nou - timp de aproximativ trei zile. În tot acest timp am încercat să înțeleg ce ar putea fi, dacă nu o sumă de control. În timp ce studiam site-urile în limba engleză, am descoperit că X-modem-ul folosește propriul calcul al sumei de control - CRC-CCITT (XModem). Nu am găsit nicio implementare C a acestui calcul, dar am găsit un site care a calculat această sumă de control online. După ce a transferat 1024 de octeți ai fișierului meu pe pagina web, site-ul mi-a arătat o sumă de control care se potrivea complet cu suma de control din fișier.

Ura! Ultima ghicitoare a fost rezolvată, acum trebuia să-mi fac propriul firmware. Apoi, mi-am transmis cunoștințele (și mi-au rămas doar în cap) lui Ilya, care este familiarizat cu puternicul set de instrumente Python.

Crearea unui program

relatează Ilya Aleshin.

După ce am primit instrucțiunile corespunzătoare, am fost foarte „fericit”.

Unde sa încep? Așa este, de la început.  Din luarea unui dump de la portul USB.

Lansați USB-pcap https://desowin.org/usbpcap/tour.html

Selectați portul la care este conectat dispozitivul și fișierul în care vom salva dump-ul.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Conectăm scanerul la o mașină în care este instalat software-ul nativ EZConfigScanning pentru Windows.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

În el găsim elementul pentru trimiterea comenzilor către dispozitiv. Dar cum rămâne cu echipele? De unde le pot lua?
Când programul pornește, echipamentul este interogat automat (vom vedea acest lucru puțin mai târziu). Și erau coduri de bare de antrenament din documentele oficiale ale echipamentelor. DEFALT. Aceasta este echipa noastră.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

S-au primit datele necesare. Deschideți dump.pcap prin wireshark.

Blocați la pornirea EZConfigScanning. Locurile la care trebuie să fii atent sunt marcate cu roșu.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Văzând toate acestea pentru prima dată, mi-am pierdut inima. Nu este clar unde să sape în continuare.

Un pic de brainstorming și-și-și... Aha! În groapă afară - este inȘi in acest afară.

Am căutat pe google ce este URB_INTERRUPT. Am aflat că aceasta este o metodă de transfer de date. Și există 4 astfel de metode: control, întrerupere, izocron, în vrac. Puteți citi despre ele separat.

Iar adresele punctelor finale din interfața dispozitivului USB pot fi obținute fie prin comanda „lsusb –v”, fie folosind pyusb.

Acum trebuie să găsim toate dispozitivele cu acest VID. Puteți căuta în mod specific după VID:PID.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Arată astfel:

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Deci, avem informațiile necesare: comenzile P_INFO. sau DEFALT, adrese de unde se scrie comenzi endpoint=03 și de unde se obține răspunsul endpoint=86. Tot ce rămâne este să convertiți comenzile în hex.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Deoarece am găsit deja dispozitivul, să-l deconectăm de la kernel...

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

... și scrieți la punctul final cu adresa 0x03,

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

... și apoi citiți răspunsul de la punctul final cu adresa 0x86.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Răspuns structurat:

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

Vedem aceste date în dump.pcap.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Grozav! Convertiți codurile de bare de sistem în hexadecimale. Gata, funcționalitatea de antrenament este gata.

Dar firmware-ul? Totul pare să fie la fel, dar există o nuanță.

După o descărcare completă a procesului de intermitent, am înțeles aproximativ cu ce avem de-a face. Iată un articol despre XMODEM, care a fost de mare ajutor pentru a înțelege cum are loc această comunicare, deși în termeni generali: http://microsin.net/adminstuff/others/xmodem-protocol-overview.html Recomand lectura.

Privind la dump, puteți vedea că dimensiunea cadrului este 1024, iar dimensiunea datelor URB este 64.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Prin urmare – 1024/64 – obținem 16 linii într-un bloc, citim fișierul firmware câte un caracter și formăm un bloc. Complementarea unui rând într-un bloc cu caractere speciale fd1e1 + numărul blocului.
Următoarele 14 linii sunt suplimentate cu fd25 +, folosind XMODEM.calc_crc() se calculează suma de control a întregului bloc (a fost nevoie de mult timp pentru a înțelege că „FF – 1” este CSUM) și ultima, a 16-a linie este suplimentată cu fd3e.

S-ar părea că asta este, citiți fișierul firmware, loviți blocurile, deconectați scanerul de la kernel și trimiteți-l la dispozitiv. Dar nu este atât de simplu. Scanerul trebuie să fie comutat în modul firmware,
отправив ему NEWAPP = ‘\xfd\x0a\x16\x4e\x2c\x4e\x45\x57\x41\x50\x50\x0d’.
De unde este echipa asta?? Din groapa.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Dar nu putem trimite un întreg bloc la scaner din cauza limitei de 64:

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

Ei bine, scanerul în modul intermitent NEWAPP nu acceptă hex. Prin urmare, va trebui să traduceți fiecare linie 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]

Și apoi trimiteți aceste date la scaner.

Primim raspunsul:

[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]

Dacă verificați articolul despre XMODEM, va deveni clar: datele au fost acceptate.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

După ce toate blocurile au fost transferate, completăm transferul END_TRANSFER = 'xfdx01x04'.

Ei bine, deoarece aceste blocuri nu conțin informații pentru oamenii obișnuiți, vom instala firmware-ul în modul ascuns în mod implicit. Și pentru orice eventualitate, vom organiza o bară de progres prin tqdm.

O sarcină pentru un dezvoltator sau modul în care am făcut flash scanere portabile fără un furnizor

De fapt, atunci este o chestiune de lucruri mărunte. Tot ce rămâne este să împachetăm soluția în scripturi pentru replicarea în masă la un moment clar definit, pentru a nu încetini procesul de lucru la casele de casă și să adăugați înregistrarea în jurnal.

Total

După ce am petrecut mult timp, efort și păr pe cap, am reușit să dezvoltăm soluțiile de care aveam nevoie și, de asemenea, am îndeplinit termenul limită. În același timp, scanerele sunt acum reflashate și reinstruite central, controlăm în mod clar întregul proces. Compania a economisit timp și bani și am câștigat o experiență neprețuită în echipamentele de inginerie inversă de acest tip.

Sursa: www.habr.com

Adauga un comentariu