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