Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
P
platform_packages_services_VncFlinger
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
LMODroid
platform_packages_services_VncFlinger
Commits
107d2e51
Commit
107d2e51
authored
7 years ago
by
Steve Kondik
Browse files
Options
Downloads
Patches
Plain Diff
vnc: Add uinput support
parent
dda11006
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
Android.mk
+2
-1
2 additions, 1 deletion
Android.mk
src/InputDevice.cpp
+466
-0
466 additions, 0 deletions
src/InputDevice.cpp
src/InputDevice.h
+39
-0
39 additions, 0 deletions
src/InputDevice.h
src/VNCFlinger.cpp
+5
-0
5 additions, 0 deletions
src/VNCFlinger.cpp
with
512 additions
and
1 deletion
Android.mk
+
2
−
1
View file @
107d2e51
...
...
@@ -4,7 +4,8 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES
:=
\
src/EglWindow.cpp
\
src/EventQueue.cpp
\
src/EventQueue.cpp
\
src/InputDevice.cpp
\
src/Program.cpp
\
src/VirtualDisplay.cpp
\
src/VNCFlinger.cpp
\
...
...
This diff is collapsed.
Click to expand it.
src/InputDevice.cpp
0 → 100644
+
466
−
0
View file @
107d2e51
#define LOG_TAG "VNC-InputDevice"
#include
<utils/Log.h>
#include
"InputDevice.h"
#include
<fcntl.h>
#include
<stdio.h>
#include
<sys/ioctl.h>
#include
<linux/input.h>
#include
<linux/uinput.h>
#include
<rfb/keysym.h>
using
namespace
android
;
static
const
struct
UInputOptions
{
int
cmd
;
int
bit
;
}
kOptions
[]
=
{
{
UI_SET_EVBIT
,
EV_KEY
},
{
UI_SET_EVBIT
,
EV_REP
},
{
UI_SET_EVBIT
,
EV_ABS
},
{
UI_SET_EVBIT
,
EV_SYN
},
{
UI_SET_ABSBIT
,
ABS_X
},
{
UI_SET_ABSBIT
,
ABS_Y
},
{
UI_SET_PROPBIT
,
INPUT_PROP_DIRECT
},
};
int
InputDevice
::
sFD
=
-
1
;
status_t
InputDevice
::
start
(
uint32_t
width
,
uint32_t
height
)
{
status_t
err
=
OK
;
struct
uinput_user_dev
user_dev
;
struct
input_id
id
=
{
BUS_VIRTUAL
,
/* Bus type */
1
,
/* Vendor */
1
,
/* Product */
1
,
/* Version */
};
if
(
sFD
>=
0
)
{
ALOGE
(
"Input device already open!"
);
return
NO_INIT
;
}
sFD
=
open
(
UINPUT_DEVICE
,
O_WRONLY
|
O_NONBLOCK
);
if
(
sFD
<
0
)
{
ALOGE
(
"Failed to open %s: err=%d"
,
UINPUT_DEVICE
,
sFD
);
return
NO_INIT
;
}
unsigned
int
idx
=
0
;
for
(
idx
=
0
;
idx
<
sizeof
(
kOptions
)
/
sizeof
(
kOptions
[
0
]);
idx
++
)
{
if
(
ioctl
(
sFD
,
kOptions
[
idx
].
cmd
,
kOptions
[
idx
].
bit
)
<
0
)
{
ALOGE
(
"uinput ioctl failed: %d %d"
,
kOptions
[
idx
].
cmd
,
kOptions
[
idx
].
bit
);
goto
err_ioctl
;
}
}
for
(
idx
=
0
;
idx
<
KEY_MAX
;
idx
++
)
{
if
(
ioctl
(
sFD
,
UI_SET_KEYBIT
,
idx
)
<
0
)
{
ALOGE
(
"UI_SET_KEYBIT failed"
);
goto
err_ioctl
;
}
}
memset
(
&
user_dev
,
0
,
sizeof
(
user_dev
));
strncpy
(
user_dev
.
name
,
"VNC"
,
UINPUT_MAX_NAME_SIZE
);
user_dev
.
id
=
id
;
user_dev
.
absmin
[
ABS_X
]
=
0
;
user_dev
.
absmax
[
ABS_X
]
=
width
;
user_dev
.
absmin
[
ABS_Y
]
=
0
;
user_dev
.
absmax
[
ABS_Y
]
=
height
;
if
(
write
(
sFD
,
&
user_dev
,
sizeof
(
user_dev
))
!=
sizeof
(
user_dev
))
{
ALOGE
(
"Failed to configure uinput device"
);
goto
err_ioctl
;
}
if
(
ioctl
(
sFD
,
UI_DEV_CREATE
)
==
-
1
)
{
ALOGE
(
"UI_DEV_CREATE failed"
);
goto
err_ioctl
;
}
return
OK
;
err_ioctl
:
int
prev_errno
=
errno
;
::
close
(
sFD
);
errno
=
prev_errno
;
sFD
=
-
1
;
return
NO_INIT
;
}
status_t
InputDevice
::
stop
()
{
if
(
sFD
<
0
)
{
return
OK
;
}
sleep
(
2
);
ioctl
(
sFD
,
UI_DEV_DESTROY
);
close
(
sFD
);
sFD
=
-
1
;
return
OK
;
}
status_t
InputDevice
::
inject
(
uint16_t
type
,
uint16_t
code
,
int32_t
value
)
{
struct
input_event
event
;
memset
(
&
event
,
0
,
sizeof
(
event
));
gettimeofday
(
&
event
.
time
,
0
);
/* This should not be able to fail ever.. */
event
.
type
=
type
;
event
.
code
=
code
;
event
.
value
=
value
;
if
(
write
(
sFD
,
&
event
,
sizeof
(
event
))
!=
sizeof
(
event
))
return
BAD_VALUE
;
return
OK
;
}
status_t
InputDevice
::
injectSyn
(
uint16_t
type
,
uint16_t
code
,
int32_t
value
)
{
if
(
inject
(
type
,
code
,
value
)
!=
OK
)
{
return
BAD_VALUE
;
}
return
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
}
status_t
InputDevice
::
movePointer
(
int32_t
x
,
int32_t
y
)
{
if
(
inject
(
EV_REL
,
REL_X
,
x
)
!=
OK
)
{
return
BAD_VALUE
;
}
return
injectSyn
(
EV_REL
,
REL_Y
,
y
);
}
status_t
InputDevice
::
setPointer
(
int32_t
x
,
int32_t
y
)
{
if
(
inject
(
EV_ABS
,
ABS_X
,
x
)
!=
OK
)
{
return
BAD_VALUE
;
}
return
injectSyn
(
EV_ABS
,
ABS_Y
,
y
);
}
status_t
InputDevice
::
press
(
uint16_t
code
)
{
return
inject
(
EV_KEY
,
code
,
1
);
}
status_t
InputDevice
::
release
(
uint16_t
code
)
{
return
inject
(
EV_KEY
,
code
,
0
);
}
status_t
InputDevice
::
click
(
uint16_t
code
)
{
if
(
press
(
code
)
!=
OK
)
{
return
BAD_VALUE
;
}
return
release
(
code
);
}
void
InputDevice
::
keyEvent
(
rfbBool
down
,
rfbKeySym
key
,
rfbClientPtr
cl
)
{
int
code
;
int
sh
=
0
;
int
alt
=
0
;
if
(
sFD
<
0
)
return
;
if
((
code
=
keysym2scancode
(
key
,
cl
,
&
sh
,
&
alt
)))
{
int
ret
=
0
;
if
(
key
&&
down
)
{
if
(
sh
)
press
(
42
);
// left shift
if
(
alt
)
press
(
56
);
// left alt
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
ret
=
press
(
code
);
if
(
ret
!=
0
)
{
ALOGE
(
"Error: %d (%s)
\n
"
,
errno
,
strerror
(
errno
));
}
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
ret
=
release
(
code
);
if
(
ret
!=
0
)
{
ALOGE
(
"Error: %d (%s)
\n
"
,
errno
,
strerror
(
errno
));
}
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
if
(
alt
)
release
(
56
);
// left alt
if
(
sh
)
release
(
42
);
// left shift
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
}
}
}
void
InputDevice
::
pointerEvent
(
int
buttonMask
,
int
x
,
int
y
,
rfbClientPtr
cl
)
{
static
int
leftClicked
=
0
,
rightClicked
=
0
,
middleClicked
=
0
;
(
void
)
cl
;
if
(
sFD
<
0
)
return
;
if
((
buttonMask
&
1
)
&&
leftClicked
)
{
// left btn clicked and moving
static
int
i
=
0
;
i
=
i
+
1
;
if
(
i
%
10
==
1
)
// some tweak to not report every move event
{
inject
(
EV_ABS
,
ABS_X
,
x
);
inject
(
EV_ABS
,
ABS_Y
,
y
);
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
}
}
else
if
(
buttonMask
&
1
)
// left btn clicked
{
leftClicked
=
1
;
inject
(
EV_ABS
,
ABS_X
,
x
);
inject
(
EV_ABS
,
ABS_Y
,
y
);
inject
(
EV_KEY
,
BTN_TOUCH
,
1
);
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
}
else
if
(
leftClicked
)
// left btn released
{
leftClicked
=
0
;
inject
(
EV_ABS
,
ABS_X
,
x
);
inject
(
EV_ABS
,
ABS_Y
,
y
);
inject
(
EV_KEY
,
BTN_TOUCH
,
0
);
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
}
if
(
buttonMask
&
4
)
// right btn clicked
{
rightClicked
=
1
;
press
(
158
);
// back key
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
}
else
if
(
rightClicked
)
// right button released
{
rightClicked
=
0
;
release
(
158
);
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
}
if
(
buttonMask
&
2
)
// mid btn clicked
{
middleClicked
=
1
;
press
(
KEY_END
);
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
}
else
if
(
middleClicked
)
// mid btn released
{
middleClicked
=
0
;
release
(
KEY_END
);
inject
(
EV_SYN
,
SYN_REPORT
,
0
);
}
}
// q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m
static
const
int
qwerty
[]
=
{
30
,
48
,
46
,
32
,
18
,
33
,
34
,
35
,
23
,
36
,
37
,
38
,
50
,
49
,
24
,
25
,
16
,
19
,
31
,
20
,
22
,
47
,
17
,
45
,
21
,
44
};
// ,!,",#,$,%,&,',(,),*,+,,,-,.,/
static
const
int
spec1
[]
=
{
57
,
2
,
40
,
4
,
5
,
6
,
8
,
40
,
10
,
11
,
9
,
13
,
51
,
12
,
52
,
52
};
static
const
int
spec1sh
[]
=
{
0
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
1
};
// :,;,<,=,>,?,@
static
const
int
spec2
[]
=
{
39
,
39
,
227
,
13
,
228
,
53
,
3
};
static
const
int
spec2sh
[]
=
{
1
,
0
,
1
,
1
,
1
,
1
,
1
};
// [,\,],^,_,`
static
const
int
spec3
[]
=
{
26
,
43
,
27
,
7
,
12
,
399
};
static
const
int
spec3sh
[]
=
{
0
,
0
,
0
,
1
,
1
,
0
};
// {,|,},~
static
const
int
spec4
[]
=
{
26
,
43
,
27
,
215
,
14
};
static
const
int
spec4sh
[]
=
{
1
,
1
,
1
,
1
,
0
};
int
InputDevice
::
keysym2scancode
(
rfbKeySym
c
,
rfbClientPtr
cl
,
int
*
sh
,
int
*
alt
)
{
int
real
=
1
;
if
(
'a'
<=
c
&&
c
<=
'z'
)
return
qwerty
[
c
-
'a'
];
if
(
'A'
<=
c
&&
c
<=
'Z'
)
{
(
*
sh
)
=
1
;
return
qwerty
[
c
-
'A'
];
}
if
(
'1'
<=
c
&&
c
<=
'9'
)
return
c
-
'1'
+
2
;
if
(
c
==
'0'
)
return
11
;
if
(
32
<=
c
&&
c
<=
47
)
{
(
*
sh
)
=
spec1sh
[
c
-
32
];
return
spec1
[
c
-
32
];
}
if
(
58
<=
c
&&
c
<=
64
)
{
(
*
sh
)
=
spec2sh
[
c
-
58
];
return
spec2
[
c
-
58
];
}
if
(
91
<=
c
&&
c
<=
96
)
{
(
*
sh
)
=
spec3sh
[
c
-
91
];
return
spec3
[
c
-
91
];
}
if
(
123
<=
c
&&
c
<=
127
)
{
(
*
sh
)
=
spec4sh
[
c
-
123
];
return
spec4
[
c
-
123
];
}
switch
(
c
)
{
case
0xff08
:
return
14
;
// backspace
case
0xff09
:
return
15
;
// tab
case
1
:
(
*
alt
)
=
1
;
return
34
;
// ctrl+a
case
3
:
(
*
alt
)
=
1
;
return
46
;
// ctrl+c
case
4
:
(
*
alt
)
=
1
;
return
32
;
// ctrl+d
case
18
:
(
*
alt
)
=
1
;
return
31
;
// ctrl+r
case
0xff0D
:
return
28
;
// enter
case
0xff1B
:
return
158
;
// esc -> back
case
0xFF51
:
return
105
;
// left -> DPAD_LEFT
case
0xFF53
:
return
106
;
// right -> DPAD_RIGHT
case
0xFF54
:
return
108
;
// down -> DPAD_DOWN
case
0xFF52
:
return
103
;
// up -> DPAD_UP
// case 360:
// return 232;// end -> DPAD_CENTER (ball click)
case
0xff50
:
return
KEY_HOME
;
// home
case
0xFFC8
:
rfbShutdownServer
(
cl
->
screen
,
TRUE
);
return
0
;
// F11 disconnect
case
0xffff
:
return
158
;
// del -> back
case
0xff55
:
return
229
;
// PgUp -> menu
case
0xffcf
:
return
127
;
// F2 -> search
case
0xffe3
:
return
127
;
// left ctrl -> search
case
0xff56
:
return
61
;
// PgUp -> call
case
0xff57
:
return
107
;
// End -> endcall
case
0xffc2
:
return
211
;
// F5 -> focus
case
0xffc3
:
return
212
;
// F6 -> camera
case
0xffc4
:
return
150
;
// F7 -> explorer
case
0xffc5
:
return
155
;
// F8 -> envelope
case
50081
:
case
225
:
(
*
alt
)
=
1
;
if
(
real
)
return
48
;
// a with acute
return
30
;
// a with acute -> a with ring above
case
50049
:
case
193
:
(
*
sh
)
=
1
;
(
*
alt
)
=
1
;
if
(
real
)
return
48
;
// A with acute
return
30
;
// A with acute -> a with ring above
case
50089
:
case
233
:
(
*
alt
)
=
1
;
return
18
;
// e with acute
case
50057
:
case
201
:
(
*
sh
)
=
1
;
(
*
alt
)
=
1
;
return
18
;
// E with acute
case
50093
:
case
0xffbf
:
(
*
alt
)
=
1
;
if
(
real
)
return
36
;
// i with acute
return
23
;
// i with acute -> i with grave
case
50061
:
case
205
:
(
*
sh
)
=
1
;
(
*
alt
)
=
1
;
if
(
real
)
return
36
;
// I with acute
return
23
;
// I with acute -> i with grave
case
50099
:
case
243
:
(
*
alt
)
=
1
;
if
(
real
)
return
16
;
// o with acute
return
24
;
// o with acute -> o with grave
case
50067
:
case
211
:
(
*
sh
)
=
1
;
(
*
alt
)
=
1
;
if
(
real
)
return
16
;
// O with acute
return
24
;
// O with acute -> o with grave
case
50102
:
case
246
:
(
*
alt
)
=
1
;
return
25
;
// o with diaeresis
case
50070
:
case
214
:
(
*
sh
)
=
1
;
(
*
alt
)
=
1
;
return
25
;
// O with diaeresis
case
50577
:
case
245
:
(
*
alt
)
=
1
;
if
(
real
)
return
19
;
// Hungarian o
return
25
;
// Hungarian o -> o with diaeresis
case
50576
:
case
213
:
(
*
sh
)
=
1
;
(
*
alt
)
=
1
;
if
(
real
)
return
19
;
// Hungarian O
return
25
;
// Hungarian O -> O with diaeresis
case
50106
:
// case 0xffbe:
// (*alt)=1;
// if (real)
// return 17; //u with acute
// return 22; //u with acute -> u with grave
case
50074
:
case
218
:
(
*
sh
)
=
1
;
(
*
alt
)
=
1
;
if
(
real
)
return
17
;
// U with acute
return
22
;
// U with acute -> u with grave
case
50108
:
case
252
:
(
*
alt
)
=
1
;
return
47
;
// u with diaeresis
case
50076
:
case
220
:
(
*
sh
)
=
1
;
(
*
alt
)
=
1
;
return
47
;
// U with diaeresis
case
50609
:
case
251
:
(
*
alt
)
=
1
;
if
(
real
)
return
45
;
// Hungarian u
return
47
;
// Hungarian u -> u with diaeresis
case
50608
:
case
219
:
(
*
sh
)
=
1
;
(
*
alt
)
=
1
;
if
(
real
)
return
45
;
// Hungarian U
return
47
;
// Hungarian U -> U with diaeresis
}
return
0
;
}
This diff is collapsed.
Click to expand it.
src/InputDevice.h
0 → 100644
+
39
−
0
View file @
107d2e51
#ifndef INPUT_DEVICE_H
#define INPUT_DEVICE_H
#include
<utils/Errors.h>
#include
<utils/RefBase.h>
#include
<rfb/rfb.h>
#define UINPUT_DEVICE "/dev/uinput"
namespace
android
{
class
InputDevice
:
public
RefBase
{
public:
static
status_t
start
(
uint32_t
width
,
uint32_t
height
);
static
status_t
stop
();
static
void
keyEvent
(
rfbBool
down
,
rfbKeySym
key
,
rfbClientPtr
cl
);
static
void
pointerEvent
(
int
buttonMask
,
int
x
,
int
y
,
rfbClientPtr
cl
);
private:
static
status_t
inject
(
uint16_t
type
,
uint16_t
code
,
int32_t
value
);
static
status_t
injectSyn
(
uint16_t
type
,
uint16_t
code
,
int32_t
value
);
static
status_t
movePointer
(
int32_t
x
,
int32_t
y
);
static
status_t
setPointer
(
int32_t
x
,
int32_t
y
);
static
status_t
press
(
uint16_t
code
);
static
status_t
release
(
uint16_t
code
);
static
status_t
click
(
uint16_t
code
);
static
int
keysym2scancode
(
rfbKeySym
c
,
rfbClientPtr
cl
,
int
*
sh
,
int
*
alt
);
static
int
sFD
;
};
};
#endif
This diff is collapsed.
Click to expand it.
src/VNCFlinger.cpp
+
5
−
0
View file @
107d2e51
...
...
@@ -9,6 +9,7 @@
#include
<gui/SurfaceComposerClient.h>
#include
<gui/IGraphicBufferProducer.h>
#include
"InputDevice.h"
#include
"VNCFlinger.h"
using
namespace
android
;
...
...
@@ -74,6 +75,8 @@ status_t VNCFlinger::setup_l() {
mVNCScreen
->
httpDir
=
NULL
;
mVNCScreen
->
port
=
VNC_PORT
;
mVNCScreen
->
newClientHook
=
(
rfbNewClientHookPtr
)
VNCFlinger
::
onNewClient
;
mVNCScreen
->
kbdAddEvent
=
InputDevice
::
keyEvent
;
mVNCScreen
->
ptrAddEvent
=
InputDevice
::
pointerEvent
;
mVNCScreen
->
serverFormat
.
trueColour
=
true
;
mVNCScreen
->
serverFormat
.
bitsPerPixel
=
32
;
mVNCScreen
->
handleEventsEagerly
=
true
;
...
...
@@ -111,6 +114,7 @@ void VNCFlinger::onEvent(const Event& event) {
switch
(
event
.
mId
)
{
case
EVENT_CLIENT_CONNECT
:
if
(
mClientCount
==
0
)
{
InputDevice
::
start
(
mWidth
,
mHeight
);
mVirtualDisplay
->
start
(
mMainDpyInfo
,
sQueue
);
}
mClientCount
++
;
...
...
@@ -123,6 +127,7 @@ void VNCFlinger::onEvent(const Event& event) {
mClientCount
--
;
if
(
mClientCount
==
0
)
{
mVirtualDisplay
->
stop
();
InputDevice
::
stop
();
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment