📄 main.c
字号:
/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2003-2008 Marcel Holtmann <marcel@holtmann.org> * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <gdbus.h>#include "cups.h"#include "sdp-xml.h"extern int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel);extern int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm);extern int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class);extern int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class);#define PRINTER_SERVICE_CLASS_NAME "printer"struct cups_device { char *bdaddr; char *name; char *id;};static GSList *device_list = NULL;static GMainLoop *loop = NULL;static DBusConnection *conn = NULL;#define ATTRID_1284ID 0x0300static char *parse_xml_sdp(const char *xml){ sdp_record_t *sdp_record; sdp_list_t *l; char *str = NULL; sdp_record = sdp_xml_parse_record(xml, strlen(xml)); if (sdp_record == NULL) return NULL; for (l = sdp_record->attrlist; l != NULL; l = l->next) { sdp_data_t *data; data = (sdp_data_t *) l->data; if (data->attrId != ATTRID_1284ID) continue; /* Ignore the length, it's null terminated */ str = g_strdup(data->val.str + 2); break; } sdp_record_free(sdp_record); return str;}static char *device_get_ieee1284_id(const char *adapter, const char *bdaddr){ guint service_handle; DBusMessage *message, *reply; DBusMessageIter iter, reply_iter, iter_array; const char *hcr_print = "00001126-0000-1000-8000-00805f9b34fb"; char *xml, *id; /* Look for the service handle of the HCRP service */ message = dbus_message_new_method_call("org.bluez", adapter, "org.bluez.Adapter", "GetRemoteServiceHandles"); dbus_message_iter_init_append(message, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &hcr_print); reply = dbus_connection_send_with_reply_and_block(conn, message, -1, NULL); dbus_message_unref(message); if (!reply) return NULL; dbus_message_iter_init(reply, &reply_iter); if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) { dbus_message_unref(reply); return NULL; } /* Hopefully we only get one handle, or take a punt */ dbus_message_iter_recurse(&reply_iter, &iter_array); while (dbus_message_iter_get_arg_type(&iter_array) == DBUS_TYPE_UINT32) { dbus_message_iter_get_basic(&iter_array, &service_handle); dbus_message_iter_next(&iter_array); } dbus_message_unref(reply); /* Now get the XML for the HCRP service record */ message = dbus_message_new_method_call("org.bluez", adapter, "org.bluez.Adapter", "GetRemoteServiceRecordAsXML"); dbus_message_iter_init_append(message, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr); dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &service_handle); reply = dbus_connection_send_with_reply_and_block(conn, message, -1, NULL); dbus_message_unref(message); if (!reply) return NULL; dbus_message_iter_init(reply, &reply_iter); dbus_message_iter_get_basic(&reply_iter, &xml); id = parse_xml_sdp(xml); dbus_message_unref(reply); return id;}static void add_device_to_list(const char *name, const char *bdaddr, const char *id){ struct cups_device *device; GSList *l; /* Look for the device in the list */ for (l = device_list; l != NULL; l = l->next) { device = (struct cups_device *) l->data; if (strcmp(device->bdaddr, bdaddr) == 0) { g_free(device->name); device->name = g_strdup(name); return; } } /* Or add it to the list if it's not there */ device = g_new0(struct cups_device, 1); device->bdaddr = g_strdup(bdaddr); device->name = g_strdup(name); device->id = g_strdup(id); device_list = g_slist_prepend(device_list, device);}static char *escape_name(const char *str, char orig, char dest){ char *ret, *s; ret = g_strdup(str); while ((s = strchr(ret, orig)) != NULL) s[0] = dest; return ret;}static void print_printer_details(const char *name, const char *bdaddr, const char *id){ char *uri, *escaped; guint len; escaped = escape_name(name, '\"', '\''); len = strlen("bluetooth://") + 12 + 1; uri = g_malloc(len); snprintf(uri, len, "bluetooth://%c%c%c%c%c%c%c%c%c%c%c%c", bdaddr[0], bdaddr[1], bdaddr[3], bdaddr[4], bdaddr[6], bdaddr[7], bdaddr[9], bdaddr[10], bdaddr[12], bdaddr[13], bdaddr[15], bdaddr[16]); printf("network %s \"Unknown\" \"%s (Bluetooth)\"", uri, escaped); if (id != NULL) printf(" \"%s\"\n", id); else printf ("\n"); g_free(escaped); g_free(uri);}static gboolean device_is_printer(const char *adapter, const char *bdaddr){ char *class; DBusMessage *message, *reply; DBusMessageIter iter, reply_iter; message = dbus_message_new_method_call("org.bluez", adapter, "org.bluez.Adapter", "GetRemoteMinorClass"); dbus_message_iter_init_append(message, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr); reply = dbus_connection_send_with_reply_and_block(conn, message, -1, NULL); dbus_message_unref(message); if (!reply) return FALSE; dbus_message_iter_init(reply, &reply_iter); dbus_message_iter_get_basic(&reply_iter, &class); if (class != NULL && strcmp(class, PRINTER_SERVICE_CLASS_NAME) == 0) { dbus_message_unref(reply); return TRUE; } return FALSE;}static char *device_get_name(const char *adapter, const char *bdaddr){ DBusMessage *message, *reply; DBusMessageIter iter, reply_iter; char *name; message = dbus_message_new_method_call("org.bluez", adapter, "org.bluez.Adapter", "GetRemoteName"); dbus_message_iter_init_append(message, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr); reply = dbus_connection_send_with_reply_and_block(conn, message, -1, NULL); dbus_message_unref(message); if (!reply) return NULL; dbus_message_iter_init(reply, &reply_iter); dbus_message_iter_get_basic(&reply_iter, &name); name = g_strdup(name); dbus_message_unref(reply); return name;}static void remote_device_found(const char *adapter, const char *bdaddr, guint class, int rssi){ uint8_t major_index = (class >> 8) & 0x1F; uint8_t minor_index; uint8_t shift_minor = 0; gboolean found = FALSE; char *name, *id; /* Check if we have a printer * From hcid/dbus-adapter.c minor_class_str() */ if (major_index != 6) return; minor_index = (class >> 4) & 0x0F; while (shift_minor < 4) { if (((minor_index >> shift_minor) & 0x01) == 0x01) { if (shift_minor == 3) { found = TRUE; break; } } shift_minor++; } if (!found) return; name = device_get_name(adapter, bdaddr); id = device_get_ieee1284_id(adapter, bdaddr); add_device_to_list(name, bdaddr, id); g_free(name); g_free(id);}static void remote_name_updated(const char *bdaddr, const char *name){ add_device_to_list(name, bdaddr, NULL);}static void discovery_completed(void){ GSList *l; for (l = device_list; l != NULL; l = l->next) { struct cups_device *device = (struct cups_device *) l->data; if (device->name == NULL) device->name = escape_name(device->bdaddr, ':', '-'); print_printer_details(device->name, device->bdaddr, device->id); g_free(device->name); g_free(device->bdaddr); g_free(device->id); g_free(device); } g_slist_free(device_list); device_list = NULL; g_main_loop_quit(loop);}static void remote_device_disappeared(const char *bdaddr){ GSList *l; for (l = device_list; l != NULL; l = l->next) { struct cups_device *device = (struct cups_device *) l->data; if (strcmp(device->bdaddr, bdaddr) == 0) { g_free(device->name); g_free(device->bdaddr); g_free(device); device_list = g_slist_delete_link(device_list, l); return; } }}static gboolean list_known_printers(const char *adapter){ DBusMessageIter reply_iter, iter_array; DBusError error; DBusMessage *message, *reply;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -