For discussions about development of TAPs, patches and other software for the Toppy

Moderator: Technical

deangelj
Frequent contributor
Posts: 316
Joined: Tue Mar 29, 2005 10:33 pm
Location: Sydney, Australia

USB interface patch request

Post by deangelj »

Hi guys,

we know that the current firmware has a broken usb firmware interface as far as developing TAPs that respond to USB requests are concerned. Is anyone interested in developing a patch to fix that interface so that developers can build these types of TAPs? I don't know if it can even be done by I do know that I don't have the skills :(

What do you guys think?

cheers,
john
R2-D2
Frequent contributor
Posts: 12148
Joined: Mon Dec 18, 2006 11:15 am
Contact:

Post by R2-D2 »

It might be nice if somebody could summarise the problems, and maybe indicate what modified behaviour would be better.
deangelj
Frequent contributor
Posts: 316
Joined: Tue Mar 29, 2005 10:33 pm
Location: Sydney, Australia

Post by deangelj »

ok - the quickest way to communicate from a PC to the toppy is via the USB interface. If you talk directly to the firmware then all is well. But as soon as you want to use the API and create a tap to listen on the USB interface and do things, the toppy crashes.

I have a PC based tool that talks to the toppy - I'd like to have a tap that I can communicate with directly instead of having to send "command files" which a tap has to poll for. Additionally with my workaround the disk needs to be spun up for this to work.

So, the basic issue is that when I use the TAP USB API interface the tap crashes. This is a well known issue with the all of the firmwares releases (from my understanding this is still the case). I was wondering whether the f/w could be patched so the API worked... Maybe I'm dreaming :)

cheers,
John
R2-D2
Frequent contributor
Posts: 12148
Joined: Mon Dec 18, 2006 11:15 am
Contact:

Post by R2-D2 »

Does the TAPdiskFix patch make any difference? If you're starting & stopping a TAP a lot of times it will (incorrectly) use up the resources which the USB system also uses -- when those resources are gone there will be a problem.
deangelj
Frequent contributor
Posts: 316
Joined: Tue Mar 29, 2005 10:33 pm
Location: Sydney, Australia

Post by deangelj »

well the usb issue that I'm not talking about is not about resources cause as you start it and then connect to it from a PC it crashes. Also, the TAP API sample (from Topfield Korea) called usbtest also crashes.

cheers,
John
R2-D2
Frequent contributor
Posts: 12148
Joined: Mon Dec 18, 2006 11:15 am
Contact:

Post by R2-D2 »

deangelj wrote:Also, the TAP API sample (from Topfield Korea) called usbtest also crashes.
OK, that sounds like somewhere to start looking.
rwg
TAP author
Posts: 604
Joined: Sat Oct 29, 2005 4:31 pm
Location: Oxfordshire
Contact:

Post by rwg »

There is some background in this thread

http://forum.toppy.org.uk/forum/viewtopic.php?t=330

I have to admit that I never got around to trying anything out based on the write only approach :(

Robin
Toppy: TF5800PVR; Firmware: 5.13.65 + patches + aXel; Remote: Pronto RU940; Autostart TAPs: MyStuff 6.5 and friends
R2-D2
Frequent contributor
Posts: 12148
Joined: Mon Dec 18, 2006 11:15 am
Contact:

Post by R2-D2 »

Had a look at the callback stuff and it seems that the firmware goes to some lengths to set things up for the TAP's callback to work... but only if exactly one TAP is running! :) It seems like they might have forgotten to restore the stuff they so carefully set up. If I'm right, problems will occur unpredictably when there are 2 or more TAPs running and calling TAP API functions, with the result being corrupt access to a TAP's globals when a TAP API function returns.

I think it would be easy to fix, if those sound like the correct symptoms.
deangelj
Frequent contributor
Posts: 316
Joined: Tue Mar 29, 2005 10:33 pm
Location: Sydney, Australia

Post by deangelj »

That could be it R2-D2 - I know at least one other person reported that symptom: ie. that it would work ok when only that tap was running. I must admit that I haven't tried that variation since I always had at least 2-3 taps running. I'll try that tonight but it sounds like you could be right!

Thanks for looking at this too.

Cheers,
John
R2-D2
Frequent contributor
Posts: 12148
Joined: Mon Dec 18, 2006 11:15 am
Contact:

Post by R2-D2 »

Have a crack at this Callback patch, which also fixes the PlayPCM callback in the same way. I've not been able to test whether it works...

I'm not sure if this is well documented, but the USB_Write callback may be called a number of times with 0 size before the write succeeds (and then the callback will be called with the correct size). And I think that the USB_Read callback mechanism is a bit tricky to use for just continuous reads -- it's set up in a way that means you'll probably miss packets unless you ack them (with a USB_Write) to signal to the other end to send another packet. This is because all the callback mechanism is deactivated after a callback -- I suppose there's the possibility of fixing this to make you need to USB_Cancel, or alternatively enabling another callback during the USB_Read callback (by calling USB_Read again -- which won't work at the moment).
deangelj
Frequent contributor
Posts: 316
Joined: Tue Mar 29, 2005 10:33 pm
Location: Sydney, Australia

Post by deangelj »

thanks R2-D2 - probably won't get a chance to test this until Wed (Aust time), so I'll give it a go then and get back with the results. Thanks again.

Cheers,
John
deangelj
Frequent contributor
Posts: 316
Joined: Tue Mar 29, 2005 10:33 pm
Location: Sydney, Australia

Post by deangelj »

R2-D2- I'd welcome a sanity check here if you have some time. I'll be using the usbtest.c sample from Topfield as a starting point. This tap handles a file transfer (receiving a file).

In TAP_Main it calls TAP_Usb_packetread passing the readcallback routine and the buffersize.

In readcallback it gets passed a size parameter but that is never used. It checks that the 32 bit header of the data is one of the ones it is expecting:

USB_CmdHddFileSend || USB_DataHddFileStart || Usb_DataHddFileData ||
USB_DataHddFileEnd

If it is, it sets a flag (A) and exits with a 0 value otherwise it sets a diferent global flag (B) and exits with 1

In the Event Handler, if A is set it calls a routine (Receive) to process the buffer, else if B is set (ie other USB data) it resets the flag and posts another TAP_Usb_packetread

In the Receive routine it does:

While more data
call TAP_usb_packetwrite (null, 0, writecallback, USB_success) //?ack
process the received buffer
call TAP_usb_packetread
if it was and end command exit while
R2-D2
Frequent contributor
Posts: 12148
Joined: Mon Dec 18, 2006 11:15 am
Contact:

Post by R2-D2 »

deangelj wrote:I'll be using the usbtest.c sample from Topfield as a starting point.
The first thing that worries me about that example code is the fact that the _usbBuf is freed in TAP_Main(), rather than, say, after the TAP_Exit() -- although the TAP doesn't appear to ever actually exit. So it doesn't look good to start with -- continually running and scribbling all over unallocated memory...
If it is, it sets a flag (A) and exits with a 0 value otherwise it sets a diferent global flag (B) and exits with 1
This is to flag to both the TAP and the firmware whether the packet was one this TAP wanted. If the callback returns 0 then the packet was not one it wanted, so it's passed on to other possible recipients (i.e., the firmware). And in this case the callback must also be re-registered, so this must be flagged back to the TAP (since the callback will have been deactivated by the receipt of this packet). You may have now noticed that there is the possibility of missing packets if the system is a bit busy and your TAP doesn't get an EVT_IDLE or do its processing quickly enough.

In my opinion (and I'm not an expert), I'd leave the callbacks active (especially if the packet was not one that was processed), or I'd deactivate them before the callback was processed and allow the callback to re-register itself (or another callback) if necessary.
call TAP_usb_packetwrite (null, 0, writecallback, USB_success) //?ack
Yes, that's the ACK to the sender to tell it that it can send another packet. The callback is not really relevant in this case, since it's just a simple ACK packet, but in theory the TAP should wait until it knows that has been sent before it tries reading more packets. However....

...my post about the Write callbacks was wrong. The system will wait for up to 500 ticks for the USB system to be ready for the Write, and if that times out then the Write callback is called with a size of zero. So I was wrong, and the Write callback only ever gets called once. But in the case of the simple PacketWrite commands (which have a "size" of zero, like the USB_Success one above) it will therefore be very hard for a TAP to detect whether they have been successfully written...
simonc
Frequent contributor
Posts: 5648
Joined: Tue Apr 12, 2005 1:31 pm
Location: Cheltenham
Contact:

Post by simonc »

This has the potential to be extremely handy. I've never really liked the file based USB communication that TAPs have had to employ for remote timer setting and the like.

I had a bash at circumventing the bug a year ago buy intercepting the callback before it had a chance to crash. However, my MIPS isn't as polished as yours and I couldn't quite make the leap to a generic solution. Even with my fix, I still found USB to be unreliable, mysteriously ceasing to communicate after a period of time. Perhaps this patch will be more successful.
deangelj
Frequent contributor
Posts: 316
Joined: Tue Mar 29, 2005 10:33 pm
Location: Sydney, Australia

Post by deangelj »

R2-D2 wrote:
deangelj wrote:I'll be using the usbtest.c sample from Topfield as a starting point.
The first thing that worries me about that example code is the fact that the _usbBuf is freed in TAP_Main(), rather than, say, after the TAP_Exit() -- although the TAP doesn't appear to ever actually exit. So it doesn't look good to start with -- continually running and scribbling all over unallocated memory...
yep - you're right - I've changed this to deallocate on exit.
R2-D2 wrote:
If it is, it sets a flag (A) and exits with a 0 value otherwise it sets a diferent global flag (B) and exits with 1
This is to flag to both the TAP and the firmware whether the packet was one this TAP wanted. If the callback returns 0 then the packet was not one it wanted, so it's passed on to other possible recipients (i.e., the firmware). And in this case the callback must also be re-registered, so this must be flagged back to the TAP (since the callback will have been deactivated by the receipt of this packet). You may have now noticed that there is the possibility of missing packets if the system is a bit busy and your TAP doesn't get an EVT_IDLE or do its processing quickly enough.

In my opinion (and I'm not an expert), I'd leave the callbacks active (especially if the packet was not one that was processed), or I'd deactivate them before the callback was processed and allow the callback to re-register itself (or another callback) if necessary.
Now this part I don't quite understand. From my reading of the code, it either passes the usb call on to the firmware or processes it but in either case it posts a read?
R2-D2 wrote:
call TAP_usb_packetwrite (null, 0, writecallback, USB_success) //?ack
Yes, that's the ACK to the sender to tell it that it can send another packet. The callback is not really relevant in this case, since it's just a simple ACK packet, but in theory the TAP should wait until it knows that has been sent before it tries reading more packets. However....

...my post about the Write callbacks was wrong. The system will wait for up to 500 ticks for the USB system to be ready for the Write, and if that times out then the Write callback is called with a size of zero. So I was wrong, and the Write callback only ever gets called once. But in the case of the simple PacketWrite commands (which have a "size" of zero, like the USB_Success one above) it will therefore be very hard for a TAP to detect whether they have been successfully written...
But isn't this the reason for the ack so that the other end doesn't send anything until it is received? Therefore on the TAP end, if it gets something more then the ack was ok otherwise it should have some sort of timeout?

I did some tests on this yesterday - it took me a while cause I needed to get into the world of firmware patches for the first time so loaded firebird's HDFW tap, patched and reloaded the firmware, then tested the usb tap. It sort of worked but didn't :cry: - I did get it to receive a file but it would hang randomly. That's why I'm trying to understand what you said cause therein might lie the solution :wink:

Cheers and thanks for the help so far.

John
Post Reply