Added syslogd pseudo-tweak.
[veency.git] / Tweak.mm
1 #include <substrate.h>
2
3 #include <rfb/rfb.h>
4 #include <rfb/keysym.h>
5
6 #include <mach/mach_port.h>
7
8 #import <QuartzCore/CAWindowServer.h>
9 #import <QuartzCore/CAWindowServerDisplay.h>
10
11 #import <CoreGraphics/CGGeometry.h>
12 #import <GraphicsServices/GraphicsServices.h>
13 #import <Foundation/Foundation.h>
14 #import <IOMobileFramebuffer/IOMobileFramebuffer.h>
15 #import <IOKit/IOKitLib.h>
16
17 #define IOMobileFramebuffer "/System/Library/PrivateFrameworks/IOMobileFramebuffer.framework/IOMobileFramebuffer"
18
19 static const size_t Width = 320;
20 static const size_t Height = 480;
21 static const size_t BytesPerPixel = 4;
22 static const size_t BitsPerSample = 8;
23
24 static const size_t Stride = Width * BytesPerPixel;
25 static const size_t Size32 = Width * Height;
26 static const size_t Size8 = Size32 * BytesPerPixel;
27
28 static pthread_t thread_;
29 static rfbScreenInfoPtr screen_;
30 static bool running_;
31 static int buttons_;
32 static int x_, y_;
33
34 static void VNCPointer(int buttons, int x, int y, rfbClientPtr client) {
35 x_ = x;
36 y_ = y;
37
38 int diff = buttons_ ^ buttons;
39
40 rfbDefaultPtrAddEvent(buttons, x, y, client);
41
42 mach_port_t purple(0);
43
44 bool twas((buttons_ & 0x1) != 0);
45 bool tis((buttons & 0x1) != 0);
46
47 buttons_ = buttons;
48
49 if ((diff & 0x10) != 0) {
50 struct GSEventRecord record;
51
52 memset(&record, 0, sizeof(record));
53
54 record.type = (buttons & 0x4) != 0 ?
55 GSEventTypeHeadsetButtonDown :
56 GSEventTypeHeadsetButtonUp;
57
58 record.timestamp = GSCurrentEventTimestamp();
59
60 GSSendSystemEvent(&record);
61 }
62
63 if ((diff & 0x08) != 0 && (buttons & 0x4) != 0) {
64 struct GSEventRecord record;
65
66 memset(&record, 0, sizeof(record));
67
68 record.type = GSEventTypeRingerChanged0;
69
70 record.timestamp = GSCurrentEventTimestamp();
71
72 GSSendSystemEvent(&record);
73 }
74
75 if ((diff & 0x04) != 0) {
76 struct GSEventRecord record;
77
78 memset(&record, 0, sizeof(record));
79
80 record.type = (buttons & 0x4) != 0 ?
81 GSEventTypeMenuButtonDown :
82 GSEventTypeMenuButtonUp;
83
84 record.timestamp = GSCurrentEventTimestamp();
85
86 GSSendSystemEvent(&record);
87 }
88
89 if ((diff & 0x02) != 0) {
90 struct GSEventRecord record;
91
92 memset(&record, 0, sizeof(record));
93
94 record.type = (buttons & 0x2) != 0 ?
95 GSEventTypeLockButtonDown :
96 GSEventTypeLockButtonUp;
97
98 record.timestamp = GSCurrentEventTimestamp();
99
100 GSSendSystemEvent(&record);
101 }
102
103 if (twas != tis || tis) {
104 struct {
105 struct GSEventRecord record;
106 struct {
107 struct GSEventRecordInfo info;
108 struct GSPathInfo path;
109 } data;
110 } event;
111
112 memset(&event, 0, sizeof(event));
113
114 event.record.type = GSEventTypeMouse;
115 event.record.locationInWindow.x = x;
116 event.record.locationInWindow.y = y;
117 event.record.timestamp = GSCurrentEventTimestamp();
118 event.record.size = sizeof(event.data);
119
120 event.data.info.handInfo.type = twas == tis ?
121 GSMouseEventTypeDragged :
122 tis ?
123 GSMouseEventTypeDown :
124 GSMouseEventTypeUp;
125
126 event.data.info.handInfo.x34 = 0x1;
127 event.data.info.handInfo.x38 = tis ? 0x1 : 0x0;
128
129 event.data.info.pathPositions = 1;
130
131 event.data.path.x00 = 0x01;
132 event.data.path.x01 = 0x02;
133 event.data.path.x02 = tis ? 0x03 : 0x00;
134 event.data.path.position = event.record.locationInWindow;
135
136 mach_port_t port(0);
137
138 if (CAWindowServer *server = [CAWindowServer serverIfRunning]) {
139 NSArray *displays([server displays]);
140 if (displays != nil && [displays count] != 0)
141 if (CAWindowServerDisplay *display = [displays objectAtIndex:0])
142 port = [display clientPortAtPosition:event.record.locationInWindow];
143 }
144
145 if (port == 0) {
146 if (purple == 0)
147 purple = GSCopyPurpleSystemEventPort();
148 port = purple;
149 }
150
151 GSSendEvent(&event.record, port);
152 }
153
154 if (purple != 0)
155 mach_port_deallocate(mach_task_self(), purple);
156 }
157
158 static void VNCKeyboard(rfbBool down, rfbKeySym key, rfbClientPtr client) {
159 if (!down)
160 return;
161
162 switch (key) {
163 case XK_Return: key = '\r'; break;
164 case XK_BackSpace: key = 0x7f; break;
165 }
166
167 if (key > 0xfff)
168 return;
169
170 struct {
171 struct GSEventRecord record;
172 struct GSEventKeyInfo data;
173 } event;
174
175 memset(&event, 0, sizeof(event));
176
177 event.record.type = GSEventTypeKeyDown;
178 event.record.timestamp = GSCurrentEventTimestamp();
179 event.record.size = sizeof(event.data);
180
181 event.data.character = key;
182
183 mach_port_t port(0);
184
185 if (CAWindowServer *server = [CAWindowServer serverIfRunning]) {
186 NSArray *displays([server displays]);
187 if (displays != nil && [displays count] != 0)
188 if (CAWindowServerDisplay *display = [displays objectAtIndex:0])
189 port = [display clientPortAtPosition:CGPointMake(x_, y_)];
190 }
191
192 if (port != 0)
193 GSSendEvent(&event.record, port);
194 }
195
196 static void *VNCServer(IOMobileFramebufferRef fb) {
197 CGRect rect(CGRectMake(0, 0, Width, Height));
198
199 CoreSurfaceBufferRef surface(NULL);
200 kern_return_t value(IOMobileFramebufferGetLayerDefaultSurface(fb, 0, &surface));
201 if (value != 0)
202 return NULL;
203
204 int argc(1);
205 char *arg0(strdup("VNCServer"));
206 char *argv[] = {arg0, NULL};
207
208 io_service_t service(IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOCoreSurfaceRoot")));
209 CFMutableDictionaryRef properties(NULL);
210 IORegistryEntryCreateCFProperties(service, &properties, kCFAllocatorDefault, kNilOptions);
211
212 screen_ = rfbGetScreen(&argc, argv, Width, Height, BitsPerSample, 3, BytesPerPixel);
213 screen_->desktopName = "iPhone";
214 screen_->alwaysShared = TRUE;
215 screen_->handleEventsEagerly = TRUE;
216 screen_->deferUpdateTime = 5;
217
218 screen_->serverFormat.redShift = BitsPerSample * 2;
219 screen_->serverFormat.greenShift = BitsPerSample * 1;
220 screen_->serverFormat.blueShift = BitsPerSample * 0;
221
222 CoreSurfaceBufferLock(surface, kCoreSurfaceLockTypeGimmeVRAM);
223 screen_->frameBuffer = reinterpret_cast<char *>(CoreSurfaceBufferGetBaseAddress(surface));
224 CoreSurfaceBufferUnlock(surface);
225
226 screen_->kbdAddEvent = &VNCKeyboard;
227 screen_->ptrAddEvent = &VNCPointer;
228
229 rfbInitServer(screen_);
230 running_ = true;
231
232 rfbRunEventLoop(screen_, -1, true);
233 return NULL;
234
235 running_ = false;
236 rfbScreenCleanup(screen_);
237
238 CFRelease(surface);
239
240 free(arg0);
241 return NULL;
242 }
243
244 static rfbPixel black_[320][480];
245
246 MSHook(kern_return_t, IOMobileFramebufferSwapSetLayer,
247 IOMobileFramebufferRef fb,
248 int layer,
249 CoreSurfaceBufferRef buffer,
250 CGRect bounds,
251 CGRect frame,
252 int flags
253 ) {
254 /*if (
255 bounds.origin.x != 0 || bounds.origin.y != 0 || bounds.size.width != 320 || bounds.size.height != 480 ||
256 frame.origin.x != 0 || frame.origin.y != 0 || frame.size.width != 320 || frame.size.height != 480
257 ) NSLog(@"VNC:%f,%f:%f,%f:%f,%f:%f,%f",
258 bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height,
259 frame.origin.x, frame.origin.y, frame.size.width, frame.size.height
260 );*/
261
262 if (running_) {
263 if (buffer == NULL)
264 screen_->frameBuffer = reinterpret_cast<char *>(black_);
265 else {
266 CoreSurfaceBufferLock(buffer, kCoreSurfaceLockTypeGimmeVRAM);
267 rfbPixel (*data)[480] = reinterpret_cast<rfbPixel (*)[480]>(CoreSurfaceBufferGetBaseAddress(buffer));
268 /*memcpy(black_, data, sizeof(black_));
269 screen_->frameBuffer = reinterpret_cast<char *>(black_);*/
270 data[x_][y_] = screen_->whitePixel;
271 screen_->frameBuffer = reinterpret_cast<char *>(data);
272 CoreSurfaceBufferUnlock(buffer);
273 }
274 }
275
276 kern_return_t value(_IOMobileFramebufferSwapSetLayer(fb, layer, buffer, bounds, frame, flags));
277
278 if (thread_ == NULL)
279 pthread_create(&thread_, NULL, &VNCServer, fb);
280 else if (running_)
281 rfbMarkRectAsModified(screen_, 0, 0, Width, Height);
282
283 return value;
284 }
285
286 extern "C" void TweakInitialize() {
287 if (objc_getClass("SpringBoard") == nil)
288 return;
289 MSHookFunction(&IOMobileFramebufferSwapSetLayer, &$IOMobileFramebufferSwapSetLayer, &_IOMobileFramebufferSwapSetLayer);
290 }