ref: 207a95163f5a047e1f8ed8b77f1c4ab2b08edb64
dir: /gui-android/cpp/devandroid.c/
#include "u.h"
#include "lib.h"
#include "dat.h"
#include "fns.h"
#include "error.h"
//#include <android/log.h>
#include <android/sensor.h>
void show_notification(char *buf);
void take_picture(int id);
int num_cameras();
long getlocation(char *a, long n);
int Ncameras = 0;
uchar *cambuf = nil;
int camlen = 0;
static char camopen = 0;
ASensorManager *sensorManager = NULL;
enum
{
Qdir = 0,
Qaccel,
Qcompass,
Qnotify,
Qlocation,
Ntab,
Qcam = 8,
};
Dirtab
androiddir[] =
{
".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
"accel", {Qaccel}, 0, 0444,
"compass", {Qcompass}, 0, 0444,
"notify", {Qnotify}, 0, 0222,
"location", {Qlocation}, 0, 0444,
"camNNNN", {Qcam}, 0, 0444,
};
static void androidinit(void);
static void
androidinit(void)
{
sensorManager = ASensorManager_getInstance();
Ncameras = num_cameras();
}
static Chan*
androidattach(char *param)
{
return devattach('N', param);
}
int
androidgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
{
Qid q;
if(tab == 0)
return -1;
if(i == DEVDOTDOT){
/* nothing */
}else if(name){
// __android_log_print(ANDROID_LOG_WARN, "drawterm", "androidgen name %s", name);
for(i=1; i<Ntab; i++)
if(strcmp(tab[i].name, name) == 0)
break;
if (i == Ntab) {
if (strncmp("cam", name, 3) == 0 &&
name[3] >= '0' && name[3] <= '9' &&
strspn(&name[3], "0123456789") == (strlen(name) - 3) &&
(i = atoi(&name[3])) < Ncameras)
i += Ntab;
else
return -1;
}
if(i > Ntab)
tab += Ntab;
else
tab += i;
}else{
// __android_log_print(ANDROID_LOG_WARN, "drawterm", "androidgen i %d", i);
/* skip over the first element, that for . itself */
i++;
if(i >= ntab)
return -1;
if(i >= Ntab)
tab += Ntab;
else
tab += i;
}
if (i >= Ntab) {
q = tab->qid;
q.path |= ((i - Ntab) << 16);
sprintf(up->genbuf, "cam%d", i - Ntab);
devdir(c, q, up->genbuf, tab->length, eve, tab->perm, dp);
return 1;
}
devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
return 1;
}
static Walkqid*
androidwalk(Chan *c, Chan *nc, char **name, int nname)
{
return devwalk(c, nc, name, nname, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
}
static int
androidstat(Chan *c, uchar *db, int n)
{
return devstat(c, db, n, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
}
static Chan*
androidopen(Chan *c, int omode)
{
int i;
if (c->qid.path & Qcam) {
if (camopen != 0) {
error(Einuse);
} else {
camopen = 1;
i = c->qid.path >> 16;
take_picture(i);
}
}
c = devopen(c, omode, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
return c;
}
static void
androidclose(Chan *c)
{
if (c->qid.path & Qcam && camopen != 0) {
free(cambuf);
cambuf = nil;
camlen = 0;
camopen = 0;
}
}
long
readsensor(char *a, long n, int type) {
long l;
const ASensor *sensor;
ASensorEventQueue *queue = NULL;
ASensorEvent data;
queue = ASensorManager_createEventQueue(sensorManager, ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS), 1, NULL, NULL);
if (queue == NULL)
return 0;
sensor = ASensorManager_getDefaultSensor(sensorManager, type);
if (sensor == NULL) {
ASensorManager_destroyEventQueue(sensorManager, queue);
return 0;
}
if (ASensorEventQueue_enableSensor(queue, sensor)) {
ASensorEventQueue_disableSensor(queue, sensor);
ASensorManager_destroyEventQueue(sensorManager, queue);
return 0;
}
l = 0;
if (ALooper_pollAll(1000, NULL, NULL, NULL) == 1) {
if (ASensorEventQueue_getEvents(queue, &data, 1)) {
l = snprint(a, n, "%11f %11f %11f\n", data.vector.x, data.vector.y, data.vector.z);
}
}
ASensorEventQueue_disableSensor(queue, sensor);
ASensorManager_destroyEventQueue(sensorManager, queue);
return l;
}
static long
androidread(Chan *c, void *v, long n, vlong off)
{
char *a = v;
long l;
switch((ulong)c->qid.path & 0xF) {
default:
error(Eperm);
return -1;
case Qcam:
while(camlen == 0)
usleep(10 * 1000);
if(camlen < 0) {
error(Eio);
return -1;
}
l = camlen - off;
if (l > n)
l = n;
if (l > 0)
memcpy(a, cambuf + off, l);
return l;
case Qaccel:
return readsensor(a, n, ASENSOR_TYPE_ACCELEROMETER);
case Qcompass:
return readsensor(a, n, ASENSOR_TYPE_MAGNETIC_FIELD);
case Qlocation:
return getlocation(a, n);
case Qdir:
return devdirread(c, a, n, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
}
}
static long
androidwrite(Chan *c, void *vp, long n, vlong off)
{
char *a = vp;
char *str;
switch((ulong)c->qid.path) {
case Qnotify:
str = malloc(n+1);
memcpy(str, a, n);
str[n] = '\0';
show_notification(str);
free(str);
return n;
default:
error(Eperm);
break;
}
return -1;
}
Dev androiddevtab = {
'N',
"android",
devreset,
androidinit,
devshutdown,
androidattach,
androidwalk,
androidstat,
androidopen,
devcreate,
androidclose,
androidread,
devbread,
androidwrite,
devbwrite,
devremove,
devwstat,
};