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.
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__
30 #include <sys/types.h>
32 // forward declarations
37 ///////////////////////////////////////////////////////////////////////////////
42 } __attribute__ ((packed
));
44 ///////////////////////////////////////////////////////////////////////////////
49 } __attribute__ ((packed
));
51 ///////////////////////////////////////////////////////////////////////////////
52 struct SequenceCommand
58 } __attribute__ ((packed
));
60 ///////////////////////////////////////////////////////////////////////////////
61 struct ModeSelectCommand
69 } __attribute__ ((packed
)) response
;
70 } __attribute__ ((packed
));
72 ///////////////////////////////////////////////////////////////////////////////
75 uint8_t operation
; // see below
76 uint16_t databaseId
; // value from the Database Database
78 } __attribute__ ((packed
));
79 #define DB_COMMAND_HEADER_SIZE (sizeof(Barry::DBCommand) - 1)
87 } __attribute__ ((packed
));
88 #define DB_RESPONSE_HEADER_SIZE (sizeof(Barry::DBResponse) - 1)
96 } __attribute__ ((packed
));
97 #define OLD_DB_RESPONSE_HEADER_SIZE (sizeof(Barry::OldDBResponse) - 1)
102 uint16_t databaseId
; // value from the Database Database
103 uint8_t unknown
; // observed: 00 or 05
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
118 } __attribute__ ((packed
));
120 #define COMMAND_FIELD_HEADER_SIZE (sizeof(Barry::CommandTableField) - 1)
124 ///////////////////////////////////////////////////////////////////////////////
125 // Database database command and field structures
131 uint32_t dbSize
; // assumed from Cassis docs...
133 uint16_t dbRecordCount
;
135 uint16_t nameSize
; // includes null terminator
137 } __attribute__ ((packed
));
138 #define OLD_DBDB_FIELD_HEADER_SIZE (sizeof(Barry::OldDBDBField) - 1)
144 uint32_t dbSize
; // assumed from Cassis docs...
146 uint32_t dbRecordCount
;
148 uint16_t nameSize
; // includes null terminator
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)
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))
171 } __attribute__ ((packed
));
172 #define DBDB_RECORD_HEADER_SIZE (sizeof(Barry::DBDBRecord) - sizeof(Barry::DBDBField))
177 ///////////////////////////////////////////////////////////////////////////////
178 // Address book sub-field structs
184 } __attribute__ ((packed
));
187 ///////////////////////////////////////////////////////////////////////////////
188 // Message sub-field structs
190 struct MessageAddress
193 uint8_t addr
[1]; // 2 null terminated strings: first
194 // contains full name, second contains
196 } __attribute__ ((packed
));
202 ///////////////////////////////////////////////////////////////////////////////
203 // Common database field structure
205 union CommonFieldData
212 } __attribute__ ((packed
));
216 uint16_t size
; // including null terminator
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
233 } __attribute__ ((packed
));
234 #define PACKED_FIELD_02_HEADER_SIZE (sizeof(Barry::PackedField_02) - 1)
236 struct PackedField_10
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
252 CommonField field
[1];
253 } __attribute__ ((packed
));
254 #define OLD_CONTACT_RECORD_HEADER_SIZE (sizeof(Barry::OldContactRecord) - sizeof(Barry::CommonField))
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
));
276 uint8_t timeBlock
[0x74];
277 CommonField field
[1];
278 } __attribute__ ((packed
));
282 ///////////////////////////////////////////////////////////////////////////////
283 // Calendar field and record structures
285 struct OldCalendarRecord
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
309 } __attribute__ ((packed
));
311 struct OldServiceBookRecord
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
332 OldDBResponse old_response
;
333 UploadCommand upload
;
334 CommandTableField table
[1];
335 OldDBDBRecord old_dbdb
;
341 } __attribute__ ((packed
)) u
;
342 } __attribute__ ((packed
));
346 ///////////////////////////////////////////////////////////////////////////////
347 // Main packet struct
351 uint16_t socket
; // socket ID... 0 is always there
352 uint16_t size
; // total size of data packet
358 SocketCommand socket
;
359 SequenceCommand sequence
;
360 ModeSelectCommand mode
;
364 } __attribute__ ((packed
)) u
;
365 } __attribute__ ((packed
));
367 // minimum required sizes for various responses
368 #define MIN_PACKET_SIZE 6
372 #define MAX_PACKET_SIZE 0x400 // anything beyond this needs to be
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)
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
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
);