Initialize Tizen 2.3
[framework/connectivity/bluez.git] / wearable / sap / server.c
1 /*
2  *  BlueZ - Bluetooth protocol stack for Linux
3  *
4  *  Copyright (C) 2010 Instituto Nokia de Tecnologia - INdT
5  *  Copyright (C) 2010 ST-Ericsson SA
6  *  Copyright (C) 2011 Tieto Poland
7  *
8  *  Author: Marek Skowron <marek.skowron@tieto.com> for ST-Ericsson.
9  *  Author: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
10  *          for ST-Ericsson.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30
31 #include <errno.h>
32 #include <glib.h>
33 #include <bluetooth/sdp.h>
34 #include <bluetooth/sdp_lib.h>
35 #include <bluetooth/uuid.h>
36
37 #include "adapter.h"
38 #include "btio.h"
39 #include "sdpd.h"
40 #include "log.h"
41 #include "error.h"
42 #include "dbus-common.h"
43 #include "sap.h"
44 #include "server.h"
45
46 #define SAP_SERVER_INTERFACE    "org.bluez.SimAccess"
47 #define SAP_SERVER_CHANNEL      8
48
49 #define PADDING4(x) ((4 - ((x) & 0x03)) & 0x03)
50 #define PARAMETER_SIZE(x) (sizeof(struct sap_parameter) + x + PADDING4(x))
51
52 #define SAP_NO_REQ 0xFF
53
54 #define SAP_TIMER_GRACEFUL_DISCONNECT 30
55 #define SAP_TIMER_NO_ACTIVITY 30
56
57 enum {
58         SAP_STATE_DISCONNECTED,
59         SAP_STATE_CONNECT_IN_PROGRESS,
60         SAP_STATE_CONNECT_MODEM_BUSY,
61         SAP_STATE_CONNECTED,
62         SAP_STATE_GRACEFUL_DISCONNECT,
63         SAP_STATE_IMMEDIATE_DISCONNECT,
64         SAP_STATE_CLIENT_DISCONNECT
65 };
66
67 struct sap_connection {
68         GIOChannel *io;
69         uint32_t state;
70         uint8_t processing_req;
71         guint timer_id;
72 };
73
74 struct sap_server {
75         char *path;
76         uint32_t record_id;
77         GIOChannel *listen_io;
78         struct sap_connection *conn;
79 };
80
81 static DBusConnection *connection;
82 static struct sap_server *server;
83
84 static void start_guard_timer(struct sap_connection *conn, guint interval);
85 static void stop_guard_timer(struct sap_connection *conn);
86 static gboolean guard_timeout(gpointer data);
87
88 static size_t add_result_parameter(uint8_t result,
89                                         struct sap_parameter *param)
90 {
91         param->id = SAP_PARAM_ID_RESULT_CODE;
92         param->len = htons(SAP_PARAM_ID_RESULT_CODE_LEN);
93         *param->val = result;
94
95         return PARAMETER_SIZE(SAP_PARAM_ID_RESULT_CODE_LEN);
96 }
97
98 static int is_power_sim_off_req_allowed(uint8_t processing_req)
99 {
100         switch (processing_req) {
101         case SAP_NO_REQ:
102         case SAP_TRANSFER_APDU_REQ:
103         case SAP_TRANSFER_ATR_REQ:
104         case SAP_POWER_SIM_ON_REQ:
105         case SAP_RESET_SIM_REQ:
106         case SAP_TRANSFER_CARD_READER_STATUS_REQ:
107                 return 1;
108         default:
109                 return 0;
110         }
111 }
112
113 static int is_reset_sim_req_allowed(uint8_t processing_req)
114 {
115         switch (processing_req) {
116         case SAP_NO_REQ:
117         case SAP_TRANSFER_APDU_REQ:
118         case SAP_TRANSFER_ATR_REQ:
119         case SAP_TRANSFER_CARD_READER_STATUS_REQ:
120                 return 1;
121         default:
122                 return 0;
123         }
124 }
125
126 static int check_msg(struct sap_message *msg)
127 {
128         switch (msg->id) {
129         case SAP_CONNECT_REQ:
130                 if (msg->nparam != 0x01)
131                         return -EBADMSG;
132
133                 if (msg->param->id != SAP_PARAM_ID_MAX_MSG_SIZE)
134                         return -EBADMSG;
135
136                 if (ntohs(msg->param->len) != SAP_PARAM_ID_MAX_MSG_SIZE_LEN)
137                         return -EBADMSG;
138
139                 break;
140
141         case SAP_TRANSFER_APDU_REQ:
142                 if (msg->nparam != 0x01)
143                         return -EBADMSG;
144
145                 if (msg->param->id != SAP_PARAM_ID_COMMAND_APDU)
146                         if (msg->param->id != SAP_PARAM_ID_COMMAND_APDU7816)
147                                 return -EBADMSG;
148
149                 if (msg->param->len == 0x00)
150                         return -EBADMSG;
151
152                 break;
153
154         case SAP_SET_TRANSPORT_PROTOCOL_REQ:
155                 if (msg->nparam != 0x01)
156                         return -EBADMSG;
157
158                 if (msg->param->id != SAP_PARAM_ID_TRANSPORT_PROTOCOL)
159                         return -EBADMSG;
160
161                 if (ntohs(msg->param->len) != SAP_PARAM_ID_TRANSPORT_PROTO_LEN)
162                         return -EBADMSG;
163
164                 if (*msg->param->val != SAP_TRANSPORT_PROTOCOL_T0)
165                         if (*msg->param->val != SAP_TRANSPORT_PROTOCOL_T1)
166                                 return -EBADMSG;
167
168                 break;
169
170         case SAP_DISCONNECT_REQ:
171         case SAP_TRANSFER_ATR_REQ:
172         case SAP_POWER_SIM_OFF_REQ:
173         case SAP_POWER_SIM_ON_REQ:
174         case SAP_RESET_SIM_REQ:
175         case SAP_TRANSFER_CARD_READER_STATUS_REQ:
176                 if (msg->nparam != 0x00)
177                         return -EBADMSG;
178
179                 break;
180         }
181
182         return 0;
183 }
184
185 static sdp_record_t *create_sap_record(uint8_t channel)
186 {
187         sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id;
188         uuid_t sap_uuid, gt_uuid, root_uuid, l2cap, rfcomm;
189         sdp_profile_desc_t profile;
190         sdp_record_t *record;
191         sdp_data_t *ch;
192
193         record = sdp_record_alloc();
194         if (!record)
195                 return NULL;
196
197         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
198         root = sdp_list_append(NULL, &root_uuid);
199         sdp_set_browse_groups(record, root);
200         sdp_list_free(root, NULL);
201
202         sdp_uuid16_create(&sap_uuid, SAP_SVCLASS_ID);
203         svclass_id = sdp_list_append(NULL, &sap_uuid);
204         sdp_uuid16_create(&gt_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
205         svclass_id = sdp_list_append(svclass_id, &gt_uuid);
206
207         sdp_set_service_classes(record, svclass_id);
208         sdp_list_free(svclass_id, NULL);
209
210         sdp_uuid16_create(&profile.uuid, SAP_PROFILE_ID);
211         profile.version = SAP_VERSION;
212         profiles = sdp_list_append(NULL, &profile);
213         sdp_set_profile_descs(record, profiles);
214         sdp_list_free(profiles, NULL);
215
216         sdp_uuid16_create(&l2cap, L2CAP_UUID);
217         proto[0] = sdp_list_append(NULL, &l2cap);
218         apseq = sdp_list_append(NULL, proto[0]);
219
220         sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
221         proto[1] = sdp_list_append(NULL, &rfcomm);
222         ch = sdp_data_alloc(SDP_UINT8, &channel);
223         proto[1] = sdp_list_append(proto[1], ch);
224         apseq = sdp_list_append(apseq, proto[1]);
225
226         aproto = sdp_list_append(NULL, apseq);
227         sdp_set_access_protos(record, aproto);
228
229         sdp_set_info_attr(record, "SIM Access Server", NULL, NULL);
230
231         sdp_data_free(ch);
232         sdp_list_free(proto[0], NULL);
233         sdp_list_free(proto[1], NULL);
234         sdp_list_free(apseq, NULL);
235         sdp_list_free(aproto, NULL);
236
237         return record;
238 }
239
240 static int send_message(struct sap_connection *conn, void *buf, size_t size)
241 {
242         size_t written = 0;
243         GError *gerr = NULL;
244         GIOStatus gstatus;
245
246         if (!conn || !buf)
247                 return -EINVAL;
248
249         DBG("conn %p, size %zu", conn, size);
250
251         gstatus = g_io_channel_write_chars(conn->io, buf, size, &written,
252                                                                         &gerr);
253         if (gstatus != G_IO_STATUS_NORMAL) {
254                 if (gerr)
255                         g_error_free(gerr);
256
257                 error("write error (0x%02x).", gstatus);
258                 return -EIO;
259         }
260
261         if (written != size) {
262                 error("written %zu bytes out of %zu", written, size);
263                 return -EIO;
264         }
265
266         return written;
267 }
268
269 static int disconnect_ind(void *sap_device, uint8_t disc_type)
270 {
271         struct sap_connection *conn = sap_device;
272         char buf[SAP_BUF_SIZE];
273         struct sap_message *msg = (struct sap_message *) buf;
274         struct sap_parameter *param = (struct sap_parameter *) msg->param;
275         size_t size = sizeof(struct sap_message);
276
277         DBG("data %p state %d disc_type 0x%02x", conn, conn->state, disc_type);
278
279         memset(buf, 0, sizeof(buf));
280         msg->id = SAP_DISCONNECT_IND;
281         msg->nparam = 0x01;
282
283         /* Add disconnection type param. */
284         param->id  = SAP_PARAM_ID_DISCONNECT_IND;
285         param->len = htons(SAP_PARAM_ID_DISCONNECT_IND_LEN);
286         *param->val = disc_type;
287         size += PARAMETER_SIZE(SAP_PARAM_ID_DISCONNECT_IND_LEN);
288
289         return send_message(sap_device, buf, size);
290 }
291
292 static void connect_req(struct sap_connection *conn,
293                                 struct sap_parameter *param)
294 {
295         uint16_t maxmsgsize, *val;
296
297         DBG("conn %p state %d", conn, conn->state);
298
299         if (!param)
300                 goto error_rsp;
301
302         if (conn->state != SAP_STATE_DISCONNECTED)
303                 goto error_rsp;
304
305         stop_guard_timer(conn);
306
307         val = (uint16_t *) &param->val;
308         maxmsgsize = ntohs(*val);
309
310         DBG("Connect MaxMsgSize: 0x%04x", maxmsgsize);
311
312         conn->state = SAP_STATE_CONNECT_IN_PROGRESS;
313
314         if (maxmsgsize <= SAP_BUF_SIZE) {
315                 conn->processing_req = SAP_CONNECT_REQ;
316                 sap_connect_req(conn, maxmsgsize);
317         } else {
318                 sap_connect_rsp(conn, SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED,
319                                                                 SAP_BUF_SIZE);
320         }
321
322         return;
323
324 error_rsp:
325         sap_error_rsp(conn);
326 }
327
328 static int disconnect_req(struct sap_connection *conn, uint8_t disc_type)
329 {
330         DBG("conn %p state %d disc_type 0x%02x", conn, conn->state, disc_type);
331
332         switch (disc_type) {
333         case SAP_DISCONNECTION_TYPE_GRACEFUL:
334                 if (conn->state == SAP_STATE_DISCONNECTED ||
335                                 conn->state == SAP_STATE_CONNECT_IN_PROGRESS ||
336                                 conn->state == SAP_STATE_CONNECT_MODEM_BUSY)
337                         return -EPERM;
338
339                 if (conn->state == SAP_STATE_CONNECTED) {
340                         conn->state = SAP_STATE_GRACEFUL_DISCONNECT;
341                         conn->processing_req = SAP_NO_REQ;
342
343                         disconnect_ind(conn, disc_type);
344                         /* Timer will disconnect if client won't do.*/
345                         start_guard_timer(conn, SAP_TIMER_GRACEFUL_DISCONNECT);
346                 }
347
348                 return 0;
349
350         case SAP_DISCONNECTION_TYPE_IMMEDIATE:
351                 if (conn->state == SAP_STATE_DISCONNECTED ||
352                                 conn->state == SAP_STATE_CONNECT_IN_PROGRESS ||
353                                 conn->state == SAP_STATE_CONNECT_MODEM_BUSY)
354                         return -EPERM;
355
356                 if (conn->state == SAP_STATE_CONNECTED ||
357                                 conn->state == SAP_STATE_GRACEFUL_DISCONNECT) {
358                         conn->state = SAP_STATE_IMMEDIATE_DISCONNECT;
359                         conn->processing_req = SAP_NO_REQ;
360
361                         stop_guard_timer(conn);
362                         disconnect_ind(conn, disc_type);
363                         sap_disconnect_req(conn, 0);
364                 }
365
366                 return 0;
367
368         case SAP_DISCONNECTION_TYPE_CLIENT:
369                 if (conn->state != SAP_STATE_CONNECTED &&
370                                 conn->state != SAP_STATE_GRACEFUL_DISCONNECT) {
371                         sap_error_rsp(conn);
372                         return -EPERM;
373                 }
374
375                 conn->state = SAP_STATE_CLIENT_DISCONNECT;
376                 conn->processing_req = SAP_NO_REQ;
377
378                 stop_guard_timer(conn);
379                 sap_disconnect_req(conn, 0);
380
381                 return 0;
382
383         default:
384                 error("Unknown disconnection type (0x%02x).", disc_type);
385                 return -EINVAL;
386         }
387 }
388
389 static void transfer_apdu_req(struct sap_connection *conn,
390                                         struct sap_parameter *param)
391 {
392         DBG("conn %p state %d", conn, conn->state);
393
394         if (!param)
395                 goto error_rsp;
396
397         param->len = ntohs(param->len);
398
399         if (conn->state != SAP_STATE_CONNECTED &&
400                         conn->state != SAP_STATE_GRACEFUL_DISCONNECT)
401                 goto error_rsp;
402
403         if (conn->processing_req != SAP_NO_REQ)
404                 goto error_rsp;
405
406         conn->processing_req = SAP_TRANSFER_APDU_REQ;
407         sap_transfer_apdu_req(conn, param);
408
409         return;
410
411 error_rsp:
412         sap_error_rsp(conn);
413 }
414
415 static void transfer_atr_req(struct sap_connection *conn)
416 {
417         DBG("conn %p state %d", conn, conn->state);
418
419         if (conn->state != SAP_STATE_CONNECTED)
420                 goto error_rsp;
421
422         if (conn->processing_req != SAP_NO_REQ)
423                 goto error_rsp;
424
425         conn->processing_req = SAP_TRANSFER_ATR_REQ;
426         sap_transfer_atr_req(conn);
427
428         return;
429
430 error_rsp:
431         sap_error_rsp(conn);
432 }
433
434 static void power_sim_off_req(struct sap_connection *conn)
435 {
436         DBG("conn %p state %d", conn, conn->state);
437
438         if (conn->state != SAP_STATE_CONNECTED)
439                 goto error_rsp;
440
441         if (!is_power_sim_off_req_allowed(conn->processing_req))
442                 goto error_rsp;
443
444         conn->processing_req = SAP_POWER_SIM_OFF_REQ;
445         sap_power_sim_off_req(conn);
446
447         return;
448
449 error_rsp:
450         sap_error_rsp(conn);
451 }
452
453 static void power_sim_on_req(struct sap_connection *conn)
454 {
455         DBG("conn %p state %d", conn, conn->state);
456
457         if (conn->state != SAP_STATE_CONNECTED)
458                 goto error_rsp;
459
460         if (conn->processing_req != SAP_NO_REQ)
461                 goto error_rsp;
462
463         conn->processing_req = SAP_POWER_SIM_ON_REQ;
464         sap_power_sim_on_req(conn);
465
466         return;
467
468 error_rsp:
469         sap_error_rsp(conn);
470 }
471
472 static void reset_sim_req(struct sap_connection *conn)
473 {
474         DBG("conn %p state %d", conn, conn->state);
475
476         if (conn->state != SAP_STATE_CONNECTED)
477                 goto error_rsp;
478
479         if (!is_reset_sim_req_allowed(conn->processing_req))
480                 goto error_rsp;
481
482         conn->processing_req = SAP_RESET_SIM_REQ;
483         sap_reset_sim_req(conn);
484
485         return;
486
487 error_rsp:
488         sap_error_rsp(conn);
489 }
490
491 static void transfer_card_reader_status_req(struct sap_connection *conn)
492 {
493         DBG("conn %p state %d", conn, conn->state);
494
495         if (conn->state != SAP_STATE_CONNECTED)
496                 goto error_rsp;
497
498         if (conn->processing_req != SAP_NO_REQ)
499                 goto error_rsp;
500
501         conn->processing_req = SAP_TRANSFER_CARD_READER_STATUS_REQ;
502         sap_transfer_card_reader_status_req(conn);
503
504         return;
505
506 error_rsp:
507         sap_error_rsp(conn);
508 }
509
510 static void set_transport_protocol_req(struct sap_connection *conn,
511                                         struct sap_parameter *param)
512 {
513         if (!param)
514                 goto error_rsp;
515
516         DBG("conn %p state %d param %p", conn, conn->state, param);
517
518         if (conn->state != SAP_STATE_CONNECTED)
519                 goto error_rsp;
520
521         if (conn->processing_req != SAP_NO_REQ)
522                 goto error_rsp;
523
524         conn->processing_req = SAP_SET_TRANSPORT_PROTOCOL_REQ;
525         sap_set_transport_protocol_req(conn, param);
526
527         return;
528
529 error_rsp:
530         sap_error_rsp(conn);
531 }
532
533 static void start_guard_timer(struct sap_connection *conn, guint interval)
534 {
535         if (!conn)
536                 return;
537
538         if (!conn->timer_id)
539                 conn->timer_id = g_timeout_add_seconds(interval, guard_timeout,
540                                                                         conn);
541         else
542                 error("Timer is already active.");
543 }
544
545 static void stop_guard_timer(struct sap_connection *conn)
546 {
547         if (conn  && conn->timer_id) {
548                 g_source_remove(conn->timer_id);
549                 conn->timer_id = 0;
550         }
551 }
552
553 static gboolean guard_timeout(gpointer data)
554 {
555         struct sap_connection *conn = data;
556
557         if (!conn)
558                 return FALSE;
559
560         DBG("conn %p state %d pr 0x%02x", conn, conn->state,
561                                                 conn->processing_req);
562
563         conn->timer_id = 0;
564
565         switch (conn->state) {
566         case SAP_STATE_DISCONNECTED:
567                 /* Client opened RFCOMM channel but didn't send CONNECT_REQ,
568                  * in fixed time or client disconnected SAP connection but
569                  * didn't closed RFCOMM channel in fixed time.*/
570                 if (conn->io) {
571                         g_io_channel_shutdown(conn->io, TRUE, NULL);
572                         g_io_channel_unref(conn->io);
573                 }
574                 break;
575
576         case SAP_STATE_GRACEFUL_DISCONNECT:
577                 /* Client didn't disconnect SAP connection in fixed time,
578                  * so close SAP connection immediately. */
579                 disconnect_req(conn, SAP_DISCONNECTION_TYPE_IMMEDIATE);
580                 break;
581
582         default:
583                 error("Unexpected state (%d).", conn->state);
584                 break;
585         }
586
587         return FALSE;
588 }
589
590 static void sap_set_connected(struct sap_connection *conn)
591 {
592         gboolean connected = TRUE;
593
594         emit_property_changed(connection, server->path,
595                                         SAP_SERVER_INTERFACE,
596                 "Connected", DBUS_TYPE_BOOLEAN, &connected);
597
598         conn->state = SAP_STATE_CONNECTED;
599 }
600
601 int sap_connect_rsp(void *sap_device, uint8_t status, uint16_t maxmsgsize)
602 {
603         struct sap_connection *conn = sap_device;
604         char buf[SAP_BUF_SIZE];
605         struct sap_message *msg = (struct sap_message *) buf;
606         struct sap_parameter *param = (struct sap_parameter *) msg->param;
607         size_t size = sizeof(struct sap_message);
608
609         if (!conn)
610                 return -EINVAL;
611
612         DBG("state %d pr 0x%02x status 0x%02x", conn->state,
613                                                 conn->processing_req, status);
614
615         if (conn->state != SAP_STATE_CONNECT_IN_PROGRESS)
616                 return -EPERM;
617
618         memset(buf, 0, sizeof(buf));
619         msg->id = SAP_CONNECT_RESP;
620         msg->nparam = 0x01;
621
622         /* Add connection status */
623         param->id = SAP_PARAM_ID_CONN_STATUS;
624         param->len = htons(SAP_PARAM_ID_CONN_STATUS_LEN);
625         *param->val = status;
626         size += PARAMETER_SIZE(SAP_PARAM_ID_CONN_STATUS_LEN);
627
628         /* Add MaxMsgSize */
629         if (maxmsgsize) {
630                 uint16_t *len;
631
632                 msg->nparam++;
633                 param = (struct sap_parameter *) &buf[size];
634                 param->id = SAP_PARAM_ID_MAX_MSG_SIZE;
635                 param->len = htons(SAP_PARAM_ID_MAX_MSG_SIZE_LEN);
636                 len = (uint16_t *) &param->val;
637                 *len = htons(maxmsgsize);
638                 size += PARAMETER_SIZE(SAP_PARAM_ID_MAX_MSG_SIZE_LEN);
639         }
640
641         if (status == SAP_STATUS_OK) {
642                 sap_set_connected(conn);
643         } else if (status == SAP_STATUS_OK_ONGOING_CALL) {
644                 DBG("ongoing call. Wait for reset indication!");
645                 conn->state = SAP_STATE_CONNECT_MODEM_BUSY;
646         } else {
647                 conn->state = SAP_STATE_DISCONNECTED;
648
649                 /* Timer will shutdown channel if client doesn't send
650                  * CONNECT_REQ or doesn't shutdown channel itself.*/
651                 start_guard_timer(conn, SAP_TIMER_NO_ACTIVITY);
652         }
653
654         conn->processing_req = SAP_NO_REQ;
655
656         return send_message(sap_device, buf, size);
657 }
658
659 int sap_disconnect_rsp(void *sap_device)
660 {
661         struct sap_connection *conn = sap_device;
662         struct sap_message msg;
663
664         if (!conn)
665                 return -EINVAL;
666
667         DBG("state %d pr 0x%02x", conn->state, conn->processing_req);
668
669         switch (conn->state) {
670         case SAP_STATE_CLIENT_DISCONNECT:
671                 memset(&msg, 0, sizeof(msg));
672                 msg.id = SAP_DISCONNECT_RESP;
673
674                 conn->state = SAP_STATE_DISCONNECTED;
675                 conn->processing_req = SAP_NO_REQ;
676
677                 /* Timer will close channel if client doesn't do it.*/
678                 start_guard_timer(conn, SAP_TIMER_NO_ACTIVITY);
679
680                 return send_message(sap_device, &msg, sizeof(msg));
681
682         case SAP_STATE_IMMEDIATE_DISCONNECT:
683                 conn->state = SAP_STATE_DISCONNECTED;
684                 conn->processing_req = SAP_NO_REQ;
685
686                 if (conn->io) {
687                         g_io_channel_shutdown(conn->io, TRUE, NULL);
688                         g_io_channel_unref(conn->io);
689                 }
690
691                 return 0;
692
693         default:
694                 break;
695         }
696
697         return 0;
698 }
699
700 int sap_transfer_apdu_rsp(void *sap_device, uint8_t result, uint8_t *apdu,
701                                         uint16_t length)
702 {
703         struct sap_connection *conn = sap_device;
704         char buf[SAP_BUF_SIZE];
705         struct sap_message *msg = (struct sap_message *) buf;
706         struct sap_parameter *param = (struct sap_parameter *) msg->param;
707         size_t size = sizeof(struct sap_message);
708
709         if (!conn)
710                 return -EINVAL;
711
712         DBG("state %d pr 0x%02x", conn->state, conn->processing_req);
713
714         if (conn->processing_req != SAP_TRANSFER_APDU_REQ)
715                 return 0;
716
717         if (result == SAP_RESULT_OK && (!apdu || (apdu && length == 0x00)))
718                 return -EINVAL;
719
720         memset(buf, 0, sizeof(buf));
721         msg->id = SAP_TRANSFER_APDU_RESP;
722         msg->nparam = 0x01;
723         size += add_result_parameter(result, param);
724
725         /* Add APDU response. */
726         if (result == SAP_RESULT_OK) {
727                 msg->nparam++;
728                 param = (struct sap_parameter *) &buf[size];
729                 param->id = SAP_PARAM_ID_RESPONSE_APDU;
730                 param->len = htons(length);
731
732                 size += PARAMETER_SIZE(length);
733
734                 if (size > SAP_BUF_SIZE)
735                         return -EOVERFLOW;
736
737                 memcpy(param->val, apdu, length);
738         }
739
740         conn->processing_req = SAP_NO_REQ;
741
742         return send_message(sap_device, buf, size);
743 }
744
745 int sap_transfer_atr_rsp(void *sap_device, uint8_t result, uint8_t *atr,
746                                         uint16_t length)
747 {
748         struct sap_connection *conn = sap_device;
749         char buf[SAP_BUF_SIZE];
750         struct sap_message *msg = (struct sap_message *) buf;
751         struct sap_parameter *param = (struct sap_parameter *) msg->param;
752         size_t size = sizeof(struct sap_message);
753
754         if (!conn)
755                 return -EINVAL;
756
757         DBG("result 0x%02x state %d pr 0x%02x len %d", result, conn->state,
758                         conn->processing_req, length);
759
760         if (conn->processing_req != SAP_TRANSFER_ATR_REQ)
761                 return 0;
762
763         if (result == SAP_RESULT_OK && (!atr || (atr && length == 0x00)))
764                 return -EINVAL;
765
766         memset(buf, 0, sizeof(buf));
767         msg->id = SAP_TRANSFER_ATR_RESP;
768         msg->nparam = 0x01;
769         size += add_result_parameter(result, param);
770
771         /* Add ATR response */
772         if (result == SAP_RESULT_OK) {
773                 msg->nparam++;
774                 param = (struct sap_parameter *) &buf[size];
775                 param->id = SAP_PARAM_ID_ATR;
776                 param->len = htons(length);
777                 size += PARAMETER_SIZE(length);
778
779                 if (size > SAP_BUF_SIZE)
780                         return -EOVERFLOW;
781
782                 memcpy(param->val, atr, length);
783         }
784
785         conn->processing_req = SAP_NO_REQ;
786
787         return send_message(sap_device, buf, size);
788 }
789
790 int sap_power_sim_off_rsp(void *sap_device, uint8_t result)
791 {
792         struct sap_connection *conn = sap_device;
793         char buf[SAP_BUF_SIZE];
794         struct sap_message *msg = (struct sap_message *) buf;
795         size_t size = sizeof(struct sap_message);
796
797         if (!conn)
798                 return -EINVAL;
799
800         DBG("state %d pr 0x%02x", conn->state, conn->processing_req);
801
802         if (conn->processing_req != SAP_POWER_SIM_OFF_REQ)
803                 return 0;
804
805         memset(buf, 0, sizeof(buf));
806         msg->id = SAP_POWER_SIM_OFF_RESP;
807         msg->nparam = 0x01;
808         size += add_result_parameter(result, msg->param);
809
810         conn->processing_req = SAP_NO_REQ;
811
812         return send_message(sap_device, buf, size);
813 }
814
815 int sap_power_sim_on_rsp(void *sap_device, uint8_t result)
816 {
817         struct sap_connection *conn = sap_device;
818         char buf[SAP_BUF_SIZE];
819         struct sap_message *msg = (struct sap_message *) buf;
820         size_t size = sizeof(struct sap_message);
821
822         if (!conn)
823                 return -EINVAL;
824
825         DBG("state %d pr 0x%02x", conn->state, conn->processing_req);
826
827         if (conn->processing_req != SAP_POWER_SIM_ON_REQ)
828                 return 0;
829
830         memset(buf, 0, sizeof(buf));
831         msg->id = SAP_POWER_SIM_ON_RESP;
832         msg->nparam = 0x01;
833         size += add_result_parameter(result, msg->param);
834
835         conn->processing_req = SAP_NO_REQ;
836
837         return send_message(sap_device, buf, size);
838 }
839
840 int sap_reset_sim_rsp(void *sap_device, uint8_t result)
841 {
842         struct sap_connection *conn = sap_device;
843         char buf[SAP_BUF_SIZE];
844         struct sap_message *msg = (struct sap_message *) buf;
845         size_t size = sizeof(struct sap_message);
846
847         if (!conn)
848                 return -EINVAL;
849
850         DBG("state %d pr 0x%02x result 0x%02x", conn->state,
851                                                 conn->processing_req, result);
852
853         if (conn->processing_req != SAP_RESET_SIM_REQ)
854                 return 0;
855
856         memset(buf, 0, sizeof(buf));
857         msg->id = SAP_RESET_SIM_RESP;
858         msg->nparam = 0x01;
859         size += add_result_parameter(result, msg->param);
860
861         conn->processing_req = SAP_NO_REQ;
862
863         return send_message(sap_device, buf, size);
864 }
865
866 int sap_transfer_card_reader_status_rsp(void *sap_device, uint8_t result,
867                                                 uint8_t status)
868 {
869         struct sap_connection *conn = sap_device;
870         char buf[SAP_BUF_SIZE];
871         struct sap_message *msg = (struct sap_message *) buf;
872         struct sap_parameter *param = (struct sap_parameter *) msg->param;
873         size_t size = sizeof(struct sap_message);
874
875         if (!conn)
876                 return -EINVAL;
877
878         DBG("state %d pr 0x%02x result 0x%02x", conn->state,
879                                                 conn->processing_req, result);
880
881         if (conn->processing_req != SAP_TRANSFER_CARD_READER_STATUS_REQ)
882                 return 0;
883
884         memset(buf, 0, sizeof(buf));
885         msg->id = SAP_TRANSFER_CARD_READER_STATUS_RESP;
886         msg->nparam = 0x01;
887         size += add_result_parameter(result, param);
888
889         /* Add card reader status. */
890         if (result == SAP_RESULT_OK) {
891                 msg->nparam++;
892                 param = (struct sap_parameter *) &buf[size];
893                 param->id = SAP_PARAM_ID_CARD_READER_STATUS;
894                 param->len = htons(SAP_PARAM_ID_CARD_READER_STATUS_LEN);
895                 *param->val = status;
896                 size += PARAMETER_SIZE(SAP_PARAM_ID_CARD_READER_STATUS_LEN);
897         }
898
899         conn->processing_req = SAP_NO_REQ;
900
901         return send_message(sap_device, buf, size);
902 }
903
904 int sap_transport_protocol_rsp(void *sap_device, uint8_t result)
905 {
906         struct sap_connection *conn = sap_device;
907         char buf[SAP_BUF_SIZE];
908         struct sap_message *msg = (struct sap_message *) buf;
909         size_t size = sizeof(struct sap_message);
910
911         if (!conn)
912                 return -EINVAL;
913
914         DBG("state %d pr 0x%02x result 0x%02x", conn->state,
915                                                 conn->processing_req, result);
916
917         if (conn->processing_req != SAP_SET_TRANSPORT_PROTOCOL_REQ)
918                 return 0;
919
920         memset(buf, 0, sizeof(buf));
921         msg->id = SAP_SET_TRANSPORT_PROTOCOL_RESP;
922         msg->nparam = 0x01;
923         size += add_result_parameter(result, msg->param);
924
925         conn->processing_req = SAP_NO_REQ;
926
927         return send_message(sap_device, buf, size);
928 }
929
930 int sap_error_rsp(void *sap_device)
931 {
932         struct sap_message msg;
933         struct sap_connection *conn = sap_device;
934
935         memset(&msg, 0, sizeof(msg));
936         msg.id = SAP_ERROR_RESP;
937
938         error("SAP error (state %d pr 0x%02x).", conn->state,
939                                                         conn->processing_req);
940
941         return send_message(conn, &msg, sizeof(msg));
942 }
943
944 int sap_status_ind(void *sap_device, uint8_t status_change)
945 {
946         struct sap_connection *conn = sap_device;
947         char buf[SAP_BUF_SIZE];
948         struct sap_message *msg = (struct sap_message *) buf;
949         struct sap_parameter *param = (struct sap_parameter *) msg->param;
950         size_t size = sizeof(struct sap_message);
951
952         if (!conn)
953                 return -EINVAL;
954
955         DBG("state %d pr 0x%02x sc 0x%02x", conn->state, conn->processing_req,
956                                                                 status_change);
957
958         /* Might be need to change state to connected after ongoing call.*/
959         if (conn->state == SAP_STATE_CONNECT_MODEM_BUSY &&
960                         status_change == SAP_STATUS_CHANGE_CARD_RESET)
961                 sap_set_connected(conn);
962
963         if (conn->state != SAP_STATE_CONNECTED &&
964                         conn->state != SAP_STATE_GRACEFUL_DISCONNECT)
965                 return 0;
966
967         memset(buf, 0, sizeof(buf));
968         msg->id = SAP_STATUS_IND;
969         msg->nparam = 0x01;
970
971         /* Add status change. */
972         param->id  = SAP_PARAM_ID_STATUS_CHANGE;
973         param->len = htons(SAP_PARAM_ID_STATUS_CHANGE_LEN);
974         *param->val = status_change;
975         size += PARAMETER_SIZE(SAP_PARAM_ID_STATUS_CHANGE_LEN);
976
977         return send_message(sap_device, buf, size);
978 }
979
980 int sap_disconnect_ind(void *sap_device, uint8_t disc_type)
981 {
982         struct sap_connection *conn = sap_device;
983
984         return disconnect_req(conn, SAP_DISCONNECTION_TYPE_IMMEDIATE);
985 }
986
987 static int handle_cmd(struct sap_connection *conn, void *buf, size_t size)
988 {
989         struct sap_message *msg = buf;
990
991         if (!conn)
992                 return -EINVAL;
993
994         if (size < sizeof(struct sap_message))
995                 goto error_rsp;
996
997         if (msg->nparam != 0 && size < (sizeof(struct sap_message) +
998                                         sizeof(struct sap_parameter) + 4))
999                 goto error_rsp;
1000
1001         if (check_msg(msg) < 0)
1002                 goto error_rsp;
1003
1004         switch (msg->id) {
1005         case SAP_CONNECT_REQ:
1006                 connect_req(conn, msg->param);
1007                 return 0;
1008         case SAP_DISCONNECT_REQ:
1009                 disconnect_req(conn, SAP_DISCONNECTION_TYPE_CLIENT);
1010                 return 0;
1011         case SAP_TRANSFER_APDU_REQ:
1012                 transfer_apdu_req(conn, msg->param);
1013                 return 0;
1014         case SAP_TRANSFER_ATR_REQ:
1015                 transfer_atr_req(conn);
1016                 return 0;
1017         case SAP_POWER_SIM_OFF_REQ:
1018                 power_sim_off_req(conn);
1019                 return 0;
1020         case SAP_POWER_SIM_ON_REQ:
1021                 power_sim_on_req(conn);
1022                 return 0;
1023         case SAP_RESET_SIM_REQ:
1024                 reset_sim_req(conn);
1025                 return 0;
1026         case SAP_TRANSFER_CARD_READER_STATUS_REQ:
1027                 transfer_card_reader_status_req(conn);
1028                 return 0;
1029         case SAP_SET_TRANSPORT_PROTOCOL_REQ:
1030                 set_transport_protocol_req(conn, msg->param);
1031                 return 0;
1032         default:
1033                 DBG("Unknown SAP message id 0x%02x.", msg->id);
1034                 break;
1035         }
1036
1037 error_rsp:
1038         DBG("Invalid SAP message format.");
1039         sap_error_rsp(conn);
1040         return -EBADMSG;
1041 }
1042
1043 static void sap_conn_remove(struct sap_connection *conn)
1044 {
1045         DBG("conn %p", conn);
1046
1047         if (!conn)
1048                 return;
1049
1050         if (conn->io) {
1051                 g_io_channel_shutdown(conn->io, TRUE, NULL);
1052                 g_io_channel_unref(conn->io);
1053         }
1054
1055         conn->io = NULL;
1056         g_free(conn);
1057         server->conn = NULL;
1058 }
1059
1060 static gboolean sap_io_cb(GIOChannel *io, GIOCondition cond, gpointer data)
1061 {
1062         struct sap_connection *conn = data;
1063
1064         char buf[SAP_BUF_SIZE];
1065         size_t bytes_read = 0;
1066         GError *gerr = NULL;
1067         GIOStatus gstatus;
1068
1069         DBG("conn %p io %p", conn, io);
1070
1071         if (cond & G_IO_NVAL) {
1072                 DBG("ERR (G_IO_NVAL) on rfcomm socket.");
1073                 return FALSE;
1074         }
1075
1076         if (cond & G_IO_ERR) {
1077                 DBG("ERR (G_IO_ERR) on rfcomm socket.");
1078                 return FALSE;
1079         }
1080
1081         if (cond & G_IO_HUP) {
1082                 DBG("HUP on rfcomm socket.");
1083                 return FALSE;
1084         }
1085
1086         gstatus = g_io_channel_read_chars(io, buf, sizeof(buf) - 1,
1087                                                         &bytes_read, &gerr);
1088         if (gstatus != G_IO_STATUS_NORMAL) {
1089                 if (gerr)
1090                         g_error_free(gerr);
1091
1092                 return TRUE;
1093         }
1094
1095         if (handle_cmd(conn, buf, bytes_read) < 0)
1096                 error("SAP protocol processing failure.");
1097
1098         return TRUE;
1099 }
1100
1101 static void sap_io_destroy(void *data)
1102 {
1103         struct sap_connection *conn = data;
1104         gboolean connected = FALSE;
1105
1106         DBG("conn %p", conn);
1107
1108         if (!conn || !conn->io)
1109                 return;
1110
1111         stop_guard_timer(conn);
1112
1113         if (conn->state != SAP_STATE_CONNECT_IN_PROGRESS &&
1114                         conn->state != SAP_STATE_CONNECT_MODEM_BUSY)
1115                 emit_property_changed(connection, server->path,
1116                                         SAP_SERVER_INTERFACE, "Connected",
1117                                         DBUS_TYPE_BOOLEAN, &connected);
1118
1119         if (conn->state == SAP_STATE_CONNECT_IN_PROGRESS ||
1120                         conn->state == SAP_STATE_CONNECT_MODEM_BUSY ||
1121                         conn->state == SAP_STATE_CONNECTED ||
1122                         conn->state == SAP_STATE_GRACEFUL_DISCONNECT)
1123                 sap_disconnect_req(NULL, 1);
1124
1125         sap_conn_remove(conn);
1126 }
1127
1128 static void sap_connect_cb(GIOChannel *io, GError *gerr, gpointer data)
1129 {
1130         struct sap_connection *conn = data;
1131
1132         DBG("conn %p, io %p", conn, io);
1133
1134         if (!conn)
1135                 return;
1136
1137         /* Timer will shutdown the channel in case of lack of client
1138            activity */
1139         start_guard_timer(conn, SAP_TIMER_NO_ACTIVITY);
1140
1141         g_io_add_watch_full(io, G_PRIORITY_DEFAULT,
1142                         G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1143                         sap_io_cb, conn, sap_io_destroy);
1144 }
1145
1146 static void connect_auth_cb(DBusError *derr, void *data)
1147 {
1148         struct sap_connection *conn = data;
1149         GError *gerr = NULL;
1150
1151         DBG("conn %p", conn);
1152
1153         if (!conn)
1154                 return;
1155
1156         if (derr && dbus_error_is_set(derr)) {
1157                 error("Access has been denied (%s)", derr->message);
1158                 sap_conn_remove(conn);
1159                 return;
1160         }
1161
1162         if (!bt_io_accept(conn->io, sap_connect_cb, conn, NULL, &gerr)) {
1163                 error("bt_io_accept: %s", gerr->message);
1164                 g_error_free(gerr);
1165                 sap_conn_remove(conn);
1166                 return;
1167         }
1168
1169         DBG("Access has been granted.");
1170 }
1171
1172 static void connect_confirm_cb(GIOChannel *io, gpointer data)
1173 {
1174         struct sap_connection *conn = server->conn;
1175         GError *gerr = NULL;
1176         bdaddr_t src, dst;
1177         char dstaddr[18];
1178         int err;
1179
1180         DBG("conn %p io %p", conn, io);
1181
1182         if (!io)
1183                 return;
1184
1185         if (conn) {
1186                 DBG("Another SAP connection already exists.");
1187                 g_io_channel_shutdown(io, TRUE, NULL);
1188                 return;
1189         }
1190
1191         conn = g_try_new0(struct sap_connection, 1);
1192         if (!conn) {
1193                 error("Can't allocate memory for incoming SAP connection.");
1194                 g_io_channel_shutdown(io, TRUE, NULL);
1195                 return;
1196         }
1197
1198         g_io_channel_set_encoding(io, NULL, NULL);
1199         g_io_channel_set_buffered(io, FALSE);
1200
1201         server->conn = conn;
1202         conn->io = g_io_channel_ref(io);
1203         conn->state = SAP_STATE_DISCONNECTED;
1204
1205         bt_io_get(io, BT_IO_RFCOMM, &gerr,
1206                         BT_IO_OPT_SOURCE_BDADDR, &src,
1207                         BT_IO_OPT_DEST_BDADDR, &dst,
1208                         BT_IO_OPT_INVALID);
1209         if (gerr) {
1210                 error("%s", gerr->message);
1211                 g_error_free(gerr);
1212                 sap_conn_remove(conn);
1213                 return;
1214         }
1215
1216         ba2str(&dst, dstaddr);
1217
1218         err = btd_request_authorization(&src, &dst, SAP_UUID, connect_auth_cb,
1219                                                                         conn);
1220         if (err < 0) {
1221                 error("Authorization failure (err %d)", err);
1222                 sap_conn_remove(conn);
1223                 return;
1224         }
1225
1226         DBG("Authorizing incoming SAP connection from %s", dstaddr);
1227 }
1228
1229 static inline DBusMessage *message_failed(DBusMessage *msg,
1230                                         const char *description)
1231 {
1232         return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "%s",
1233                                                                 description);
1234 }
1235
1236 static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
1237                                                                 void *data)
1238 {
1239         struct sap_server *server = data;
1240
1241         if (!server)
1242                 return message_failed(msg, "Server internal error.");
1243
1244         DBG("conn %p", server->conn);
1245
1246         if (!server->conn)
1247                 return message_failed(msg, "Client already disconnected");
1248
1249         if (disconnect_req(server->conn, SAP_DISCONNECTION_TYPE_GRACEFUL) < 0)
1250                 return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
1251                                         "There is no active connection");
1252
1253         return dbus_message_new_method_return(msg);
1254 }
1255
1256 static DBusMessage *get_properties(DBusConnection *c,
1257                                 DBusMessage *msg, void *data)
1258 {
1259         struct sap_connection *conn = data;
1260         DBusMessage *reply;
1261         DBusMessageIter iter;
1262         DBusMessageIter dict;
1263         dbus_bool_t connected;
1264
1265         if (!conn)
1266                 return message_failed(msg, "Server internal error.");
1267
1268         reply = dbus_message_new_method_return(msg);
1269         if (!reply)
1270                 return NULL;
1271
1272         dbus_message_iter_init_append(reply, &iter);
1273
1274         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1275                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1276                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
1277                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
1278
1279         connected = (conn->state == SAP_STATE_CONNECTED ||
1280                                 conn->state == SAP_STATE_GRACEFUL_DISCONNECT);
1281         dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &connected);
1282
1283         dbus_message_iter_close_container(&iter, &dict);
1284
1285         return reply;
1286 }
1287
1288 static const GDBusMethodTable server_methods[] = {
1289         { GDBUS_METHOD("GetProperties",
1290                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1291                         get_properties) },
1292         { GDBUS_METHOD("Disconnect", NULL, NULL, disconnect) },
1293         { }
1294 };
1295
1296 static const GDBusSignalTable server_signals[] = {
1297         { GDBUS_SIGNAL("PropertyChanged",
1298                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1299         { }
1300 };
1301
1302 static void server_free(struct sap_server *server)
1303 {
1304         if (!server)
1305                 return;
1306
1307         sap_conn_remove(server->conn);
1308         g_free(server->path);
1309         g_free(server);
1310         server = NULL;
1311 }
1312
1313 static void destroy_sap_interface(void *data)
1314 {
1315         struct sap_server *server = data;
1316
1317         DBG("Unregistered interface %s on path %s", SAP_SERVER_INTERFACE,
1318                                                                 server->path);
1319
1320         server_free(server);
1321 }
1322
1323 int sap_server_register(const char *path, bdaddr_t *src)
1324 {
1325         sdp_record_t *record = NULL;
1326         GError *gerr = NULL;
1327         GIOChannel *io;
1328
1329         if (sap_init() < 0) {
1330                 error("Sap driver initialization failed.");
1331                 return -1;
1332         }
1333
1334         server = g_try_new0(struct sap_server, 1);
1335         if (!server) {
1336                 sap_exit();
1337                 return -ENOMEM;
1338         }
1339
1340         server->path = g_strdup(path);
1341
1342         record = create_sap_record(SAP_SERVER_CHANNEL);
1343         if (!record) {
1344                 error("Creating SAP SDP record failed.");
1345                 goto sdp_err;
1346         }
1347
1348         if (add_record_to_server(src, record) < 0) {
1349                 error("Adding SAP SDP record to the SDP server failed.");
1350                 sdp_record_free(record);
1351                 goto sdp_err;
1352         }
1353
1354         server->record_id = record->handle;
1355
1356         io = bt_io_listen(BT_IO_RFCOMM, NULL, connect_confirm_cb, server,
1357                         NULL, &gerr,
1358                         BT_IO_OPT_SOURCE_BDADDR, src,
1359                         BT_IO_OPT_CHANNEL, SAP_SERVER_CHANNEL,
1360                         BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH,
1361                         BT_IO_OPT_MASTER, TRUE,
1362                         BT_IO_OPT_INVALID);
1363         if (!io) {
1364                 error("Can't listen at channel %d.", SAP_SERVER_CHANNEL);
1365                 g_error_free(gerr);
1366                 goto server_err;
1367         }
1368
1369         DBG("Listen socket 0x%02x", g_io_channel_unix_get_fd(io));
1370
1371         server->listen_io = io;
1372         server->conn = NULL;
1373
1374         if (!g_dbus_register_interface(connection, path, SAP_SERVER_INTERFACE,
1375                                         server_methods, server_signals, NULL,
1376                                         server, destroy_sap_interface)) {
1377                 error("D-Bus failed to register %s interface",
1378                                                         SAP_SERVER_INTERFACE);
1379                 goto server_err;
1380         }
1381
1382         return 0;
1383
1384 server_err:
1385         remove_record_from_server(server->record_id);
1386 sdp_err:
1387         server_free(server);
1388         sap_exit();
1389
1390         return -1;
1391 }
1392
1393 int sap_server_unregister(const char *path)
1394 {
1395         if (!server)
1396                 return -EINVAL;
1397
1398         remove_record_from_server(server->record_id);
1399
1400         if (server->conn)
1401                 sap_conn_remove(server->conn);
1402
1403         if (server->listen_io) {
1404                 g_io_channel_shutdown(server->listen_io, TRUE, NULL);
1405                 g_io_channel_unref(server->listen_io);
1406                 server->listen_io = NULL;
1407         }
1408
1409         g_dbus_unregister_interface(connection, path, SAP_SERVER_INTERFACE);
1410
1411         sap_exit();
1412
1413         return 0;
1414 }
1415
1416 int sap_server_init(DBusConnection *conn)
1417 {
1418         connection = dbus_connection_ref(conn);
1419         return 0;
1420 }
1421
1422 void sap_server_exit(void)
1423 {
1424         dbus_connection_unref(connection);
1425         connection = NULL;
1426 }