bluetooth 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+