1/*
2 * Copyright 2009 VMware, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19 * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/*
26 * This file holds the function implementation for one of the rbug extensions.
27 * Prototypes and declerations of functions and structs is in the same folder
28 * in the header file matching this file's name.
29 *
30 * The functions starting rbug_send_* encodes a call to the write format and
31 * sends that to the supplied connection, while functions starting with
32 * rbug_demarshal_* demarshal data in the wire protocol.
33 *
34 * Functions ending with _reply are replies to requests.
35 */
36
37#include "rbug_internal.h"
38#include "rbug_context.h"
39
40int rbug_send_context_list(struct rbug_connection *__con,
41                           uint32_t *__serial)
42{
43	uint32_t __len = 0;
44	uint32_t __pos = 0;
45	uint8_t *__data = NULL;
46	int __ret = 0;
47
48	LEN(8); /* header */
49
50	/* align */
51	PAD(__len, 8);
52
53	__data = (uint8_t*)MALLOC(__len);
54	if (!__data)
55		return -ENOMEM;
56
57	WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_LIST));
58	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
59
60	/* final pad */
61	PAD(__pos, 8);
62
63	if (__pos != __len) {
64		__ret = -EINVAL;
65	} else {
66		rbug_connection_send_start(__con, RBUG_OP_CONTEXT_LIST, __len);
67		rbug_connection_write(__con, __data, __len);
68		__ret = rbug_connection_send_finish(__con, __serial);
69	}
70
71	FREE(__data);
72	return __ret;
73}
74
75int rbug_send_context_info(struct rbug_connection *__con,
76                           rbug_context_t context,
77                           uint32_t *__serial)
78{
79	uint32_t __len = 0;
80	uint32_t __pos = 0;
81	uint8_t *__data = NULL;
82	int __ret = 0;
83
84	LEN(8); /* header */
85	LEN(8); /* context */
86
87	/* align */
88	PAD(__len, 8);
89
90	__data = (uint8_t*)MALLOC(__len);
91	if (!__data)
92		return -ENOMEM;
93
94	WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_INFO));
95	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
96	WRITE(8, rbug_context_t, context); /* context */
97
98	/* final pad */
99	PAD(__pos, 8);
100
101	if (__pos != __len) {
102		__ret = -EINVAL;
103	} else {
104		rbug_connection_send_start(__con, RBUG_OP_CONTEXT_INFO, __len);
105		rbug_connection_write(__con, __data, __len);
106		__ret = rbug_connection_send_finish(__con, __serial);
107	}
108
109	FREE(__data);
110	return __ret;
111}
112
113int rbug_send_context_draw_block(struct rbug_connection *__con,
114                                 rbug_context_t context,
115                                 rbug_block_t block,
116                                 uint32_t *__serial)
117{
118	uint32_t __len = 0;
119	uint32_t __pos = 0;
120	uint8_t *__data = NULL;
121	int __ret = 0;
122
123	LEN(8); /* header */
124	LEN(8); /* context */
125	LEN(4); /* block */
126
127	/* align */
128	PAD(__len, 8);
129
130	__data = (uint8_t*)MALLOC(__len);
131	if (!__data)
132		return -ENOMEM;
133
134	WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_BLOCK));
135	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
136	WRITE(8, rbug_context_t, context); /* context */
137	WRITE(4, rbug_block_t, block); /* block */
138
139	/* final pad */
140	PAD(__pos, 8);
141
142	if (__pos != __len) {
143		__ret = -EINVAL;
144	} else {
145		rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_BLOCK, __len);
146		rbug_connection_write(__con, __data, __len);
147		__ret = rbug_connection_send_finish(__con, __serial);
148	}
149
150	FREE(__data);
151	return __ret;
152}
153
154int rbug_send_context_draw_step(struct rbug_connection *__con,
155                                rbug_context_t context,
156                                rbug_block_t step,
157                                uint32_t *__serial)
158{
159	uint32_t __len = 0;
160	uint32_t __pos = 0;
161	uint8_t *__data = NULL;
162	int __ret = 0;
163
164	LEN(8); /* header */
165	LEN(8); /* context */
166	LEN(4); /* step */
167
168	/* align */
169	PAD(__len, 8);
170
171	__data = (uint8_t*)MALLOC(__len);
172	if (!__data)
173		return -ENOMEM;
174
175	WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_STEP));
176	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
177	WRITE(8, rbug_context_t, context); /* context */
178	WRITE(4, rbug_block_t, step); /* step */
179
180	/* final pad */
181	PAD(__pos, 8);
182
183	if (__pos != __len) {
184		__ret = -EINVAL;
185	} else {
186		rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_STEP, __len);
187		rbug_connection_write(__con, __data, __len);
188		__ret = rbug_connection_send_finish(__con, __serial);
189	}
190
191	FREE(__data);
192	return __ret;
193}
194
195int rbug_send_context_draw_unblock(struct rbug_connection *__con,
196                                   rbug_context_t context,
197                                   rbug_block_t unblock,
198                                   uint32_t *__serial)
199{
200	uint32_t __len = 0;
201	uint32_t __pos = 0;
202	uint8_t *__data = NULL;
203	int __ret = 0;
204
205	LEN(8); /* header */
206	LEN(8); /* context */
207	LEN(4); /* unblock */
208
209	/* align */
210	PAD(__len, 8);
211
212	__data = (uint8_t*)MALLOC(__len);
213	if (!__data)
214		return -ENOMEM;
215
216	WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_UNBLOCK));
217	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
218	WRITE(8, rbug_context_t, context); /* context */
219	WRITE(4, rbug_block_t, unblock); /* unblock */
220
221	/* final pad */
222	PAD(__pos, 8);
223
224	if (__pos != __len) {
225		__ret = -EINVAL;
226	} else {
227		rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_UNBLOCK, __len);
228		rbug_connection_write(__con, __data, __len);
229		__ret = rbug_connection_send_finish(__con, __serial);
230	}
231
232	FREE(__data);
233	return __ret;
234}
235
236int rbug_send_context_draw_rule(struct rbug_connection *__con,
237                                rbug_context_t context,
238                                rbug_shader_t vertex,
239                                rbug_shader_t fragment,
240                                rbug_texture_t texture,
241                                rbug_texture_t surface,
242                                rbug_block_t block,
243                                uint32_t *__serial)
244{
245	uint32_t __len = 0;
246	uint32_t __pos = 0;
247	uint8_t *__data = NULL;
248	int __ret = 0;
249
250	LEN(8); /* header */
251	LEN(8); /* context */
252	LEN(8); /* vertex */
253	LEN(8); /* fragment */
254	LEN(8); /* texture */
255	LEN(8); /* surface */
256	LEN(4); /* block */
257
258	/* align */
259	PAD(__len, 8);
260
261	__data = (uint8_t*)MALLOC(__len);
262	if (!__data)
263		return -ENOMEM;
264
265	WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_RULE));
266	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
267	WRITE(8, rbug_context_t, context); /* context */
268	WRITE(8, rbug_shader_t, vertex); /* vertex */
269	WRITE(8, rbug_shader_t, fragment); /* fragment */
270	WRITE(8, rbug_texture_t, texture); /* texture */
271	WRITE(8, rbug_texture_t, surface); /* surface */
272	WRITE(4, rbug_block_t, block); /* block */
273
274	/* final pad */
275	PAD(__pos, 8);
276
277	if (__pos != __len) {
278		__ret = -EINVAL;
279	} else {
280		rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_RULE, __len);
281		rbug_connection_write(__con, __data, __len);
282		__ret = rbug_connection_send_finish(__con, __serial);
283	}
284
285	FREE(__data);
286	return __ret;
287}
288
289int rbug_send_context_flush(struct rbug_connection *__con,
290                            rbug_context_t context,
291                            uint32_t *__serial)
292{
293	uint32_t __len = 0;
294	uint32_t __pos = 0;
295	uint8_t *__data = NULL;
296	int __ret = 0;
297
298	LEN(8); /* header */
299	LEN(8); /* context */
300
301	/* align */
302	PAD(__len, 8);
303
304	__data = (uint8_t*)MALLOC(__len);
305	if (!__data)
306		return -ENOMEM;
307
308	WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_FLUSH));
309	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
310	WRITE(8, rbug_context_t, context); /* context */
311
312	/* final pad */
313	PAD(__pos, 8);
314
315	if (__pos != __len) {
316		__ret = -EINVAL;
317	} else {
318		rbug_connection_send_start(__con, RBUG_OP_CONTEXT_FLUSH, __len);
319		rbug_connection_write(__con, __data, __len);
320		__ret = rbug_connection_send_finish(__con, __serial);
321	}
322
323	FREE(__data);
324	return __ret;
325}
326
327int rbug_send_context_list_reply(struct rbug_connection *__con,
328                                 uint32_t serial,
329                                 rbug_context_t *contexts,
330                                 uint32_t contexts_len,
331                                 uint32_t *__serial)
332{
333	uint32_t __len = 0;
334	uint32_t __pos = 0;
335	uint8_t *__data = NULL;
336	int __ret = 0;
337
338	LEN(8); /* header */
339	LEN(4); /* serial */
340	LEN_ARRAY(8, contexts); /* contexts */
341
342	/* align */
343	PAD(__len, 8);
344
345	__data = (uint8_t*)MALLOC(__len);
346	if (!__data)
347		return -ENOMEM;
348
349	WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_LIST_REPLY));
350	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
351	WRITE(4, uint32_t, serial); /* serial */
352	WRITE_ARRAY(8, rbug_context_t, contexts); /* contexts */
353
354	/* final pad */
355	PAD(__pos, 8);
356
357	if (__pos != __len) {
358		__ret = -EINVAL;
359	} else {
360		rbug_connection_send_start(__con, RBUG_OP_CONTEXT_LIST_REPLY, __len);
361		rbug_connection_write(__con, __data, __len);
362		__ret = rbug_connection_send_finish(__con, __serial);
363	}
364
365	FREE(__data);
366	return __ret;
367}
368
369int rbug_send_context_info_reply(struct rbug_connection *__con,
370                                 uint32_t serial,
371                                 rbug_shader_t vertex,
372                                 rbug_shader_t fragment,
373                                 rbug_texture_t *texs,
374                                 uint32_t texs_len,
375                                 rbug_texture_t *cbufs,
376                                 uint32_t cbufs_len,
377                                 rbug_texture_t zsbuf,
378                                 rbug_block_t blocker,
379                                 rbug_block_t blocked,
380                                 uint32_t *__serial)
381{
382	uint32_t __len = 0;
383	uint32_t __pos = 0;
384	uint8_t *__data = NULL;
385	int __ret = 0;
386
387	LEN(8); /* header */
388	LEN(4); /* serial */
389	LEN(8); /* vertex */
390	LEN(8); /* fragment */
391	LEN_ARRAY(8, texs); /* texs */
392	LEN_ARRAY(8, cbufs); /* cbufs */
393	LEN(8); /* zsbuf */
394	LEN(4); /* blocker */
395	LEN(4); /* blocked */
396
397	/* align */
398	PAD(__len, 8);
399
400	__data = (uint8_t*)MALLOC(__len);
401	if (!__data)
402		return -ENOMEM;
403
404	WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_INFO_REPLY));
405	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
406	WRITE(4, uint32_t, serial); /* serial */
407	WRITE(8, rbug_shader_t, vertex); /* vertex */
408	WRITE(8, rbug_shader_t, fragment); /* fragment */
409	WRITE_ARRAY(8, rbug_texture_t, texs); /* texs */
410	WRITE_ARRAY(8, rbug_texture_t, cbufs); /* cbufs */
411	WRITE(8, rbug_texture_t, zsbuf); /* zsbuf */
412	WRITE(4, rbug_block_t, blocker); /* blocker */
413	WRITE(4, rbug_block_t, blocked); /* blocked */
414
415	/* final pad */
416	PAD(__pos, 8);
417
418	if (__pos != __len) {
419		__ret = -EINVAL;
420	} else {
421		rbug_connection_send_start(__con, RBUG_OP_CONTEXT_INFO_REPLY, __len);
422		rbug_connection_write(__con, __data, __len);
423		__ret = rbug_connection_send_finish(__con, __serial);
424	}
425
426	FREE(__data);
427	return __ret;
428}
429
430int rbug_send_context_draw_blocked(struct rbug_connection *__con,
431                                   rbug_context_t context,
432                                   rbug_block_t block,
433                                   uint32_t *__serial)
434{
435	uint32_t __len = 0;
436	uint32_t __pos = 0;
437	uint8_t *__data = NULL;
438	int __ret = 0;
439
440	LEN(8); /* header */
441	LEN(8); /* context */
442	LEN(4); /* block */
443
444	/* align */
445	PAD(__len, 8);
446
447	__data = (uint8_t*)MALLOC(__len);
448	if (!__data)
449		return -ENOMEM;
450
451	WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_BLOCKED));
452	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
453	WRITE(8, rbug_context_t, context); /* context */
454	WRITE(4, rbug_block_t, block); /* block */
455
456	/* final pad */
457	PAD(__pos, 8);
458
459	if (__pos != __len) {
460		__ret = -EINVAL;
461	} else {
462		rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_BLOCKED, __len);
463		rbug_connection_write(__con, __data, __len);
464		__ret = rbug_connection_send_finish(__con, __serial);
465	}
466
467	FREE(__data);
468	return __ret;
469}
470
471struct rbug_proto_context_list * rbug_demarshal_context_list(struct rbug_proto_header *header)
472{
473	struct rbug_proto_context_list *ret;
474
475	if (!header)
476		return NULL;
477	if (header->opcode != (int32_t)RBUG_OP_CONTEXT_LIST)
478		return NULL;
479
480	ret = MALLOC(sizeof(*ret));
481	if (!ret)
482		return NULL;
483
484	ret->header.__message = header;
485	ret->header.opcode = header->opcode;
486
487	return ret;
488}
489
490struct rbug_proto_context_info * rbug_demarshal_context_info(struct rbug_proto_header *header)
491{
492	uint32_t len = 0;
493	uint32_t pos = 0;
494	uint8_t *data =  NULL;
495	struct rbug_proto_context_info *ret;
496
497	if (!header)
498		return NULL;
499	if (header->opcode != (int32_t)RBUG_OP_CONTEXT_INFO)
500		return NULL;
501
502	pos = 0;
503	len = header->length * 4;
504	data = (uint8_t*)&header[1];
505	ret = MALLOC(sizeof(*ret));
506	if (!ret)
507		return NULL;
508
509	ret->header.__message = header;
510	ret->header.opcode = header->opcode;
511
512	READ(8, rbug_context_t, context); /* context */
513
514	return ret;
515}
516
517struct rbug_proto_context_draw_block * rbug_demarshal_context_draw_block(struct rbug_proto_header *header)
518{
519	uint32_t len = 0;
520	uint32_t pos = 0;
521	uint8_t *data =  NULL;
522	struct rbug_proto_context_draw_block *ret;
523
524	if (!header)
525		return NULL;
526	if (header->opcode != (int32_t)RBUG_OP_CONTEXT_DRAW_BLOCK)
527		return NULL;
528
529	pos = 0;
530	len = header->length * 4;
531	data = (uint8_t*)&header[1];
532	ret = MALLOC(sizeof(*ret));
533	if (!ret)
534		return NULL;
535
536	ret->header.__message = header;
537	ret->header.opcode = header->opcode;
538
539	READ(8, rbug_context_t, context); /* context */
540	READ(4, rbug_block_t, block); /* block */
541
542	return ret;
543}
544
545struct rbug_proto_context_draw_step * rbug_demarshal_context_draw_step(struct rbug_proto_header *header)
546{
547	uint32_t len = 0;
548	uint32_t pos = 0;
549	uint8_t *data =  NULL;
550	struct rbug_proto_context_draw_step *ret;
551
552	if (!header)
553		return NULL;
554	if (header->opcode != (int32_t)RBUG_OP_CONTEXT_DRAW_STEP)
555		return NULL;
556
557	pos = 0;
558	len = header->length * 4;
559	data = (uint8_t*)&header[1];
560	ret = MALLOC(sizeof(*ret));
561	if (!ret)
562		return NULL;
563
564	ret->header.__message = header;
565	ret->header.opcode = header->opcode;
566
567	READ(8, rbug_context_t, context); /* context */
568	READ(4, rbug_block_t, step); /* step */
569
570	return ret;
571}
572
573struct rbug_proto_context_draw_unblock * rbug_demarshal_context_draw_unblock(struct rbug_proto_header *header)
574{
575	uint32_t len = 0;
576	uint32_t pos = 0;
577	uint8_t *data =  NULL;
578	struct rbug_proto_context_draw_unblock *ret;
579
580	if (!header)
581		return NULL;
582	if (header->opcode != (int32_t)RBUG_OP_CONTEXT_DRAW_UNBLOCK)
583		return NULL;
584
585	pos = 0;
586	len = header->length * 4;
587	data = (uint8_t*)&header[1];
588	ret = MALLOC(sizeof(*ret));
589	if (!ret)
590		return NULL;
591
592	ret->header.__message = header;
593	ret->header.opcode = header->opcode;
594
595	READ(8, rbug_context_t, context); /* context */
596	READ(4, rbug_block_t, unblock); /* unblock */
597
598	return ret;
599}
600
601struct rbug_proto_context_draw_rule * rbug_demarshal_context_draw_rule(struct rbug_proto_header *header)
602{
603	uint32_t len = 0;
604	uint32_t pos = 0;
605	uint8_t *data =  NULL;
606	struct rbug_proto_context_draw_rule *ret;
607
608	if (!header)
609		return NULL;
610	if (header->opcode != (int32_t)RBUG_OP_CONTEXT_DRAW_RULE)
611		return NULL;
612
613	pos = 0;
614	len = header->length * 4;
615	data = (uint8_t*)&header[1];
616	ret = MALLOC(sizeof(*ret));
617	if (!ret)
618		return NULL;
619
620	ret->header.__message = header;
621	ret->header.opcode = header->opcode;
622
623	READ(8, rbug_context_t, context); /* context */
624	READ(8, rbug_shader_t, vertex); /* vertex */
625	READ(8, rbug_shader_t, fragment); /* fragment */
626	READ(8, rbug_texture_t, texture); /* texture */
627	READ(8, rbug_texture_t, surface); /* surface */
628	READ(4, rbug_block_t, block); /* block */
629
630	return ret;
631}
632
633struct rbug_proto_context_flush * rbug_demarshal_context_flush(struct rbug_proto_header *header)
634{
635	uint32_t len = 0;
636	uint32_t pos = 0;
637	uint8_t *data =  NULL;
638	struct rbug_proto_context_flush *ret;
639
640	if (!header)
641		return NULL;
642	if (header->opcode != (int32_t)RBUG_OP_CONTEXT_FLUSH)
643		return NULL;
644
645	pos = 0;
646	len = header->length * 4;
647	data = (uint8_t*)&header[1];
648	ret = MALLOC(sizeof(*ret));
649	if (!ret)
650		return NULL;
651
652	ret->header.__message = header;
653	ret->header.opcode = header->opcode;
654
655	READ(8, rbug_context_t, context); /* context */
656
657	return ret;
658}
659
660struct rbug_proto_context_list_reply * rbug_demarshal_context_list_reply(struct rbug_proto_header *header)
661{
662	uint32_t len = 0;
663	uint32_t pos = 0;
664	uint8_t *data =  NULL;
665	struct rbug_proto_context_list_reply *ret;
666
667	if (!header)
668		return NULL;
669	if (header->opcode != (int32_t)RBUG_OP_CONTEXT_LIST_REPLY)
670		return NULL;
671
672	pos = 0;
673	len = header->length * 4;
674	data = (uint8_t*)&header[1];
675	ret = MALLOC(sizeof(*ret));
676	if (!ret)
677		return NULL;
678
679	ret->header.__message = header;
680	ret->header.opcode = header->opcode;
681
682	READ(4, uint32_t, serial); /* serial */
683	READ_ARRAY(8, rbug_context_t, contexts); /* contexts */
684
685	return ret;
686}
687
688struct rbug_proto_context_info_reply * rbug_demarshal_context_info_reply(struct rbug_proto_header *header)
689{
690	uint32_t len = 0;
691	uint32_t pos = 0;
692	uint8_t *data =  NULL;
693	struct rbug_proto_context_info_reply *ret;
694
695	if (!header)
696		return NULL;
697	if (header->opcode != (int32_t)RBUG_OP_CONTEXT_INFO_REPLY)
698		return NULL;
699
700	pos = 0;
701	len = header->length * 4;
702	data = (uint8_t*)&header[1];
703	ret = MALLOC(sizeof(*ret));
704	if (!ret)
705		return NULL;
706
707	ret->header.__message = header;
708	ret->header.opcode = header->opcode;
709
710	READ(4, uint32_t, serial); /* serial */
711	READ(8, rbug_shader_t, vertex); /* vertex */
712	READ(8, rbug_shader_t, fragment); /* fragment */
713	READ_ARRAY(8, rbug_texture_t, texs); /* texs */
714	READ_ARRAY(8, rbug_texture_t, cbufs); /* cbufs */
715	READ(8, rbug_texture_t, zsbuf); /* zsbuf */
716	READ(4, rbug_block_t, blocker); /* blocker */
717	READ(4, rbug_block_t, blocked); /* blocked */
718
719	return ret;
720}
721
722struct rbug_proto_context_draw_blocked * rbug_demarshal_context_draw_blocked(struct rbug_proto_header *header)
723{
724	uint32_t len = 0;
725	uint32_t pos = 0;
726	uint8_t *data =  NULL;
727	struct rbug_proto_context_draw_blocked *ret;
728
729	if (!header)
730		return NULL;
731	if (header->opcode != (int32_t)RBUG_OP_CONTEXT_DRAW_BLOCKED)
732		return NULL;
733
734	pos = 0;
735	len = header->length * 4;
736	data = (uint8_t*)&header[1];
737	ret = MALLOC(sizeof(*ret));
738	if (!ret)
739		return NULL;
740
741	ret->header.__message = header;
742	ret->header.opcode = header->opcode;
743
744	READ(8, rbug_context_t, context); /* context */
745	READ(4, rbug_block_t, block); /* block */
746
747	return ret;
748}
749