Seite 1 von 2
für Entwickler: Tuner per API
Verfasst: Fr 10. Mär 2006, 23:52
von Harvey
Hai,
ich habe seit Wochen vor, einen Hook zu schreiben, mit dem man den aktiven Tuner herausbekommt. Da ich doch nicht dazu komme, selbst diese Kleinigkeit zu programmieren, hier eine erst mal rein theoretische Anleitung, falls das jemand anderer machen möchte.
Errata sind sehr wahrscheinlich, da vollkommen aus dem Kopf geschrieben (da wo ich nicht sicher bin folgt ein (?).
1.) Man schaue sich DeadBeefs Quellcode für die Display Tap Library (?) an. Dort entnimmt man, wie man die Funktion TAP-GetTime (?) kopiert, in diesem Fall um Firmwarefunktionen aufzurufen zu können.
2.) Man kopiere auf diese Weise TAP_GetSignalQuality, das ergibt bei der akuten FW vom TF5x00:
Code: Alles auswählen
0r 8018f0b4: 27bdffe0 addiu $sp,-32
4r 8018f0b8: afbe001c sw $fp,28($sp)
8r 8018f0bc: 3c1e8018 lui $fp,0x8018
cr 8018f0c0: afbf0014 sw $ra,20($sp)
10r 8018f0c4: 27de6674 addiu $fp,26228=0x6674 # 80186674 VAR_TabIdent -> 0
14r 8018f0c8: afb60018 sw $s6,24($sp)
18r 8018f0cc: 8fcf0000 lw $t7,0($fp)
1cr 8018f0d0: 3c168018 lui $s6,0x8018
20r 8018f0d4: 26d66474 addiu $s6,25716=0x6474 # 80186474 VAR_TabTable -> 0
24r 8018f0d8: 000f7940 sll $t7,5
28r 8018f0dc: 02cf7821 addu $t7,$s6
2cr 8018f0e0: 8de30000 lw $v1,0($t7)
30r 8018f0e4: 00000000 nop
34r 8018f0e8: 00000000 nop
38r 8018f0ec: 03801025 move $v0,$gp
3cr 8018f0f0: 00000000 nop
40r 8018f0f4: 00000000 nop
44r 8018f0f8: 0060e025 move $gp,$v1
48r 8018f0fc: 8f999ec4 lw $t9,-24892($gp) # 803814f4 @ptrEepromETC
4cr 8018f100: 27a50010 addiu $a1,$sp,16=0x0010
50r 8018f104: 0c06c07b jal 0x801b01ec #
54r 8018f108: 93240015 lbu $a0,21($t9)
58r 8018f10c: 8fcf0000 lw $t7,0($fp)
5cr 8018f110: 000f7940 sll $t7,5
60r 8018f114: 02cf7821 addu $t7,$s6
64r 8018f118: 8dfe0004 lw $fp,4($t7)
68r 8018f11c: 00000000 nop
6cr 8018f120: 00000000 nop
70r 8018f124: 03801025 move $v0,$gp
74r 8018f128: 00000000 nop
78r 8018f12c: 00000000 nop
7cr 8018f130: 03c0e025 move $gp,$fp
80r 8018f134: 93a20010 lbu $v0,16($sp)
84r 8018f138: 8fbf0014 lw $ra,20($sp)
88r 8018f13c: 8fb60018 lw $s6,24($sp)
8cr 8018f140: 8fbe001c lw $fp,28($sp)
90r 8018f144: 03e00008 jr $ra
94r 8018f148: 27bd0020 addiu $sp,32
3.) Man suche und ersetzte das hoffentlich in allen FWs einzig vorkommende jal durch nop (eigentlich nicht wichtig, könnte aber die Performance erhöhen). Wie das geht kann man ganz gut aus 1.) erfahren.
4.) Man suche und ersetzte lbu $v0,16($sp) durch addiu $v0,0,$a0
Für Support stehe ich aus beruflichen Gründen die nächste Zeit leider kaum zur Verfügung (sonst hätte ich es auch selber gemacht).
Verfasst: Sa 11. Mär 2006, 00:04
von t3xi
Ich glaube das gibt es schon. Ich weis nur nicht mehr von wem ich den Code geklaut habe. Vermutlich von DeadBeef.
Code: Alles auswählen
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "tap.h"
#define CMD_MASK 0xfc000000
#define REG_MASK 0x03ff0000
#define LOAD_TYPE 0x9000000b
#define LOAD_TUNER 0x90000015
#define JR_CMD 0x03e00008
#define SHIFT_CMD 0
#define NOP_CMD 0
//-----------------------------------------------------------------------------
// function pointer definitions for the wrapped code
// The returned tuner number is zero-based (i.e. 0 = Tuner 1, 1 = Tuner 2).
// The return value contains the channel number (as in TAP_Channel_GetCurrent).
typedef dword (*GetTuner)(dword* tuner, dword* chNum);
GetTuner getTuner = NULL;
//-----------------------------------------------------------------------------
// initCodeWrapper() creates a code wrapper based on TAP_Channel_GetCurrent. The
// function allocates a buffer and copies the code of TAP_Channel_GetCurrent into
// it except for the actual memory access operations.
// initCodeWrapper() returns a buffer with code returning the current tuner number.
// The initialization is to be done only once.
// For simplicity reasons the function signature remains unchanged (that is, two
// parameters and a return value).
// The returned tuner number is zero-based (i.e. 0 = Tuner 1, 1 = Tuner 2).
// The return value contains the channel number (as in TAP_Channel_GetCurrent).
dword* initCodeWrapper()
{
int i;
dword *pSrc = (dword*)TAP_Channel_GetCurrent;
dword *pBuffer;
bool found = FALSE;
int bufSize = 0;
int count = 0;
// find the return statement
while(pSrc[bufSize] != JR_CMD)
{
bufSize++;
}
// the buffer should include the return statement and the command following
// the return statement
bufSize += 2;
// allocate memory
pBuffer = malloc(sizeof(dword) * bufSize);
if(pBuffer == NULL)
{
return NULL;
}
for(i = 0; i < bufSize; i++, pSrc++)
{
if((*pSrc & ~REG_MASK) == LOAD_TYPE)
{
// the command loads the service type (offset 11(0x000b) in the structure)
// replace it with loading the tuner number (offset 21(0x0015) in the structure)
// preserve used registers
pBuffer[i] = LOAD_TUNER | (*pSrc & REG_MASK);
found = TRUE;
}
else
{
// replace the two shift operations following the load operation
if(found && (count < 2) && ((*pSrc & CMD_MASK) == SHIFT_CMD))
{
pBuffer[i] = NOP_CMD;
count++;
}
else
{
pBuffer[i] = *pSrc;
}
}
}
if(!found)
{
free(pBuffer);
pBuffer = NULL;
}
return pBuffer;
}
void InitTuner()
{
getTuner = (GetTuner)initCodeWrapper();
}
int GetCurrentTuner()
{
dword tuner = -1, chNum;
if (getTuner == NULL) return -1;
getTuner(&tuner, &chNum);
if (tuner > 1) return -1;
return (int)tuner;
}
Verfasst: Sa 11. Mär 2006, 00:11
von Happy
Das war von
hier
Funktioniert es denn ?
Gruß,
Happy
Verfasst: Sa 11. Mär 2006, 00:14
von t3xi
Ja, bei mir schon.
Verfasst: Sa 11. Mär 2006, 00:57
von ibbi
t3xi hat geschrieben:
Code: Alles auswählen
// find the return statement
while(pSrc[bufSize] != JR_CMD)
{
bufSize++;
}
Hier sollte man noch eine Notbremse (Maximalwert) für bufSize einbauen und prüfen, welche Endebedingung eingetreten ist. Das verhindert eine Schleife, die sich munter durch den Speicher kämpft, falls JR_CMD nicht gefunden wird.
Verfasst: Sa 11. Mär 2006, 07:14
von t3xi
Ja, könnte man machen, aber ich glaube dass TAP_Channel_GetCurrent immer ein JR am Ende haben wird.
Verfasst: Sa 11. Mär 2006, 08:49
von Gerti
Hi!
Habe es gerade mal auf dem 6000 getestet und auch dort funktioniert es...
Ich denke daher mal, dass es wohl auf allen Firmwareversionen laufen müsste...
Habe es jedenfalls gerade noch mit in ImproBox eingebaut, weil ja so oft danach gefragt wurde, ich habe bisher immer noch auf eine erweiterte API gehofft hatte.
Gruß und Danke,
Gerti
Verfasst: Sa 11. Mär 2006, 09:38
von StevieC
Hi,
Erdnussnase hat das schon seit einigen Wochen in Quicktimer eingebaut, es funktioniert absolut zuverlässig.
Gruß
StevieC
Verfasst: Sa 11. Mär 2006, 13:44
von ibbi
t3xi hat geschrieben:Ja, könnte man machen, aber ich glaube dass TAP_Channel_GetCurrent immer ein JR am Ende haben wird.
Bill Gates hat mal geglaubt, 640 KByte reichen für jeden Computer, und viele Programmierer glauben, Ihre Puffer seien ausreichend groß, oder der Divisor kann gar nicht Null sein.
Ich habe mir angewöhnt, keine Annahmen zu machen, sondern einfach immer vom schlimmsten Fall auszugehen. Kommen sehr stabile Programme dabei heraus.
PS: Übrigens fehlt in Deinem Code-Fragment die Routine zur Freigabe des allokierten Puffers, die man vor Programmende aufrufen sollte.
Verfasst: Sa 11. Mär 2006, 14:02
von t3xi
Ich freu mich schon auf dein erstes TAP

