
; CGSN-патч v.1.2

;AT+CGSN? - версию патча выдаёт
;AT+CGSN - (стандартно) IMEI master-платформы
;AT+CGSN=0,XXXXXXXX,YYYY - чтение данных с адреса XXXXXXXX длиной YYYY
;AT+CGSN=1,XXXXXXXX,#YYYYYYY... - запись данных YYYYYYYY... по адресу XXXXXXXX
;AT+CGSN=2,XXXXXXXX,YYYYYYYY,#ZZZZZZZZ - поиск данных ZZZZZ... с адреса XXXXXXXX в блоке длиной YYYYYYYY
;AT+CGSN=3 - получение адреса текущей MCC команды
;AT+CGSN=4,XXXXXXXX - запуск MCC с адреса XXXXXXXX
; # - обязательный модификатора (иначе система выкидывает ведущие нули)

.patchname "CGSN"
.patchinfo "CGSN патч. AT+CGSN? - справка."

.little
.thumb

;переключалка компиляции
;.xdef D780XEHE1
;.xdef D880XEHG2
.xdef D980XEHJ6

.ifdef D780XEHE1
.equ a_atp_Result 0x308A3AF4
.equ s_atp_CurrentCommandInfo 0x308A4B94
.equ gs_look 0x30613A04
.equ CGSNCommand 0x20EB92B4
.equ SendDataReq 0x2170BD50
.equ memcpy 0x20961E00
.equ s_RunMcc 0x20F30834
.equ s_rep01 0x20C50C58
.equ s_rep02 0x20C50C60
.equ s_rep03 0x20C5551C
.equ s_rep04 0x20EB7FA1
.equ s_rep05 0x212F3C53
.equ s_patch 0x214E23C0
.endif

.ifdef D880XEHG2
.equ a_atp_Result 0x3088E454
.equ s_atp_CurrentCommandInfo 0x3088F4F4
.equ gs_look 0x306048B8
.equ CGSNCommand 0x2062FD20
.equ SendDataReq 0x2062E948
.equ memcpy 0x205A5BE0
.equ s_RunMcc 0x217ACA64
.equ s_rep01 0x21137020
.equ s_rep02 0x21137028
.equ s_rep03 0x2113B6D0
.equ s_rep04 0x2014E153
.equ s_rep05 0x2062E7C1
.equ s_patch 0x2084BC90
.endif

.ifdef D980XEHJ6
.equ a_atp_Result 0x307530F0
.equ s_atp_CurrentCommandInfo 0x30754198
.equ gs_look 0x303DB7F4
.equ CGSNCommand 0x20653C94
.equ SendDataReq 0x20A0FEE0
.equ memcpy 0x2056B91C
.equ s_RunMcc 0x203107D8
.equ s_rep01 0x218CD840
.equ s_rep02 0x218CD848
.equ s_rep03 0x218D2298
.equ s_rep04 0x20257551
.equ s_rep05 0x20651BD5
.equ s_patch 0x2176A84C
.endif


.start s_rep01
.word metka2+1 ; изначально там был переход на s_cod01
.start s_rep02
.word metka1+1 ; изначально там было 0x00000000
.start s_rep03
.short 0x071D ; не знаю что это, предыдущий адрес указывает на адрес строки "CGSN"
.start s_rep04
.byte 0xE0 ; какая-то замена BNE на B
.start s_rep05
.byte 0xE0 ; какая-то замена BEQ на B

.start s_patch

;----------------------------------------------------------------------------
; подсказка выдаваемая по AT+CGSN?
metka1:
PUSH	{R1-R7,LR}
LDR	R0, =a_atp_Result ;s_mem01
LDR 	R0, [R0]
LDR	R1, =t_cgsn ; "CGSN patch…"
LDR	R2, =t_cgsn_size ; длинна строки
BLX	memcpy
LDR	R0, =t_cgsn_size ; длинна строки
BL	SendDataReq
MOV	R0, 0
POP	{R1-R7,PC}


