blob: 7f8d0e0ed9befecbcad4f6157048e9471d004b3a [file] [log] [blame]
Mike Lockwood94afecf2012-10-24 10:45:23 -07001/* Copyright 2008 The Android Open Source Project
2 */
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <errno.h>
7#include <unistd.h>
8#include <fcntl.h>
9#include <sys/mman.h>
10
11#include "binder.h"
12
13#define MAX_BIO_SIZE (1 << 30)
14
15#define TRACE 0
16
17#define LOG_TAG "Binder"
18#include <cutils/log.h>
19
Serban Constantinescubcf38882014-01-10 13:56:27 +000020void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn);
Mike Lockwood94afecf2012-10-24 10:45:23 -070021
22#if TRACE
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000023void hexdump(void *_data, size_t len)
Mike Lockwood94afecf2012-10-24 10:45:23 -070024{
25 unsigned char *data = _data;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000026 size_t count;
Mike Lockwood94afecf2012-10-24 10:45:23 -070027
28 for (count = 0; count < len; count++) {
29 if ((count & 15) == 0)
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000030 fprintf(stderr,"%04zu:", count);
Mike Lockwood94afecf2012-10-24 10:45:23 -070031 fprintf(stderr," %02x %c", *data,
32 (*data < 32) || (*data > 126) ? '.' : *data);
33 data++;
34 if ((count & 15) == 15)
35 fprintf(stderr,"\n");
36 }
37 if ((count & 15) != 0)
38 fprintf(stderr,"\n");
39}
40
Serban Constantinescubcf38882014-01-10 13:56:27 +000041void binder_dump_txn(struct binder_transaction_data *txn)
Mike Lockwood94afecf2012-10-24 10:45:23 -070042{
Serban Constantinescubcf38882014-01-10 13:56:27 +000043 struct flat_binder_object *obj;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000044 size_t *offs = txn->data.ptr.offsets;
45 size_t count = txn->offsets_size / sizeof(size_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -070046
47 fprintf(stderr," target %p cookie %p code %08x flags %08x\n",
Serban Constantinescubcf38882014-01-10 13:56:27 +000048 txn->target.ptr, txn->cookie, txn->code, txn->flags);
49 fprintf(stderr," pid %8d uid %8d data %zu offs %zu\n",
50 txn->sender_pid, txn->sender_euid, txn->data_size, txn->offsets_size);
51 hexdump(txn->data.ptr.buffer, txn->data_size);
Mike Lockwood94afecf2012-10-24 10:45:23 -070052 while (count--) {
Serban Constantinescubcf38882014-01-10 13:56:27 +000053 obj = (struct flat_binder_object *) (((char*) txn->data.ptr.buffer) + *offs++);
Mike Lockwood94afecf2012-10-24 10:45:23 -070054 fprintf(stderr," - type %08x flags %08x ptr %p cookie %p\n",
Serban Constantinescubcf38882014-01-10 13:56:27 +000055 obj->type, obj->flags, obj->binder, obj->cookie);
Mike Lockwood94afecf2012-10-24 10:45:23 -070056 }
57}
58
59#define NAME(n) case n: return #n
60const char *cmd_name(uint32_t cmd)
61{
62 switch(cmd) {
63 NAME(BR_NOOP);
64 NAME(BR_TRANSACTION_COMPLETE);
65 NAME(BR_INCREFS);
66 NAME(BR_ACQUIRE);
67 NAME(BR_RELEASE);
68 NAME(BR_DECREFS);
69 NAME(BR_TRANSACTION);
70 NAME(BR_REPLY);
71 NAME(BR_FAILED_REPLY);
72 NAME(BR_DEAD_REPLY);
73 NAME(BR_DEAD_BINDER);
74 default: return "???";
75 }
76}
77#else
78#define hexdump(a,b) do{} while (0)
79#define binder_dump_txn(txn) do{} while (0)
80#endif
81
82#define BIO_F_SHARED 0x01 /* needs to be buffer freed */
83#define BIO_F_OVERFLOW 0x02 /* ran out of space */
84#define BIO_F_IOERROR 0x04
85#define BIO_F_MALLOCED 0x08 /* needs to be free()'d */
86
87struct binder_state
88{
89 int fd;
90 void *mapped;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000091 size_t mapsize;
Mike Lockwood94afecf2012-10-24 10:45:23 -070092};
93
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000094struct binder_state *binder_open(size_t mapsize)
Mike Lockwood94afecf2012-10-24 10:45:23 -070095{
96 struct binder_state *bs;
Serban Constantinescua44542c2014-01-30 15:16:45 +000097 struct binder_version vers;
Mike Lockwood94afecf2012-10-24 10:45:23 -070098
99 bs = malloc(sizeof(*bs));
100 if (!bs) {
101 errno = ENOMEM;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000102 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700103 }
104
105 bs->fd = open("/dev/binder", O_RDWR);
106 if (bs->fd < 0) {
107 fprintf(stderr,"binder: cannot open device (%s)\n",
108 strerror(errno));
109 goto fail_open;
110 }
111
Serban Constantinescua44542c2014-01-30 15:16:45 +0000112 if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
113 (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
114 fprintf(stderr, "binder: driver version differs from user space\n");
115 goto fail_open;
116 }
117
Mike Lockwood94afecf2012-10-24 10:45:23 -0700118 bs->mapsize = mapsize;
119 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
120 if (bs->mapped == MAP_FAILED) {
121 fprintf(stderr,"binder: cannot map device (%s)\n",
122 strerror(errno));
123 goto fail_map;
124 }
125
Mike Lockwood94afecf2012-10-24 10:45:23 -0700126 return bs;
127
128fail_map:
129 close(bs->fd);
130fail_open:
131 free(bs);
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000132 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700133}
134
135void binder_close(struct binder_state *bs)
136{
137 munmap(bs->mapped, bs->mapsize);
138 close(bs->fd);
139 free(bs);
140}
141
142int binder_become_context_manager(struct binder_state *bs)
143{
144 return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
145}
146
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000147int binder_write(struct binder_state *bs, void *data, size_t len)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700148{
149 struct binder_write_read bwr;
150 int res;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000151
Mike Lockwood94afecf2012-10-24 10:45:23 -0700152 bwr.write_size = len;
153 bwr.write_consumed = 0;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000154 bwr.write_buffer = (uintptr_t) data;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700155 bwr.read_size = 0;
156 bwr.read_consumed = 0;
157 bwr.read_buffer = 0;
158 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
159 if (res < 0) {
160 fprintf(stderr,"binder_write: ioctl failed (%s)\n",
161 strerror(errno));
162 }
163 return res;
164}
165
166void binder_send_reply(struct binder_state *bs,
167 struct binder_io *reply,
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000168 const void *buffer_to_free,
Mike Lockwood94afecf2012-10-24 10:45:23 -0700169 int status)
170{
171 struct {
172 uint32_t cmd_free;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000173 uintptr_t buffer;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700174 uint32_t cmd_reply;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000175 struct binder_transaction_data txn;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700176 } __attribute__((packed)) data;
177
178 data.cmd_free = BC_FREE_BUFFER;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000179 data.buffer = (uintptr_t) buffer_to_free;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700180 data.cmd_reply = BC_REPLY;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000181 data.txn.target.ptr = 0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700182 data.txn.cookie = 0;
183 data.txn.code = 0;
184 if (status) {
185 data.txn.flags = TF_STATUS_CODE;
186 data.txn.data_size = sizeof(int);
Serban Constantinescubcf38882014-01-10 13:56:27 +0000187 data.txn.offsets_size = 0;
188 data.txn.data.ptr.buffer = &status;
189 data.txn.data.ptr.offsets = 0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700190 } else {
191 data.txn.flags = 0;
192 data.txn.data_size = reply->data - reply->data0;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000193 data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
194 data.txn.data.ptr.buffer = reply->data0;
195 data.txn.data.ptr.offsets = reply->offs0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700196 }
197 binder_write(bs, &data, sizeof(data));
198}
199
200int binder_parse(struct binder_state *bs, struct binder_io *bio,
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000201 uintptr_t ptr, size_t size, binder_handler func)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700202{
203 int r = 1;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000204 uintptr_t end = ptr + (uintptr_t) size;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700205
206 while (ptr < end) {
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000207 uint32_t cmd = *(uint32_t *) ptr;
208 ptr += sizeof(uint32_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700209#if TRACE
210 fprintf(stderr,"%s:\n", cmd_name(cmd));
211#endif
212 switch(cmd) {
213 case BR_NOOP:
214 break;
215 case BR_TRANSACTION_COMPLETE:
216 break;
217 case BR_INCREFS:
218 case BR_ACQUIRE:
219 case BR_RELEASE:
220 case BR_DECREFS:
221#if TRACE
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000222 fprintf(stderr," %p, %p\n", ptr, (ptr + sizeof(void *)));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700223#endif
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000224 ptr += sizeof(struct binder_ptr_cookie);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700225 break;
226 case BR_TRANSACTION: {
Serban Constantinescubcf38882014-01-10 13:56:27 +0000227 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000228 if ((end - ptr) < sizeof(*txn)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700229 ALOGE("parse: txn too small!\n");
230 return -1;
231 }
232 binder_dump_txn(txn);
233 if (func) {
234 unsigned rdata[256/4];
235 struct binder_io msg;
236 struct binder_io reply;
237 int res;
238
239 bio_init(&reply, rdata, sizeof(rdata), 4);
240 bio_init_from_txn(&msg, txn);
241 res = func(bs, txn, &msg, &reply);
Serban Constantinescubcf38882014-01-10 13:56:27 +0000242 binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700243 }
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000244 ptr += sizeof(*txn);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700245 break;
246 }
247 case BR_REPLY: {
Serban Constantinescubcf38882014-01-10 13:56:27 +0000248 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000249 if ((end - ptr) < sizeof(*txn)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700250 ALOGE("parse: reply too small!\n");
251 return -1;
252 }
253 binder_dump_txn(txn);
254 if (bio) {
255 bio_init_from_txn(bio, txn);
256 bio = 0;
257 } else {
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000258 /* todo FREE BUFFER */
Mike Lockwood94afecf2012-10-24 10:45:23 -0700259 }
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000260 ptr += sizeof(*txn);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700261 r = 0;
262 break;
263 }
264 case BR_DEAD_BINDER: {
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000265 struct binder_death *death = (struct binder_death *) *(intptr_t *)ptr;
266 ptr += sizeof(void *);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700267 death->func(bs, death->ptr);
268 break;
269 }
270 case BR_FAILED_REPLY:
271 r = -1;
272 break;
273 case BR_DEAD_REPLY:
274 r = -1;
275 break;
276 default:
277 ALOGE("parse: OOPS %d\n", cmd);
278 return -1;
279 }
280 }
281
282 return r;
283}
284
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000285void binder_acquire(struct binder_state *bs, uint32_t target)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700286{
287 uint32_t cmd[2];
288 cmd[0] = BC_ACQUIRE;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000289 cmd[1] = target;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700290 binder_write(bs, cmd, sizeof(cmd));
291}
292
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000293void binder_release(struct binder_state *bs, uint32_t target)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700294{
295 uint32_t cmd[2];
296 cmd[0] = BC_RELEASE;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000297 cmd[1] = target;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700298 binder_write(bs, cmd, sizeof(cmd));
299}
300
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000301void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700302{
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000303 struct {
304 uint32_t cmd;
305 struct binder_handle_cookie payload;
306 } __attribute__((packed)) data;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700307
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000308 data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
309 data.payload.handle = target;
310 data.payload.cookie = (uintptr_t) death;
311 binder_write(bs, &data, sizeof(data));
312}
Mike Lockwood94afecf2012-10-24 10:45:23 -0700313
314int binder_call(struct binder_state *bs,
315 struct binder_io *msg, struct binder_io *reply,
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000316 uint32_t target, uint32_t code)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700317{
318 int res;
319 struct binder_write_read bwr;
320 struct {
321 uint32_t cmd;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000322 struct binder_transaction_data txn;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000323 } __attribute__((packed)) writebuf;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700324 unsigned readbuf[32];
325
326 if (msg->flags & BIO_F_OVERFLOW) {
327 fprintf(stderr,"binder: txn buffer overflow\n");
328 goto fail;
329 }
330
331 writebuf.cmd = BC_TRANSACTION;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000332 writebuf.txn.target.handle = target;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700333 writebuf.txn.code = code;
334 writebuf.txn.flags = 0;
335 writebuf.txn.data_size = msg->data - msg->data0;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000336 writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
337 writebuf.txn.data.ptr.buffer = msg->data0;
338 writebuf.txn.data.ptr.offsets = msg->offs0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700339
340 bwr.write_size = sizeof(writebuf);
341 bwr.write_consumed = 0;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000342 bwr.write_buffer = (uintptr_t) &writebuf;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000343
Mike Lockwood94afecf2012-10-24 10:45:23 -0700344 hexdump(msg->data0, msg->data - msg->data0);
345 for (;;) {
346 bwr.read_size = sizeof(readbuf);
347 bwr.read_consumed = 0;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000348 bwr.read_buffer = (uintptr_t) readbuf;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700349
350 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
351
352 if (res < 0) {
353 fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
354 goto fail;
355 }
356
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000357 res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700358 if (res == 0) return 0;
359 if (res < 0) goto fail;
360 }
361
362fail:
363 memset(reply, 0, sizeof(*reply));
364 reply->flags |= BIO_F_IOERROR;
365 return -1;
366}
367
368void binder_loop(struct binder_state *bs, binder_handler func)
369{
370 int res;
371 struct binder_write_read bwr;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000372 uint32_t readbuf[32];
Mike Lockwood94afecf2012-10-24 10:45:23 -0700373
374 bwr.write_size = 0;
375 bwr.write_consumed = 0;
376 bwr.write_buffer = 0;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000377
Mike Lockwood94afecf2012-10-24 10:45:23 -0700378 readbuf[0] = BC_ENTER_LOOPER;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000379 binder_write(bs, readbuf, sizeof(uint32_t));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700380
381 for (;;) {
382 bwr.read_size = sizeof(readbuf);
383 bwr.read_consumed = 0;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000384 bwr.read_buffer = (uintptr_t) readbuf;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700385
386 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
387
388 if (res < 0) {
389 ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
390 break;
391 }
392
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000393 res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700394 if (res == 0) {
395 ALOGE("binder_loop: unexpected reply?!\n");
396 break;
397 }
398 if (res < 0) {
399 ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
400 break;
401 }
402 }
403}
404
Serban Constantinescubcf38882014-01-10 13:56:27 +0000405void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700406{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000407 bio->data = bio->data0 = txn->data.ptr.buffer;
408 bio->offs = bio->offs0 = txn->data.ptr.offsets;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700409 bio->data_avail = txn->data_size;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000410 bio->offs_avail = txn->offsets_size / sizeof(size_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700411 bio->flags = BIO_F_SHARED;
412}
413
414void bio_init(struct binder_io *bio, void *data,
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000415 size_t maxdata, size_t maxoffs)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700416{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000417 size_t n = maxoffs * sizeof(size_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700418
419 if (n > maxdata) {
420 bio->flags = BIO_F_OVERFLOW;
421 bio->data_avail = 0;
422 bio->offs_avail = 0;
423 return;
424 }
425
426 bio->data = bio->data0 = (char *) data + n;
427 bio->offs = bio->offs0 = data;
428 bio->data_avail = maxdata - n;
429 bio->offs_avail = maxoffs;
430 bio->flags = 0;
431}
432
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000433static void *bio_alloc(struct binder_io *bio, size_t size)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700434{
435 size = (size + 3) & (~3);
436 if (size > bio->data_avail) {
437 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000438 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700439 } else {
440 void *ptr = bio->data;
441 bio->data += size;
442 bio->data_avail -= size;
443 return ptr;
444 }
445}
446
447void binder_done(struct binder_state *bs,
448 struct binder_io *msg,
449 struct binder_io *reply)
450{
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000451 struct {
452 uint32_t cmd;
453 uintptr_t buffer;
454 } __attribute__((packed)) data;
455
Mike Lockwood94afecf2012-10-24 10:45:23 -0700456 if (reply->flags & BIO_F_SHARED) {
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000457 data.cmd = BC_FREE_BUFFER;
458 data.buffer = (uintptr_t) reply->data0;
459 binder_write(bs, &data, sizeof(data));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700460 reply->flags = 0;
461 }
462}
463
Serban Constantinescubcf38882014-01-10 13:56:27 +0000464static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700465{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000466 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700467
468 obj = bio_alloc(bio, sizeof(*obj));
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000469
Mike Lockwood94afecf2012-10-24 10:45:23 -0700470 if (obj && bio->offs_avail) {
471 bio->offs_avail--;
472 *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
473 return obj;
474 }
475
476 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000477 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700478}
479
480void bio_put_uint32(struct binder_io *bio, uint32_t n)
481{
482 uint32_t *ptr = bio_alloc(bio, sizeof(n));
483 if (ptr)
484 *ptr = n;
485}
486
487void bio_put_obj(struct binder_io *bio, void *ptr)
488{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000489 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700490
491 obj = bio_alloc_obj(bio);
492 if (!obj)
493 return;
494
495 obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
496 obj->type = BINDER_TYPE_BINDER;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000497 obj->binder = ptr;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700498 obj->cookie = 0;
499}
500
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000501void bio_put_ref(struct binder_io *bio, uint32_t handle)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700502{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000503 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700504
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000505 if (handle)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700506 obj = bio_alloc_obj(bio);
507 else
508 obj = bio_alloc(bio, sizeof(*obj));
509
510 if (!obj)
511 return;
512
513 obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
514 obj->type = BINDER_TYPE_HANDLE;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000515 obj->handle = handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700516 obj->cookie = 0;
517}
518
519void bio_put_string16(struct binder_io *bio, const uint16_t *str)
520{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000521 size_t len;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700522 uint16_t *ptr;
523
524 if (!str) {
525 bio_put_uint32(bio, 0xffffffff);
526 return;
527 }
528
529 len = 0;
530 while (str[len]) len++;
531
532 if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
533 bio_put_uint32(bio, 0xffffffff);
534 return;
535 }
536
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000537 /* Note: The payload will carry 32bit size instead of size_t */
538 bio_put_uint32(bio, (uint32_t) len);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700539 len = (len + 1) * sizeof(uint16_t);
540 ptr = bio_alloc(bio, len);
541 if (ptr)
542 memcpy(ptr, str, len);
543}
544
545void bio_put_string16_x(struct binder_io *bio, const char *_str)
546{
547 unsigned char *str = (unsigned char*) _str;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000548 size_t len;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700549 uint16_t *ptr;
550
551 if (!str) {
552 bio_put_uint32(bio, 0xffffffff);
553 return;
554 }
555
556 len = strlen(_str);
557
558 if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
559 bio_put_uint32(bio, 0xffffffff);
560 return;
561 }
562
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000563 /* Note: The payload will carry 32bit size instead of size_t */
Mike Lockwood94afecf2012-10-24 10:45:23 -0700564 bio_put_uint32(bio, len);
565 ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
566 if (!ptr)
567 return;
568
569 while (*str)
570 *ptr++ = *str++;
571 *ptr++ = 0;
572}
573
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000574static void *bio_get(struct binder_io *bio, size_t size)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700575{
576 size = (size + 3) & (~3);
577
578 if (bio->data_avail < size){
579 bio->data_avail = 0;
580 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000581 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700582 } else {
583 void *ptr = bio->data;
584 bio->data += size;
585 bio->data_avail -= size;
586 return ptr;
587 }
588}
589
590uint32_t bio_get_uint32(struct binder_io *bio)
591{
592 uint32_t *ptr = bio_get(bio, sizeof(*ptr));
593 return ptr ? *ptr : 0;
594}
595
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000596uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700597{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000598 size_t len;
599
600 /* Note: The payload will carry 32bit size instead of size_t */
601 len = (size_t) bio_get_uint32(bio);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700602 if (sz)
603 *sz = len;
604 return bio_get(bio, (len + 1) * sizeof(uint16_t));
605}
606
Serban Constantinescubcf38882014-01-10 13:56:27 +0000607static struct flat_binder_object *_bio_get_obj(struct binder_io *bio)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700608{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000609 size_t n;
610 size_t off = bio->data - bio->data0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700611
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000612 /* TODO: be smarter about this? */
Mike Lockwood94afecf2012-10-24 10:45:23 -0700613 for (n = 0; n < bio->offs_avail; n++) {
614 if (bio->offs[n] == off)
Serban Constantinescubcf38882014-01-10 13:56:27 +0000615 return bio_get(bio, sizeof(struct flat_binder_object));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700616 }
617
618 bio->data_avail = 0;
619 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000620 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700621}
622
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000623uint32_t bio_get_ref(struct binder_io *bio)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700624{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000625 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700626
627 obj = _bio_get_obj(bio);
628 if (!obj)
629 return 0;
630
631 if (obj->type == BINDER_TYPE_HANDLE)
Serban Constantinescubcf38882014-01-10 13:56:27 +0000632 return obj->handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700633
634 return 0;
635}