Verfasst: Sa 11. Mär 2006, 18:43
von ibbi
t3xi hat geschrieben:Ich freu mich schon auf dein erstes TAP
Ich auch.

Verfasst: Sa 11. Mär 2006, 23:27
von Harvey
Oha - daß es sowas schon auskodiert gibt ist mir irgendwie entfleucht.

ops:
Sieht in der Tat schwer nach dem Stiel vom toten Rind aus

Verfasst: Fr 9. Jun 2006, 22:30
von Happy
Hallo,
habe versucht den obigen Code für NiceDisplay zu verwenden.
Im Prinzip klappts auch, solange ich vor und nach getTuner eine Debugausgabe mit TAP_Print drinhabe. Mache ich die raus, führt der Aufruf zum Einfrieren des Topfes.
Aber der Code wird doch zumindest für IB und QT verwendet. Hattet Ihr keine Probleme?
Gruß,
Happy
Verfasst: Fr 9. Jun 2006, 23:04
von Elle4u
Happy hat geschrieben:Mache ich die raus, führt der Aufruf zum Einfrieren des Topfes.
Aber der Code wird doch zumindest für IB und QT verwendet. Hattet Ihr keine Probleme?
So Phänomene hatte ich auch schon gehabt.
Laß die Zeile raus und programmiere irgend wo anders weiter und plötzlich geht es wieder...

