bluetooth 1.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -0,0 +1,4 @@
1
+ === 1.0
2
+
3
+ * Major Enhancements
4
+ * Birthday
@@ -0,0 +1,21 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ ext/bluetooth/extconf.rb
6
+ ext/bluetooth/linux/ruby_bluetooth.c
7
+ ext/bluetooth/linux/ruby_bluetooth.h
8
+ ext/bluetooth/macosx/device.m
9
+ ext/bluetooth/macosx/error.m
10
+ ext/bluetooth/macosx/host_controller.m
11
+ ext/bluetooth/macosx/ruby_bluetooth.h
12
+ ext/bluetooth/macosx/ruby_bluetooth.m
13
+ ext/bluetooth/macosx/scan.m
14
+ ext/bluetooth/win32/ruby_bluetooth.cpp
15
+ ext/bluetooth/win32/ruby_bluetooth.h
16
+ lib/bluetooth.rb
17
+ lib/bluetooth/device.rb
18
+ sample/name.rb
19
+ sample/pair.rb
20
+ sample/quality.rb
21
+ sample/scan.rb
@@ -0,0 +1,20 @@
1
+ = ruby-bluetooth
2
+
3
+ * http://github.com/yaksnrainbows/ruby-bluetooth
4
+
5
+ == DESCRIPTION:
6
+
7
+ A bluetooth library for ruby
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Only known to work on OS X
12
+
13
+ == INSTALL:
14
+
15
+ gem install ruby-bluetooth
16
+
17
+ == LICENSE:
18
+
19
+ Unknown
20
+
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+ #require 'rake/extensiontask'
4
+
5
+ hoe = Hoe.spec 'bluetooth' do
6
+ developer 'Eric Hodel', 'drbrain@segment7.net'
7
+ developer 'Jeremie Castagna', ''
8
+ developer 'Esteve Fernandez', ''
9
+
10
+ extra_dev_deps << ['rake-compiler', '~> 0.6']
11
+
12
+ self.clean_globs = %w[
13
+ ext/bluetooth/Makefile
14
+ ext/bluetooth/mkmf.log
15
+ ext/bluetooth/bluetooth.bundle
16
+ ext/bluetooth/*.o
17
+ ]
18
+
19
+ self.spec_extras[:extensions] = 'ext/bluetooth/extconf.rb'
20
+ end
21
+
22
+ #Rake::ExtensionTask.new 'bluetooth' do |ext|
23
+ # ext.source_pattern = '*/*.{c,cpp,h,m}'
24
+ # ext.gem_spec = hoe.spec
25
+ #end
26
+ #
27
+ #task :test => :compile
28
+
@@ -0,0 +1,30 @@
1
+ require 'mkmf'
2
+
3
+ dir_config 'bluetooth'
4
+
5
+ name = case RUBY_PLATFORM
6
+ when /linux/ then
7
+ abort 'could not find bluetooth library' unless
8
+ have_library 'bluetooth'
9
+
10
+ 'linux'
11
+ when /(win32|mingw32)/
12
+ abort 'could not find Ws2bth.h' unless
13
+ find_header('Ws2bth.h', 'c:\archiv~1\micros~2\include')
14
+
15
+ 'win32'
16
+ when /darwin/ then
17
+ $LDFLAGS << ' -framework IOBluetooth'
18
+ 'macosx'
19
+ else
20
+ abort "unknown platform #{RUBY_PLATFORM}"
21
+ end
22
+
23
+ create_makefile 'bluetooth', name
24
+
25
+ if RUBY_PLATFORM =~ /darwin/ then
26
+ open 'Makefile', 'a' do |io|
27
+ io.write "\n.m.o:\n\t#{COMPILE_C}\n\n"
28
+ end
29
+ end
30
+
@@ -0,0 +1,539 @@
1
+ // Include the Ruby headers and goodies
2
+ #include <ruby.h>
3
+ #include <rubyio.h>
4
+ #include <rubysig.h>
5
+ #include <util.h>
6
+ #include "ruby_bluetooth.h"
7
+ #include <arpa/inet.h>
8
+
9
+ VALUE bt_module;
10
+ VALUE bt_devices_class;
11
+ VALUE bt_socket_class;
12
+ VALUE bt_rfcomm_socket_class;
13
+ VALUE bt_l2cap_socket_class;
14
+ VALUE bt_service_class;
15
+ VALUE bt_services_class;
16
+ VALUE bt_cBluetoothDevice;
17
+
18
+ // The initialization method for this module
19
+ void Init_bluetooth()
20
+ {
21
+ bt_module = rb_define_module("Bluetooth");
22
+
23
+ rb_define_singleton_method(bt_devices_class, "scan", bt_devices_scan, 0);
24
+ rb_undef_method(bt_devices_class, "initialize");
25
+
26
+ bt_socket_class = rb_define_class_under(bt_module, "BluetoothSocket", rb_cIO);
27
+ rb_define_method(bt_socket_class, "inspect", bt_socket_inspect, 0);
28
+ rb_define_method(bt_socket_class, "for_fd", bt_socket_s_for_fd, 1);
29
+ rb_define_method(bt_socket_class, "listen", bt_socket_listen, 1);
30
+ rb_define_method(bt_socket_class, "accept", bt_socket_accept, 0);
31
+ rb_undef_method(bt_socket_class, "initialize");
32
+
33
+ bt_rfcomm_socket_class = rb_define_class_under(bt_module, "RFCOMMSocket", bt_socket_class);
34
+ rb_define_method(bt_rfcomm_socket_class, "initialize", bt_rfcomm_socket_init, -1);
35
+ rb_define_method(bt_rfcomm_socket_class, "connect", bt_rfcomm_socket_connect, 2);
36
+ rb_define_method(bt_rfcomm_socket_class, "bind", bt_rfcomm_socket_bind, 1);
37
+
38
+ bt_l2cap_socket_class = rb_define_class_under(bt_module, "L2CAPSocket", bt_socket_class);
39
+ rb_define_method(bt_l2cap_socket_class, "initialize", bt_l2cap_socket_init, -1);
40
+ rb_define_method(bt_l2cap_socket_class, "connect", bt_l2cap_socket_connect, 2);
41
+ rb_define_method(bt_l2cap_socket_class, "bind", bt_l2cap_socket_bind, 1);
42
+
43
+ bt_services_class = rb_define_class_under(bt_module, "Services", rb_cObject);
44
+ //rb_define_singleton_method(bt_services_class, "scan", bt_services_scan, 3);
45
+ rb_undef_method(bt_services_class, "initialize");
46
+
47
+ bt_service_class = rb_define_class_under(bt_module, "Service", rb_cObject);
48
+ rb_define_singleton_method(bt_service_class, "new", bt_service_new, 4);
49
+ rb_define_method(bt_service_class, "register", bt_service_register, 1);
50
+ rb_define_method(bt_service_class, "unregister", bt_service_unregister, 0);
51
+ rb_define_attr(bt_service_class, "uuid", Qtrue, Qfalse);
52
+ rb_define_attr(bt_service_class, "name", Qtrue, Qfalse);
53
+ rb_define_attr(bt_service_class, "description", Qtrue, Qfalse);
54
+ rb_define_attr(bt_service_class, "provider", Qtrue, Qfalse);
55
+
56
+ rb_define_method(bt_service_class, "registered?", bt_service_registered, 0);
57
+
58
+ bt_cBluetoothDevice = rb_const_get(mBluetooth, rb_intern("Device"));
59
+ }
60
+
61
+ static VALUE bt_socket_accept(VALUE self) {
62
+ OpenFile *fptr;
63
+ VALUE sock2;
64
+ char buf[1024];
65
+ socklen_t len = sizeof(buf);
66
+
67
+ // struct sockaddr_rc rcaddr;
68
+ // addr_len = sizeof(rcaddr);
69
+
70
+ GetOpenFile(self, fptr);
71
+ //sock2 = s_accept(bt_socket_class, fileno(fptr->f), (struct sockaddr *)&rcaddr, &addr_len);
72
+ sock2 = s_accept(bt_socket_class, fileno(fptr->f), (struct sockaddr *)buf, &len);
73
+ return rb_assoc_new(sock2, rb_str_new(buf, len));
74
+ }
75
+
76
+
77
+ static VALUE
78
+ bt_socket_listen(sock, log)
79
+ VALUE sock, log;
80
+ {
81
+ OpenFile *fptr;
82
+ int backlog;
83
+
84
+ rb_secure(4);
85
+ backlog = NUM2INT(log);
86
+ GetOpenFile(sock, fptr);
87
+ if (listen(fileno(fptr->f), backlog) < 0)
88
+ rb_sys_fail("listen(2)");
89
+
90
+ return INT2FIX(0);
91
+ }
92
+
93
+
94
+ static VALUE bt_service_register(VALUE self, VALUE socket) {
95
+ VALUE registered = rb_iv_get(self, "@registered");
96
+ if (registered == Qfalse) {
97
+ VALUE port_v = rb_iv_get(socket, "@port");
98
+ if(Qnil == port_v) {
99
+ rb_raise (rb_eIOError, "a bound socket must be passed");
100
+ }
101
+
102
+ // uint32_t service_uuid_int[] = { 0, 0, 0, 0xABCD };
103
+ const char *service_name = STR2CSTR(rb_iv_get(self, "@name"));
104
+ const char *service_dsc = STR2CSTR(rb_iv_get(self, "@description"));
105
+ const char *service_prov = STR2CSTR(rb_iv_get(self, "@provider"));
106
+
107
+ uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid;
108
+ sdp_list_t *l2cap_list = 0,
109
+ *rfcomm_list = 0,
110
+ *root_list = 0,
111
+ *proto_list = 0,
112
+ *access_proto_list = 0;
113
+ sdp_data_t *channel = 0, *psm = 0;
114
+
115
+ sdp_record_t *record = sdp_record_alloc();
116
+
117
+ // set the general service ID
118
+ // sdp_uuid128_create( &svc_uuid, &service_uuid_int );
119
+ char *service_id = STR2CSTR(rb_iv_get(self, "@uuid"));
120
+ if(str2uuid(service_id, &svc_uuid) != 0) {
121
+ rb_raise (rb_eIOError, "a valid uuid must be passed");
122
+ }
123
+ sdp_set_service_id( record, svc_uuid );
124
+
125
+ // make the service record publicly browsable
126
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
127
+ root_list = sdp_list_append(0, &root_uuid);
128
+ sdp_set_browse_groups( record, root_list );
129
+
130
+ // set l2cap information
131
+ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
132
+ l2cap_list = sdp_list_append( 0, &l2cap_uuid );
133
+ if (bt_l2cap_socket_class == CLASS_OF(socket)) {
134
+ uint16_t l2cap_port = FIX2UINT(port_v);
135
+ psm = sdp_data_alloc(SDP_UINT16, &l2cap_port);
136
+ sdp_list_append(l2cap_list, psm);
137
+ }
138
+ proto_list = sdp_list_append( 0, l2cap_list );
139
+
140
+ // set rfcomm information
141
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
142
+ rfcomm_list = sdp_list_append( 0, &rfcomm_uuid );
143
+ if (bt_rfcomm_socket_class == CLASS_OF(socket)) {
144
+ uint16_t rfcomm_channel = FIX2UINT(port_v);
145
+ channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
146
+ sdp_list_append(rfcomm_list, channel);
147
+ }
148
+ sdp_list_append( proto_list, rfcomm_list );
149
+
150
+ // attach protocol information to service record
151
+ access_proto_list = sdp_list_append( 0, proto_list );
152
+ sdp_set_access_protos( record, access_proto_list );
153
+
154
+ // set the name, provider, and description
155
+ sdp_set_info_attr(record, service_name, service_prov, service_dsc);
156
+ int err = 0;
157
+ sdp_session_t *session = 0;
158
+
159
+ // connect to the local SDP server, register the service record, and
160
+ // disconnect
161
+ session = sdp_connect( BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY );
162
+ err = sdp_record_register(session, record, 0);
163
+
164
+ // cleanup
165
+ if (channel != 0) {
166
+ sdp_data_free( channel );
167
+ }
168
+ sdp_list_free( l2cap_list, 0 );
169
+ sdp_list_free( rfcomm_list, 0 );
170
+ sdp_list_free( root_list, 0 );
171
+ sdp_list_free( access_proto_list, 0 );
172
+
173
+ struct bluetooth_service_struct *bss;
174
+ Data_Get_Struct(self, struct bluetooth_service_struct, bss);
175
+ bss->session = session;
176
+ // Do something
177
+ rb_iv_set(self, "@registered", Qtrue);
178
+ }
179
+ return Qnil;
180
+ }
181
+
182
+ static VALUE bt_service_unregister(VALUE self) {
183
+ VALUE registered = rb_iv_get(self, "@registered");
184
+ if (registered == Qtrue) {
185
+ struct bluetooth_service_struct *bss;
186
+ Data_Get_Struct(self, struct bluetooth_service_struct, bss);
187
+ sdp_close(bss->session);
188
+ bss->session = NULL;
189
+ // Do something
190
+ rb_iv_set(self, "@registered", Qfalse);
191
+ }
192
+ return registered;
193
+ }
194
+
195
+ static VALUE bt_service_registered(VALUE self) {
196
+ VALUE registered = rb_iv_get(self, "@registered");
197
+ if (registered == Qtrue) {
198
+ // Do something
199
+ }
200
+ return registered;
201
+ }
202
+
203
+ static VALUE bt_service_new(VALUE self, VALUE uuid, VALUE name, VALUE description, VALUE provider) {
204
+ struct bluetooth_service_struct *bss;
205
+
206
+ VALUE obj = Data_Make_Struct(self,
207
+ struct bluetooth_service_struct, NULL,
208
+ free, bss);
209
+
210
+ rb_iv_set(obj, "@uuid", uuid);
211
+ rb_iv_set(obj, "@name", name);
212
+ rb_iv_set(obj, "@description", description);
213
+ rb_iv_set(obj, "@provider", provider);
214
+ rb_iv_set(obj, "@registered", Qfalse);
215
+
216
+ return obj;
217
+ }
218
+
219
+ static VALUE
220
+ bt_l2cap_socket_connect(VALUE self, VALUE host, VALUE port)
221
+ {
222
+ OpenFile *fptr;
223
+ int fd;
224
+
225
+ GetOpenFile(self, fptr);
226
+ fd = fileno(fptr->f);
227
+
228
+ struct sockaddr_l2 addr = { 0 };
229
+ char *dest = STR2CSTR(host);
230
+
231
+ // set the connection parameters (who to connect to)
232
+ addr.l2_family = AF_BLUETOOTH;
233
+ addr.l2_psm = (uint8_t) FIX2UINT(port);
234
+ str2ba( dest, &addr.l2_bdaddr );
235
+
236
+ // connect to server
237
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
238
+ rb_sys_fail("connect(2)");
239
+ }
240
+
241
+ return INT2FIX(0);
242
+ }
243
+
244
+ static VALUE
245
+ bt_rfcomm_socket_connect(VALUE self, VALUE host, VALUE port)
246
+ {
247
+ OpenFile *fptr;
248
+ int fd;
249
+
250
+ GetOpenFile(self, fptr);
251
+ fd = fileno(fptr->f);
252
+
253
+ struct sockaddr_rc addr = { 0 };
254
+ char *dest = STR2CSTR(host);
255
+
256
+ // set the connection parameters (who to connect to)
257
+ addr.rc_family = AF_BLUETOOTH;
258
+ addr.rc_channel = (uint8_t) FIX2UINT(port);
259
+ str2ba( dest, &addr.rc_bdaddr );
260
+
261
+ // connect to server
262
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
263
+ rb_sys_fail("connect(2)");
264
+ }
265
+
266
+ return INT2FIX(0);
267
+ }
268
+
269
+ static VALUE
270
+ bt_socket_s_for_fd(VALUE klass, VALUE fd)
271
+ {
272
+ OpenFile *fptr;
273
+ VALUE sock = bt_init_sock(rb_obj_alloc(klass), NUM2INT(fd));
274
+
275
+ GetOpenFile(sock, fptr);
276
+ return sock;
277
+ }
278
+
279
+ static VALUE
280
+ bt_rfcomm_socket_bind(VALUE self, VALUE port)
281
+ {
282
+ OpenFile *fptr;
283
+ int fd;
284
+
285
+ GetOpenFile(self, fptr);
286
+ fd = fileno(fptr->f);
287
+
288
+ struct sockaddr_rc loc_addr = { 0 };
289
+ loc_addr.rc_family = AF_BLUETOOTH;
290
+ loc_addr.rc_bdaddr = *BDADDR_ANY;
291
+ loc_addr.rc_channel = (uint8_t) FIX2UINT(port);
292
+
293
+ if (bind(fd, (struct sockaddr *)&loc_addr, sizeof(loc_addr)) >= 0)
294
+ rb_iv_set(self, "@port", port);
295
+ return INT2FIX(0);
296
+ }
297
+
298
+ static VALUE
299
+ bt_l2cap_socket_bind(VALUE self, VALUE port)
300
+ {
301
+ OpenFile *fptr;
302
+ int fd;
303
+
304
+ GetOpenFile(self, fptr);
305
+ fd = fileno(fptr->f);
306
+
307
+ struct sockaddr_l2 loc_addr = { 0 };
308
+ loc_addr.l2_family = AF_BLUETOOTH;
309
+ loc_addr.l2_bdaddr = *BDADDR_ANY;
310
+ loc_addr.l2_psm = (uint8_t) FIX2UINT(port);
311
+
312
+ if (bind(fd, (struct sockaddr *)&loc_addr, sizeof(loc_addr)) >= 0)
313
+ rb_iv_set(self, "@port", port);
314
+ return INT2FIX(0);
315
+ }
316
+
317
+ static VALUE bt_socket_inspect(VALUE self)
318
+ {
319
+ return self;
320
+ }
321
+
322
+ static int
323
+ bt_ruby_socket(int domain, int type, int proto)
324
+ {
325
+ int fd;
326
+
327
+ fd = socket(domain, type, proto);
328
+ if (fd < 0) {
329
+ if (errno == EMFILE || errno == ENFILE) {
330
+ rb_gc();
331
+ fd = socket(domain, type, proto);
332
+ }
333
+ }
334
+ return fd;
335
+ }
336
+
337
+ static VALUE
338
+ bt_init_sock(VALUE sock, int fd)
339
+ {
340
+ OpenFile *fp = NULL;
341
+
342
+ MakeOpenFile(sock, fp);
343
+
344
+ fp->f = rb_fdopen(fd, "r");
345
+ fp->f2 = rb_fdopen(fd, "w");
346
+ fp->mode = FMODE_READWRITE;
347
+
348
+ rb_io_synchronized(fp);
349
+
350
+ return sock;
351
+ }
352
+
353
+ // Initialization of a RFCOMM socket
354
+ static VALUE bt_rfcomm_socket_init(int argc, VALUE *argv, VALUE sock)
355
+ {
356
+ int fd = bt_ruby_socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
357
+ if (fd < 0) {
358
+ rb_sys_fail("socket(2) - bt");
359
+ }
360
+ VALUE ret = bt_init_sock(sock, fd);
361
+ return ret;
362
+ }
363
+
364
+ // Initialization of a L2CAP socket
365
+ static VALUE bt_l2cap_socket_init(int argc, VALUE *argv, VALUE sock)
366
+ {
367
+ int fd = bt_ruby_socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
368
+ if (fd < 0) {
369
+ rb_sys_fail("socket(2) - bt");
370
+ }
371
+ VALUE ret = bt_init_sock(sock, fd);
372
+ return ret;
373
+ }
374
+
375
+ // Scan local network for visible remote devices
376
+ static VALUE bt_devices_scan(VALUE self)
377
+ {
378
+ inquiry_info *ii = NULL;
379
+ int max_rsp, num_rsp;
380
+ int dev_id, sock, len, flags;
381
+ int i;
382
+
383
+ dev_id = hci_get_route(NULL);
384
+ sock = hci_open_dev( dev_id );
385
+ if (dev_id < 0 || sock < 0)
386
+ {
387
+ rb_raise (rb_eIOError, "error opening socket");
388
+ }
389
+
390
+ len = 8;
391
+ max_rsp = 255;
392
+ flags = IREQ_CACHE_FLUSH;
393
+ ii = (inquiry_info*)malloc(max_rsp * sizeof(inquiry_info));
394
+
395
+ num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
396
+ if( num_rsp < 0 )
397
+ rb_raise(rb_eIOError, "hci_inquiry");
398
+
399
+ VALUE devices_array = rb_ary_new();
400
+
401
+ // Iterate over every device found and add it to result array
402
+ for (i = 0; i < num_rsp; i++)
403
+ {
404
+ char addr[19] = { 0 };
405
+ char name[248] = { 0 };
406
+
407
+ ba2str(&(ii+i)->bdaddr, addr);
408
+ memset(name, 0, sizeof(name));
409
+ if (hci_read_remote_name(sock, &(ii+i)->bdaddr, sizeof(name),
410
+ name, 0) < 0)
411
+ strcpy(name, "(unknown)");
412
+
413
+ VALUE bt_dev = rb_funcall(bt_cBluetoothDevice, rb_intern("new"), 2,
414
+ rb_str_new(name), rb_str_new2(addr));
415
+
416
+ rb_ary_push(devices_array, bt_dev);
417
+ }
418
+
419
+ free( ii );
420
+ close( sock );
421
+ return devices_array;
422
+ }
423
+
424
+ static VALUE
425
+ s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len) {
426
+ int fd2;
427
+ int retry = 0;
428
+
429
+ rb_secure(3);
430
+ retry:
431
+ rb_thread_wait_fd(fd);
432
+ #if defined(_nec_ews)
433
+ fd2 = accept(fd, sockaddr, len);
434
+ #else
435
+ TRAP_BEG;
436
+ fd2 = accept(fd, sockaddr, len);
437
+ TRAP_END;
438
+ #endif
439
+ if (fd2 < 0) {
440
+ switch (errno) {
441
+ case EMFILE:
442
+ case ENFILE:
443
+ if (retry) break;
444
+ rb_gc();
445
+ retry = 1;
446
+ goto retry;
447
+ case EWOULDBLOCK:
448
+ break;
449
+ default:
450
+ if (!rb_io_wait_readable(fd)) break;
451
+ retry = 0;
452
+ goto retry;
453
+ }
454
+ rb_sys_fail(0);
455
+ }
456
+ if (!klass) return INT2NUM(fd2);
457
+ return bt_init_sock(rb_obj_alloc(klass), fd2);
458
+ }
459
+ // Code from PyBlueZ
460
+ int
461
+ str2uuid(char *uuid_str, uuid_t *uuid)
462
+ {
463
+ uint32_t uuid_int[4];
464
+ char *endptr;
465
+
466
+ if(strlen(uuid_str) == 36) {
467
+ // Parse uuid128 standard format: 12345678-9012-3456-7890-123456789012
468
+ char buf[9] = { 0 };
469
+
470
+ if(uuid_str[8] != '-' && uuid_str[13] != '-' &&
471
+ uuid_str[18] != '-' && uuid_str[23] != '-') {
472
+ return -1;
473
+ }
474
+ // first 8-bytes
475
+ strncpy(buf, uuid_str, 8);
476
+ uuid_int[0] = htonl(strtoul(buf, &endptr, 16));
477
+ if(endptr != buf + 8) return -1;
478
+
479
+ // second 8-bytes
480
+ strncpy(buf, uuid_str+9, 4);
481
+ strncpy(buf+4, uuid_str+14, 4);
482
+ uuid_int[1] = htonl(strtoul( buf, &endptr, 16));
483
+ if(endptr != buf + 8) return -1;
484
+
485
+ // third 8-bytes
486
+ strncpy(buf, uuid_str+19, 4);
487
+ strncpy(buf+4, uuid_str+24, 4);
488
+ uuid_int[2] = htonl(strtoul(buf, &endptr, 16));
489
+ if(endptr != buf + 8) return -1;
490
+
491
+ // fourth 8-bytes
492
+ strncpy(buf, uuid_str+28, 8);
493
+ uuid_int[3] = htonl(strtoul(buf, &endptr, 16));
494
+ if(endptr != buf + 8) return -1;
495
+
496
+ if(uuid != NULL) sdp_uuid128_create(uuid, uuid_int);
497
+ }
498
+
499
+ else if(strlen(uuid_str) == 8) {
500
+ // 32-bit reserved UUID
501
+ uint32_t i = strtoul(uuid_str, &endptr, 16);
502
+ if(endptr != uuid_str + 8) return -1;
503
+ if(uuid != NULL) sdp_uuid32_create(uuid, i);
504
+ }
505
+
506
+ else if(strlen(uuid_str) == 6) {
507
+ // 16-bit reserved UUID with 0x on front
508
+ if(uuid_str[0] == '0' && (uuid_str[1] == 'x' || uuid_str[1] == 'X')) {
509
+ // move chars up
510
+ uuid_str[0] = uuid_str[2];
511
+ uuid_str[1] = uuid_str[3];
512
+ uuid_str[2] = uuid_str[4];
513
+ uuid_str[3] = uuid_str[5];
514
+ uuid_str[4] = '\0';
515
+ int i = strtol(uuid_str, &endptr, 16);
516
+ if(endptr != uuid_str + 4) return -1;
517
+ if(uuid != NULL) sdp_uuid16_create(uuid, i);
518
+ }
519
+
520
+ else return(-1);
521
+ }
522
+
523
+ else if(strlen(uuid_str) == 4) {
524
+ // 16-bit reserved UUID
525
+ int i = strtol(uuid_str, &endptr, 16);
526
+ if(endptr != uuid_str + 4) return -1;
527
+ if(uuid != NULL) sdp_uuid16_create(uuid, i);
528
+ }
529
+
530
+ else {
531
+ return -1;
532
+ }
533
+
534
+ return 0;
535
+ }
536
+
537
+
538
+
539
+