[Q] Multi-Touch support on Nook Simple Touch? - Nook Touch General

Ok, I rooted my Nook Simple Touch (Running 1.1) using:
http://forum.xda-developers.com/showthread.php?t=1351719
Many things aren't working as expected (e.g. The Android Market doesn't work), but in reading the thread it sounds like that might be a common problem. I do have root access, and can connect via ADB and side-load apps.
I'm looking to do pinch-zoom on PDF documents, but I can't seem to get it to work in Aldiko, and I'm not sure if that's because pinch-zoom isn't supported, or I'm doing something wrong.
There appears to be conflicting information on multi-touch support on the Nook Simple Touch on the forums.
Can anyone clarify whether this support is present, and if so, maybe suggest a good PDF app that enables it?

Well, on version 1.0.0 and 1.0.1 there was no support for multitouch. When we read the announcement for 1.1.0, we saw that multitouch would be enabled, but nobody has seen a trace of that yet.
I talked to some guys in here, and asked for info on where it can be enabled (it is disabled when rooting).

I downloaded a midi controller(an app that shows a bunch of sliders on the screen and communicates its position to a pc) and I noticed I could move a vertical slider and another horizontal one at the same time... but then google maps didnt react to my pinching

I have tried with Multitouch Test ( https://market.android.com/details?...DEsImRlLmdyZWVucm9ib3QubXVsdGl0b3VjaHRlc3QiXQ..) and it looks like the hw is capable of multitouch!
I don't know how to enable it, though

I've tried to enable it by using this http://nookdevs.com/NookColor_Enable_MultiTouch
but Multitouch tester only detects one input....
Although if I used two fingers the second registered movement intermittently, jumping from on to another instead of two solid points.

You can try this:
Unpack this file to where adb is (unless you have adb in your path)
Then in cmd:
Code:
adb shell
mount -o remount,rw -t ext2 /dev/block/mmcblk0p5 /system
exit
adb push android.hardware.touchscreen.multitouch.distinct.xml /system/etc/permissions/android.hardware.touchscreen.multitouch.distinct.xml
A reboot is probably needed

Thanks, going to try it right now.
---------- Post added at 10:13 PM ---------- Previous post was at 10:03 PM ----------
Same behaviour, mmmmmm, are we sure they enabled multitouch?
Anyway thanks for the help

eded333 said:
Thanks, going to try it right now.
---------- Post added at 10:13 PM ---------- Previous post was at 10:03 PM ----------
Same behaviour, mmmmmm, are we sure they enabled multitouch?
Anyway thanks for the help
Click to expand...
Click to collapse
Well:
Code:
include/linux/zforce.h:#define ZF_NUM_FINGER_SUPPORT 2
..
drivers/input/touchscreen/zforce.c: #define ZF_SETCONFIG_DUALTOUCH 0x00000001
I'd say yes

ros87 said:
Well:
Code:
include/linux/zforce.h:#define ZF_NUM_FINGER_SUPPORT 2
..
drivers/input/touchscreen/zforce.c: #define ZF_SETCONFIG_DUALTOUCH 0x00000001
I'd say yes
Click to expand...
Click to collapse
Then something else is missing

eded333 said:
Then something else is missing
Click to expand...
Click to collapse
Very likely.
Maybe some kernel flag .. I dunno .. but I'm sure Google can tell you how that chain is supposed to be set up

eded333 said:
I've tried to enable it by using this http://nookdevs.com/NookColor_Enable_MultiTouch
but Multitouch tester only detects one input....
Although if I used two fingers the second registered movement intermittently, jumping from on to another instead of two solid points.
Click to expand...
Click to collapse
Which Tester did you use? I could see it work only with the one I linked, from greenrobot...
I have also tried to enable moultitouch per Nookdevs instruction, but had no effect

met67 said:
Which Tester did you use? I could see it work only with the one I linked, from greenrobot...
I have also tried to enable moultitouch per Nookdevs instruction, but had no effect
Click to expand...
Click to collapse
I used multitouch tester, but that one gives the same output as the one I used, it dosnt really show two points, it goes intermitently but fast fom one to another, if you check the number of pointers, its allways 1.

I tried both XML's and I'm getting the same results as everyone else.
The multitest app doesn't detect the multitouch (not even periodically) for me.
Arg, I was hoping this was going to be an easy question :-(.

Well, what is 100% certain is that the driver is building the data needed for dualtouch.
Code:
int touchdata_collect( u8* payload )
{
u8 i;
reported_finger_count = payload[0];
framecounter++;
if( reported_finger_count > ZF_NUM_FINGER_SUPPORT )
{
zforce_error("Detected (%d) more fingers the max(%d) number supported\n",
reported_finger_count, ZF_NUM_FINGER_SUPPORT );
return -EINVAL ;
}
for( i=0; i< reported_finger_count; i++ )
{
tinfo[i].x = (u16)((payload[2+i*ZF_COORDATA_SIZE]<<8)|
payload[1+i*ZF_COORDATA_SIZE]);
tinfo[i].y = (u16)((payload[4+i*ZF_COORDATA_SIZE]<<8)|
payload[3+i*ZF_COORDATA_SIZE]);
tinfo[i].id = (u8)((payload[5+i*ZF_COORDATA_SIZE]&0x3C)>>2);
tinfo[i].state = (u8)((payload[5+i*ZF_COORDATA_SIZE]&0xC0)>>6);
tinfo[i].rsvrd = (u8)( payload[6+i*ZF_COORDATA_SIZE] );
tinfo[i].prblty = (u8)( payload[7+i*ZF_COORDATA_SIZE] );
tinfo[i].valid = 1;
tinfo[i].z = reported_finger_count == 0 ? 0 : 20;
}
return reported_finger_count;
}
How that data is used further on in the chain is beyond my knowledge, but the data is there.
This is a somewhat absurd situation as usually the lack of dual/multitouch are on hardware/driver level

ros87 said:
Well, what is 100% certain is that the driver is building the data needed for dualtouch.
Code:
int touchdata_collect( u8* payload )
{
u8 i;
reported_finger_count = payload[0];
framecounter++;
if( reported_finger_count > ZF_NUM_FINGER_SUPPORT )
{
zforce_error("Detected (%d) more fingers the max(%d) number supported\n",
reported_finger_count, ZF_NUM_FINGER_SUPPORT );
return -EINVAL ;
}
for( i=0; i< reported_finger_count; i++ )
{
tinfo[i].x = (u16)((payload[2+i*ZF_COORDATA_SIZE]<<8)|
payload[1+i*ZF_COORDATA_SIZE]);
tinfo[i].y = (u16)((payload[4+i*ZF_COORDATA_SIZE]<<8)|
payload[3+i*ZF_COORDATA_SIZE]);
tinfo[i].id = (u8)((payload[5+i*ZF_COORDATA_SIZE]&0x3C)>>2);
tinfo[i].state = (u8)((payload[5+i*ZF_COORDATA_SIZE]&0xC0)>>6);
tinfo[i].rsvrd = (u8)( payload[6+i*ZF_COORDATA_SIZE] );
tinfo[i].prblty = (u8)( payload[7+i*ZF_COORDATA_SIZE] );
tinfo[i].valid = 1;
tinfo[i].z = reported_finger_count == 0 ? 0 : 20;
}
return reported_finger_count;
}
How that data is used further on in the chain is beyond my knowledge, but the data is there.
This is a somewhat absurd situation as usually the lack of dual/multitouch are on hardware/driver level
Click to expand...
Click to collapse
That is VERY interesting.
Is it possible that its something simple like the permissions XML file has a different name with the Simple Touch?

I'm monitoring this thread. Sure hope some multi-touch function can be gotten out of the NST

I tried the xml file from the Sony PRS-T1 as well (which apparently has multitouch), but still no luck.
Did not look so much different, though.
I uploaded the files from the Sony reader here, in case someone wants to look into them: mediafire.com/?vuv6v4y4yd44o97
(Won't let me post a clickable link, sorry)

i hope to see Multitouch working well on nst

Market
Install the "SearchMarket" app. And the Android Market will work just fine!

I may be wrong, but isn't touch screen tech infrared on Nst? if so multitouch is not possible.

Related

[APP][updated 25/08/2008 - Ver 0.4] YABGBT - Yet Another Ball Game Based on Tilt

Hy Guys,
Here is my first dev for the touch Diamond.
It is a kind of juggle ball game using tilt sensor SDK and XFlib.
It is just a test for me, so I don't kown if i will had time to improve it.
Ver 0.4.1 [11/01/2009]:
Added : Suport for Touch HD
Ver 0.4 [25/08/2008]:
Added : Now the backlight is allways on
Added : about screen
Ver 0.3.1 [22/08/2008]:
Added : You can chose if the camera follow the ball or the base
Added : Sound when ball hit the base
Ver 0.3 [21/08/2008]:
Added : Biggest playing aera
Ver 0.2 [10/08/2008]:
Added : Menu to select difficulty level
p.s. the game is also playable with stylus, so it is not reserved to the diamond
Hey, that plays quite allright!
First things to polish up would be a higher ball res, a nice background and another cooler paddle image. Bouncesound ?
But gameplay is pretty great already, well done !! Got it bouncing for about 5 minutes and enjoyed it
Awsome gonna chek it out after the Dammm JOb!
Cheers and thanks!
cool...will try it out asap
Pretty cool little app. Good work
Stupid question... But how to play?
potiron4o said:
Stupid question... But how to play?
Click to expand...
Click to collapse
the scene is view by the top.. so move your phone to juggle with the ball
Video of the game here.
http://wmpoweruser.com/?p=621
Great game.
May I suggest to the developer that he may want to also make the square bigger and smaller based on the height of the ball, and further make the background dynamic, so that it e.g. moves in the opposite direction to the ball, to exploit the paralax effect and give the user a feeling they are actually looking into a 3 dimensional box.
Surur
tanks for the video and the review.
I will think about adding paralax effect in the next weeks !
update
update 0.3 (21/082008)
new playing aera !
update 0.3.1 (22/082008)
Now you can chose if the camera will follow the ball or if it will follow the base!
I Need Help :
I hope some Dev will read this,
this game use the Tilt sensor, so the game goes to standby mode after few seconds because we don't touch screen. I don't kown how to prevent the standby mode, so if someone got an idea.....
(i use C language)
edit : the forum got a new section, so i guess my game is not in the right one, so moderator could you move this thread ! thanks
great work
hellgod said:
update 0.3.1 (22/082008)
Now you can chose if the camera will follow the ball or if it will follow the base!
I Need Help :
I hope some Dev will read this,
this game use the Tilt sensor, so the game goes to standby mode after few seconds because we don't touch screen. I don't kown how to prevent the standby mode, so if someone got an idea.....
(i use C language)
edit : the forum got a new section, so i guess my game is not in the right one, so moderator could you move this thread ! thanks
Click to expand...
Click to collapse
this is c# - should work on c, too... found it on msdn and there should be an example for c, too... I just don't find the URL, so google may help (just enter something from below ;-))
public enum CEDevicePowerState
{
D0 = 0, //Full on
D1, //Low on
D2, //Standby
D3, //Sleep
D4, //Off
}
[DllImport("coredll.dll", SetLastError = true)]
static extern IntPtr SetPowerRequirement(string device, CEDevicePowerState ceDevicePowerState, uint deviceFlags, IntPtr systemState, ulong stateFlags);
[DllImport("coredll.dll", SetLastError = true)]
static extern int ReleasePowerRequirement(IntPtr handle);
[DllImport("coredll.dll", SetLastError = true)]
static extern void SystemIdleTimerReset();
on the onload i do following:
IntPtr handle = SetPowerRequirement("BKL1:", CEDevicePowerState.D0, 1, IntPtr.Zero, 0);
to release it, try the 2nd handle...
I use a timer which ticks every 10 seconds and performs this:
SystemIdleTimerReset();
I don't know if it's necessary, but I think so... hope that helps...
Thanks a lot Ageye !! it works !!
for information here is the code :
main.c :
Code:
...
...
#define POWER_DLL L"coredll.dll"
typedef enum _CEDEVICE_POWER_STATE {
PwrDeviceUnspecified = -1,
D0 = 0,
D1=1,
D2=2,
D3=3,
D4=4,
PwrDeviceMaximum=5
} CEDEVICE_POWER_STATE, *PCEDEVICE_POWER_STATE;
typedef HANDLE (WINAPI * PFN_SetPowerRequirement)(PVOID,CEDEVICE_POWER_STATE,ULONG,PVOID,ULONG);
PFN_SetPowerRequirement pfnSetPowerRequirement;
typedef DWORD (WINAPI * PFN_ReleasePowerRequirement)(HANDLE);
PFN_ReleasePowerRequirement pfnReleasePowerRequirement;
const int POWER_NAME = 0x00000001;
const int POWER_FORCE = 0x00001000;
HMODULE hPowerlib;
...
...
...
int main(void){
...
...
hPowerlib= LoadLibrary(POWER_DLL);
pfnSetPowerRequirement = (PFN_SetPowerRequirement)GetProcAddress(hPowerlib, L"SetPowerRequirement");
pfnReleasePowerRequirement = (PFN_ReleasePowerRequirement)GetProcAddress(hPowerlib, L"ReleasePowerRequirement");
HANDLE IntPtr = pfnSetPowerRequirement(TEXT("BKL1:"), D0, POWER_NAME | POWER_FORCE,NULL, 0);
...
...
pfnReleasePowerRequirement(IntPtr);
return0;
}
you're welcome!
I am very thanks.............
Awsome. thanks!
I have a problem with this game.
I copy it in the SD, and I execute it, but it has a problem.
The game doesn't work, and it enables the screen to send a report to microsoft.
I don't understand why it happens this.
Thanks a lot.
(sorry, my english is very bad).
skynetent said:
I have a problem with this game.
I copy it in the SD, and I execute it, but it has a problem.
The game doesn't work, and it enables the screen to send a report to microsoft.
I don't understand why it happens this.
Thanks a lot.
(sorry, my english is very bad).
Click to expand...
Click to collapse
Did you use a touch Diamond ?
Oh sorry. I didn't mention it.
I use a HTC touch HD (blackstone)
Thanks.

Calculations At Lower Level?

Is there any way to force certain calculations to be done out of the VM? Basically I have algorithms (math) in a program that are slow as balls in Java and would really like if it went faster. I optimized it the best that's really possible, plus Java does some optimizations, but it's still way too slow.
Any way I can kick these calculations off to C land and get things done quicker? I mean my phone's not the fastest (1Ghz Hummingbird), but it should be pretty quick. The JVM is slowing it down by leaps and bounds.
Anybody know anything?
TIA
You can use the NDK to write C code.
Can you provide an example of your problems, though?
hrk said:
You can use the NDK to write C code.
Can you provide an example of your problems, though?
Click to expand...
Click to collapse
Ah, NDK looks like it is exactly what I'm looking for. Looks like the C aspect has to be kind of jammed in there, but I kind of need the performance, so I don't really mind.
As for an example, the program is an image manipulator, so there's many loops. While not a direct pull from my code, an example could be something like this:
Code:
int i, j;
int height = bmp.getHeight();
int width = bmp.getWidth();
int color = 0xFFFF0000;
int count = 0;
for (i = 0 ; i < width ; ++i) {
for (j = 0 ; j < height ; ++j) {
bmp.setPixel(i, j, color);
switch(count % 3) {
case 0:
color = 0xFF00FF00; break;
case 1:
color = 0xFF0000FF; break;
case 2:
color = 0xFFFF0000; break;
}
count++;
}
}
So I do still need access to things (the bitmap) up in Java land.
I see that NDK passes some environment stuff (a pointer to a JNIEnv struct/class, and a copy of a jobject come with each function call, aside from any additional parameters somebody wishes to use). Do you know what those are? I mean I get that one's a pointer to the Java native interface environment, and I'm assuming the object copy is a copy of the object called on it? And types in C land are prefixed with a 'j'?
Thanks for your time and help!
I haven't used JNI in the last... ten?... years, so my memory is a bit dusty there.
In JNI you don't use C-types, but those "J prefixed types" which internally handle all the compiler-platform-java specific differences (simple example: how big is a "long" on an ARM, ia32 and ia64 computer? A jlong has the same size on all of them).
I recommend you these two links: Java programming with JNI (IBM developer network) and Wikipedia: Java Native Interface. I'm not joking, Wikipedia has some basic examples and links to useful informations!
Having said that... can't you go for a different approach, like...
Code:
int[][] rawData = new int[bmp.getWidth(), bmp.getHeight()];
...
for (int i ...) {
for (int j ...) {
// color from switch
// ...
rawData[i][j] = color;
}
}
bmp.somehowSetRawDataInOneCall(rawData);
I don't know which image manipulating class you're using (and I don't know how specific your code was!), but I clearly remember using "mass"-setting methods in one of my projects to speed things up after trying myself your setColor(i, j, color) approach.
hrk said:
I haven't used JNI in the last... ten?... years, so my memory is a bit dusty there.
In JNI you don't use C-types, but those "J prefixed types" which internally handle all the compiler-platform-java specific differences (simple example: how big is a "long" on an ARM, ia32 and ia64 computer? A jlong has the same size on all of them).
I recommend you these two links: Java programming with JNI (IBM developer network) and Wikipedia: Java Native Interface. I'm not joking, Wikipedia has some basic examples and links to useful informations!
Having said that... can't you go for a different approach, like...
Code:
int[][] rawData = new int[bmp.getWidth(), bmp.getHeight()];
...
for (int i ...) {
for (int j ...) {
// color from switch
// ...
rawData[i][j] = color;
}
}
bmp.somehowSetRawDataInOneCall(rawData);
I don't know which image manipulating class you're using (and I don't know how specific your code was!), but I clearly remember using "mass"-setting methods in one of my projects to speed things up after trying myself your setColor(i, j, color) approach.
Click to expand...
Click to collapse
Yeah, using a raw buffer will definitely alleviate some of the overhead simply by removing function calls from the task loop. I'm using the Bitmap class, it has a setPixel method. I'm sure there's a way to dump a new buffer in there. That would definitely speed things up.
Good to know the types are standard sizes, unlike C/C++.
I'll look into the links above, and yes, I trust Wikipedia for all things factual. Not like I'm looking up political stuff there, math and CS is pretty set in stone.
That being said, while it will definitely remove some of the overhead to modify a primitive data structure, that was a fairly simplistic example. The problem is that some of the filters do multiple passes, multiple filter applications, and are in general more complex. I don't believe Java will prove quick enough.
I'll give it a whirl, though, I'll see what happens, maybe I can get some times. I'll post back at some point (few days) when I get time to test it (too busy atm).
Thanks for your time, I'll get back to ya.

USB Mouse support

Edit:
I released a compiled APK that I believe is done. Please check http://forum.xda-developers.com/showpost.php?p=13809172&postcount=8 for more info!
I made this over the past few days for my Iconia. Since we're going to be getting 3.1 soon, I don't think I want to bother cleaning it up and finishing it.
And, before someone says something about how it's crappy, it was the first android project (Not first Java/Linux) I've ever done, I think it came out pretty well. I've put most of the major issues into //TODO:'s (such as proper detection on what event to use)
Credits to whoever posted the service example I used. I looked, but I couldn't seem to track it back down.
(Feel free to do whatever you want with it, just please include my name somewhere on it. )
Hi, can you post a guide to install your mod? Thank you
sto88 said:
Hi, can you post a guide to install your mod? Thank you
Click to expand...
Click to collapse
Yak, I don't know how the zip is related to USB mouse support. Please tell us how to use the mouse.zip. Thanks very much.
netham45 said:
I made this over the past few days for my Iconia. Since we're going to be getting 3.1 soon, I don't think I want to bother cleaning it up and finishing it.
And, before someone says something about how it's crappy, it was the first android project (Not first Java/Linux) I've ever done, I think it came out pretty well. I've put most of the major issues into //TODO:'s (such as proper detection on what event to use)
Credits to whoever posted the service example I used. I looked, but I couldn't seem to track it back down.
(Feel free to do whatever you want with it, just please include my name somewhere on it. )
Click to expand...
Click to collapse
Firstly Great work to the OP, I never considered redirecting mouse events to the touch screen.
I hope you don't mind, but considering 3.1 is a little while away I'd like to upload this as an apk with a few tweaks.
Tweaks so far:
Moved the SU request to the app instead of the service, that way all su calls are caught by Superuser manager and permissions are requested appropriately.
Set boundaries so your mouse can't wander off the screen.
Changed the text cursor to a png cursor.
When I work out a way to detect which event entry is the mouse I'll upload the APK, until then it's not likely to work for most people.
Keep in mind when I do upload it'll be fragile and possibly won't work for everybody.
Now I'm going to get some much needed sleep
very nice. I looked into detecting the mouse automatically, all I could come up with is reading the dmesg logs and relating them to getevents' output, which seems a bit over the top for this.
Perhaps ask for what dev to use on launch?
netham45 said:
very nice. I looked into detecting the mouse automatically, all I could come up with is reading the dmesg logs and relating them to getevents' output, which seems a bit over the top for this.
Perhaps ask for what dev to use on launch?
Click to expand...
Click to collapse
Yeah that or have a detection mode which asks you to unplug the mouse if plugged in, then to plug it in and detect the added entry.
that would work too. You'll still neneed to match it with aan input from getevent, though.
Edit: Just use getevents. It returns every system event, and only the mouse ones will start with 0003.
Edit2: Ignore that edit. Doesn't return info like I was thinking it did.
Edit3: Actually..... my keyboard doesn't send any events that'd conflict.
(values are hex strings)
/dev/input/event4: 0001 0110 00000001 = left down
/dev/input/event4: 0001 0110 00000000 = left up
/dev/input/event4: 0001 0111 00000001 = right down
/dev/input/event4: 0001 0111 00000000 = right up
/dev/input/event4: 0002 0001 XXXXXXX = Y coord change
/dev/input/event4: 0002 0000 XXXXXXX = X coord change
Sec, I'll write up code to parse this type too, and attach it here.
Edit 4:Not going to work decently. getevent buffers far too much when not outputting to a tty.
Edit 5: Okay, realized that I could check what keycodes a device could send, and that there are some mouse specific keycodes. (getevent -p)
This should return the path to a mouse, or 'NONE' if there is no mouse.
Code:
String getMouse()
{
String Message = "";
String[] Parts;
String curDevice = "";
Process process = null;
boolean deviceFound = false;
boolean isInKey = false;
try {process = Runtime.getRuntime().exec("getevent -p");} catch (IOException e) {}
DataInputStream in = new DataInputStream(process.getInputStream());
try
{
while (true)
{
Message = in.readLine();
if (Message.indexOf("(") >= 0)
isInKey = false;
if (Message.indexOf("KEY (0001):") >= 0)
isInKey = true;
if (isInKey && Message.indexOf("0110") >= 0)
{
deviceFound = true;
break;
}
Parts = Message.trim().split(" ");
if (Parts.length <4) continue;
if(Message.indexOf("add device") >= 0){
curDevice = Parts[3];
}
}
}
catch(Exception a){}
if (!deviceFound)
{
curDevice="NONE";
Log.e("Mouse","No Mouse Found!");
}
else
Log.i("Mouse","Mouse Found At: " + curDevice);
return curDevice;
}
This works for the two mice I have that generate events, Logitech Wireless USB Mouse, and a generic PS2 -> USB adaptor. For some reason, my Razr Naga doesn't even generate events.
Okay, I felt that this warranted a doublepost. If not, sue me.
I've made this APK for mouse support.
Known issues:
Mouse cursor is slow
Android doesn't create events for all mice, so not all mice are compatible. Simple mice have the highest chance of working.
Makes frequent calls to root when trying to find a mouse. This will drain your battery, if you plan to unplug it for a long time, I suggest opening the app and hitting stop. Maybe someone could add a timeout to it?
Can't go onto the menu bar. I don't know how to draw over that too.
Features:
Automatically detects the mouse
Automatically disables cursor when mouse is unplugged
Automatically enables cursor when mouse is replugged
Supports clicking -AND- dragging!
This may not work for everyone. If it doesn't work for you, I'm sorry. Maybe you could talk one of the other devs here into fixing it.
This may work on other tablets, I'm not sure. There is a build compiled with Froyo libs too.
This program requires root.
Attached is the source and a compiled APK. I think I did the APK right, first one I've ever made.
If someone could let me know if this works on bluetooth mice, that'd be awesome. I think it might, but I don't know. I don't have one, and if it doesn't, I won't be the one to add support.
Do you suggest to install the standard or the froyo version on Iconia? I tried the standard and it worked fine =)
I don't think it should matter, they both work fine for me.
Glad to hear it works!
Since I've already finished this I'll post it anyway, this detects the mouse by detecting which mouse input device is missing when unplugged against that of when it's plugged in (this doesn't always work with complex mouses). It also allows you to override and choose your device, in which case if it doesn't work stop the service and try another device.
I've included source which is a bit rushed and is based on the source in the original post
yours seems to work alot better than mine. I'ma have to peek at the source.
Must be some difference in how you draw, its really noticable in angry birds.
hellcat82 said:
Since I've already finished this I'll post it anyway, this detects the mouse by detecting which mouse input device is missing when unplugged against that of when it's plugged in (this doesn't always work with complex mouses). It also allows you to override and choose your device, in which case if it doesn't work stop the service and try another device.
I've included source which is a bit rushed and is based on the source in the original post
Click to expand...
Click to collapse
Works very nicely - thanks. Is there any way to control speed and add mouse pointers?
docfreed said:
Works very nicely - thanks. Is there any way to control speed and add mouse pointers?
Click to expand...
Click to collapse
Theoretically speed control wouldn't be too difficult. Just a case of multiplying the X and Y coord movements by a ratio.
Dynamically loading mouse pointers should also be possible but could take a bit more time to implement.
I'll try my hand at speed control if I get some time this week.
hellcat82 said:
Theoretically speed control wouldn't be too difficult. Just a case of multiplying the X and Y coord movements by a ratio.
Dynamically loading mouse pointers should also be possible but could take a bit more time to implement.
I'll try my hand at speed control if I get some time this week.
Click to expand...
Click to collapse
Great, look forward to your work. Also, would this work with a bluetooth mouse?
docfreed said:
Great, look forward to your work. Also, would this work with a bluetooth mouse?
Click to expand...
Click to collapse
I'm not sure if Android generates events for them (I don't have one to test on), but if it does, it's possible.
could a trackpad on a bluetooth keyboard work thanks to this patch?
This is working really well on my a500. Thanks a bunch! This along with my bt kybd and pocketcloud I leave the laptop at home for good.
Observations:
Lots of cursor lag when doing moderate to high level tasks
Cursor hidden behind the status bar, though clicking on the buttons still works.
Thanks again!!
Sent from my DROID2 using XDA App
great
brilliant !! it works well with usb keyboard and bluetooth mouse via usb hub
Got this working with a Microsoft wireless keyboard and mouse combo (1 rf receiver). Would be perfect for when hooking up the unit via HDMI to a home theater. Also I can confirm that it doesn't work with a Logitech G500 gaming mouse. lol didn't really expect that it would, but of course I had to try.

[DEV]Porting Nexus S touchscreen drivers to HTC phones for ICS

EDIT:
A better fix has been found for touchscreens using HTCs driver allowing us to actually use the original driver instead of porting another (although porting did seem to work mostly, this seems more ideal).
http://forum.xda-developers.com/showthread.php?p=19047963
Guess I'll leave this all here though in case someone ever looks it up again.
Ok, since I've been getting so many requests for information about how I did this, I decided to start a thread dedicated to it.
With Ice Cream Sandwich, Google seems to have changed the way it expects the touchscreen drivers to behave. Many of the HTC phones (starting with the Evo and Inc) all the way up to current HTC phones utilize some version of HTC's driver (drivers/input/touchscreen/atmel.c) written for the Atmel maXTouch touchscreen. This driver doesn't work at all on ICS. Many people will say its only the SDK port we're working with, but I have a good feeling some adjustments will need to be made to get the HTC driver working when the source is released anyways.
The few drivers that do work are:
synaptics-i2c-rmi.c - for Synaptics TS
---> Nexus One, Desire...possibly others that utilize this driver
mxt224.c - for Atmel maXTouch
---> Samsung Nexus S and most likely other Samsung phones
elan8232-i2c.c for elan TS
---> HTC Leo/HD2
From what I can tell, the only real big different that jumps out at me between these drivers and ours is the way the driver WRITES to the i2c bus. The Samsung and elan drivers both use i2c_master_send to write to the i2c bus. The Synaptics driver does it a little differently, using i2c_smbus_write_byte_data, which appears to do something similar, but needs to be used more often to accomplish the same thing.
The HTC driver uses i2c_transfer, which according to what I've found online, is not the preferred method of writing to the bus and i2c_master_send should be used instead.
It would seem like it would be easier to just modify the existing HTC driver to incorporate the newer method, but I didn't realize that until after I had already gotten the Samsung driver working! It should be possible, but I'm not sure I have the expertise to do this as it would require tweaking a lot of code in the driver.
Anyways, on to what I actually did.
I was able to compile the Samsung driver into cuviper's CM7 kernel, but the driver kept hanging on reading the i2c bus from what I could see. I figured it'd have this problem with writing to it as well, so I changed both methods at the same time.
Here's the original read and write methods from HTC's atmel.c driver
Code:
int i2c_atmel_read(struct i2c_client *client, uint16_t address, uint8_t *data, uint8_t length)
{
int retry;
uint8_t addr[2];
struct i2c_msg msg[] = {
{
.addr = client->addr,
.flags = 0,
.len = 2,
.buf = addr,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = length,
.buf = data,
}
};
addr[0] = address & 0xFF;
addr[1] = (address >> 8) & 0xFF;
for (retry = 0; retry < ATMEL_I2C_RETRY_TIMES; retry++) {
if (i2c_transfer(client->adapter, msg, 2) == 2)
break;
mdelay(10);
}
if (retry == ATMEL_I2C_RETRY_TIMES) {
printk(KERN_ERR "i2c_read_block retry over %d\n",
ATMEL_I2C_RETRY_TIMES);
return -EIO;
}
return 0;
}
int i2c_atmel_write(struct i2c_client *client, uint16_t address, uint8_t *data, uint8_t length)
{
int retry, loop_i;
uint8_t buf[length + 2];
struct i2c_msg msg[] = {
{
.addr = client->addr,
.flags = 0,
.len = length + 2,
.buf = buf,
}
};
buf[0] = address & 0xFF;
buf[1] = (address >> 8) & 0xFF;
for (loop_i = 0; loop_i < length; loop_i++)
buf[loop_i + 2] = data[loop_i];
for (retry = 0; retry < ATMEL_I2C_RETRY_TIMES; retry++) {
if (i2c_transfer(client->adapter, msg, 1) == 1)
break;
mdelay(10);
}
if (retry == ATMEL_I2C_RETRY_TIMES) {
printk(KERN_ERR "i2c_write_block retry over %d\n",
ATMEL_I2C_RETRY_TIMES);
return -EIO;
}
return 0;
}
And here's Samsung's methods from their mxt224.c driver
Code:
static int read_mem(struct mxt224_data *data, u16 reg, u8 len, u8 *buf)
{
int ret;
u16 le_reg = cpu_to_le16(reg);
struct i2c_msg msg[2] = {
{
.addr = data->client->addr,
.flags = 0,
.len = 2,
.buf = (u8 *)&le_reg,
},
{
.addr = data->client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buf,
},
};
ret = i2c_transfer(data->client->adapter, msg, 2);
if (ret < 0)
return ret;
return ret == 2 ? 0 : -EIO;
}
static int write_mem(struct mxt224_data *data, u16 reg, u8 len, const u8 *buf)
{
int ret;
u8 tmp[len + 2];
put_unaligned_le16(cpu_to_le16(reg), tmp);
memcpy(tmp + 2, buf, len);
ret = i2c_master_send(data->client, tmp, sizeof(tmp));
if (ret < 0)
return ret;
return ret == sizeof(tmp) ? 0 : -EIO;
}
You can see they're very similar. Anyways, for some reason, cpu_to_le16 function either doesn't work correctly with the Snapdragon, or the build isn't linking them right, even though I made sure it had all the right files and #includes. So I took them out. And replaced them with part of the functions from the HTC driver. And after a couple failed attempts at booting, I came up with this:
Code:
static int read_mem(struct mxt224_data *data, u16 reg, u8 len, u8 *buf)
{
int ret;
uint8_t addr[2];
struct i2c_msg msg[] = {
{
.addr = data->client->addr,
.flags = 0,
.len = 2,
.buf = addr,
},
{
.addr = data->client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buf,
},
};
addr[0] = reg & 0xFF;
addr[1] = (reg >> 8) & 0xFF;
ret = i2c_transfer(data->client->adapter, msg, 2);
if (ret < 0)
return ret;
return ret == 2 ? 0 : -EIO;
}
static int write_mem(struct mxt224_data *data, u16 reg, u8 len, const u8 *buf)
{
int ret;
uint8_t addr[len + 2];
addr[0] = reg & 0xFF;
addr[1] = (reg >> 8) & 0xFF;
memcpy(addr, buf, len);
ret = i2c_master_send(data->client, addr, sizeof(addr));
if (ret < 0)
return ret;
return ret == sizeof(addr) ? 0 : -EIO;
}
After those changes, I was able to use the touchscreen in CM7 just like I had with the HTC driver. Very responsive, no problems whatsoever. Also works fine in the ICS SDK ports. It only works in pointer mode in ICS currently, but that isn't a driver issue I don't think and can be fixed by changing a couple of the configuration files.
The only other things I had to change where in my board init file, but that was simply adding and deleting some of the touchscreen init functions and replacing them with similar ones from the Samsung driver. As well as populating the config info with HTC's values (although they also seemed to work fine with the stock ones from the Samsung build).
Anyways, if you have any questions, or more information please let me know. I could be totally wrong about the i2c bus thing, but as of right now it seems to make sense to me!
Here's my github for anyone that wishes to look at my changes.
Edit: atmel.c is the correct name of the driver source file. I got it mixed up with the way the HTC driver identifies itself in the kernel, which is atmel-touchscreen. Sorry for the confusion. Thanks to the_platypus to catching this.
Also, just wanted to reiterate this should work with just about any HTC phone using the maXTouch sensor. Just grab mxt224.c and .h and put them in the correct spot, modify the Kconfig file for touchscreens, and edit your board init file accordingly.
To clear up some confusion and so I don't have to answer too many PMs, I'm going to add some details about how to get this to work.
First of all, grab mxt224.c, Kconfig, and Makefile from drivers/input/touchscreen/, and place them in your build folder in the same place.
Then do the same with mxt224.h, which is under include/linux/input/.
Go to arch/arm/mach-msm and grab my board-incrediblec.c. Compare it to whatever yours is (i.e. board-supersonic.c).
You'll need to change the name of the power init function for the touchscreen, and do something similar with the config data that I added to my init file. Make sure you scroll alllll the way down until you find the section about virtual keys. Make sure you change the name of "virtualkeys.atmel-touchscreen" to "virtualkeys.mxt224_ts_input" (I think thats correct, I'll check in a bit and correct if I'm wrong).
A note about the config data section for initializing the touchscreen:
I took the values from the original struct that was there from HTC, for my touchscreen revision. Normally, there are multiple hardware revisions of the touchscreen it seems, and upon booting, the kernel checks which one you have, and picks the correct one. I took this out since I was only trying to get it to work on my phone. Now that I know it works, I'm going to go back and readd the code to check the rev so it'll get the right config data.
This also means there's a good chance you need to copy the values from the original HTC init functions and put them into the struct I made. It can be a pain in the ass kind of, but it'll ensure your touchscreen works correctly. I want to note that mine worked fine with the actual Samsung values, but was kind of wonky.
Also, you'll have to edit your .config if you already have one. Go in there and put a big ol # in front of the line about atmel-touchscreen or whatever and save it. When you make your build it'll tell you about a great new driver that it found (surprise!) and ask if you want to enable it. Say yes, obviously. The first part is only important if you already have a .config or if your config wants to use atmel.c by default. Cause you don't. You ARENT using the HTC driver anymore. You want to use mxt224!
Sorry for being confusing, I'm not always the best at explaining things
Hey guys, I see this has about a thousand views. I'm not demanding a response but I'm curious if anyone else was able to get this working. If you did, please post!
Sent from my ADR6300 using xda premium
After porting the driver on Thunderbolt, I do get a log of the init, but there is no getevent data and it is currently unresponsive. I think it is related to my specific functions and the way they are translated, but in theory it does recognize the new driver.
Sent from my ADR6400L using Tapatalk
Interesting...
Would you mind posting a logcat (from cold boot) and a dmesg dump?
Also, are you using the kernel on ICS or some other ROM? I found it helpful to test my kernel changes in CM7 until I got it working, only because I was more sure of what would work.
I'm actually trying to tweak the original HTC driver now to use the newer i2c_master_send method, which is proving somewhat difficult. It actually works using i2c_master_send instead of i2c_message, but its god awfully slow. I'm chalking that up to the ridiculous amount of i2c_writes (only 1 byte each!) the HTC driver wants to do individually to modify touch settings on the fly. I'm trying to see if there's a better way to do this and group them together to make less writes on the bus. The Samsung driver seems to do this pretty well...
swm5126 said:
Interesting...
Would you mind posting a logcat (from cold boot) and a dmesg dump?
Also, are you using the kernel on ICS or some other ROM? I found it helpful to test my kernel changes in CM7 until I got it working, only because I was more sure of what would work.
I'm actually trying to tweak the original HTC driver now to use the newer i2c_master_send method, which is proving somewhat difficult. It actually works using i2c_master_send instead of i2c_message, but its god awfully slow. I'm chalking that up to the ridiculous amount of i2c_writes (only 1 byte each!) the HTC driver wants to do individually to modify touch settings on the fly. I'm trying to see if there's a better way to do this and group them together to make less writes on the bus. The Samsung driver seems to do this pretty well...
Click to expand...
Click to collapse
I really think HTC takes everything 1 byte at a time. Look at how many devices they have released and they are still using almost the same size battery they had in the G1. Anyway, back to the topic at hand.
For anyone else, here are the commands to get those files if you need to post them:
Code:
adb shell logcat -d > logcat.txt
adb shell dmesg > dmesg.txt
And mine are included with this post. I didn't try running it on CM7 because my daily driver is a Sense ROM. Even I don't understand why I run Sense when I use SPB launcher and disable most of the Sense features anyway.
swm5126 said:
Hey guys, I see this has about a thousand views. I'm not demanding a response but I'm curious if anyone else was able to get this working. If you did, please post!
Sent from my ADR6300 using xda premium
Click to expand...
Click to collapse
I am working on porting it to the G2 but am having problems getting it to init. got the kernel to build, and boot but no joy with the ts... let me get the logcat and i will post
http://www.mediafire.com/?jpt3estxqxs4i - logcat and dmesg
Is there any way to just edit the kernel and ROM instead of using the Source Code?
twistedumbrella said:
I really think HTC takes everything 1 byte at a time. Look at how many devices they have released and they are still using almost the same size battery they had in the G1. Anyway, back to the topic at hand.
For anyone else, here are the commands to get those files if you need to post them:
Code:
adb shell logcat -d > logcat.txt
adb shell dmesg > dmesg.txt
And mine are included with this post. I didn't try running it on CM7 because my daily driver is a Sense ROM. Even I don't understand why I run Sense when I use SPB launcher and disable most of the Sense features anyway.
Click to expand...
Click to collapse
Looks like the touchscreen never actually gets to power on for some reason...probably something in your board init file I would think, but I'm not sure. Wish I had more devices to test this out on. If you can, I'd try the latest CM7 for the Tbolt, and grab the kernel from whoever maintains it and build that one and see if it works, since that's how I had success so far.
OdiemanSAM said:
I am working on porting it to the G2 but am having problems getting it to init. got the kernel to build, and boot but no joy with the ts... let me get the logcat and i will post
http://www.mediafire.com/?jpt3estxqxs4i - logcat and dmesg
Click to expand...
Click to collapse
Sounds like you have about the same issue as twisted does. Try CM7 and adding it to the current kernel for your device, unless that's what you've already done.
swm5126 said:
Looks like the touchscreen never actually gets to power on for some reason...probably something in your board init file I would think, but I'm not sure. Wish I had more devices to test this out on. If you can, I'd try the latest CM7 for the Tbolt, and grab the kernel from whoever maintains it and build that one and see if it works, since that's how I had success so far.
Sounds like you have about the same issue as twisted does. Try CM7 and adding it to the current kernel for your device, unless that's what you've already done.
Click to expand...
Click to collapse
I'm on CM7 and not sure what ts i have... the desire z/g2???? anyone... I tried changing it to the synaptics i2c rmi and the init file to synaptics_i2c_rmi_ts_input... is that right???
EDIT: I found it... it is synaptics-rmi-touchscreen
OdiemanSAM said:
I'm on CM7 and not sure what ts i have... the desire z/g2???? anyone... I tried changing it to the synaptics i2c rmi and the init file to synaptics_i2c_rmi_ts_input... is that right???
EDIT: I found it... it is synaptics-rmi-touchscreen
Click to expand...
Click to collapse
Well you have the Atmel maXTouch, just like the Incredible and many other HTC phones. You shouldn't need to change any files other than your board init file and adding the mxt224.c/.h to their respective directories. It's a little more than renaming functions in the board init file, by the way. And it should be mxt224_ts_input. The synaptics stuff doesn't relate to our phones, only the Nexus One, Desire, and maybe earlier models.
djpbx said:
Is there any way to just edit the kernel and ROM instead of using the Source Code?
Click to expand...
Click to collapse
Uhh... well we are editing the kernel. That's what we're doing. You can't edit much of anything at all in a kernel once it's built, that's why I modified the source.
swm5126 said:
Looks like the touchscreen never actually gets to power on for some reason...probably something in your board init file I would think, but I'm not sure. Wish I had more devices to test this out on. If you can, I'd try the latest CM7 for the Tbolt, and grab the kernel from whoever maintains it and build that one and see if it works, since that's how I had success so far.
Sounds like you have about the same issue as twisted does. Try CM7 and adding it to the current kernel for your device, unless that's what you've already done.
Click to expand...
Click to collapse
I grabbed CM7 just after making that post. The kernel built for CM7 is a port from other devices, modified to work. The version I am using is a newer replacement CM7 kernel made from the source for the Tbolt. I am pretty sure the same results happened with the CM "port" kernel that was being tested.
I remember hearing about the issue when they ported gingerbread. Let me see if I can find the info.
swm5126 said:
Well you have the Atmel maXTouch, just like the Incredible and many other HTC phones. You shouldn't need to change any files other than your board init file and adding the mxt224.c/.h to their respective directories. It's a little more than renaming functions in the board init file, by the way. And it should be mxt224_ts_input. The synaptics stuff doesn't relate to our phones, only the Nexus One, Desire, and maybe earlier models.
Click to expand...
Click to collapse
ok so my init file is board-vision.c???? right??? what else do i need to change??? besides the virtualkeys.mxt224_ stuff????
I'd like to help out but you'll have to give me until later tonight or tomorrow. I'd like to see if I can get the HTC driver working in ICS with some changes, thus eliminating the confusion of getting the Samsung driver to work people seem to be having.
If its not possible to fix the HTC driver I'll post a step by step guide on how to apply what I've done with the Samsung driver to a kernel.
Sent from my ADR6300 using xda premium
twistedumbrella said:
I grabbed CM7 just after making that post. The kernel built for CM7 is a port from other devices, modified to work. The version I am using is a newer replacement CM7 kernel made from the source for the Tbolt. I am pretty sure the same results happened with the CM "port" kernel that was being tested.
I remember hearing about the issue when they ported gingerbread. Let me see if I can find the info.
Click to expand...
Click to collapse
Ok. I actually just compiled the Tbolt kernel for someone else, I don't have the download link handy but I'll post it here in a few hours.
Sent from my ADR6300 using xda premium
swm5126 said:
Ok. I actually just compiled the Tbolt kernel for someone else, I don't have the download link handy but I'll post it here in a few hours.
Sent from my ADR6300 using xda premium
Click to expand...
Click to collapse
Lol. **** you. Bust my *** and you just sneeze and make the thing. Haha. Thanks. I am curious what the difference was that I didn't catch. I will have to post my board c file if you want to take a glance at it, but the driver file should be exactly the same because I was comparing Incredible to Tbolt and the atmel config and such were word for work. The big difference was the init method. Everything else matched up.
twistedumbrella said:
Lol. **** you. Bust my *** and you just sneeze and make the thing. Haha. Thanks. I am curious what the difference was that I didn't catch. I will have to post my board c file if you want to take a glance at it, but the driver file should be exactly the same because I was comparing Incredible to Tbolt and the atmel config and such were word for work. The big difference was the init method. Everything else matched up.
Click to expand...
Click to collapse
Yeah didn't mean to make you do work for nothing, I had just done it for someone on a whim using a different source than you were using and I'm not sure if it worked or not yet.
He said it was working under CM7 for sure though, he just PMed me.
http://www.mediafire.com/?avcb4ev5k31indm
Sent from my ADR6300 using xda premium
swm5126 said:
Yeah didn't mean to make you do work for nothing, I had just done it for someone on a whim using a different source than you were using and I'm not sure if it worked or not yet.
He said it was working under CM7 for sure though, he just PMed me.
http://www.mediafire.com/?avcb4ev5k31indm
Sent from my ADR6300 using xda premium
Click to expand...
Click to collapse
I'll have to try it out against my setup. It is good I did it either way because I am sure more changes will be needed down the road. I just couldn't help giving you a hard time
Sent from my ADR6400L using Tapatalk
Didn't seem to work in ICS. No getevent data, and no touch response. Making sure I properly added in the zimage just in case, but it should be right.

File transfer over TCP sockets

I've been trying to get a simple file transfer between desktop app and phone app. The transfer works up to a point, when it simply ...stops dead.
The server(aka desktop client) enters the listening state, and the phone goes idle.
Anyone has any samples on transfers of large file (bigger than 1 MB)?
mcosmin222 said:
I've been trying to get a simple file transfer between desktop app and phone app. The transfer works up to a point, when it simply ...stops dead.
The server(aka desktop client) enters the listening state, and the phone goes idle.
Anyone has any samples on transfers of large file (bigger than 1 MB)?
Click to expand...
Click to collapse
Have you looked through GoodDayToDie's source code for the File Server? I wonder if he has anything in there that could make that work.
snickler said:
Have you looked through GoodDayToDie's source code for the File Server? I wonder if he has anything in there that could make that work.
Click to expand...
Click to collapse
lalz.
Completely forgot about that one xD
Meh he has it written in C++
Apparently, he didn't do anything that I didn't.
mcosmin222 said:
lalz.
Completely forgot about that one xD
Meh he has it written in C++
Click to expand...
Click to collapse
You can still utilize the transfer portion . I was thinking of seeing what I could do with sockets on the phone. I know it could come in handy somehow
snickler said:
You can still utilize the transfer portion . I was thinking of seeing what I could do with sockets on the phone. I know it could come in handy somehow
Click to expand...
Click to collapse
It's a pain in the ***.
It stops transfer at random points.
mcosmin222 said:
It's a pain in the ***.
It stops transfer at random points.
Click to expand...
Click to collapse
That doesn't surprise me at all for some reason.
Did you double-check your socket multithreading code?
I recently had problems with sockets and it turned out that I had the muti-threading thing wrong.
I think you shouldn't use only one connection and fail if it drops ...
ScRePt said:
Did you double-check your socket multithreading code?
I recently had problems with sockets and it turned out that I had the muti-threading thing wrong.
I think you shouldn't use only one connection and fail if it drops ...
Click to expand...
Click to collapse
What do you mean by socket multthreading code? You mean the use of async methods? or having the thread work on background, using the socket?
Take a look to the Tim Laverty's networking samples.
sensboston said:
Take a look to the Tim Laverty's networking samples.
Click to expand...
Click to collapse
That's what im doing (more or less)
@mcosmin222: The most common reason I saw for why that happened was the thread doing the transfer would crash. There's a lot of things that could cause such a crash, but because it's not the main thread or a UI thread, you don't see it. It just stops. In fact, even the debugger usually doesn't catch it (annoying as hell...)
There are a few common things that non-UI threads aren't allowed to do which you might be trying. For example, attempting to show a MessageBox on a non-UI thread will crash the thread (you can do it by adding a lambda or function to the dispatcher for the UI). In any case, feel free to use or adapt my code, or share yours here and if there's an obvious issue I'll point it out. Incidentally, you can set a larger buffer on the socket if you want the operation to complete without looping.
By the way, the only portion of my webserver that's written in C++ is the file I/O code, which I chose to do in C++ rather than .NET because the phone's stunted .NET framework makes it more difficult than I like to access arbitrary file paths. That code is all fairly clean wrappers around the Win32 calls; I suppose I could comment it more but it's very straightforward to read even if you aren't familiar with managed C++. The actual network code is entirely written in C# 4.5. You could actually simplify it a bit for a direct transfer app, too; I wrote it with a lot of multithreading in case I wanted to re-use the code somewhere that might be expected to have more than one client connecting at a time.
GoodDayToDie said:
@mcosmin222: The most common reason I saw for why that happened was the thread doing the transfer would crash. There's a lot of things that could cause such a crash, but because it's not the main thread or a UI thread, you don't see it. It just stops. In fact, even the debugger usually doesn't catch it (annoying as hell...)
There are a few common things that non-UI threads aren't allowed to do which you might be trying. For example, attempting to show a MessageBox on a non-UI thread will crash the thread (you can do it by adding a lambda or function to the dispatcher for the UI). In any case, feel free to use or adapt my code, or share yours here and if there's an obvious issue I'll point it out. Incidentally, you can set a larger buffer on the socket if you want the operation to complete without looping.
By the way, the only portion of my webserver that's written in C++ is the file I/O code, which I chose to do in C++ rather than .NET because the phone's stunted .NET framework makes it more difficult than I like to access arbitrary file paths. That code is all fairly clean wrappers around the Win32 calls; I suppose I could comment it more but it's very straightforward to read even if you aren't familiar with managed C++. The actual network code is entirely written in C# 4.5. You could actually simplify it a bit for a direct transfer app, too; I wrote it with a lot of multithreading in case I wanted to re-use the code somewhere that might be expected to have more than one client connecting at a time.
Click to expand...
Click to collapse
I am aware that some calls from background threads are not allowed, especially those that have to do with the UI thread.
This is the code for the server. It would seem this one is the problem, somewhere...I just can't see where...
I tried limiting the number of packages sent (that's what the timer is all about).
Code:
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public static string[] TransferStages = new string[] { "sendmetadataz-length", "sendmetadataz", "file-length", "file" };
public static int Index = -1;
public static List<string> FilePaths = new List<string>();
public static long CurrentStreamPosition = 0;
public static FileStream ifs;
static int pocketspersecond = 0;
static bool LimitExceded = false;
DispatcherTimer timer = new DispatcherTimer();
public static int CurrentArraySize = 0;
public static int FileIndex = 0;
public AsynchronousSocketListener()
{
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += timer_Tick;
}
void timer_Tick(object sender, EventArgs e)
{
LimitExceded = false;
}
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[StateObject.BufferSize];
// Establish the local endpoint for the socket.
// Note: remember to keep the portnumber updated if you change
// it on here, or on the client
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 13001);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.UTF8.GetString(
state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// Respond to the client
Send(handler, content);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
public static void Send(Socket handler, String data)
{
//handler.SendBufferSize = File.ReadAllBytes(@"D:\MUZICA\Activ - Visez.mp3").Length;
// handler.BeginSendFile(@"D:\MUZICA\Activ - Visez.mp3", new AsyncCallback(SendCallback), handler);
#region cotobatura
data = data.Replace("<EOF>", "");
if (data.Contains("sendmetadataz") && data.Contains("length")==false)
{
data = MainWindow.DataContextModel.Files.ElementAt(FileIndex).ToString()+"<EOF>";
byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
else if (data.Contains("sendmetadataz-length"))
{
Index++;
if (Index >= MainWindow.DataContextModel.Files.Count)
{
//FileIndex++;
data = "TransfersComplete<EOF>";
}
data = Encoding.UTF8.GetByteCount((MainWindow.DataContextModel.Files.ElementAt(FileIndex).ToString() + "<EOF>").ToString()).ToString();
byte[] MetaDataLength = Encoding.UTF8.GetBytes(data);
handler.SendBufferSize = MetaDataLength.Length;
handler.BeginSend(MetaDataLength, 0, MetaDataLength.Length, 0, new AsyncCallback(SendCallback), handler);
}
else if (data.Contains("file-length"))
{
ifs = File.Open(MainWindow.DataContextModel.Files.ElementAt(FileIndex).Location, FileMode.Open);
byte[] gugu = Encoding.UTF8.GetBytes(ifs.Length.ToString());
handler.SendBufferSize = gugu.Length;
handler.BeginSend(gugu, 0, gugu.Length, 0, new AsyncCallback(SendCallback), handler);
}
else if (data.Contains("file") && data.Contains("length") == false)
{
//byte[] filedata = File.ReadAllBytes(MainWindow.DataContextModel.Files.ElementAt(FileIndex).Location);
//handler.BeginSend(filedata, 0, filedata.Length, 0,
//new AsyncCallback(SendCallback), handler);
byte[] filedata = new byte[150];
for (int i = 0; i < 150; i++)
{
if (CurrentStreamPosition < ifs.Length)
{
filedata[i] = (byte)ifs.ReadByte();
CurrentStreamPosition++;
CurrentArraySize++;
}
else
{
Array.Resize(ref filedata, CurrentArraySize);
break;
}
CurrentArraySize = 0;
}
// if (pocketspersecond == 25) LimitExceded = true;
//Thread.Sleep(1000);
handler.BeginSend(filedata, 0, filedata.Length, 0, new AsyncCallback(SendCallback), handler);
}
//handler.BeginSendFile(MainWindow.DataContextModel.Files.ElementAt(FileIndex).Location, filedata, null, TransmitFileOptions.ReuseSocket, new AsyncCallback(SendCallback), handler );
// What we want to send back in this application is a game move based on what
// has been received. So we call Play on the GameLogic to give us a move to send back
// data = GameLogic.Play(data);
// Convert the string data to byte data using ASCII encoding.
//byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
//handler.BeginSend(byteData, 0, byteData.Length, 0,
// new AsyncCallback(SendCallback), handler);
#endregion
}
public static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
This is basically modified from the tick tak toe over sockets sample from MSDN.
The only possible call that would affect the UI is the call to the Console, but the code works fine for a while, after it just crashes.
I tried running the whole thing synchronously on the UI thread, the result appears to be the same.
In the Send method, the first 3 stages work (file-legth, metadata, metadata-length) and a few steps in the file stage (which actually sends the file).
AT some point, I assumed the thread was guilty somehow, but I just can't prove it. Running the thing directly on UI thread does not seem to change anything.
If the async method finishes and the socket gets disposed, the thread would "die".
PS: the entire thing is hosted by a WPF application.
Hmm... OK, there are several bugs here. I'm not sure which, if any, are responsible for the problem. I'd be tempted to overuse try-catch-log (for example, on the Send() function) and debug-print statements, but here are some things I can see that could cause a crash or other unexpected failure:
There is no guarantee that "ifs" is instantiated before use. If you for some reason skip the file-length step, the file step will crash with a null pointer exception.
The entire send function is hugely thread-unsafe. For example, if a second request arrives before you're done servicing the first one (which is entirely possible due to where the event gets signaled) then the values of "ifs" and "CurrentStreamPosition" and so on will be unpredictable at any given time. Since CurrentStreamPosition seems to be monotonically increasing, that's probably not going to cause an out-of-bounds exception, but it could cause you to enter a state where the test "if (CurrentStreamPosition < ifs.Length)" always fails.
The line "data = "TransfersComplete<EOF>";" never does anything; the next line (immediately following it) overwrites that variable. If you cared about that string, too bad.
FileIndex never changes; I hope you're only ever sending one file here...
You don't actually check that the number of bytes sent is the number you meant to send (admittedly, it *should* be, but there are cases where it won't be).
The last 150-byte chunk of every file transfer is truncated to the first byte. This is because "CurrentArraySize" is reset to 0 on every iteration of the byte-read loop (why use a byte-read loop?) so whenever "CurrentStreamPosition < ifs.Length" tests false, the "filedata" array will be resized to one byte (or zero if the file is an exact multiple of 150 bytes, which presumeably be correct).
There are probably more, but that's what jumped out at me (well, and some technically correct stylistic issues, like the "... == false" test). Given that your protocol seems to rely on end-of-message flags, I'm guessing that your problem is that since the last part of the file is almost always truncated, that marker is never getting sent. This probably leads to the client concluding that the server will be sending it more data, which it does by sending another "file" request. The server attempts to respond and immedately hits the CurrentStreamPosition < ifs.Length check, fails, goes to the else case, and tries to send a 1-byte packet containing a NULL byte.
Incidentally, does your file transfer protocol really require that the client request each 150-byte chunk one at a time, using a new TCP connection each time? That's... awfully inefficient.
GoodDayToDie said:
Hmm... OK, there are several bugs here. I'm not sure which, if any, are responsible for the problem. I'd be tempted to overuse try-catch-log (for example, on the Send() function) and debug-print statements, but here are some things I can see that could cause a crash or other unexpected failure:
There is no guarantee that "ifs" is instantiated before use. If you for some reason skip the file-length step, the file step will crash with a null pointer exception.
The entire send function is hugely thread-unsafe. For example, if a second request arrives before you're done servicing the first one (which is entirely possible due to where the event gets signaled) then the values of "ifs" and "CurrentStreamPosition" and so on will be unpredictable at any given time. Since CurrentStreamPosition seems to be monotonically increasing, that's probably not going to cause an out-of-bounds exception, but it could cause you to enter a state where the test "if (CurrentStreamPosition < ifs.Length)" always fails.
The line "data = "TransfersComplete<EOF>";" never does anything; the next line (immediately following it) overwrites that variable. If you cared about that string, too bad.
FileIndex never changes; I hope you're only ever sending one file here...
You don't actually check that the number of bytes sent is the number you meant to send (admittedly, it *should* be, but there are cases where it won't be).
The last 150-byte chunk of every file transfer is truncated to the first byte. This is because "CurrentArraySize" is reset to 0 on every iteration of the byte-read loop (why use a byte-read loop?) so whenever "CurrentStreamPosition < ifs.Length" tests false, the "filedata" array will be resized to one byte (or zero if the file is an exact multiple of 150 bytes, which presumeably be correct).
There are probably more, but that's what jumped out at me (well, and some technically correct stylistic issues, like the "... == false" test). Given that your protocol seems to rely on end-of-message flags, I'm guessing that your problem is that since the last part of the file is almost always truncated, that marker is never getting sent. This probably leads to the client concluding that the server will be sending it more data, which it does by sending another "file" request. The server attempts to respond and immedately hits the CurrentStreamPosition < ifs.Length check, fails, goes to the else case, and tries to send a 1-byte packet containing a NULL byte.
Incidentally, does your file transfer protocol really require that the client request each 150-byte chunk one at a time, using a new TCP connection each time? That's... awfully inefficient.
Click to expand...
Click to collapse
I know it is inefficient, but I'm rather new to sockets. I just want it to get working in a "beta stage" then ill optimize it (hance the FileIndex never increasing, the blatant lack of try-catch blocks).
On the client side, once the bytes in the buffer are processed, the server gets another send that to send the following 150 bytes (i use 150 just for the lulz).
So basically, the workfow is as follows:
ask metadata length >server gives the length >client adjusts buffer>ask metadata
ask metdata >server gives metdata>client processes the data>asks file length
ask file length>server gives file length>client adjusts a huge array of bytes in which the file will reside (i know this is horribly inefficient, but at some point i will write directly to a file stream)>asks for the first 150 bytes in the file.
server gets the request, sends 150 bytes to client>client copies the 150 bytes in the array created earlier, the asks for the next 150.
I am using 150 just to make sure the data never splits in more than one buffer.
When the file transfer occurs, a different message is used to signal the end of transfer. Client side counts the bytes it gets, and when it is equal to the file length, it no longer asks 150 bytes.
The whole thing seems to be safe from crashing until it gets to the part where it sends the file. I am aware that in the code i gave you there's some file streams not getting closed, but i've fixed that and the problem still occurs.
Since The debugger won't help me at all, I decided to use a WCF service instead.
mcosmin222 said:
What do you mean by socket multthreading code? You mean the use of async methods? or having the thread work on background, using the socket?
Click to expand...
Click to collapse
I mean worker threads not async.You will always have to have a thread in the background to "accept". once you accept you "read" in a new thread and the parent thread "accepts" again. Accept will freeze the thread.
On the other side, you simply "connect" and "write" in the same thread.
Read and Write is done in a loop via pre-defined buffers syncronously.
But if you want the server to give a response, the above flow is the other way around, and it is then when things get complicated. (server needs to "connect" and client needs to "accept" over a different set of ports and different threads)
Probably if you want to have reliable connection you will need the server to come back with a response "give me more" or sth.
So, trying to assist, it was my guess that drops or stalls could be because the above flow is not implemented properly.
Edit Oh ho, missed a whole new page so I am sorry if the reply is irrelevant now.
I would suggest you use the sync methods of sockets and not callbacks because is super easier to debug. ThreadPool.QueueSth (ctr + space I dont remember how it's called is your friend to handle threads yourself.
And try to separate pure socket handling from domain handling (lengths, metadata, etc). Send some bytes back and forth, clean-up and then move to domain specific things!
Moving the line that resets CurrentArraySize to outside of the for loop may well sove your problem. I'd try that first.
Optimization involves, among other things, removing try blocks. Unoptimized code, when you're trying to just make thigns work, ought to be full of them.
Don't forget that exceptions will not bubble up the call stack across threads. In addition to threads you create yourself, any async callback will happen on a different thread than the one that called the async function. If an uncaught exception occurs, the thread will die. If enough threads die, the program may crash (or at least hang) due to threadpool exhaustion.
GoodDayToDie said:
Moving the line that resets CurrentArraySize to outside of the for loop may well sove your problem. I'd try that first.
Optimization involves, among other things, removing try blocks. Unoptimized code, when you're trying to just make thigns work, ought to be full of them.
Don't forget that exceptions will not bubble up the call stack across threads. In addition to threads you create yourself, any async callback will happen on a different thread than the one that called the async function. If an uncaught exception occurs, the thread will die. If enough threads die, the program may crash (or at least hang) due to threadpool exhaustion.
Click to expand...
Click to collapse
I avoid try-catch in unoptimized code to see where actual exceptions occur (sometime the debugger doesn't break on exception).
Nop still not working.
The thread still appears to be crashing, even wrapped with try catch.
Do you at least know *which* function it's crashing in? Try putting a breakpoint on each function header and then, when one of them is hit, step through the execution until the thread dies. Work backward from there to find the problem.
GoodDayToDie said:
Do you at least know *which* function it's crashing in? Try putting a breakpoint on each function header and then, when one of them is hit, step through the execution until the thread dies. Work backward from there to find the problem.
Click to expand...
Click to collapse
The send function (the one with the case switch) appears to be crashing.
It executes the function then enters the listening stage (does not execute the callback).

Categories

Resources