?? manager.c
字號:
DBusMessage *msg, *reply; DBusError derr; msg = dbus_message_new_method_call("org.bluez", "/org/bluez", "org.bluez.Database", "RemoveServiceRecord"); if (!msg) { error("Can't allocate new method call"); return -ENOMEM; } dbus_message_append_args(msg, DBUS_TYPE_UINT32, &rec_id, DBUS_TYPE_INVALID); dbus_error_init(&derr); reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr); dbus_message_unref(msg); if (dbus_error_is_set(&derr)) { error("Removing service record 0x%x failed: %s", rec_id, derr.message); dbus_error_free(&derr); return -1; } dbus_message_unref(reply); return 0;}static inline int unix_socket_connect(const char *address){ struct sockaddr_un addr; int err, sk; memset(&addr, 0, sizeof(addr)); addr.sun_family = PF_UNIX; if (strncmp("x00", address, 3) == 0) { /* * Abstract namespace: first byte NULL, x00 * must be removed from the original address. */ strcpy(addr.sun_path + 1, address + 3); } else { /* Filesystem address */ strcpy(addr.sun_path, address); } /* Unix socket */ sk = socket(AF_UNIX, SOCK_STREAM, 0); if (sk < 0) { err = errno; error("Unix socket(%s) create failed: %s(%d)", address, strerror(err), err); return -err; } if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { err = errno; error("Unix socket(%s) connect failed: %s(%d)", address, strerror(err), err); close(sk); errno = err; return -err; } return sk;}static int tcp_socket_connect(const char *address){ struct sockaddr_in addr; int err, sk; unsigned short int port; memset(&addr, 0, sizeof(addr)); if (strncmp(address, "localhost", 9) != 0) { error("Address should have the form localhost:port."); return -1; } port = atoi(strchr(address, ':') + 1); if (port <= 0) { error("Invalid port '%d'.", port); return -1; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_port = htons(port); sk = socket(PF_INET, SOCK_STREAM, 0); if (sk < 0) { err = errno; error("TCP socket(%s) create failed %s(%d)", address, strerror(err), err); return -err; } if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { err = errno; error("TCP socket(%s) connect failed: %s(%d)", address, strerror(err), err); close(sk); errno = err; return -err; } return sk;}static inline int tty_open(const char *tty, struct termios *ti){ int err, sk; sk = open(tty, O_RDWR | O_NOCTTY); if (sk < 0) { err = errno; error("Can't open TTY %s: %s(%d)", tty, strerror(err), err); return -err; } if (ti && tcsetattr(sk, TCSANOW, ti) < 0) { err = errno; error("Can't change serial settings: %s(%d)", strerror(err), err); close(sk); errno = err; return -err; } return sk;}static gboolean connect_event(GIOChannel *chan, GIOCondition cond, gpointer data){ struct proxy *prx = data; struct sockaddr_rc raddr; GIOChannel *rio, *lio; socklen_t alen; int sk, rsk, lsk; if (cond & G_IO_NVAL) return FALSE; if (cond & (G_IO_ERR | G_IO_HUP)) { g_io_channel_close(chan); return FALSE; } sk = g_io_channel_unix_get_fd(chan); memset(&raddr, 0, sizeof(raddr)); alen = sizeof(raddr); rsk = accept(sk, (struct sockaddr *) &raddr, &alen); if (rsk < 0) return TRUE; bacpy(&prx->dst, &raddr.rc_bdaddr); switch (prx->type) { case UNIX_SOCKET_PROXY: lsk = unix_socket_connect(prx->address); break; case TTY_PROXY: lsk = tty_open(prx->address, &prx->proxy_ti); break; case TCP_SOCKET_PROXY: lsk = tcp_socket_connect(prx->address); break; default: lsk = -1; } if (lsk < 0) { close(rsk); return TRUE; } rio = g_io_channel_unix_new(rsk); g_io_channel_set_close_on_unref(rio, TRUE); lio = g_io_channel_unix_new(lsk); g_io_channel_set_close_on_unref(lio, TRUE); prx->rfcomm_watch = g_io_add_watch(rio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, forward_data, lio); prx->local_watch = g_io_add_watch(lio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, forward_data, rio); g_io_channel_unref(rio); g_io_channel_unref(lio); return TRUE;}static void listen_watch_notify(gpointer data){ struct proxy *prx = data; prx->listen_watch = 0; if (prx->rfcomm_watch) { g_source_remove(prx->rfcomm_watch); prx->rfcomm_watch = 0; } if (prx->local_watch) { g_source_remove(prx->local_watch); prx->local_watch = 0; } remove_proxy_record(connection, prx->record_id); prx->record_id = 0;}static DBusHandlerResult proxy_enable(DBusConnection *conn, DBusMessage *msg, void *data){ struct proxy *prx = data; GIOChannel *io; sdp_buf_t buf; int sk; if (prx->listen_watch) return error_failed(conn, msg, "Already enabled"); /* Listen */ /* FIXME: missing options */ sk = rfcomm_listen(&prx->src, &prx->channel, 0); if (sk < 0) { const char *strerr = strerror(errno); error("RFCOMM listen socket failed: %s(%d)", strerr, errno); return error_failed(conn, msg, strerr); } /* Create the record */ create_proxy_record(&buf, prx->uuid128, prx->channel); /* Register the record */ prx->record_id = add_proxy_record(conn, &buf); if (!prx->record_id) { close(sk); return error_failed(conn, msg, "Service registration failed"); } /* Add incomming connection watch */ io = g_io_channel_unix_new(sk); g_io_channel_set_close_on_unref(io, TRUE); prx->listen_watch = g_io_add_watch_full(io, G_PRIORITY_DEFAULT, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, connect_event, prx, listen_watch_notify); g_io_channel_unref(io); return send_message_and_unref(conn, dbus_message_new_method_return(msg));}static DBusHandlerResult proxy_disable(DBusConnection *conn, DBusMessage *msg, void *data){ struct proxy *prx = data; if (!prx->listen_watch) return error_failed(conn, msg, "Not enabled"); /* Remove the watches and unregister the record: see watch notify */ g_source_remove(prx->listen_watch); return send_message_and_unref(conn, dbus_message_new_method_return(msg));}static DBusHandlerResult proxy_get_info(DBusConnection *conn, DBusMessage *msg, void *data){ struct proxy *prx = data; DBusMessage *reply; DBusMessageIter iter, dict; dbus_bool_t boolean; reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_iter_init_append(reply, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); dbus_message_iter_append_dict_entry(&dict, "uuid", DBUS_TYPE_STRING, &prx->uuid128); dbus_message_iter_append_dict_entry(&dict, "address", DBUS_TYPE_STRING, &prx->address); if (prx->channel) dbus_message_iter_append_dict_entry(&dict, "channel", DBUS_TYPE_BYTE, &prx->channel); boolean = (prx->listen_watch ? TRUE : FALSE); dbus_message_iter_append_dict_entry(&dict, "enabled", DBUS_TYPE_BOOLEAN, &boolean); boolean = (prx->rfcomm_watch ? TRUE : FALSE); dbus_message_iter_append_dict_entry(&dict, "connected", DBUS_TYPE_BOOLEAN, &boolean); /* If connected: append the remote address */ if (boolean) { char bda[18]; const char *pstr = bda; ba2str(&prx->dst, bda); dbus_message_iter_append_dict_entry(&dict, "address", DBUS_TYPE_STRING, &pstr); } dbus_message_iter_close_container(&iter, &dict); return send_message_and_unref(conn, reply);}static struct { const char *str; speed_t speed;} supported_speed[] = { {"50", B50 }, {"300", B300 }, {"600", B600 }, {"1200", B1200 }, {"1800", B1800 }, {"2400", B2400 }, {"4800", B4800 }, {"9600", B9600 }, {"19200", B19200 }, {"38400", B38400 }, {"57600", B57600 }, {"115200", B115200 }, { NULL, B0 }};static speed_t str2speed(const char *str, speed_t *speed){ int i; for (i = 0; supported_speed[i].str; i++) { if (strcmp(supported_speed[i].str, str) != 0) continue; if (speed) *speed = supported_speed[i].speed; return supported_speed[i].speed; } return B0;}static int set_parity(const char *str, tcflag_t *ctrl){ if (strcasecmp("even", str) == 0) { *ctrl |= PARENB; *ctrl &= ~PARODD; } else if (strcasecmp("odd", str) == 0) { *ctrl |= PARENB; *ctrl |= PARODD; } else if (strcasecmp("mark", str) == 0) *ctrl |= PARENB; else if ((strcasecmp("none", str) == 0) || (strcasecmp("space", str) == 0)) *ctrl &= ~PARENB; else return -1; return 0;}static int set_databits(uint8_t databits, tcflag_t *ctrl){ if (databits < 5 || databits > 8) return -EINVAL; *ctrl &= ~CSIZE; switch (databits) { case 5: *ctrl |= CS5; break; case 6: *ctrl |= CS6; break; case 7: *ctrl |= CS7; break; case 8: *ctrl |= CS8; break; } return 0;}static int set_stopbits(uint8_t stopbits, tcflag_t *ctrl){ /* 1.5 will not be allowed */ switch (stopbits) { case 1: *ctrl &= ~CSTOPB; return 0; case 2: *ctrl |= CSTOPB; return 0; } return -EINVAL;}static DBusHandlerResult proxy_set_serial_params(DBusConnection *conn, DBusMessage *msg, void *data){ DBusError derr; struct proxy *prx = data; const char *ratestr, *paritystr; uint8_t databits, stopbits; tcflag_t ctrl; /* Control mode flags */ speed_t speed = B0; /* In/Out speed */ /* Don't allow change TTY settings if it is open */ if (prx->local_watch) return error_failed(conn, msg, "Not allowed"); dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, DBUS_TYPE_STRING, &ratestr, DBUS_TYPE_BYTE, &databits, DBUS_TYPE_BYTE, &stopbits, DBUS_TYPE_STRING, &paritystr, DBUS_TYPE_INVALID)) { error_invalid_arguments(conn, msg, derr.message); dbus_error_free(&derr); return DBUS_HANDLER_RESULT_HANDLED; } if (str2speed(ratestr, &speed) == B0) return error_invalid_arguments(conn, msg, "Invalid baud rate"); ctrl = prx->proxy_ti.c_cflag; if (set_databits(databits, &ctrl) < 0) return error_invalid_arguments(conn, msg, "Invalid data bits"); if (set_stopbits(stopbits, &ctrl) < 0) return error_invalid_arguments(conn, msg, "Invalid stop bits"); if (set_parity(paritystr, &ctrl) < 0) return error_invalid_arguments(conn, msg, "Invalid parity"); prx->proxy_ti.c_cflag = ctrl; prx->proxy_ti.c_cflag |= (CLOCAL | CREAD); cfsetispeed(&prx->proxy_ti, speed); cfsetospeed(&prx->proxy_ti, speed); return send_message_and_unref(conn, dbus_message_new_method_return(msg));}static DBusMethodVTable proxy_methods[] = { { "Enable", proxy_enable, "", "" }, { "Disable", proxy_disable, "", "" }, { "GetInfo", proxy_get_info, "", "a{sv}" }, { "SetSerialParameters", proxy_set_serial_params, "syys", "" }, { NULL, NULL, NULL, NULL },};static void proxy_handler_unregister(DBusConnection *conn, void *data){ struct proxy *prx = data; int sk; info("Unregistered proxy: %s", prx->address); if (prx->type != TTY_PROXY) goto done; /* Restore the initial TTY configuration */ sk = open(prx->address, O_RDWR | O_NOCTTY); if (sk) { tcsetattr(sk, TCSAFLUSH, &prx->sys_ti); close(sk); }done: if (prx->listen_watch) g_source_remove(prx->listen_watch); proxy_free(prx);}static int register_proxy_object(struct proxy *prx, char *outpath, size_t size){ char path[MAX_PATH_LENGTH + 1]; snprintf(path, MAX_PATH_LENGTH, "/org/bluez/serial/proxy%d", sk_counter++); if (!dbus_connection_create_object_path(connection, path, prx, proxy_handler_unregister)) { error("D-Bus failed to register %s path", path); return -1; } dbus_connection_register_interface(connection, path, SERIAL_PROXY_INTERFACE, proxy_methods, NULL, NULL); proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); if (outpath) strncpy(outpath, path, size); info("Registered proxy:%s", path); return 0;}static int proxy_tty_register(bdaddr_t *src, const char *uuid128, const char *address, struct termios *ti, char *outpath, size_t size){ struct termios sys_ti; struct proxy *prx; int sk, ret; sk = open(address, O_RDONLY | O_NOCTTY); if (sk < 0) { error("Cant open TTY: %s(%d)", strerror(errno), errno); return -EINVAL; } prx = g_new0(struct proxy, 1); prx->address = g_strdup(address); prx->uuid128 = g_strdup(uuid128); prx->type = TTY_PROXY; bacpy(&prx->src, src); /* Current TTY settings */ memset(&sys_ti, 0, sizeof(sys_ti)); tcgetattr(sk, &sys_ti); memcpy(&prx->sys_ti, &sys_ti, sizeof(sys_ti)); close(sk); if (!ti) { /* Use current settings */ memcpy(&prx->proxy_ti, &sys_ti, sizeof(sys_ti)); } else { /* New TTY settings: user provided */ memcpy(&prx->proxy_ti, ti, sizeof(*ti)); } ret = register_proxy_object(prx, outpath, size); if (ret < 0) proxy_free(prx); return ret;}static int proxy_socket_register(bdaddr_t *src, const char *uuid128, const char *address, char *outpath, size_t size){ struct proxy *prx; int ret; prx = g_new0(struct proxy, 1); prx->address = g_strdup(address); prx->uuid128 = g_strdup(uuid128); prx->type = UNIX_SOCKET_PROXY; bacpy(&prx->src, src); ret = register_proxy_object(prx, outpath, size); if (ret < 0) proxy_free(prx); return ret;}static int proxy_tcp_register(bdaddr_t *src, const char *uuid128, const char *address, char *outpath, size_t size){ struct proxy *prx; int ret; prx = g_new0(struct proxy, 1); prx->address = g_strdup(address); prx->uuid128 = g_strdup(uuid128); prx->type = TCP_SOCKET_PROXY; bacpy(&prx->src, src); ret = register_proxy_object(prx, outpath, size); if (ret < 0) proxy_free(prx); return ret;}static proxy_type_t addr2type(const char *address){ struct stat st; if (stat(address, &st) < 0) { /*
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -