- added src/endian.h... still need to add configure support to
[barry.git] / src / protostructs.h
blobb5bb1e8b5910a7d121a0938fd773940451403dc5
1 ///
2 /// \file protostructs.h
3 /// USB Blackberry bulk protocol API. This is split out from
4 /// protocol.h so that low level, packed structs can be
5 /// compiled separately from the application. This prevents
6 /// aliasing problems in the application, or using
7 /// -fno-strict-aliasing, which the library only needs.
8 ///
11 Copyright (C) 2005-2006, Net Direct Inc. (http://www.netdirect.ca/)
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 See the GNU General Public License in the COPYING file at the
23 root directory of this project for more details.
26 #ifndef __BARRY_PROTOSTRUCTS_H__
27 #define __BARRY_PROTOSTRUCTS_H__
29 #include <stdint.h>
30 #include <sys/types.h>
32 // forward declarations
33 class Data;
35 namespace Barry {
37 ///////////////////////////////////////////////////////////////////////////////
38 union SizePacket
40 uint16_t size;
41 char buffer[4];
42 } __attribute__ ((packed));
44 ///////////////////////////////////////////////////////////////////////////////
45 struct SocketCommand
47 uint16_t socket;
48 uint8_t param;
49 } __attribute__ ((packed));
51 ///////////////////////////////////////////////////////////////////////////////
52 struct SequenceCommand
54 uint8_t unknown1;
55 uint8_t unknown2;
56 uint8_t unknown3;
57 uint32_t sequenceId;
58 } __attribute__ ((packed));
60 ///////////////////////////////////////////////////////////////////////////////
61 struct ModeSelectCommand
63 uint16_t socket;
64 uint8_t flag;
65 uint8_t modeName[16];
66 struct ResponseBlock
68 uint8_t unknown[20];
69 } __attribute__ ((packed)) response;
70 } __attribute__ ((packed));
72 ///////////////////////////////////////////////////////////////////////////////
73 struct DBCommand
75 uint8_t operation; // see below
76 uint16_t databaseId; // value from the Database Database
77 uint8_t data[1];
78 } __attribute__ ((packed));
79 #define DB_COMMAND_HEADER_SIZE (sizeof(Barry::DBCommand) - 1)
81 struct DBResponse
83 uint8_t operation;
84 uint32_t unknown;
85 uint16_t count;
86 uint8_t data[1];
87 } __attribute__ ((packed));
88 #define DB_RESPONSE_HEADER_SIZE (sizeof(Barry::DBResponse) - 1)
90 struct OldDBResponse
92 uint8_t operation;
93 uint8_t unknown;
94 uint16_t count;
95 uint8_t data[1];
96 } __attribute__ ((packed));
97 #define OLD_DB_RESPONSE_HEADER_SIZE (sizeof(Barry::OldDBResponse) - 1)
99 struct UploadCommand
101 uint8_t operation;
102 uint16_t databaseId; // value from the Database Database
103 uint8_t unknown; // observed: 00 or 05
104 uint8_t data[1];
105 } __attribute__ ((packed));
106 #define UPLOAD_HEADER_SIZE (sizeof(Barry::UploadCommand) - 1)
110 ///////////////////////////////////////////////////////////////////////////////
111 // CommandTable command and field structures
113 struct CommandTableField
115 uint8_t size; // no null terminator
116 uint8_t code;
117 uint8_t name[1];
118 } __attribute__ ((packed));
120 #define COMMAND_FIELD_HEADER_SIZE (sizeof(Barry::CommandTableField) - 1)
124 ///////////////////////////////////////////////////////////////////////////////
125 // Database database command and field structures
127 struct OldDBDBField
129 uint16_t dbNumber;
130 uint8_t unknown1;
131 uint32_t dbSize; // assumed from Cassis docs...
132 // always 0 in USB
133 uint16_t dbRecordCount;
134 uint16_t unknown2;
135 uint16_t nameSize; // includes null terminator
136 uint8_t name[1];
137 } __attribute__ ((packed));
138 #define OLD_DBDB_FIELD_HEADER_SIZE (sizeof(Barry::OldDBDBField) - 1)
140 struct DBDBField
142 uint16_t dbNumber;
143 uint8_t unknown1;
144 uint32_t dbSize; // assumed from Cassis docs...
145 // always 0 in USB
146 uint32_t dbRecordCount;
147 uint16_t unknown2;
148 uint16_t nameSize; // includes null terminator
149 uint8_t unknown3;
150 uint8_t name[1]; // followed by 2 zeros!
151 uint16_t unknown; // this comes after the
152 // null terminated name, but
153 // is here for size calcs
154 } __attribute__ ((packed));
155 #define DBDB_FIELD_HEADER_SIZE (sizeof(Barry::DBDBField) - 1)
157 struct OldDBDBRecord
159 uint8_t operation;
160 uint16_t count; // number of fields in record
161 OldDBDBField field[1];
162 } __attribute__ ((packed));
163 #define OLD_DBDB_RECORD_HEADER_SIZE (sizeof(Barry::OldDBDBRecord) - sizeof(Barry::OldDBDBField))
165 struct DBDBRecord
167 uint8_t operation;
168 uint16_t count;
169 uint8_t unknown[3];
170 DBDBField field[1];
171 } __attribute__ ((packed));
172 #define DBDB_RECORD_HEADER_SIZE (sizeof(Barry::DBDBRecord) - sizeof(Barry::DBDBField))
177 ///////////////////////////////////////////////////////////////////////////////
178 // Address book sub-field structs
180 struct GroupLink
182 uint32_t uniqueId;
183 uint16_t unknown;
184 } __attribute__ ((packed));
187 ///////////////////////////////////////////////////////////////////////////////
188 // Message sub-field structs
190 struct MessageAddress
192 uint8_t unknown[8];
193 uint8_t addr[1]; // 2 null terminated strings: first
194 // contains full name, second contains
195 // the email address
196 } __attribute__ ((packed));
202 ///////////////////////////////////////////////////////////////////////////////
203 // Common database field structure
205 union CommonFieldData
207 GroupLink link;
208 MessageAddress addr;
209 int32_t min1900;
210 uint8_t raw[1];
212 } __attribute__ ((packed));
214 struct CommonField
216 uint16_t size; // including null terminator
217 uint8_t type;
218 CommonFieldData u;
219 } __attribute__ ((packed));
220 #define COMMON_FIELD_HEADER_SIZE (sizeof(Barry::CommonField) - sizeof(Barry::CommonFieldData))
221 #define COMMON_FIELD_MIN1900_SIZE (sizeof(int32_t))
224 ///////////////////////////////////////////////////////////////////////////////
225 // Packed field structures
227 struct PackedField_02
229 uint8_t code;
230 uint8_t size;
231 uint8_t type;
232 uint8_t raw[1];
233 } __attribute__ ((packed));
234 #define PACKED_FIELD_02_HEADER_SIZE (sizeof(Barry::PackedField_02) - 1)
236 struct PackedField_10
238 uint8_t type;
239 uint8_t size;
240 uint8_t raw[1];
241 } __attribute__ ((packed));
242 #define PACKED_FIELD_10_HEADER_SIZE (sizeof(Barry::PackedField_10) - 1)
245 ///////////////////////////////////////////////////////////////////////////////
246 // Address book / Contact record data
248 struct OldContactRecord
250 uint32_t uniqueId;
251 uint8_t unknown;
252 CommonField field[1];
253 } __attribute__ ((packed));
254 #define OLD_CONTACT_RECORD_HEADER_SIZE (sizeof(Barry::OldContactRecord) - sizeof(Barry::CommonField))
256 struct ContactRecord
258 uint32_t uniqueId;
259 uint8_t unknown[3];
260 CommonField field[1];
261 } __attribute__ ((packed));
262 #define CONTACT_RECORD_HEADER_SIZE (sizeof(Barry::ContactRecord) - sizeof(Barry::CommonField))
265 ///////////////////////////////////////////////////////////////////////////////
266 // Message field and record structures
268 struct OldMessageRecord
270 uint8_t timeBlock[0x72];
271 CommonField field[1];
272 } __attribute__ ((packed));
274 struct MessageRecord
276 uint8_t timeBlock[0x74];
277 CommonField field[1];
278 } __attribute__ ((packed));
282 ///////////////////////////////////////////////////////////////////////////////
283 // Calendar field and record structures
285 struct OldCalendarRecord
287 uint32_t uniqueId;
288 uint8_t unknown; // observed as 0 or 1
289 CommonField field[1];
290 } __attribute__ ((packed));
291 #define OLD_CALENDAR_RECORD_HEADER_SIZE (sizeof(Barry::OldCalendarRecord) - sizeof(Barry::CommonField))
293 struct CalendarRecord
295 // FIXME - not yet implemented
296 CommonField field[1];
297 } __attribute__ ((packed));
298 //#define CALENDAR_RECORD_HEADER_SIZE (sizeof(Barry::CalendarRecord) - sizeof(Barry::CommonField))
302 ///////////////////////////////////////////////////////////////////////////////
303 // Service Book field and record structures
305 struct ServiceBookConfigField
307 uint8_t format;
308 uint8_t fields[1];
309 } __attribute__ ((packed));
311 struct OldServiceBookRecord
313 uint32_t uniqueId;
314 uint8_t unknown;
315 CommonField field[1];
316 } __attribute__ ((packed));
317 #define OLD_SERVICE_BOOK_RECORD_HEADER_SIZE (sizeof(Barry::OldServiceBookRecord) - sizeof(Barry::CommonField))
321 ///////////////////////////////////////////////////////////////////////////////
322 // Database access command structure
324 // even fragmented packets have a tableCmd
325 struct DBAccess
327 uint8_t tableCmd;
328 union DBData
330 DBCommand command;
331 DBResponse response;
332 OldDBResponse old_response;
333 UploadCommand upload;
334 CommandTableField table[1];
335 OldDBDBRecord old_dbdb;
336 DBDBRecord dbdb;
337 uint8_t return_code;
339 uint8_t fragment[1];
341 } __attribute__ ((packed)) u;
342 } __attribute__ ((packed));
346 ///////////////////////////////////////////////////////////////////////////////
347 // Main packet struct
349 struct Packet
351 uint16_t socket; // socket ID... 0 is always there
352 uint16_t size; // total size of data packet
353 uint8_t command;
355 union PacketData
358 SocketCommand socket;
359 SequenceCommand sequence;
360 ModeSelectCommand mode;
361 DBAccess db;
362 uint8_t raw[1];
364 } __attribute__ ((packed)) u;
365 } __attribute__ ((packed));
367 // minimum required sizes for various responses
368 #define MIN_PACKET_SIZE 6
371 // maximum sizes
372 #define MAX_PACKET_SIZE 0x400 // anything beyond this needs to be
373 // fragmented
374 // various useful sizes
375 #define SB_PACKET_HEADER_SIZE (sizeof(Barry::Packet) - sizeof(Barry::Packet::PacketData))
376 #define SB_DBACCESS_HEADER_SIZE (sizeof(Barry::DBAccess) - sizeof(Barry::DBAccess::DBData))
377 #define SB_PACKET_DBACCESS_HEADER_SIZE (SB_PACKET_HEADER_SIZE + SB_DBACCESS_HEADER_SIZE)
379 #define SB_FRAG_HEADER_SIZE SB_PACKET_DBACCESS_HEADER_SIZE
380 #define SB_SEQUENCE_PACKET_SIZE (SB_PACKET_HEADER_SIZE + sizeof(Barry::SequenceCommand))
381 #define SB_SOCKET_PACKET_SIZE (SB_PACKET_HEADER_SIZE + sizeof(Barry::SocketCommand))
382 #define SB_MODE_PACKET_COMMAND_SIZE (SB_PACKET_HEADER_SIZE + sizeof(Barry::ModeSelectCommand) - sizeof(Barry::ModeSelectCommand::ResponseBlock))
383 #define SB_MODE_PACKET_RESPONSE_SIZE (SB_PACKET_HEADER_SIZE + sizeof(Barry::ModeSelectCommand))
384 #define SB_PACKET_DBDB_HEADER_SIZE (SB_PACKET_HEADER_SIZE + SB_DBACCESS_HEADER_SIZE + DBDB_RECORD_HEADER_SIZE)
385 #define SB_PACKET_OLD_DBDB_HEADER_SIZE (SB_PACKET_HEADER_SIZE + SB_DBACCESS_HEADER_SIZE + OLD_DBDB_RECORD_HEADER_SIZE)
387 #define SB_PACKET_RESPONSE_HEADER_SIZE (SB_PACKET_DBACCESS_HEADER_SIZE + DB_RESPONSE_HEADER_SIZE)
388 #define SB_PACKET_OLD_RESPONSE_HEADER_SIZE (SB_PACKET_DBACCESS_HEADER_SIZE + OLD_DB_RESPONSE_HEADER_SIZE)
389 #define SB_PACKET_UPLOAD_HEADER_SIZE (SB_PACKET_DBACCESS_HEADER_SIZE + UPLOAD_HEADER_SIZE)
393 // Macros
394 #define COMMAND(data) (((const Barry::Packet *)data.GetData())->command)
395 #define IS_COMMAND(data, cmd) (COMMAND(data) == cmd)
396 #define MAKE_PACKET(var, data) const Barry::Packet *var = (const Barry::Packet *) data.GetData()
397 #define MAKE_PACKETPTR_BUF(var, ptr) Barry::Packet *var = (Barry::Packet *)ptr
398 #define MAKE_RECORD(type,var,data,off) type *var = (type *) (data.GetData() + (off))
399 #define MAKE_RECORD_PTR(type,var,data,off) type *var = (type *) (data + (off))
401 // fragmentation protocol
402 // send DATA first, then keep sending DATA packets, FRAGMENTing
403 // as required until finished, then send DONE. Both sides behave
404 // this way, so different sized data can be sent in both
405 // directions
407 // the fragmented piece only has a the param header, and then continues
408 // right on with the data
412 // checks packet size and throws BError if not right
413 void CheckSize(const Data &packet, size_t requiredsize = MIN_PACKET_SIZE);
415 } // namespace Barry
417 #endif