Verfasst: Fr 9. Jun 2006, 23:05
von StevieC
Happy hat geschrieben:Hallo,
habe versucht den obigen Code für NiceDisplay zu verwenden.
Im Prinzip klappts auch, solange ich vor und nach getTuner eine Debugausgabe mit TAP_Print drinhabe. Mache ich die raus, führt der Aufruf zum Einfrieren des Topfes.
Aber der Code wird doch zumindest für IB und QT verwendet. Hattet Ihr keine Probleme?
Gruß,
Happy
Keine Probleme mit der Tunererkennung in Quicktimer.
Gruß
StevieC
Verfasst: Fr 9. Jun 2006, 23:44
von Happy
Elle4u hat geschrieben:So Phänomene hatte ich auch schon gehabt.
Laß die Zeile raus und programmiere irgend wo anders weiter und plötzlich geht es wieder...
Du meinst wahscheinlich das Phänomen, dass TAPs gleich beim Start abstürzen.
Die haben dann ein Vielfaches von 512 Byte an Größe.
Bei mir stürzt es erst beim Aufruf der Funktion ab.
Werde das aber demnächst nochmal probieren.
@ steviec
Ihr habt da auch nichts entscheidendes mehr modifiziert ?
Gruß,
Happy
Verfasst: Fr 9. Jun 2006, 23:48
von Elle4u
Happy hat geschrieben:Du meinst wahscheinlich das Phänomen, dass TAPs gleich beim Start abstürzen.
Die haben dann ein Vielfaches von 512 Byte an Größe.
Ah. Den Zusammenhang kannte ich noch nicht
Hatte mich immer nur gewundert...

Verfasst: Sa 10. Jun 2006, 10:32
von StevieC
Happy hat geschrieben:
@ steviec
Ihr habt da auch nichts entscheidendes mehr modifiziert ?
Gruß,
Happy
Ich hab mir grad mal den QT Code angesehen, soweit ich das beurteilen kann, ist da nix anders.
Gruß
StevieC
Verfasst: Sa 10. Jun 2006, 12:57
von DeadBeef
Happy hat geschrieben:Im Prinzip klappts auch, solange ich vor und nach getTuner eine Debugausgabe mit TAP_Print drinhabe. Mache ich die raus, führt der Aufruf zum Einfrieren des Topfes.
Wenn Du mir die Exception-Ausgabe zuschickst, könnte ich mal versuchen, das Problem zu analysieren. Die Adressen des TAPs und der Wrapper-Funktion wären auch hilfreich.
Verfasst: So 11. Jun 2006, 23:42
von Happy
DeadBeef hat geschrieben:Wenn Du mir die Exception-Ausgabe zuschickst, könnte ich mal versuchen, das Problem zu analysieren. Die Adressen des TAPs und der Wrapper-Funktion wären auch hilfreich.
Hi,
ich habe jetzt noch ein bißchen experimentiert.
Das Ergebnis ist, dass das man die Funktion nicht im TAP_Main aufrufen kann, dann kommt es zum Absturz.
Im Idle-Event scheint es stabil zu sein.
Sieht dann so aus:
Code: Alles auswählen
$sp=803ac3e8
$at=00000000 $v0=82154ca0 $v1=80190000 $a0=803ac474
$a1=803ac478 $a2=8018b424 $a3=0000000f $t0=801e7924
$t1=803ac6d8 $t2=803ac6d4 $t3=8018b224 $t4=82cf5e78
$t5=00000000 $t6=803ac383 $t7=00000000 $t8=0000000d
$t9=82154ca0 $s0=00000001 $s1=0000000a $s2=00000000
$s3=00000000 $s4=8018b224 $s5=8018b224 $s6=82cf5e78
$s7=82cf5e78 $s8=00000000 $ra=82cd1b40 $t0=00000000
$t1=00000000 $gp=82cf5e78 $k1=82154cbc
<<< Unexpected Exception >>>
CAUSE = 00008428
EPC = 82154cbc
*EPC = 8de70000
SR = 10000403
badVAddr = 2d7be400
task = 0
_runCount=1
lastTask(0) = 0
memory monitor
cmd number = 10
>
Das passiert auch in einem Testprojekt, das ich Dir zuschicken werde.
Gruß,
Happy