19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* Copyright 2008 The Android Open Source Project
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h>
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h>
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h>
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/mman.h>
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "binder.h"
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define MAX_BIO_SIZE (1 << 30)
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define TRACE 0
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "Binder"
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/log.h>
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_init_from_txn(struct binder_io *io, struct binder_txn *txn);
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if TRACE
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid hexdump(void *_data, unsigned len)
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned char *data = _data;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned count;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (count = 0; count < len; count++) {
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((count & 15) == 0)
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr,"%04x:", count);
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr," %02x %c", *data,
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (*data < 32) || (*data > 126) ? '.' : *data);
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data++;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((count & 15) == 15)
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr,"\n");
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((count & 15) != 0)
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr,"\n");
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_dump_txn(struct binder_txn *txn)
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct binder_object *obj;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned *offs = txn->offs;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned count = txn->offs_size / 4;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fprintf(stderr,"  target %p  cookie %p  code %08x  flags %08x\n",
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            txn->target, txn->cookie, txn->code, txn->flags);
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fprintf(stderr,"  pid %8d  uid %8d  data %8d  offs %8d\n",
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            txn->sender_pid, txn->sender_euid, txn->data_size, txn->offs_size);
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    hexdump(txn->data, txn->data_size);
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (count--) {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        obj = (void*) (((char*) txn->data) + *offs++);
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr,"  - type %08x  flags %08x  ptr %p  cookie %p\n",
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                obj->type, obj->flags, obj->pointer, obj->cookie);
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define NAME(n) case n: return #n
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char *cmd_name(uint32_t cmd)
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    switch(cmd) {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_NOOP);
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_TRANSACTION_COMPLETE);
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_INCREFS);
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_ACQUIRE);
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_RELEASE);
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_DECREFS);
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_TRANSACTION);
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_REPLY);
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_FAILED_REPLY);
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_DEAD_REPLY);
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NAME(BR_DEAD_BINDER);
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    default: return "???";
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define hexdump(a,b) do{} while (0)
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define binder_dump_txn(txn)  do{} while (0)
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BIO_F_SHARED    0x01  /* needs to be buffer freed */
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BIO_F_OVERFLOW  0x02  /* ran out of space */
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BIO_F_IOERROR   0x04
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BIO_F_MALLOCED  0x08  /* needs to be free()'d */
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct binder_state
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void *mapped;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned mapsize;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct binder_state *binder_open(unsigned mapsize)
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct binder_state *bs;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bs = malloc(sizeof(*bs));
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!bs) {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        errno = ENOMEM;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bs->fd = open("/dev/binder", O_RDWR);
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bs->fd < 0) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr,"binder: cannot open device (%s)\n",
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                strerror(errno));
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto fail_open;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bs->mapsize = mapsize;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bs->mapped == MAP_FAILED) {
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr,"binder: cannot map device (%s)\n",
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                strerror(errno));
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto fail_map;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* TODO: check version */
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return bs;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectfail_map:
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    close(bs->fd);
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectfail_open:
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    free(bs);
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_close(struct binder_state *bs)
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    munmap(bs->mapped, bs->mapsize);
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    close(bs->fd);
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    free(bs);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint binder_become_context_manager(struct binder_state *bs)
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint binder_write(struct binder_state *bs, void *data, unsigned len)
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct binder_write_read bwr;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int res;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.write_size = len;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.write_consumed = 0;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.write_buffer = (unsigned) data;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.read_size = 0;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.read_consumed = 0;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.read_buffer = 0;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (res < 0) {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                strerror(errno));
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return res;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_send_reply(struct binder_state *bs,
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       struct binder_io *reply,
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       void *buffer_to_free,
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       int status)
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct {
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t cmd_free;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void *buffer;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t cmd_reply;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        struct binder_txn txn;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } __attribute__((packed)) data;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    data.cmd_free = BC_FREE_BUFFER;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    data.buffer = buffer_to_free;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    data.cmd_reply = BC_REPLY;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    data.txn.target = 0;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    data.txn.cookie = 0;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    data.txn.code = 0;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (status) {
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data.txn.flags = TF_STATUS_CODE;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data.txn.data_size = sizeof(int);
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data.txn.offs_size = 0;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data.txn.data = &status;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data.txn.offs = 0;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data.txn.flags = 0;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data.txn.data_size = reply->data - reply->data0;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data.txn.offs_size = ((char*) reply->offs) - ((char*) reply->offs0);
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data.txn.data = reply->data0;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        data.txn.offs = reply->offs0;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    binder_write(bs, &data, sizeof(data));
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint binder_parse(struct binder_state *bs, struct binder_io *bio,
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 uint32_t *ptr, uint32_t size, binder_handler func)
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int r = 1;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t *end = ptr + (size / 4);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (ptr < end) {
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t cmd = *ptr++;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if TRACE
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr,"%s:\n", cmd_name(cmd));
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch(cmd) {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_NOOP:
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_TRANSACTION_COMPLETE:
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_INCREFS:
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_ACQUIRE:
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_RELEASE:
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_DECREFS:
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if TRACE
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr,"  %08x %08x\n", ptr[0], ptr[1]);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ptr += 2;
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_TRANSACTION: {
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            struct binder_txn *txn = (void *) ptr;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
2223762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("parse: txn too small!\n");
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return -1;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            binder_dump_txn(txn);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (func) {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                unsigned rdata[256/4];
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                struct binder_io msg;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                struct binder_io reply;
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int res;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                bio_init(&reply, rdata, sizeof(rdata), 4);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                bio_init_from_txn(&msg, txn);
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                res = func(bs, txn, &msg, &reply);
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                binder_send_reply(bs, &reply, txn->data, res);
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ptr += sizeof(*txn) / sizeof(uint32_t);
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_REPLY: {
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            struct binder_txn *txn = (void*) ptr;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
2433762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("parse: reply too small!\n");
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return -1;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            binder_dump_txn(txn);
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (bio) {
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                bio_init_from_txn(bio, txn);
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                bio = 0;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    /* todo FREE BUFFER */
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ptr += (sizeof(*txn) / sizeof(uint32_t));
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            r = 0;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_DEAD_BINDER: {
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            struct binder_death *death = (void*) *ptr++;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            death->func(bs, death->ptr);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_FAILED_REPLY:
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            r = -1;
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BR_DEAD_REPLY:
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            r = -1;
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
2693762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("parse: OOPS %d\n", cmd);
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return r;
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_acquire(struct binder_state *bs, void *ptr)
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t cmd[2];
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    cmd[0] = BC_ACQUIRE;
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    cmd[1] = (uint32_t) ptr;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    binder_write(bs, cmd, sizeof(cmd));
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_release(struct binder_state *bs, void *ptr)
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t cmd[2];
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    cmd[0] = BC_RELEASE;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    cmd[1] = (uint32_t) ptr;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    binder_write(bs, cmd, sizeof(cmd));
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_link_to_death(struct binder_state *bs, void *ptr, struct binder_death *death)
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t cmd[3];
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    cmd[0] = BC_REQUEST_DEATH_NOTIFICATION;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    cmd[1] = (uint32_t) ptr;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    cmd[2] = (uint32_t) death;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    binder_write(bs, cmd, sizeof(cmd));
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint binder_call(struct binder_state *bs,
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                struct binder_io *msg, struct binder_io *reply,
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                void *target, uint32_t code)
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int res;
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct binder_write_read bwr;
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t cmd;
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        struct binder_txn txn;
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } writebuf;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned readbuf[32];
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (msg->flags & BIO_F_OVERFLOW) {
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr,"binder: txn buffer overflow\n");
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto fail;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    writebuf.cmd = BC_TRANSACTION;
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    writebuf.txn.target = target;
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    writebuf.txn.code = code;
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    writebuf.txn.flags = 0;
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    writebuf.txn.data_size = msg->data - msg->data0;
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    writebuf.txn.offs_size = ((char*) msg->offs) - ((char*) msg->offs0);
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    writebuf.txn.data = msg->data0;
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    writebuf.txn.offs = msg->offs0;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.write_size = sizeof(writebuf);
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.write_consumed = 0;
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.write_buffer = (unsigned) &writebuf;
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    hexdump(msg->data0, msg->data - msg->data0);
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (;;) {
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bwr.read_size = sizeof(readbuf);
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bwr.read_consumed = 0;
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bwr.read_buffer = (unsigned) readbuf;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (res < 0) {
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto fail;
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        res = binder_parse(bs, reply, readbuf, bwr.read_consumed, 0);
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (res == 0) return 0;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (res < 0) goto fail;
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectfail:
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    memset(reply, 0, sizeof(*reply));
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    reply->flags |= BIO_F_IOERROR;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_loop(struct binder_state *bs, binder_handler func)
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int res;
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct binder_write_read bwr;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned readbuf[32];
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.write_size = 0;
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.write_consumed = 0;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bwr.write_buffer = 0;
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    readbuf[0] = BC_ENTER_LOOPER;
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    binder_write(bs, readbuf, sizeof(unsigned));
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (;;) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bwr.read_size = sizeof(readbuf);
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bwr.read_consumed = 0;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bwr.read_buffer = (unsigned) readbuf;
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (res < 0) {
3783762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (res == 0) {
3843762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("binder_loop: unexpected reply?!\n");
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (res < 0) {
3883762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_init_from_txn(struct binder_io *bio, struct binder_txn *txn)
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->data = bio->data0 = txn->data;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->offs = bio->offs0 = txn->offs;
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->data_avail = txn->data_size;
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->offs_avail = txn->offs_size / 4;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->flags = BIO_F_SHARED;
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_init(struct binder_io *bio, void *data,
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project              uint32_t maxdata, uint32_t maxoffs)
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t n = maxoffs * sizeof(uint32_t);
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (n > maxdata) {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->flags = BIO_F_OVERFLOW;
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->data_avail = 0;
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->offs_avail = 0;
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
41577b07ff2c10becd3223c2ed6a6052f61c826b5a1Glenn Kasten    bio->data = bio->data0 = (char *) data + n;
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->offs = bio->offs0 = data;
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->data_avail = maxdata - n;
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->offs_avail = maxoffs;
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->flags = 0;
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void *bio_alloc(struct binder_io *bio, uint32_t size)
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size = (size + 3) & (~3);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (size > bio->data_avail) {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->flags |= BIO_F_OVERFLOW;
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void *ptr = bio->data;
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->data += size;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->data_avail -= size;
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ptr;
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_done(struct binder_state *bs,
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 struct binder_io *msg,
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 struct binder_io *reply)
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (reply->flags & BIO_F_SHARED) {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t cmd[2];
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cmd[0] = BC_FREE_BUFFER;
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cmd[1] = (uint32_t) reply->data0;
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        binder_write(bs, cmd, sizeof(cmd));
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        reply->flags = 0;
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct binder_object *bio_alloc_obj(struct binder_io *bio)
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct binder_object *obj;
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj = bio_alloc(bio, sizeof(*obj));
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (obj && bio->offs_avail) {
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->offs_avail--;
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return obj;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->flags |= BIO_F_OVERFLOW;
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_put_uint32(struct binder_io *bio, uint32_t n)
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t *ptr = bio_alloc(bio, sizeof(n));
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ptr)
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *ptr = n;
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_put_obj(struct binder_io *bio, void *ptr)
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct binder_object *obj;
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj = bio_alloc_obj(bio);
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!obj)
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj->type = BINDER_TYPE_BINDER;
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj->pointer = ptr;
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj->cookie = 0;
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_put_ref(struct binder_io *bio, void *ptr)
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct binder_object *obj;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ptr)
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        obj = bio_alloc_obj(bio);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        obj = bio_alloc(bio, sizeof(*obj));
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!obj)
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj->type = BINDER_TYPE_HANDLE;
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj->pointer = ptr;
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj->cookie = 0;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_put_string16(struct binder_io *bio, const uint16_t *str)
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t len;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint16_t *ptr;
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!str) {
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio_put_uint32(bio, 0xffffffff);
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    len = 0;
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (str[len]) len++;
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio_put_uint32(bio, 0xffffffff);
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio_put_uint32(bio, len);
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    len = (len + 1) * sizeof(uint16_t);
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ptr = bio_alloc(bio, len);
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ptr)
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(ptr, str, len);
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_put_string16_x(struct binder_io *bio, const char *_str)
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned char *str = (unsigned char*) _str;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t len;
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint16_t *ptr;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!str) {
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio_put_uint32(bio, 0xffffffff);
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    len = strlen(_str);
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio_put_uint32(bio, 0xffffffff);
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio_put_uint32(bio, len);
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!ptr)
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (*str)
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *ptr++ = *str++;
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *ptr++ = 0;
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void *bio_get(struct binder_io *bio, uint32_t size)
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size = (size + 3) & (~3);
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bio->data_avail < size){
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->data_avail = 0;
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->flags |= BIO_F_OVERFLOW;
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }  else {
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void *ptr = bio->data;
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->data += size;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bio->data_avail -= size;
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ptr;
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t bio_get_uint32(struct binder_io *bio)
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t *ptr = bio_get(bio, sizeof(*ptr));
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ptr ? *ptr : 0;
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint16_t *bio_get_string16(struct binder_io *bio, unsigned *sz)
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned len;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    len = bio_get_uint32(bio);
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (sz)
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *sz = len;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return bio_get(bio, (len + 1) * sizeof(uint16_t));
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct binder_object *_bio_get_obj(struct binder_io *bio)
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned n;
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned off = bio->data - bio->data0;
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* TODO: be smarter about this? */
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (n = 0; n < bio->offs_avail; n++) {
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bio->offs[n] == off)
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return bio_get(bio, sizeof(struct binder_object));
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->data_avail = 0;
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bio->flags |= BIO_F_OVERFLOW;
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid *bio_get_ref(struct binder_io *bio)
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct binder_object *obj;
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    obj = _bio_get_obj(bio);
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!obj)
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (obj->type == BINDER_TYPE_HANDLE)
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return obj->pointer;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
617