;----------------------------------------------------------------------------
case04: ; CGSN=4 - MCC Run

PUSH	{R5,R6}
MOV	R7, 0 ; незнаю
MOV	R6, 0 ; незнаю
MOV	R5, 0 ; незнаю
MOV	R4, 0 ; незнаю
MOV	R3, 0 ; незнаю
MOV	R2, 0 ; незнаю
MOV	R1, 0 ; незнаю
;R0 - первый аргумент (адрес запускаемой команды)
BL	s_RunMcc
POP	{R5,R6}
MOV	R0, 0
POP	{R1-R4,R7,PC}

;----------------------------------------------------------------------------

metka2:
PUSH	{R1-R4,R7,LR}
LDR	R4, =s_atp_CurrentCommandInfo
LDRB	R0, [R4, 3]
CMP	R0, 0
BNE	m01
BL	CGSNCommand ; компенсация точки врезки metka2
B	m02
m01:
LDR 	R7, [R4, #0x1C]
LDRB	R7, [R7]
SUB	R7, #0x30
LDR 	R0, [R4, #0x24]
LDRH	R1, [R4, #32]
BL	Hex2Long

;---------
; выдача CR-LF перед началом ответа (любого)
PUSH	{R0-R7}
LDR	R0, =a_atp_Result
LDR 	R0, [R0]
LDR	R1, =t_cgsn 
MOV	R2, 2
BLX	memcpy
MOV	R0, 2
BL	SendDataReq
POP	{R0-R7}
;---------

CMP	R7, 0
BEQ	case00
CMP	R7, 1
BEQ	case01
CMP	R7, 2
BEQ	case02
CMP	R7, 3
BEQ	case03
CMP	R7, 4
BEQ	case04

B	m04

;----------------------------------------------------------------------------
case00: ; CGSN=0 - чтение
MOV	R3, R0
LDRH	R1, [R4, #40]
LDR 	R0, [R4, #0x2C]
BL	Hex2Long
MOV	R2, R0
MOV	R0, R3
LDR	R1, =a_atp_Result
LDR 	R1, [R1]
;BL	m05

;m05:
PUSH	{R0-R5}

;---
;если запросили больше 100h
MOV	R4, 0xFF
ADD	R4, 1
CMP	R2, R4
BLE		m43
POP	{R0-R5}
B	print_error
m43:
;---

ADD	R2, 1

m10:
LDRB	R4, [R0]
LSR	R5, R4, 4
CMP	R5, #0xA
BLT	m11
ADD	R5, 7
m11:
ADD	R5, #0x30
STRB	R5, [R1]
LSL	R5, R4, #28
LSR	R5, R5, #28
CMP	R5, #0xA
BLT	m12
ADD	R5, 7
m12:
ADD	R5, #0x30
STRB	R5, [R1, #0x1]
ADD	R0, 1
ADD	R1, 2
SUB	R2, 1
CMP	R2, 0
BHI	m10
POP	{R0-R5}
;BX	LR


LSL	R0, R2, 1
BL	SendDataReq
B	m04

;----------------------------------------------------------------------------
case01: ; CGSN=1 - запись 

LDRH	R2, [R4, #40]
LSR	R2, R2, 1
LDR 	R1, [R4, #0x2C]

PUSH	{R1-R5}
;r1 - текст, r0 - адрес, r2 - кол-во байт для записи
CMP	R2, 0 ; выход если нулевая строка ?
BEQ	m13a

;----------
;коррекция начала строки (системный интерпретатор ведущие нули теряет)

LDRB	R3, [R1]
CMP	R3, 0x23  ; "#"
BEQ	m41
m13a:
POP	{R1-R5}
B	print_error

m41:
ADD	R1, 1
;----------

m13:

;----------

LDRB	R3, [R1]

;CMP	R3, #0x3F
;BNE	m14
;STRB	R3, [R0]
;LSR	R3, R3, 4
;B	m15
;m14:

CMP	R3, #0x40
BLT	m15
ADD	R3, 9
m15:
LSL	R3, R3, #28
LSR	R4, R3, #24

LDRB	R3, [R1, 1]

;CMP	R3, #0x3F
;BNE	m17
;STRB	R3, [R0]
;B	m16
;m17:

CMP	R3, #0x40
BLT	m16
ADD	R3, 9
m16:
LSL	R3, R3, #28
LSR	R3, R3, #28

ORR	R4, R3
STRB	R4, [R0]

ADD	R0, 1
ADD	R1, 2
SUB	R2, 1
CMP	R2, 0
BHI	m13
POP	{R1-R5}

;B	m07 ; переход на печать адреса следующего после записанного (зачем - не понятно)
B	m04 ; переход на просто выход с OK

;----------------------------------------------------------------------------
case02: ; CGSN=2 - поиск

PUSH	{R1-R7}
MOV	R7, R0 ; r7 - первый аргумент команды (уже интерпретированный) - адрес с которого начать поиск
LDR	R4, =s_atp_CurrentCommandInfo
LDRH	R1, [R4, #40] ; длинна второго аргумента
LDR 	R0, [R4, #0x2C] ; адреса второго аргумента - длинна области поиска
BL	Hex2Long 
MOV	R2, R0 ; r2 - длинна поиска
ADD	R4, #0x30 ; r4+4 - адрес с адресом начала строки поиска (r4 - длинна аргумента)
LDR	R1, [R4, 4] ; r1 - адрес проверяемого полубайта

;BL	m50



;----------
;коррекция начала строки (системный интерпретатор ведущие нули теряет)
LDRB	R3, [R1]
CMP	R3, 0x23  ; "#"
BEQ	m42
POP	{R1-R7}
B	print_error
m42:
ADD	R1, 1
;----------


LDRB	R3, [R4] ; r3 - длина строки поиска в полу байтах
LSR	R3, R3, 1 ; r3 - длина строки поиска в реальных байтах
SUB	R2, R2, R3 ; r2 - не понял зачем это ?!

m18:
MOV	R3, 0
m19:
LSR	R6, R3, 1
LDRB	R5, [R7, R6]
BCS	m20
LSR	R5, 4
m20:
LDRB	R6, [R1, R3]
CMP	R6, #0x3F
BEQ	m21
CMP	R6, #0x40
BLT	m22
ADD	R6, 9
m22:	
LSL	R6, R6, #28
LSL	R5, R5, #28
CMP	R5, R6
BNE	m23
m21:
LDRB	R6, [R4]
SUB	R6, 2 ; !!! тут коррекция +1 из-за компенсации '#'
CMP	R3, R6
BEQ	m24
ADD	R3, 1
B	m19
m23:
ADD	R7, 1
SUB	R2, 1
CMP	R2, 0
BPL	m18
MOV	R7, 0
m24:
MOV	R0, R7
POP	{R1-R7}

B	m07 ; переход на печать адреса 

;----------------------------------------------------------------------------
case03: ; CGSN=3 - MCC

LDR	R0, =gs_look
LDR 	R0, [R0, #0x14]
m07:
LDR	R1, =a_atp_Result
LDR 	R1, [R1]

BL	Long2Hex

MOV	R0, 8
BL	SendDataReq
m04:
MOV	R0, 0
m02:
POP	{R1-R4,R7,PC}


print_error:
LDR	R0, =a_atp_Result ;s_mem01
LDR 	R0, [R0]
LDR	R1, =t_error ; "invalid…"
LDR	R2, =t_error_size ; длинна строки
BLX	memcpy
LDR	R0, =t_error_size ; длинна строки
BL	SendDataReq
MOV	R0, 0
POP	{R1-R4,R7,PC}


Long2Hex: ;Конвертация числа в Hex данные
; R0 - число, R1 - адрес буфера для размещения Hex данных.
PUSH {R2,R3,LR}
MOV	R2, 7
m28:
LSL	R3, R0, #28
LSR	R3, R3, #28
CMP	R3, #0xA
BLT	m29
ADD	R3, 7
m29:
ADD	R3, #0x30
STRB	R3, [R1, R2]
CMP	R2, 0
BEQ	m30
SUB	R2, 1
LSR	R0, R0, 4
B	m28
m30:
POP	{R2,R3,PC}



Hex2Long: ;Конвертация нех данных в число
; R0- адрес символьного буфера, R1-длинна буфера.
; Выход R0- значение
;m03: 
PUSH {R2,R3,LR}
MOV	R2, R0
MOV	R0, 0
m25:
CMP	R1, 0
BEQ	m26
LDRB	R3, [R2]
CMP	R3, 0
BEQ	m26
CMP	R3, #0x40
BLT	m27
ADD	R3, 9
m27: 
LSL	R3, R3, #28
LSR	R3, R3, #28
LSL	R0, R0, 4
ORR	R0, R3
SUB	R1, 1
ADD	R2, 1
B	m25
m26: 
POP {R2,R3,PC}


;m50: ; временная проверка
;PUSH {LR}
;LDR	R3, =0x3005ED04
;MOV	R5, R1
;LDRB	R6, [R5]
;STRB	R6, [R3]
;LDRB	R6, [R5, 1]
;STRB	R6, [R3, 1]
;LDRB	R6, [R5, 2]
;STRB	R6, [R3, 2]
;LDRB	R6, [R5, 3]
;STRB	R6, [R3, 3]
;LDRB	R6, [R5, 4]
;STRB	R6, [R3, 4]
;LDRB	R6, [R5, 5]
;STRB	R6, [R3, 5]
;LDRB	R6, [R5, 6]
;STRB	R6, [R3, 6]
;LDRB	R6, [R5, 7]
;STRB	R6, [R3, 7]
;LDRB	R6, [R5, 8]
;STRB	R6, [R3, 8]
;LDRB	R6, [R5, 9]
;STRB	R6, [R3, 9]
;POP	{PC}

.data
;.align 2

;t_notfnd	.byte	"not found!",0x0D,0x0A
;t_outran	.byte	"out of range!",0x0D,0x0A

; размер ответа не должен превышать ~720знаков - иначе авария.
t_error: .byte	0x0D,0x0A
	.byte	"Invalid parametrs !!! Input AT+CGSN? for help.",0x0D,0x0A
t_cgsn: .byte	0x0D,0x0A
	.byte	"CGSN patch v.1.2",0x0D,0x0A
	.byte	"AT+CGSN? - this help",0x0D,0x0A
	.byte	"AT+CGSN - (standart) IMEI master-phone",0x0D,0x0A
	.byte	"AT+CGSN=0,AAAAAAAA,LLLL - reading from AAAAAAAA address lenght LLLL,",0x0D,0x0A
	.byte	"      01 <= LLLL <= 0100",0x0D,0x0A
	.byte	"AT+CGSN=1,AAAAAAAA,#WWWWWW... - write WWWWWW... on AAAAAAAA address",0x0D,0x0A
	.byte	"AT+CGSN=2,AAAAAAAA,LLLLLL,#SSSSSSSSSSSSSSSS - search SSSS...",0x0D,0x0A
	.byte	"      from AAAAAAAA address in the block lenght LLLLLL",0x0D,0x0A
	.byte	"AT+CGSN=3 - reception of the address of a current MCC-command",0x0D,0x0A
	.byte	"AT+CGSN=4,AAAAAAAA - run MCC-commands from address AAAAAAAA",0x0D,0x0A
	.byte	"Search (and search exit for limits), reading, record outside",0x0D,0x0A
	.byte	"of real memory - will cause error and reboot!",0x0D,0x0A
	.byte	"All numbers - only in hexadecimal format.",0x0D,0x0A
	.byte	"# - modifier before the WW... or SS... - necessarily!",0x0D,0x0A
t_cgsn0: .byte 0x00
.equ	t_cgsn_size t_cgsn0-t_cgsn
.equ	t_error_size t_cgsn-t_error


