1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <plat/inc/taggedPtr.h>
18 #include <syscall.h>
19 #include <sensors.h>
20 #include <errno.h>
21 #include <osApi.h>
22 #include <timer.h>
23 #include <gpio.h>
24 #include <util.h>
25 #include <seos.h>
26 #include <slab.h>
27 #include <heap.h>
28 #include <i2c.h>
29 
30 static struct SlabAllocator *mSlabAllocator;
31 
32 
osExpApiEvtqSubscribe(uintptr_t * retValP,va_list args)33 static void osExpApiEvtqSubscribe(uintptr_t *retValP, va_list args)
34 {
35     (void)va_arg(args, uint32_t); // tid
36     uint32_t evtType = va_arg(args, uint32_t);
37 
38     *retValP = osEventSubscribe(0, evtType);
39 }
40 
osExpApiEvtqUnsubscribe(uintptr_t * retValP,va_list args)41 static void osExpApiEvtqUnsubscribe(uintptr_t *retValP, va_list args)
42 {
43     (void)va_arg(args, uint32_t); // tid
44     uint32_t evtType = va_arg(args, uint32_t);
45 
46     *retValP = osEventUnsubscribe(0, evtType);
47 }
48 
osExpApiEvtqEnqueue(uintptr_t * retValP,va_list args)49 static void osExpApiEvtqEnqueue(uintptr_t *retValP, va_list args)
50 {
51     uint32_t evtType = va_arg(args, uint32_t);
52     void *evtData = va_arg(args, void*);
53     (void)va_arg(args, uint32_t); // tid
54 
55     *retValP = osEnqueueEvtAsApp(evtType, evtData, 0);
56 }
57 
osExpApiEvtqEnqueuePrivate(uintptr_t * retValP,va_list args)58 static void osExpApiEvtqEnqueuePrivate(uintptr_t *retValP, va_list args)
59 {
60     uint32_t evtType = va_arg(args, uint32_t);
61     void *evtData = va_arg(args, void*);
62     (void)va_arg(args, uint32_t); // tid
63     uint32_t toTid = va_arg(args, uint32_t);
64 
65     *retValP = osEnqueuePrivateEvtAsApp(evtType, evtData, 0, toTid);
66 }
67 
osExpApiEvtqRetainEvt(uintptr_t * retValP,va_list args)68 static void osExpApiEvtqRetainEvt(uintptr_t *retValP, va_list args)
69 {
70     TaggedPtr *evtFreeingInfoP = va_arg(args, TaggedPtr*);
71 
72     *retValP = osRetainCurrentEvent(evtFreeingInfoP);
73 }
74 
osExpApiEvtqFreeRetained(uintptr_t * retValP,va_list args)75 static void osExpApiEvtqFreeRetained(uintptr_t *retValP, va_list args)
76 {
77     uint32_t evtType = va_arg(args, uint32_t);
78     void *evtData = va_arg(args, void*);
79     TaggedPtr *evtFreeingInfoP = va_arg(args, TaggedPtr*);
80 
81     osFreeRetainedEvent(evtType, evtData, evtFreeingInfoP);
82 }
83 
osExpApiLogLogv(uintptr_t * retValP,va_list args)84 static void osExpApiLogLogv(uintptr_t *retValP, va_list args)
85 {
86     enum LogLevel level = va_arg(args, int /* enums promoted to ints in va_args in C */);
87     const char *str = va_arg(args, const char*);
88     va_list innerArgs;
89     va_copy(innerArgs, INTEGER_TO_VA_LIST(va_arg(args, uintptr_t)));
90     osLogv(level, str, innerArgs);
91     va_end(innerArgs);
92 }
93 
osExpApiSensorSignal(uintptr_t * retValP,va_list args)94 static void osExpApiSensorSignal(uintptr_t *retValP, va_list args)
95 {
96     uint32_t handle = va_arg(args, uint32_t);
97     uint32_t intEvtNum = va_arg(args, uint32_t);
98     uint32_t value1 = va_arg(args, uint32_t);
99     uint32_t value2_lo = va_arg(args, uint32_t);
100     uint32_t value2_hi = va_arg(args, uint32_t);
101     uint64_t value2 = (((uint64_t)value2_hi) << 32) + value2_lo;
102 
103     *retValP = (uintptr_t)sensorSignalInternalEvt(handle, intEvtNum, value1, value2);
104 }
105 
osExpApiSensorReg(uintptr_t * retValP,va_list args)106 static void osExpApiSensorReg(uintptr_t *retValP, va_list args)
107 {
108     const struct SensorInfo *si = va_arg(args, const struct SensorInfo*);
109     (void)va_arg(args, uint32_t); // tid
110     void *cookie = va_arg(args, void *);
111     bool initComplete = va_arg(args, int);
112 
113     *retValP = (uintptr_t)sensorRegisterAsApp(si, 0, cookie, initComplete);
114 }
115 
osExpApiSensorUnreg(uintptr_t * retValP,va_list args)116 static void osExpApiSensorUnreg(uintptr_t *retValP, va_list args)
117 {
118     uint32_t handle = va_arg(args, uint32_t);
119 
120     *retValP = (uintptr_t)sensorUnregister(handle);
121 }
122 
osExpApiSensorRegInitComp(uintptr_t * retValP,va_list args)123 static void osExpApiSensorRegInitComp(uintptr_t *retValP, va_list args)
124 {
125     uint32_t handle = va_arg(args, uint32_t);
126 
127     *retValP = (uintptr_t)sensorRegisterInitComplete(handle);
128 }
129 
osExpApiSensorFind(uintptr_t * retValP,va_list args)130 static void osExpApiSensorFind(uintptr_t *retValP, va_list args)
131 {
132     uint32_t sensorType = va_arg(args, uint32_t);
133     uint32_t idx = va_arg(args, uint32_t);
134     uint32_t *handleP = va_arg(args, uint32_t*);
135 
136     *retValP = (uintptr_t)sensorFind(sensorType, idx, handleP);
137 }
138 
osExpApiSensorReq(uintptr_t * retValP,va_list args)139 static void osExpApiSensorReq(uintptr_t *retValP, va_list args)
140 {
141     (void)va_arg(args, uint32_t); // clientId == tid
142     uint32_t sensorHandle = va_arg(args, uint32_t);
143     uint32_t rate = va_arg(args, uint32_t);
144     uint32_t latency_lo = va_arg(args, uint32_t);
145     uint32_t latency_hi = va_arg(args, uint32_t);
146     uint64_t latency = (((uint64_t)latency_hi) << 32) + latency_lo;
147 
148     *retValP = sensorRequest(0, sensorHandle, rate, latency);
149 }
150 
osExpApiSensorRateChg(uintptr_t * retValP,va_list args)151 static void osExpApiSensorRateChg(uintptr_t *retValP, va_list args)
152 {
153     (void)va_arg(args, uint32_t); // clientId == tid
154     uint32_t sensorHandle = va_arg(args, uint32_t);
155     uint32_t newRate = va_arg(args, uint32_t);
156     uint32_t newLatency_lo = va_arg(args, uint32_t);
157     uint32_t newLatency_hi = va_arg(args, uint32_t);
158     uint64_t newLatency = (((uint64_t)newLatency_hi) << 32) + newLatency_lo;
159 
160     *retValP = sensorRequestRateChange(0, sensorHandle, newRate, newLatency);
161 }
162 
osExpApiSensorRel(uintptr_t * retValP,va_list args)163 static void osExpApiSensorRel(uintptr_t *retValP, va_list args)
164 {
165     (void)va_arg(args, uint32_t); // clientId == tid
166     uint32_t sensorHandle = va_arg(args, uint32_t);
167 
168     *retValP = sensorRelease(0, sensorHandle);
169 }
170 
osExpApiSensorTrigger(uintptr_t * retValP,va_list args)171 static void osExpApiSensorTrigger(uintptr_t *retValP, va_list args)
172 {
173     (void)va_arg(args, uint32_t); // clientId == tid
174     uint32_t sensorHandle = va_arg(args, uint32_t);
175 
176     *retValP = sensorTriggerOndemand(0, sensorHandle);
177 }
178 
osExpApiSensorGetRate(uintptr_t * retValP,va_list args)179 static void osExpApiSensorGetRate(uintptr_t *retValP, va_list args)
180 {
181     uint32_t sensorHandle = va_arg(args, uint32_t);
182 
183     *retValP = sensorGetCurRate(sensorHandle);
184 }
185 
osExpApiTimGetTime(uintptr_t * retValP,va_list args)186 static void osExpApiTimGetTime(uintptr_t *retValP, va_list args)
187 {
188     uint64_t *timeNanos = va_arg(args, uint64_t *);
189     *timeNanos = timGetTime();
190 }
191 
osExpApiTimSetTimer(uintptr_t * retValP,va_list args)192 static void osExpApiTimSetTimer(uintptr_t *retValP, va_list args)
193 {
194     uint32_t length_lo = va_arg(args, uint32_t);
195     uint32_t length_hi = va_arg(args, uint32_t);
196     uint32_t jitterPpm = va_arg(args, uint32_t);
197     uint32_t driftPpm = va_arg(args, uint32_t);
198     (void)va_arg(args, uint32_t); // tid
199     void *cookie = va_arg(args, void *);
200     bool oneshot = va_arg(args, int);
201     uint64_t length = (((uint64_t)length_hi) << 32) + length_lo;
202 
203     *retValP = timTimerSetAsApp(length, jitterPpm, driftPpm, 0, cookie, oneshot);
204 }
205 
osExpApiTimCancelTimer(uintptr_t * retValP,va_list args)206 static void osExpApiTimCancelTimer(uintptr_t *retValP, va_list args)
207 {
208     uint32_t timerId = va_arg(args, uint32_t);
209 
210     *retValP = timTimerCancel(timerId);
211 }
212 
osExpApiHeapAlloc(uintptr_t * retValP,va_list args)213 static void osExpApiHeapAlloc(uintptr_t *retValP, va_list args)
214 {
215     uint32_t sz = va_arg(args, uint32_t);
216 
217     *retValP = (uintptr_t)heapAlloc(sz);
218 }
219 
osExpApiHeapFree(uintptr_t * retValP,va_list args)220 static void osExpApiHeapFree(uintptr_t *retValP, va_list args)
221 {
222     void *mem = va_arg(args, void *);
223 
224     heapFree(mem);
225 }
226 
osExpApiSlabNew(uintptr_t * retValP,va_list args)227 static void osExpApiSlabNew(uintptr_t *retValP, va_list args)
228 {
229     uint32_t itemSz = va_arg(args, uint32_t);
230     uint32_t itemAlign = va_arg(args, uint32_t);
231     uint32_t numItems = va_arg(args, uint32_t);
232 
233     *retValP = (uintptr_t)slabAllocatorNew(itemSz, itemAlign, numItems);
234 }
235 
osExpApiSlabDestroy(uintptr_t * retValP,va_list args)236 static void osExpApiSlabDestroy(uintptr_t *retValP, va_list args)
237 {
238     struct SlabAllocator *allocator = va_arg(args, struct SlabAllocator *);
239 
240     slabAllocatorDestroy(allocator);
241 }
242 
osExpApiSlabAlloc(uintptr_t * retValP,va_list args)243 static void osExpApiSlabAlloc(uintptr_t *retValP, va_list args)
244 {
245     struct SlabAllocator *allocator = va_arg(args, struct SlabAllocator *);
246 
247     *retValP = (uintptr_t)slabAllocatorAlloc(allocator);
248 }
249 
osExpApiSlabFree(uintptr_t * retValP,va_list args)250 static void osExpApiSlabFree(uintptr_t *retValP, va_list args)
251 {
252     struct SlabAllocator *allocator = va_arg(args, struct SlabAllocator *);
253     void *mem = va_arg(args, void *);
254 
255     slabAllocatorFree(allocator, mem);
256 }
257 
osExpApiI2cCbkInfoAlloc(void * cookie)258 static union OsApiSlabItem* osExpApiI2cCbkInfoAlloc(void *cookie)
259 {
260     union OsApiSlabItem *thing = slabAllocatorAlloc(mSlabAllocator);
261 
262     if (thing) {
263         thing->i2cAppCbkInfo.toTid = osGetCurrentTid();
264         thing->i2cAppCbkInfo.cookie = cookie;
265     }
266 
267     return thing;
268 }
269 
osExpApiI2cInternalEvtFreeF(void * evt)270 static void osExpApiI2cInternalEvtFreeF(void *evt)
271 {
272     slabAllocatorFree(mSlabAllocator, evt);
273 }
274 
osExpApiI2cInternalCbk(void * cookie,size_t tx,size_t rx,int err)275 static void osExpApiI2cInternalCbk(void *cookie, size_t tx, size_t rx, int err)
276 {
277     union OsApiSlabItem *thing = (union OsApiSlabItem*)cookie;
278     uint32_t tid;
279 
280     tid = thing->i2cAppCbkInfo.toTid;
281     cookie = thing->i2cAppCbkInfo.cookie;
282 
283     //we reuse the same slab element to send the event now
284     thing->i2cAppCbkEvt.cookie = cookie;
285     thing->i2cAppCbkEvt.tx = tx;
286     thing->i2cAppCbkEvt.rx = rx;
287     thing->i2cAppCbkEvt.err = err;
288 
289     if (!osEnqueuePrivateEvt(EVT_APP_I2C_CBK, &thing->i2cAppCbkEvt, osExpApiI2cInternalEvtFreeF, tid)) {
290         osLog(LOG_WARN, "Failed to send I2C evt to app. This might end badly for the app...");
291         osExpApiI2cInternalEvtFreeF(thing);
292         // TODO: terminate app here: memory pressure is severe
293     }
294 }
295 
osExpApiGpioReq(uintptr_t * retValP,va_list args)296 static void osExpApiGpioReq(uintptr_t *retValP, va_list args)
297 {
298     uint32_t gpioNum = va_arg(args, uint32_t);
299 
300     *retValP = (uintptr_t)gpioRequest(gpioNum);
301 }
302 
osExpApiGpioRel(uintptr_t * retValP,va_list args)303 static void osExpApiGpioRel(uintptr_t *retValP, va_list args)
304 {
305     struct Gpio* gpio = va_arg(args, struct Gpio*);
306 
307     gpioRelease(gpio);
308 }
309 
osExpApiGpioCfgIn(uintptr_t * retValP,va_list args)310 static void osExpApiGpioCfgIn(uintptr_t *retValP, va_list args)
311 {
312     struct Gpio* gpio = va_arg(args, struct Gpio*);
313     int32_t speed = va_arg(args, int32_t);
314     enum GpioPullMode pullMode = va_arg(args, int);
315 
316     gpioConfigInput(gpio, speed, pullMode);
317 }
318 
osExpApiGpioCfgOut(uintptr_t * retValP,va_list args)319 static void osExpApiGpioCfgOut(uintptr_t *retValP, va_list args)
320 {
321     struct Gpio* gpio = va_arg(args, struct Gpio*);
322     int32_t speed = va_arg(args, int32_t);
323     enum GpioPullMode pullMode = va_arg(args, int);
324     enum GpioOpenDrainMode odrMode = va_arg(args, int);
325     bool value = !!va_arg(args, int);
326 
327     gpioConfigOutput(gpio, speed, pullMode, odrMode, value);
328 }
329 
osExpApiGpioCfgAlt(uintptr_t * retValP,va_list args)330 static void osExpApiGpioCfgAlt(uintptr_t *retValP, va_list args)
331 {
332     struct Gpio* gpio = va_arg(args, struct Gpio*);
333     int32_t speed = va_arg(args, int32_t);
334     enum GpioPullMode pullMode = va_arg(args, int);
335     enum GpioOpenDrainMode odrMode = va_arg(args, int);
336     uint32_t altFunc = va_arg(args, uint32_t);
337 
338     gpioConfigAlt(gpio, speed, pullMode, odrMode, altFunc);
339 }
340 
osExpApiGpioGet(uintptr_t * retValP,va_list args)341 static void osExpApiGpioGet(uintptr_t *retValP, va_list args)
342 {
343     struct Gpio* gpio = va_arg(args, struct Gpio*);
344 
345     *retValP = gpioGet(gpio);
346 }
347 
osExpApiGpioSet(uintptr_t * retValP,va_list args)348 static void osExpApiGpioSet(uintptr_t *retValP, va_list args)
349 {
350     struct Gpio* gpio = va_arg(args, struct Gpio*);
351     bool value = !!va_arg(args, int);
352 
353     gpioSet(gpio, value);
354 }
355 
osExpApiI2cMstReq(uintptr_t * retValP,va_list args)356 static void osExpApiI2cMstReq(uintptr_t *retValP, va_list args)
357 {
358     uint32_t busId = va_arg(args, uint32_t);
359     uint32_t speed = va_arg(args, uint32_t);
360 
361     *retValP = i2cMasterRequest(busId, speed);
362 }
363 
osExpApiI2cMstRel(uintptr_t * retValP,va_list args)364 static void osExpApiI2cMstRel(uintptr_t *retValP, va_list args)
365 {
366     uint32_t busId = va_arg(args, uint32_t);
367 
368     *retValP = i2cMasterRelease(busId);
369 }
370 
osExpApiI2cMstTxRx(uintptr_t * retValP,va_list args)371 static void osExpApiI2cMstTxRx(uintptr_t *retValP, va_list args)
372 {
373     uint32_t busId = va_arg(args, uint32_t);
374     uint32_t addr = va_arg(args, uint32_t);
375     const void *txBuf = va_arg(args, const void*);
376     size_t txSize = va_arg(args, size_t);
377     void *rxBuf = va_arg(args, void*);
378     size_t rxSize = va_arg(args, size_t);
379     (void)va_arg(args, uint32_t); // tid
380     void *cookie = va_arg(args, void *);
381     union OsApiSlabItem *cbkInfo = osExpApiI2cCbkInfoAlloc(cookie);
382 
383     if (!cbkInfo)
384         *retValP =  -ENOMEM;
385 
386     *retValP = i2cMasterTxRx(busId, addr, txBuf, txSize, rxBuf, rxSize, osExpApiI2cInternalCbk, cbkInfo);
387 
388     if (*retValP)
389         slabAllocatorFree(mSlabAllocator, cbkInfo);
390 }
391 
osExpApiI2cSlvReq(uintptr_t * retValP,va_list args)392 static void osExpApiI2cSlvReq(uintptr_t *retValP, va_list args)
393 {
394     uint32_t busId = va_arg(args, uint32_t);
395     uint32_t addr = va_arg(args, uint32_t);
396 
397     *retValP = i2cSlaveRequest(busId, addr);
398 }
399 
osExpApiI2cSlvRel(uintptr_t * retValP,va_list args)400 static void osExpApiI2cSlvRel(uintptr_t *retValP, va_list args)
401 {
402     uint32_t busId = va_arg(args, uint32_t);
403 
404     *retValP = i2cSlaveRelease(busId);
405 }
406 
osExpApiI2cSlvRxEn(uintptr_t * retValP,va_list args)407 static void osExpApiI2cSlvRxEn(uintptr_t *retValP, va_list args)
408 {
409     uint32_t busId = va_arg(args, uint32_t);
410     void *rxBuf = va_arg(args, void*);
411     size_t rxSize = va_arg(args, size_t);
412     (void)va_arg(args, uint32_t); // tid
413     void *cookie = va_arg(args, void *);
414     union OsApiSlabItem *cbkInfo = osExpApiI2cCbkInfoAlloc(cookie);
415 
416     if (!cbkInfo)
417         *retValP =  -ENOMEM;
418 
419     i2cSlaveEnableRx(busId, rxBuf, rxSize, osExpApiI2cInternalCbk, cbkInfo);
420 
421     if (*retValP)
422         slabAllocatorFree(mSlabAllocator, cbkInfo);
423 }
424 
osExpApiI2cSlvTxPre(uintptr_t * retValP,va_list args)425 static void osExpApiI2cSlvTxPre(uintptr_t *retValP, va_list args)
426 {
427     uint32_t busId = va_arg(args, uint32_t);
428     uint8_t byte = va_arg(args, int);
429     (void)va_arg(args, uint32_t); // tid
430     void *cookie = va_arg(args, void *);
431     union OsApiSlabItem *cbkInfo = osExpApiI2cCbkInfoAlloc(cookie);
432 
433     if (!cbkInfo)
434         *retValP =  -ENOMEM;
435 
436     *retValP = i2cSlaveTxPreamble(busId, byte, osExpApiI2cInternalCbk, cbkInfo);
437 
438     if (*retValP)
439         slabAllocatorFree(mSlabAllocator, cbkInfo);
440 }
441 
osExpApiI2cSlvTxPkt(uintptr_t * retValP,va_list args)442 static void osExpApiI2cSlvTxPkt(uintptr_t *retValP, va_list args)
443 {
444     uint32_t busId = va_arg(args, uint32_t);
445     const void *txBuf = va_arg(args, const void*);
446     size_t txSize = va_arg(args, size_t);
447     (void)va_arg(args, uint32_t); // tid
448     void *cookie = va_arg(args, void *);
449     union OsApiSlabItem *cbkInfo = osExpApiI2cCbkInfoAlloc(cookie);
450 
451     if (!cbkInfo)
452         *retValP =  -ENOMEM;
453 
454     *retValP = i2cSlaveTxPacket(busId, txBuf, txSize, osExpApiI2cInternalCbk, cbkInfo);
455 
456     if (*retValP)
457         slabAllocatorFree(mSlabAllocator, cbkInfo);
458 }
459 
osApiExport(struct SlabAllocator * mainSlubAllocator)460 void osApiExport(struct SlabAllocator *mainSlubAllocator)
461 {
462     static const struct SyscallTable osMainEvtqTable = {
463         .numEntries = SYSCALL_OS_MAIN_EVTQ_LAST,
464         .entry = {
465             [SYSCALL_OS_MAIN_EVTQ_SUBCRIBE]        = { .func = osExpApiEvtqSubscribe,   },
466             [SYSCALL_OS_MAIN_EVTQ_UNSUBCRIBE]      = { .func = osExpApiEvtqUnsubscribe, },
467             [SYSCALL_OS_MAIN_EVTQ_ENQUEUE]         = { .func = osExpApiEvtqEnqueue,     },
468             [SYSCALL_OS_MAIN_EVTQ_ENQUEUE_PRIVATE] = { .func = osExpApiEvtqEnqueuePrivate, },
469             [SYSCALL_OS_MAIN_EVTQ_RETAIN_EVT]      = { .func = osExpApiEvtqRetainEvt,      },
470             [SYSCALL_OS_MAIN_EVTQ_FREE_RETAINED]   = { .func = osExpApiEvtqFreeRetained,   },
471         },
472     };
473 
474     static const struct SyscallTable osMainLogTable = {
475         .numEntries = SYSCALL_OS_MAIN_LOG_LAST,
476         .entry = {
477             [SYSCALL_OS_MAIN_LOG_LOGV]   = { .func = osExpApiLogLogv,   },
478         },
479     };
480 
481     static const struct SyscallTable osMainSensorsTable = {
482         .numEntries = SYSCALL_OS_MAIN_SENSOR_LAST,
483         .entry = {
484             [SYSCALL_OS_MAIN_SENSOR_SIGNAL]        = { .func = osExpApiSensorSignal,  },
485             [SYSCALL_OS_MAIN_SENSOR_REG]           = { .func = osExpApiSensorReg,     },
486             [SYSCALL_OS_MAIN_SENSOR_UNREG]         = { .func = osExpApiSensorUnreg,   },
487             [SYSCALL_OS_MAIN_SENSOR_REG_INIT_COMP] = { .func = osExpApiSensorRegInitComp },
488             [SYSCALL_OS_MAIN_SENSOR_FIND]          = { .func = osExpApiSensorFind,    },
489             [SYSCALL_OS_MAIN_SENSOR_REQUEST]       = { .func = osExpApiSensorReq,     },
490             [SYSCALL_OS_MAIN_SENSOR_RATE_CHG]      = { .func = osExpApiSensorRateChg, },
491             [SYSCALL_OS_MAIN_SENSOR_RELEASE]       = { .func = osExpApiSensorRel,     },
492             [SYSCALL_OS_MAIN_SENSOR_TRIGGER]       = { .func = osExpApiSensorTrigger, },
493             [SYSCALL_OS_MAIN_SENSOR_GET_RATE]      = { .func = osExpApiSensorGetRate, },
494 
495         },
496     };
497 
498     static const struct SyscallTable osMainTimerTable = {
499         .numEntries = SYSCALL_OS_MAIN_TIME_LAST,
500         .entry = {
501             [SYSCALL_OS_MAIN_TIME_GET_TIME]     = { .func = osExpApiTimGetTime,  },
502             [SYSCALL_OS_MAIN_TIME_SET_TIMER]    = { .func = osExpApiTimSetTimer,     },
503             [SYSCALL_OS_MAIN_TIME_CANCEL_TIMER] = { .func = osExpApiTimCancelTimer,   },
504         },
505     };
506 
507     static const struct SyscallTable osMainHeapTable = {
508         .numEntries = SYSCALL_OS_MAIN_HEAP_LAST,
509         .entry = {
510             [SYSCALL_OS_MAIN_HEAP_ALLOC] = { .func = osExpApiHeapAlloc },
511             [SYSCALL_OS_MAIN_HEAP_FREE]  = { .func = osExpApiHeapFree },
512         },
513     };
514 
515     static const struct SyscallTable osMainSlabTable = {
516         .numEntries = SYSCALL_OS_MAIN_SLAB_LAST,
517         .entry = {
518             [SYSCALL_OS_MAIN_SLAB_NEW]     = { .func = osExpApiSlabNew },
519             [SYSCALL_OS_MAIN_SLAB_DESTROY] = { .func = osExpApiSlabDestroy },
520             [SYSCALL_OS_MAIN_SLAB_ALLOC]   = { .func = osExpApiSlabAlloc },
521             [SYSCALL_OS_MAIN_SLAB_FREE]    = { .func = osExpApiSlabFree },
522         },
523     };
524 
525     static const struct SyscallTable osMainTable = {
526         .numEntries = SYSCALL_OS_MAIN_LAST,
527         .entry = {
528             [SYSCALL_OS_MAIN_EVENTQ]  = { .subtable = (struct SyscallTable*)&osMainEvtqTable,    },
529             [SYSCALL_OS_MAIN_LOGGING] = { .subtable = (struct SyscallTable*)&osMainLogTable,     },
530             [SYSCALL_OS_MAIN_SENSOR]  = { .subtable = (struct SyscallTable*)&osMainSensorsTable, },
531             [SYSCALL_OS_MAIN_TIME]    = { .subtable = (struct SyscallTable*)&osMainTimerTable,   },
532             [SYSCALL_OS_MAIN_HEAP]    = { .subtable = (struct SyscallTable*)&osMainHeapTable,    },
533             [SYSCALL_OS_MAIN_SLAB]    = { .subtable = (struct SyscallTable*)&osMainSlabTable,    },
534         },
535     };
536 
537     static const struct SyscallTable osDrvGpioTable = {
538         .numEntries = SYSCALL_OS_DRV_GPIO_LAST,
539         .entry = {
540             [SYSCALL_OS_DRV_GPIO_REQ]     = { .func = osExpApiGpioReq,    },
541             [SYSCALL_OS_DRV_GPIO_REL]     = { .func = osExpApiGpioRel,    },
542             [SYSCALL_OS_DRV_GPIO_CFG_IN]  = { .func = osExpApiGpioCfgIn,  },
543             [SYSCALL_OS_DRV_GPIO_CFG_OUT] = { .func = osExpApiGpioCfgOut, },
544             [SYSCALL_OS_DRV_GPIO_CFG_ALT] = { .func = osExpApiGpioCfgAlt, },
545             [SYSCALL_OS_DRV_GPIO_GET]     = { .func = osExpApiGpioGet,    },
546             [SYSCALL_OS_DRV_GPIO_SET]     = { .func = osExpApiGpioSet,    },
547         },
548     };
549 
550     static const struct SyscallTable osGrvI2cMstTable = {
551         .numEntries = SYSCALL_OS_DRV_I2CM_LAST,
552         .entry = {
553             [SYSCALL_OS_DRV_I2CM_REQ]  = { .func = osExpApiI2cMstReq,  },
554             [SYSCALL_OS_DRV_I2CM_REL]  = { .func = osExpApiI2cMstRel,  },
555             [SYSCALL_OS_DRV_I2CM_TXRX] = { .func = osExpApiI2cMstTxRx, },
556         },
557     };
558 
559     static const struct SyscallTable osGrvI2cSlvTable = {
560         .numEntries = SYSCALL_OS_DRV_I2CS_LAST,
561         .entry = {
562             [ SYSCALL_OS_DRV_I2CS_REQ]    = { .func = osExpApiI2cSlvReq,   },
563             [ SYSCALL_OS_DRV_I2CS_REL]    = { .func = osExpApiI2cSlvRel,   },
564             [ SYSCALL_OS_DRV_I2CS_RX_EN]  = { .func = osExpApiI2cSlvRxEn,  },
565             [ SYSCALL_OS_DRV_I2CS_TX_PRE] = { .func = osExpApiI2cSlvTxPre, },
566             [ SYSCALL_OS_DRV_I2CS_TX_PKT] = { .func = osExpApiI2cSlvTxPkt, },
567         },
568     };
569 
570     static const struct SyscallTable osDriversTable = {
571         .numEntries = SYSCALL_OS_DRV_LAST,
572         .entry = {
573             [SYSCALL_OS_DRV_GPIO]       = { .subtable = (struct SyscallTable*)&osDrvGpioTable,   },
574             [SYSCALL_OS_DRV_I2C_MASTER] = { .subtable = (struct SyscallTable*)&osGrvI2cMstTable, },
575             [SYSCALL_OS_DRV_I2C_SLAVE]  = { .subtable = (struct SyscallTable*)&osGrvI2cSlvTable, },
576         },
577     };
578 
579     static const struct SyscallTable osTable = {
580         .numEntries = SYSCALL_OS_LAST,
581         .entry = {
582             [SYSCALL_OS_MAIN]    = { .subtable = (struct SyscallTable*)&osMainTable,    },
583             [SYSCALL_OS_DRIVERS] = { .subtable = (struct SyscallTable*)&osDriversTable, },
584         },
585     };
586 
587     if (!syscallAddTable(SYSCALL_DOMAIN_OS, 1, (struct SyscallTable*)&osTable))
588         osLog(LOG_ERROR, "Failed to export OS base API");
589 }
590 
591