194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* Copyright 2008 The Android Open Source Project
294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */
394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <stdio.h>
594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <stdlib.h>
694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <errno.h>
794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <unistd.h>
894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <fcntl.h>
994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <sys/mman.h>
1094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "binder.h"
1294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define MAX_BIO_SIZE (1 << 30)
1494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define TRACE 0
1694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define LOG_TAG "Binder"
1894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <cutils/log.h>
1994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid bio_init_from_txn(struct binder_io *io, struct binder_txn *txn);
2194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#if TRACE
2394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid hexdump(void *_data, unsigned len)
2494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
2594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned char *data = _data;
2694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned count;
2794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (count = 0; count < len; count++) {
2994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if ((count & 15) == 0)
3094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            fprintf(stderr,"%04x:", count);
3194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        fprintf(stderr," %02x %c", *data,
3294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                (*data < 32) || (*data > 126) ? '.' : *data);
3394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data++;
3494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if ((count & 15) == 15)
3594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            fprintf(stderr,"\n");
3694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
3794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if ((count & 15) != 0)
3894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        fprintf(stderr,"\n");
3994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
4094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
4194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid binder_dump_txn(struct binder_txn *txn)
4294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
4394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_object *obj;
4494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned *offs = txn->offs;
4594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned count = txn->offs_size / 4;
4694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
4794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    fprintf(stderr,"  target %p  cookie %p  code %08x  flags %08x\n",
4894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            txn->target, txn->cookie, txn->code, txn->flags);
4994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    fprintf(stderr,"  pid %8d  uid %8d  data %8d  offs %8d\n",
5094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            txn->sender_pid, txn->sender_euid, txn->data_size, txn->offs_size);
5194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    hexdump(txn->data, txn->data_size);
5294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (count--) {
5394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        obj = (void*) (((char*) txn->data) + *offs++);
5494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        fprintf(stderr,"  - type %08x  flags %08x  ptr %p  cookie %p\n",
5594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                obj->type, obj->flags, obj->pointer, obj->cookie);
5694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
5794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
5894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
5994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define NAME(n) case n: return #n
6094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodconst char *cmd_name(uint32_t cmd)
6194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
6294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    switch(cmd) {
6394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_NOOP);
6494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_TRANSACTION_COMPLETE);
6594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_INCREFS);
6694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_ACQUIRE);
6794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_RELEASE);
6894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_DECREFS);
6994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_TRANSACTION);
7094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_REPLY);
7194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_FAILED_REPLY);
7294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_DEAD_REPLY);
7394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        NAME(BR_DEAD_BINDER);
7494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    default: return "???";
7594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
7694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
7794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#else
7894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define hexdump(a,b) do{} while (0)
7994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define binder_dump_txn(txn)  do{} while (0)
8094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#endif
8194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
8294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define BIO_F_SHARED    0x01  /* needs to be buffer freed */
8394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define BIO_F_OVERFLOW  0x02  /* ran out of space */
8494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define BIO_F_IOERROR   0x04
8594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define BIO_F_MALLOCED  0x08  /* needs to be free()'d */
8694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
8794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstruct binder_state
8894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
8994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int fd;
9094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    void *mapped;
9194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned mapsize;
9294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood};
9394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
9494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstruct binder_state *binder_open(unsigned mapsize)
9594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
9694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_state *bs;
9794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
9894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bs = malloc(sizeof(*bs));
9994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (!bs) {
10094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        errno = ENOMEM;
10194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
10294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
10394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
10494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bs->fd = open("/dev/binder", O_RDWR);
10594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (bs->fd < 0) {
10694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        fprintf(stderr,"binder: cannot open device (%s)\n",
10794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                strerror(errno));
10894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto fail_open;
10994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
11094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
11194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bs->mapsize = mapsize;
11294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
11394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (bs->mapped == MAP_FAILED) {
11494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        fprintf(stderr,"binder: cannot map device (%s)\n",
11594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                strerror(errno));
11694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto fail_map;
11794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
11894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
11994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        /* TODO: check version */
12094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
12194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return bs;
12294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
12394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodfail_map:
12494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    close(bs->fd);
12594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodfail_open:
12694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    free(bs);
12794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
12894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
12994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
13094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid binder_close(struct binder_state *bs)
13194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
13294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    munmap(bs->mapped, bs->mapsize);
13394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    close(bs->fd);
13494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    free(bs);
13594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
13694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
13794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint binder_become_context_manager(struct binder_state *bs)
13894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
13994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
14094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
14194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
14294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint binder_write(struct binder_state *bs, void *data, unsigned len)
14394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
14494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_write_read bwr;
14594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int res;
14694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.write_size = len;
14794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.write_consumed = 0;
14894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.write_buffer = (unsigned) data;
14994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.read_size = 0;
15094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.read_consumed = 0;
15194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.read_buffer = 0;
15294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
15394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (res < 0) {
15494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
15594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                strerror(errno));
15694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
15794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return res;
15894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
15994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
16094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid binder_send_reply(struct binder_state *bs,
16194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                       struct binder_io *reply,
16294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                       void *buffer_to_free,
16394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                       int status)
16494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
16594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct {
16694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        uint32_t cmd_free;
16794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        void *buffer;
16894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        uint32_t cmd_reply;
16994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        struct binder_txn txn;
17094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } __attribute__((packed)) data;
17194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
17294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    data.cmd_free = BC_FREE_BUFFER;
17394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    data.buffer = buffer_to_free;
17494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    data.cmd_reply = BC_REPLY;
17594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    data.txn.target = 0;
17694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    data.txn.cookie = 0;
17794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    data.txn.code = 0;
17894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (status) {
17994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data.txn.flags = TF_STATUS_CODE;
18094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data.txn.data_size = sizeof(int);
18194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data.txn.offs_size = 0;
18294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data.txn.data = &status;
18394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data.txn.offs = 0;
18494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
18594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data.txn.flags = 0;
18694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data.txn.data_size = reply->data - reply->data0;
18794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data.txn.offs_size = ((char*) reply->offs) - ((char*) reply->offs0);
18894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data.txn.data = reply->data0;
18994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        data.txn.offs = reply->offs0;
19094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
19194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    binder_write(bs, &data, sizeof(data));
19294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
19394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
19494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint binder_parse(struct binder_state *bs, struct binder_io *bio,
19594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                 uint32_t *ptr, uint32_t size, binder_handler func)
19694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
19794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int r = 1;
19894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t *end = ptr + (size / 4);
19994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
20094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (ptr < end) {
20194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        uint32_t cmd = *ptr++;
20294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#if TRACE
20394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        fprintf(stderr,"%s:\n", cmd_name(cmd));
20494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#endif
20594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        switch(cmd) {
20694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_NOOP:
20794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
20894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_TRANSACTION_COMPLETE:
20994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
21094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_INCREFS:
21194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_ACQUIRE:
21294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_RELEASE:
21394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_DECREFS:
21494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#if TRACE
21594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            fprintf(stderr,"  %08x %08x\n", ptr[0], ptr[1]);
21694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#endif
21794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ptr += 2;
21894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
21994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_TRANSACTION: {
22094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            struct binder_txn *txn = (void *) ptr;
22194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
22294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("parse: txn too small!\n");
22394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                return -1;
22494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
22594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            binder_dump_txn(txn);
22694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (func) {
22794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                unsigned rdata[256/4];
22894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                struct binder_io msg;
22994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                struct binder_io reply;
23094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                int res;
23194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
23294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                bio_init(&reply, rdata, sizeof(rdata), 4);
23394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                bio_init_from_txn(&msg, txn);
23494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                res = func(bs, txn, &msg, &reply);
23594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                binder_send_reply(bs, &reply, txn->data, res);
23694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
23794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ptr += sizeof(*txn) / sizeof(uint32_t);
23894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
23994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
24094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_REPLY: {
24194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            struct binder_txn *txn = (void*) ptr;
24294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
24394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("parse: reply too small!\n");
24494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                return -1;
24594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
24694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            binder_dump_txn(txn);
24794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (bio) {
24894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                bio_init_from_txn(bio, txn);
24994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                bio = 0;
25094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            } else {
25194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    /* todo FREE BUFFER */
25294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
25394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ptr += (sizeof(*txn) / sizeof(uint32_t));
25494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            r = 0;
25594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
25694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
25794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_DEAD_BINDER: {
25894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            struct binder_death *death = (void*) *ptr++;
25994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            death->func(bs, death->ptr);
26094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
26194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
26294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_FAILED_REPLY:
26394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            r = -1;
26494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
26594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        case BR_DEAD_REPLY:
26694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            r = -1;
26794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
26894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        default:
26994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("parse: OOPS %d\n", cmd);
27094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return -1;
27194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
27294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
27394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
27494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return r;
27594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
27694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
27794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid binder_acquire(struct binder_state *bs, void *ptr)
27894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
27994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t cmd[2];
28094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    cmd[0] = BC_ACQUIRE;
28194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    cmd[1] = (uint32_t) ptr;
28294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    binder_write(bs, cmd, sizeof(cmd));
28394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
28494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
28594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid binder_release(struct binder_state *bs, void *ptr)
28694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
28794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t cmd[2];
28894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    cmd[0] = BC_RELEASE;
28994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    cmd[1] = (uint32_t) ptr;
29094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    binder_write(bs, cmd, sizeof(cmd));
29194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
29294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
29394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid binder_link_to_death(struct binder_state *bs, void *ptr, struct binder_death *death)
29494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
29594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t cmd[3];
29694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    cmd[0] = BC_REQUEST_DEATH_NOTIFICATION;
29794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    cmd[1] = (uint32_t) ptr;
29894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    cmd[2] = (uint32_t) death;
29994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    binder_write(bs, cmd, sizeof(cmd));
30094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
30194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
30294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
30394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint binder_call(struct binder_state *bs,
30494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                struct binder_io *msg, struct binder_io *reply,
30594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                void *target, uint32_t code)
30694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
30794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int res;
30894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_write_read bwr;
30994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct {
31094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        uint32_t cmd;
31194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        struct binder_txn txn;
31294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } writebuf;
31394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned readbuf[32];
31494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
31594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (msg->flags & BIO_F_OVERFLOW) {
31694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        fprintf(stderr,"binder: txn buffer overflow\n");
31794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto fail;
31894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
31994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
32094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    writebuf.cmd = BC_TRANSACTION;
32194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    writebuf.txn.target = target;
32294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    writebuf.txn.code = code;
32394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    writebuf.txn.flags = 0;
32494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    writebuf.txn.data_size = msg->data - msg->data0;
32594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    writebuf.txn.offs_size = ((char*) msg->offs) - ((char*) msg->offs0);
32694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    writebuf.txn.data = msg->data0;
32794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    writebuf.txn.offs = msg->offs0;
32894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
32994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.write_size = sizeof(writebuf);
33094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.write_consumed = 0;
33194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.write_buffer = (unsigned) &writebuf;
33294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
33394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    hexdump(msg->data0, msg->data - msg->data0);
33494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (;;) {
33594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bwr.read_size = sizeof(readbuf);
33694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bwr.read_consumed = 0;
33794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bwr.read_buffer = (unsigned) readbuf;
33894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
33994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
34094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
34194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (res < 0) {
34294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
34394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto fail;
34494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
34594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
34694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        res = binder_parse(bs, reply, readbuf, bwr.read_consumed, 0);
34794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (res == 0) return 0;
34894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (res < 0) goto fail;
34994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
35094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
35194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodfail:
35294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    memset(reply, 0, sizeof(*reply));
35394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    reply->flags |= BIO_F_IOERROR;
35494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return -1;
35594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
35694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
35794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid binder_loop(struct binder_state *bs, binder_handler func)
35894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
35994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int res;
36094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_write_read bwr;
36194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned readbuf[32];
36294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
36394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.write_size = 0;
36494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.write_consumed = 0;
36594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bwr.write_buffer = 0;
36694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
36794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    readbuf[0] = BC_ENTER_LOOPER;
36894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    binder_write(bs, readbuf, sizeof(unsigned));
36994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
37094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (;;) {
37194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bwr.read_size = sizeof(readbuf);
37294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bwr.read_consumed = 0;
37394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bwr.read_buffer = (unsigned) readbuf;
37494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
37594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
37694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
37794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (res < 0) {
37894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
37994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
38094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
38194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
38294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
38394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (res == 0) {
38494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("binder_loop: unexpected reply?!\n");
38594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
38694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
38794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (res < 0) {
38894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
38994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
39094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
39194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
39294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
39394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
39494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid bio_init_from_txn(struct binder_io *bio, struct binder_txn *txn)
39594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
39694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->data = bio->data0 = txn->data;
39794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->offs = bio->offs0 = txn->offs;
39894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->data_avail = txn->data_size;
39994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->offs_avail = txn->offs_size / 4;
40094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->flags = BIO_F_SHARED;
40194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
40294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
40394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid bio_init(struct binder_io *bio, void *data,
40494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood              uint32_t maxdata, uint32_t maxoffs)
40594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
40694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t n = maxoffs * sizeof(uint32_t);
40794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
40894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (n > maxdata) {
40994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->flags = BIO_F_OVERFLOW;
41094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->data_avail = 0;
41194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->offs_avail = 0;
41294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return;
41394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
41494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
41594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->data = bio->data0 = (char *) data + n;
41694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->offs = bio->offs0 = data;
41794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->data_avail = maxdata - n;
41894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->offs_avail = maxoffs;
41994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->flags = 0;
42094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
42194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
42294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic void *bio_alloc(struct binder_io *bio, uint32_t size)
42394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
42494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    size = (size + 3) & (~3);
42594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (size > bio->data_avail) {
42694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->flags |= BIO_F_OVERFLOW;
42794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
42894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
42994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        void *ptr = bio->data;
43094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->data += size;
43194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->data_avail -= size;
43294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return ptr;
43394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
43494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
43594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
43694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid binder_done(struct binder_state *bs,
43794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                 struct binder_io *msg,
43894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                 struct binder_io *reply)
43994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
44094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (reply->flags & BIO_F_SHARED) {
44194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        uint32_t cmd[2];
44294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        cmd[0] = BC_FREE_BUFFER;
44394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        cmd[1] = (uint32_t) reply->data0;
44494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        binder_write(bs, cmd, sizeof(cmd));
44594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        reply->flags = 0;
44694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
44794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
44894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
44994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic struct binder_object *bio_alloc_obj(struct binder_io *bio)
45094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
45194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_object *obj;
45294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
45394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj = bio_alloc(bio, sizeof(*obj));
45494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
45594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (obj && bio->offs_avail) {
45694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->offs_avail--;
45794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
45894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return obj;
45994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
46094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
46194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->flags |= BIO_F_OVERFLOW;
46294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
46394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
46494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
46594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid bio_put_uint32(struct binder_io *bio, uint32_t n)
46694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
46794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t *ptr = bio_alloc(bio, sizeof(n));
46894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (ptr)
46994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        *ptr = n;
47094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
47194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
47294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid bio_put_obj(struct binder_io *bio, void *ptr)
47394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
47494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_object *obj;
47594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
47694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj = bio_alloc_obj(bio);
47794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (!obj)
47894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return;
47994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
48094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
48194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj->type = BINDER_TYPE_BINDER;
48294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj->pointer = ptr;
48394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj->cookie = 0;
48494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
48594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
48694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid bio_put_ref(struct binder_io *bio, void *ptr)
48794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
48894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_object *obj;
48994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
49094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (ptr)
49194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        obj = bio_alloc_obj(bio);
49294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    else
49394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        obj = bio_alloc(bio, sizeof(*obj));
49494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
49594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (!obj)
49694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return;
49794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
49894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
49994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj->type = BINDER_TYPE_HANDLE;
50094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj->pointer = ptr;
50194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj->cookie = 0;
50294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
50394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
50494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid bio_put_string16(struct binder_io *bio, const uint16_t *str)
50594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
50694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t len;
50794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint16_t *ptr;
50894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
50994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (!str) {
51094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio_put_uint32(bio, 0xffffffff);
51194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return;
51294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
51394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
51494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    len = 0;
51594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (str[len]) len++;
51694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
51794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
51894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio_put_uint32(bio, 0xffffffff);
51994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return;
52094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
52194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
52294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio_put_uint32(bio, len);
52394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    len = (len + 1) * sizeof(uint16_t);
52494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    ptr = bio_alloc(bio, len);
52594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (ptr)
52694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        memcpy(ptr, str, len);
52794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
52894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
52994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid bio_put_string16_x(struct binder_io *bio, const char *_str)
53094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
53194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned char *str = (unsigned char*) _str;
53294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t len;
53394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint16_t *ptr;
53494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
53594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (!str) {
53694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio_put_uint32(bio, 0xffffffff);
53794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return;
53894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
53994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
54094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    len = strlen(_str);
54194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
54294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
54394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio_put_uint32(bio, 0xffffffff);
54494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return;
54594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
54694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
54794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio_put_uint32(bio, len);
54894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
54994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (!ptr)
55094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return;
55194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
55294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (*str)
55394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        *ptr++ = *str++;
55494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    *ptr++ = 0;
55594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
55694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
55794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic void *bio_get(struct binder_io *bio, uint32_t size)
55894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
55994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    size = (size + 3) & (~3);
56094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
56194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (bio->data_avail < size){
56294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->data_avail = 0;
56394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->flags |= BIO_F_OVERFLOW;
56494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
56594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }  else {
56694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        void *ptr = bio->data;
56794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->data += size;
56894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bio->data_avail -= size;
56994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return ptr;
57094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
57194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
57294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
57394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooduint32_t bio_get_uint32(struct binder_io *bio)
57494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
57594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t *ptr = bio_get(bio, sizeof(*ptr));
57694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return ptr ? *ptr : 0;
57794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
57894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
57994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooduint16_t *bio_get_string16(struct binder_io *bio, unsigned *sz)
58094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
58194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned len;
58294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    len = bio_get_uint32(bio);
58394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (sz)
58494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        *sz = len;
58594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return bio_get(bio, (len + 1) * sizeof(uint16_t));
58694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
58794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
58894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic struct binder_object *_bio_get_obj(struct binder_io *bio)
58994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
59094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned n;
59194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned off = bio->data - bio->data0;
59294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
59394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        /* TODO: be smarter about this? */
59494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (n = 0; n < bio->offs_avail; n++) {
59594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (bio->offs[n] == off)
59694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return bio_get(bio, sizeof(struct binder_object));
59794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
59894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
59994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->data_avail = 0;
60094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio->flags |= BIO_F_OVERFLOW;
60194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
60294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
60394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
60494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid *bio_get_ref(struct binder_io *bio)
60594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
60694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_object *obj;
60794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
60894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    obj = _bio_get_obj(bio);
60994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (!obj)
61094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
61194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
61294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (obj->type == BINDER_TYPE_HANDLE)
61394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return obj->pointer;
61494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
61594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
61694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
617