Merge lp:~timchen119/ubuntu/utopic/gnome-bluetooth/lp1035431 into lp:ubuntu/utopic/gnome-bluetooth
- Utopic (14.10)
- lp1035431
- Merge into utopic
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Mathieu Trudel-Lapierre | ||||
Approved revision: | 94 | ||||
Merge reported by: | Mathieu Trudel-Lapierre | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~timchen119/ubuntu/utopic/gnome-bluetooth/lp1035431 | ||||
Merge into: | lp:ubuntu/utopic/gnome-bluetooth | ||||
Diff against target: |
1854 lines (+1753/-12) 8 files modified
.pc/applied-patches (+1/-0) .pc/ssp-parameter-fix.patch/lib/bluetooth-agent.c (+633/-0) .pc/ssp-parameter-fix.patch/wizard/main.c (+1001/-0) debian/changelog (+10/-0) debian/patches/series (+1/-0) debian/patches/ssp-parameter-fix.patch (+86/-0) lib/bluetooth-agent.c (+4/-4) wizard/main.c (+17/-8) |
||||
To merge this branch: | bzr merge lp:~timchen119/ubuntu/utopic/gnome-bluetooth/lp1035431 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mathieu Trudel-Lapierre | Approve | ||
Review via email: mp+219628@code.launchpad.net |
Commit message
Description of the change
This fixed the issue for the paring issue on Logitech K810 and HP bluetooth keyboard K4000 and should also fixed any ssp paired bluetooth keyboard.
gnome-bluetooth is being removed in recent gnome upstream, so we need to maintain a ubuntu distro patch here.
Another related merge is at
https:/
The root problem here is that in bluez4, the doc (agent-api.txt), specific that the
function
void DisplayPasskey(
however in bluez4's src/agent.c agent_display_
didn't pass the entered correct "enter" parameter,
and most of client implementation in linux (at least gnome-bluetooth, bluedevil, blueman) follows the specification in the api document so they never receive correct parameter.
This is already fixed in bluez5,
however due to the compatibility issue between bluez4 and bluez5
this never being backported in bluez4.
This request is from our OEM so please help to review these patch and see if there's things I can improve this patch. If the patch is accepted I'll send SRUs to trusty (OEM shipping image is LTS based, so it will be trusty right now).
Preview Diff
1 | === modified file '.pc/applied-patches' | |||
2 | --- .pc/applied-patches 2014-02-25 16:32:43 +0000 | |||
3 | +++ .pc/applied-patches 2014-05-15 03:31:21 +0000 | |||
4 | @@ -7,3 +7,4 @@ | |||
5 | 7 | git_leak_fixes.patch | 7 | git_leak_fixes.patch |
6 | 8 | git_disconnect_callbacks.patch | 8 | git_disconnect_callbacks.patch |
7 | 9 | git_reference_handling.patch | 9 | git_reference_handling.patch |
8 | 10 | ssp-parameter-fix.patch | ||
9 | 10 | 11 | ||
10 | === added directory '.pc/ssp-parameter-fix.patch' | |||
11 | === added directory '.pc/ssp-parameter-fix.patch/lib' | |||
12 | === added file '.pc/ssp-parameter-fix.patch/lib/bluetooth-agent.c' | |||
13 | --- .pc/ssp-parameter-fix.patch/lib/bluetooth-agent.c 1970-01-01 00:00:00 +0000 | |||
14 | +++ .pc/ssp-parameter-fix.patch/lib/bluetooth-agent.c 2014-05-15 03:31:21 +0000 | |||
15 | @@ -0,0 +1,633 @@ | |||
16 | 1 | /* | ||
17 | 2 | * | ||
18 | 3 | * BlueZ - Bluetooth protocol stack for Linux | ||
19 | 4 | * | ||
20 | 5 | * Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org> | ||
21 | 6 | * | ||
22 | 7 | * | ||
23 | 8 | * This library is free software; you can redistribute it and/or | ||
24 | 9 | * modify it under the terms of the GNU Lesser General Public | ||
25 | 10 | * License as published by the Free Software Foundation; either | ||
26 | 11 | * version 2.1 of the License, or (at your option) any later version. | ||
27 | 12 | * | ||
28 | 13 | * This library is distributed in the hope that it will be useful, | ||
29 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
30 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
31 | 16 | * Lesser General Public License for more details. | ||
32 | 17 | * | ||
33 | 18 | * You should have received a copy of the GNU Lesser General Public | ||
34 | 19 | * License along with this library; if not, write to the Free Software | ||
35 | 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
36 | 21 | * | ||
37 | 22 | */ | ||
38 | 23 | |||
39 | 24 | #ifdef HAVE_CONFIG_H | ||
40 | 25 | #include <config.h> | ||
41 | 26 | #endif | ||
42 | 27 | |||
43 | 28 | #include <stdio.h> | ||
44 | 29 | #include <gio/gio.h> | ||
45 | 30 | |||
46 | 31 | #include "bluetooth-client-glue.h" | ||
47 | 32 | #include "bluetooth-agent.h" | ||
48 | 33 | |||
49 | 34 | #define BLUEZ_SERVICE "org.bluez" | ||
50 | 35 | |||
51 | 36 | #define BLUEZ_MANAGER_PATH "/" | ||
52 | 37 | #define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager" | ||
53 | 38 | #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device" | ||
54 | 39 | |||
55 | 40 | static const gchar introspection_xml[] = | ||
56 | 41 | "<node name='/'>" | ||
57 | 42 | " <interface name='org.bluez.Agent'>" | ||
58 | 43 | " <method name='Release'/>" | ||
59 | 44 | " <method name='RequestPinCode'>" | ||
60 | 45 | " <arg type='o' name='device' direction='in'/>" | ||
61 | 46 | " <arg type='s' name='pincode' direction='out'/>" | ||
62 | 47 | " </method>" | ||
63 | 48 | " <method name='RequestPasskey'>" | ||
64 | 49 | " <arg type='o' name='device' direction='in'/>" | ||
65 | 50 | " <arg type='u' name='passkey' direction='out'/>" | ||
66 | 51 | " </method>" | ||
67 | 52 | " <method name='DisplayPasskey'>" | ||
68 | 53 | " <arg type='o' name='device' direction='in'/>" | ||
69 | 54 | " <arg type='u' name='passkey' direction='in'/>" | ||
70 | 55 | " <arg type='y' name='entered' direction='in'/>" | ||
71 | 56 | " </method>" | ||
72 | 57 | " <method name='RequestConfirmation'>" | ||
73 | 58 | " <arg type='o' name='device' direction='in'/>" | ||
74 | 59 | " <arg type='u' name='passkey' direction='in'/>" | ||
75 | 60 | " </method>" | ||
76 | 61 | " <method name='Authorize'>" | ||
77 | 62 | " <arg type='o' name='device' direction='in'/>" | ||
78 | 63 | " <arg type='s' name='uuid' direction='in'/>" | ||
79 | 64 | " </method>" | ||
80 | 65 | " <method name='ConfirmMode'>" | ||
81 | 66 | " <arg type='s' name='mode'/>" | ||
82 | 67 | " </method>" | ||
83 | 68 | " <method name='Cancel'/>" | ||
84 | 69 | " </interface>" | ||
85 | 70 | "</node>"; | ||
86 | 71 | |||
87 | 72 | #define BLUETOOTH_AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ | ||
88 | 73 | BLUETOOTH_TYPE_AGENT, BluetoothAgentPrivate)) | ||
89 | 74 | |||
90 | 75 | typedef struct _BluetoothAgentPrivate BluetoothAgentPrivate; | ||
91 | 76 | |||
92 | 77 | struct _BluetoothAgentPrivate { | ||
93 | 78 | GDBusConnection *conn; | ||
94 | 79 | gchar *busname; | ||
95 | 80 | gchar *path; | ||
96 | 81 | GDBusProxy *adapter; | ||
97 | 82 | GDBusNodeInfo *introspection_data; | ||
98 | 83 | guint reg_id; | ||
99 | 84 | guint watch_id; | ||
100 | 85 | |||
101 | 86 | BluetoothAgentPasskeyFunc pincode_func; | ||
102 | 87 | gpointer pincode_data; | ||
103 | 88 | |||
104 | 89 | BluetoothAgentDisplayFunc display_func; | ||
105 | 90 | gpointer display_data; | ||
106 | 91 | |||
107 | 92 | BluetoothAgentPasskeyFunc passkey_func; | ||
108 | 93 | gpointer passkey_data; | ||
109 | 94 | |||
110 | 95 | BluetoothAgentConfirmFunc confirm_func; | ||
111 | 96 | gpointer confirm_data; | ||
112 | 97 | |||
113 | 98 | BluetoothAgentAuthorizeFunc authorize_func; | ||
114 | 99 | gpointer authorize_data; | ||
115 | 100 | |||
116 | 101 | BluetoothAgentCancelFunc cancel_func; | ||
117 | 102 | gpointer cancel_data; | ||
118 | 103 | }; | ||
119 | 104 | |||
120 | 105 | G_DEFINE_TYPE(BluetoothAgent, bluetooth_agent, G_TYPE_OBJECT) | ||
121 | 106 | |||
122 | 107 | static GDBusProxy * | ||
123 | 108 | get_device_from_adapter (BluetoothAgent *agent, | ||
124 | 109 | const char *path) | ||
125 | 110 | { | ||
126 | 111 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
127 | 112 | |||
128 | 113 | if (priv->adapter == NULL) | ||
129 | 114 | return NULL; | ||
130 | 115 | |||
131 | 116 | return g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, | ||
132 | 117 | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, | ||
133 | 118 | NULL, | ||
134 | 119 | g_dbus_proxy_get_name (priv->adapter), | ||
135 | 120 | path, | ||
136 | 121 | BLUEZ_DEVICE_INTERFACE, | ||
137 | 122 | NULL, | ||
138 | 123 | NULL); | ||
139 | 124 | } | ||
140 | 125 | |||
141 | 126 | static gboolean bluetooth_agent_request_pin_code(BluetoothAgent *agent, | ||
142 | 127 | const char *path, GDBusMethodInvocation *invocation) | ||
143 | 128 | { | ||
144 | 129 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
145 | 130 | GDBusProxy *device; | ||
146 | 131 | gboolean result = FALSE; | ||
147 | 132 | |||
148 | 133 | if (priv->pincode_func) { | ||
149 | 134 | device = get_device_from_adapter (agent, path); | ||
150 | 135 | |||
151 | 136 | result = priv->pincode_func(invocation, device, | ||
152 | 137 | priv->pincode_data); | ||
153 | 138 | |||
154 | 139 | if (device != NULL) | ||
155 | 140 | g_object_unref(device); | ||
156 | 141 | } | ||
157 | 142 | |||
158 | 143 | return result; | ||
159 | 144 | } | ||
160 | 145 | |||
161 | 146 | static gboolean bluetooth_agent_request_passkey(BluetoothAgent *agent, | ||
162 | 147 | const char *path, GDBusMethodInvocation *invocation) | ||
163 | 148 | { | ||
164 | 149 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
165 | 150 | GDBusProxy *device; | ||
166 | 151 | gboolean result = FALSE; | ||
167 | 152 | |||
168 | 153 | if (priv->passkey_func) { | ||
169 | 154 | device = get_device_from_adapter (agent, path); | ||
170 | 155 | |||
171 | 156 | result = priv->passkey_func(invocation, device, | ||
172 | 157 | priv->passkey_data); | ||
173 | 158 | |||
174 | 159 | if (device != NULL) | ||
175 | 160 | g_object_unref(device); | ||
176 | 161 | } | ||
177 | 162 | |||
178 | 163 | return result; | ||
179 | 164 | } | ||
180 | 165 | |||
181 | 166 | static gboolean bluetooth_agent_display_passkey(BluetoothAgent *agent, | ||
182 | 167 | const char *path, guint passkey, guint8 entered, | ||
183 | 168 | GDBusMethodInvocation *invocation) | ||
184 | 169 | { | ||
185 | 170 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
186 | 171 | GDBusProxy *device; | ||
187 | 172 | gboolean result = FALSE; | ||
188 | 173 | |||
189 | 174 | if (priv->display_func) { | ||
190 | 175 | device = get_device_from_adapter (agent, path); | ||
191 | 176 | |||
192 | 177 | result = priv->display_func(invocation, device, passkey, entered, | ||
193 | 178 | priv->display_data); | ||
194 | 179 | |||
195 | 180 | if (device != NULL) | ||
196 | 181 | g_object_unref(device); | ||
197 | 182 | } | ||
198 | 183 | |||
199 | 184 | return result; | ||
200 | 185 | } | ||
201 | 186 | |||
202 | 187 | static gboolean bluetooth_agent_request_confirmation(BluetoothAgent *agent, | ||
203 | 188 | const char *path, guint passkey, | ||
204 | 189 | GDBusMethodInvocation *invocation) | ||
205 | 190 | { | ||
206 | 191 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
207 | 192 | GDBusProxy *device; | ||
208 | 193 | gboolean result = FALSE; | ||
209 | 194 | |||
210 | 195 | if (priv->confirm_func) { | ||
211 | 196 | device = get_device_from_adapter (agent, path); | ||
212 | 197 | |||
213 | 198 | result = priv->confirm_func(invocation, device, passkey, | ||
214 | 199 | priv->confirm_data); | ||
215 | 200 | |||
216 | 201 | if (device != NULL) | ||
217 | 202 | g_object_unref(device); | ||
218 | 203 | } | ||
219 | 204 | |||
220 | 205 | return result; | ||
221 | 206 | } | ||
222 | 207 | |||
223 | 208 | static gboolean bluetooth_agent_authorize(BluetoothAgent *agent, | ||
224 | 209 | const char *path, const char *uuid, | ||
225 | 210 | GDBusMethodInvocation *invocation) | ||
226 | 211 | { | ||
227 | 212 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
228 | 213 | GDBusProxy *device; | ||
229 | 214 | gboolean result = FALSE; | ||
230 | 215 | |||
231 | 216 | if (priv->authorize_func) { | ||
232 | 217 | device = get_device_from_adapter (agent, path); | ||
233 | 218 | |||
234 | 219 | result = priv->authorize_func(invocation, device, uuid, | ||
235 | 220 | priv->authorize_data); | ||
236 | 221 | |||
237 | 222 | if (device != NULL) | ||
238 | 223 | g_object_unref(device); | ||
239 | 224 | } | ||
240 | 225 | |||
241 | 226 | return result; | ||
242 | 227 | } | ||
243 | 228 | |||
244 | 229 | static gboolean bluetooth_agent_cancel(BluetoothAgent *agent, | ||
245 | 230 | GDBusMethodInvocation *invocation) | ||
246 | 231 | { | ||
247 | 232 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
248 | 233 | gboolean result = FALSE; | ||
249 | 234 | |||
250 | 235 | if (priv->cancel_func) | ||
251 | 236 | result = priv->cancel_func(invocation, priv->cancel_data); | ||
252 | 237 | |||
253 | 238 | return result; | ||
254 | 239 | } | ||
255 | 240 | |||
256 | 241 | static void | ||
257 | 242 | name_appeared_cb (GDBusConnection *connection, | ||
258 | 243 | const gchar *name, | ||
259 | 244 | const gchar *name_owner, | ||
260 | 245 | BluetoothAgent *agent) | ||
261 | 246 | { | ||
262 | 247 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
263 | 248 | |||
264 | 249 | g_free (priv->busname); | ||
265 | 250 | priv->busname = g_strdup (name_owner); | ||
266 | 251 | } | ||
267 | 252 | |||
268 | 253 | static void | ||
269 | 254 | name_vanished_cb (GDBusConnection *connection, | ||
270 | 255 | const gchar *name, | ||
271 | 256 | BluetoothAgent *agent) | ||
272 | 257 | { | ||
273 | 258 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
274 | 259 | |||
275 | 260 | g_free (priv->busname); | ||
276 | 261 | priv->busname = NULL; | ||
277 | 262 | } | ||
278 | 263 | |||
279 | 264 | static void bluetooth_agent_init(BluetoothAgent *agent) | ||
280 | 265 | { | ||
281 | 266 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
282 | 267 | |||
283 | 268 | priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); | ||
284 | 269 | g_assert (priv->introspection_data); | ||
285 | 270 | priv->conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); | ||
286 | 271 | priv->watch_id = g_bus_watch_name_on_connection (priv->conn, | ||
287 | 272 | BLUEZ_SERVICE, | ||
288 | 273 | G_BUS_NAME_WATCHER_FLAGS_NONE, | ||
289 | 274 | (GBusNameAppearedCallback) name_appeared_cb, | ||
290 | 275 | (GBusNameVanishedCallback) name_vanished_cb, | ||
291 | 276 | agent, | ||
292 | 277 | NULL); | ||
293 | 278 | } | ||
294 | 279 | |||
295 | 280 | static void bluetooth_agent_finalize(GObject *agent) | ||
296 | 281 | { | ||
297 | 282 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
298 | 283 | |||
299 | 284 | bluetooth_agent_unregister (BLUETOOTH_AGENT (agent)); | ||
300 | 285 | |||
301 | 286 | g_bus_unwatch_name (priv->watch_id); | ||
302 | 287 | g_free (priv->busname); | ||
303 | 288 | g_dbus_node_info_unref (priv->introspection_data); | ||
304 | 289 | g_object_unref (priv->conn); | ||
305 | 290 | |||
306 | 291 | G_OBJECT_CLASS(bluetooth_agent_parent_class)->finalize(agent); | ||
307 | 292 | } | ||
308 | 293 | |||
309 | 294 | static void bluetooth_agent_class_init(BluetoothAgentClass *klass) | ||
310 | 295 | { | ||
311 | 296 | GObjectClass *object_class = (GObjectClass *) klass; | ||
312 | 297 | |||
313 | 298 | g_type_class_add_private(klass, sizeof(BluetoothAgentPrivate)); | ||
314 | 299 | |||
315 | 300 | object_class->finalize = bluetooth_agent_finalize; | ||
316 | 301 | } | ||
317 | 302 | |||
318 | 303 | BluetoothAgent * | ||
319 | 304 | bluetooth_agent_new (void) | ||
320 | 305 | { | ||
321 | 306 | return BLUETOOTH_AGENT (g_object_new (BLUETOOTH_TYPE_AGENT, NULL)); | ||
322 | 307 | } | ||
323 | 308 | |||
324 | 309 | static void | ||
325 | 310 | handle_method_call (GDBusConnection *connection, | ||
326 | 311 | const gchar *sender, | ||
327 | 312 | const gchar *object_path, | ||
328 | 313 | const gchar *interface_name, | ||
329 | 314 | const gchar *method_name, | ||
330 | 315 | GVariant *parameters, | ||
331 | 316 | GDBusMethodInvocation *invocation, | ||
332 | 317 | gpointer user_data) | ||
333 | 318 | { | ||
334 | 319 | BluetoothAgent *agent = (BluetoothAgent *) user_data; | ||
335 | 320 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
336 | 321 | |||
337 | 322 | if (g_str_equal (sender, priv->busname) == FALSE) { | ||
338 | 323 | g_assert_not_reached (); | ||
339 | 324 | /* FIXME, should this just be a D-Bus Error instead? */ | ||
340 | 325 | } | ||
341 | 326 | |||
342 | 327 | if (g_strcmp0 (method_name, "Release") == 0) { | ||
343 | 328 | g_dbus_method_invocation_return_value (invocation, NULL); | ||
344 | 329 | } else if (g_strcmp0 (method_name, "RequestPinCode") == 0) { | ||
345 | 330 | char *path; | ||
346 | 331 | g_variant_get (parameters, "(o)", &path); | ||
347 | 332 | bluetooth_agent_request_pin_code (agent, path, invocation); | ||
348 | 333 | g_free (path); | ||
349 | 334 | } else if (g_strcmp0 (method_name, "RequestPasskey") == 0) { | ||
350 | 335 | char *path; | ||
351 | 336 | g_variant_get (parameters, "(o)", &path); | ||
352 | 337 | bluetooth_agent_request_passkey (agent, path, invocation); | ||
353 | 338 | g_free (path); | ||
354 | 339 | } else if (g_strcmp0 (method_name, "DisplayPasskey") == 0) { | ||
355 | 340 | char *path; | ||
356 | 341 | guint32 passkey; | ||
357 | 342 | guint8 entered; | ||
358 | 343 | |||
359 | 344 | g_variant_get (parameters, "(ouy)", &path, &passkey, &entered); | ||
360 | 345 | bluetooth_agent_display_passkey (agent, path, passkey, entered, invocation); | ||
361 | 346 | g_free (path); | ||
362 | 347 | } else if (g_strcmp0 (method_name, "RequestConfirmation") == 0) { | ||
363 | 348 | char *path; | ||
364 | 349 | guint32 passkey; | ||
365 | 350 | |||
366 | 351 | g_variant_get (parameters, "(ou)", &path, &passkey); | ||
367 | 352 | bluetooth_agent_request_confirmation (agent, path, passkey, invocation); | ||
368 | 353 | g_free (path); | ||
369 | 354 | } else if (g_strcmp0 (method_name, "Authorize") == 0) { | ||
370 | 355 | char *path, *uuid; | ||
371 | 356 | g_variant_get (parameters, "(os)", &path, &uuid); | ||
372 | 357 | bluetooth_agent_authorize (agent, path, uuid, invocation); | ||
373 | 358 | g_free (path); | ||
374 | 359 | g_free (uuid); | ||
375 | 360 | } else if (g_strcmp0 (method_name, "Cancel") == 0) { | ||
376 | 361 | bluetooth_agent_cancel (agent, invocation); | ||
377 | 362 | } else if (g_strcmp0 (method_name, "ConfirmMode") == 0) { | ||
378 | 363 | g_dbus_method_invocation_return_value (invocation, NULL); | ||
379 | 364 | } | ||
380 | 365 | } | ||
381 | 366 | |||
382 | 367 | static const GDBusInterfaceVTable interface_vtable = | ||
383 | 368 | { | ||
384 | 369 | handle_method_call, | ||
385 | 370 | NULL, /* GetProperty */ | ||
386 | 371 | NULL, /* SetProperty */ | ||
387 | 372 | }; | ||
388 | 373 | |||
389 | 374 | gboolean bluetooth_agent_setup(BluetoothAgent *agent, const char *path) | ||
390 | 375 | { | ||
391 | 376 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
392 | 377 | GError *error = NULL; | ||
393 | 378 | |||
394 | 379 | if (priv->path != NULL) { | ||
395 | 380 | g_warning ("Agent already setup on '%s'", priv->path); | ||
396 | 381 | return FALSE; | ||
397 | 382 | } | ||
398 | 383 | |||
399 | 384 | priv->path = g_strdup(path); | ||
400 | 385 | |||
401 | 386 | priv->reg_id = g_dbus_connection_register_object (priv->conn, | ||
402 | 387 | priv->path, | ||
403 | 388 | priv->introspection_data->interfaces[0], | ||
404 | 389 | &interface_vtable, | ||
405 | 390 | agent, | ||
406 | 391 | NULL, | ||
407 | 392 | &error); | ||
408 | 393 | if (priv->reg_id == 0) { | ||
409 | 394 | g_warning ("Failed to register object: %s", error->message); | ||
410 | 395 | g_error_free (error); | ||
411 | 396 | } | ||
412 | 397 | |||
413 | 398 | return TRUE; | ||
414 | 399 | } | ||
415 | 400 | |||
416 | 401 | #define BLUEZ_SERVICE "org.bluez" | ||
417 | 402 | #define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager" | ||
418 | 403 | |||
419 | 404 | static GDBusProxy * | ||
420 | 405 | get_default_adapter (void) | ||
421 | 406 | { | ||
422 | 407 | Manager *manager; | ||
423 | 408 | char *adapter_path; | ||
424 | 409 | Adapter *adapter; | ||
425 | 410 | |||
426 | 411 | manager = manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, | ||
427 | 412 | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, | ||
428 | 413 | BLUEZ_SERVICE, | ||
429 | 414 | BLUEZ_MANAGER_PATH, | ||
430 | 415 | NULL, | ||
431 | 416 | NULL); | ||
432 | 417 | if (manager == NULL) | ||
433 | 418 | return NULL; | ||
434 | 419 | if (manager_call_default_adapter_sync (manager, &adapter_path, NULL, NULL) == FALSE) { | ||
435 | 420 | g_object_unref (manager); | ||
436 | 421 | return NULL; | ||
437 | 422 | } | ||
438 | 423 | adapter = adapter_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, | ||
439 | 424 | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, | ||
440 | 425 | BLUEZ_SERVICE, | ||
441 | 426 | adapter_path, | ||
442 | 427 | NULL, | ||
443 | 428 | NULL); | ||
444 | 429 | g_object_unref (manager); | ||
445 | 430 | g_free (adapter_path); | ||
446 | 431 | |||
447 | 432 | return G_DBUS_PROXY (adapter); | ||
448 | 433 | } | ||
449 | 434 | |||
450 | 435 | gboolean bluetooth_agent_register(BluetoothAgent *agent) | ||
451 | 436 | { | ||
452 | 437 | BluetoothAgentPrivate *priv; | ||
453 | 438 | GError *error = NULL; | ||
454 | 439 | char *path; | ||
455 | 440 | GVariant *r; | ||
456 | 441 | |||
457 | 442 | g_return_val_if_fail (BLUETOOTH_IS_AGENT (agent), FALSE); | ||
458 | 443 | |||
459 | 444 | priv = BLUETOOTH_AGENT_GET_PRIVATE (agent); | ||
460 | 445 | |||
461 | 446 | priv->adapter = get_default_adapter (); | ||
462 | 447 | |||
463 | 448 | if (priv->adapter == NULL) | ||
464 | 449 | return FALSE; | ||
465 | 450 | |||
466 | 451 | if (priv->path != NULL) { | ||
467 | 452 | g_warning ("Agent already setup on '%s'", priv->path); | ||
468 | 453 | return FALSE; | ||
469 | 454 | } | ||
470 | 455 | |||
471 | 456 | path = g_path_get_basename(g_dbus_proxy_get_object_path(priv->adapter)); | ||
472 | 457 | priv->path = g_strdup_printf("/org/bluez/agent/%s", path); | ||
473 | 458 | g_free(path); | ||
474 | 459 | |||
475 | 460 | priv->reg_id = g_dbus_connection_register_object (priv->conn, | ||
476 | 461 | priv->path, | ||
477 | 462 | priv->introspection_data->interfaces[0], | ||
478 | 463 | &interface_vtable, | ||
479 | 464 | agent, | ||
480 | 465 | NULL, | ||
481 | 466 | &error); | ||
482 | 467 | if (priv->reg_id == 0) { | ||
483 | 468 | g_warning ("Failed to register object: %s", error->message); | ||
484 | 469 | g_error_free (error); | ||
485 | 470 | error = NULL; | ||
486 | 471 | return FALSE; | ||
487 | 472 | } | ||
488 | 473 | |||
489 | 474 | r = g_dbus_proxy_call_sync (priv->adapter, "RegisterAgent", | ||
490 | 475 | g_variant_new ("(os)", priv->path, "DisplayYesNo"), | ||
491 | 476 | G_DBUS_CALL_FLAGS_NONE, | ||
492 | 477 | -1, NULL, &error); | ||
493 | 478 | if (r == NULL) { | ||
494 | 479 | g_printerr ("Agent registration failed: %s\n", error->message); | ||
495 | 480 | g_error_free (error); | ||
496 | 481 | return FALSE; | ||
497 | 482 | } | ||
498 | 483 | g_variant_unref (r); | ||
499 | 484 | |||
500 | 485 | return TRUE; | ||
501 | 486 | } | ||
502 | 487 | |||
503 | 488 | gboolean bluetooth_agent_unregister(BluetoothAgent *agent) | ||
504 | 489 | { | ||
505 | 490 | BluetoothAgentPrivate *priv; | ||
506 | 491 | GError *error = NULL; | ||
507 | 492 | |||
508 | 493 | g_return_val_if_fail (BLUETOOTH_IS_AGENT (agent), FALSE); | ||
509 | 494 | |||
510 | 495 | priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
511 | 496 | |||
512 | 497 | if (priv->adapter == NULL) | ||
513 | 498 | return FALSE; | ||
514 | 499 | |||
515 | 500 | if (g_dbus_proxy_call_sync (priv->adapter, "UnregisterAgent", | ||
516 | 501 | g_variant_new ("(o)", priv->path), | ||
517 | 502 | G_DBUS_CALL_FLAGS_NONE, | ||
518 | 503 | -1, NULL, &error) == FALSE) { | ||
519 | 504 | /* Ignore errors if the adapter is gone */ | ||
520 | 505 | if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD) == FALSE) { | ||
521 | 506 | g_printerr ("Agent unregistration failed: %s '%s'\n", | ||
522 | 507 | error->message, | ||
523 | 508 | g_quark_to_string (error->domain)); | ||
524 | 509 | } | ||
525 | 510 | g_error_free(error); | ||
526 | 511 | } | ||
527 | 512 | |||
528 | 513 | g_object_unref(priv->adapter); | ||
529 | 514 | priv->adapter = NULL; | ||
530 | 515 | |||
531 | 516 | g_free(priv->path); | ||
532 | 517 | priv->path = NULL; | ||
533 | 518 | |||
534 | 519 | g_free(priv->busname); | ||
535 | 520 | priv->busname = NULL; | ||
536 | 521 | |||
537 | 522 | if (priv->reg_id > 0) { | ||
538 | 523 | g_dbus_connection_unregister_object (priv->conn, priv->reg_id); | ||
539 | 524 | priv->reg_id = 0; | ||
540 | 525 | } | ||
541 | 526 | |||
542 | 527 | return TRUE; | ||
543 | 528 | } | ||
544 | 529 | |||
545 | 530 | void bluetooth_agent_set_pincode_func(BluetoothAgent *agent, | ||
546 | 531 | BluetoothAgentPasskeyFunc func, gpointer data) | ||
547 | 532 | { | ||
548 | 533 | BluetoothAgentPrivate *priv; | ||
549 | 534 | |||
550 | 535 | g_return_if_fail (BLUETOOTH_IS_AGENT (agent)); | ||
551 | 536 | |||
552 | 537 | priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
553 | 538 | |||
554 | 539 | priv->pincode_func = func; | ||
555 | 540 | priv->pincode_data = data; | ||
556 | 541 | } | ||
557 | 542 | |||
558 | 543 | void bluetooth_agent_set_passkey_func(BluetoothAgent *agent, | ||
559 | 544 | BluetoothAgentPasskeyFunc func, gpointer data) | ||
560 | 545 | { | ||
561 | 546 | BluetoothAgentPrivate *priv; | ||
562 | 547 | |||
563 | 548 | g_return_if_fail (BLUETOOTH_IS_AGENT (agent)); | ||
564 | 549 | |||
565 | 550 | priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
566 | 551 | |||
567 | 552 | priv->passkey_func = func; | ||
568 | 553 | priv->passkey_data = data; | ||
569 | 554 | } | ||
570 | 555 | |||
571 | 556 | void bluetooth_agent_set_display_func(BluetoothAgent *agent, | ||
572 | 557 | BluetoothAgentDisplayFunc func, gpointer data) | ||
573 | 558 | { | ||
574 | 559 | BluetoothAgentPrivate *priv; | ||
575 | 560 | |||
576 | 561 | g_return_if_fail (BLUETOOTH_IS_AGENT (agent)); | ||
577 | 562 | |||
578 | 563 | priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
579 | 564 | |||
580 | 565 | priv->display_func = func; | ||
581 | 566 | priv->display_data = data; | ||
582 | 567 | } | ||
583 | 568 | |||
584 | 569 | void bluetooth_agent_set_confirm_func(BluetoothAgent *agent, | ||
585 | 570 | BluetoothAgentConfirmFunc func, gpointer data) | ||
586 | 571 | { | ||
587 | 572 | BluetoothAgentPrivate *priv; | ||
588 | 573 | |||
589 | 574 | g_return_if_fail (BLUETOOTH_IS_AGENT (agent)); | ||
590 | 575 | |||
591 | 576 | priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
592 | 577 | |||
593 | 578 | priv->confirm_func = func; | ||
594 | 579 | priv->confirm_data = data; | ||
595 | 580 | } | ||
596 | 581 | |||
597 | 582 | void bluetooth_agent_set_authorize_func(BluetoothAgent *agent, | ||
598 | 583 | BluetoothAgentAuthorizeFunc func, gpointer data) | ||
599 | 584 | { | ||
600 | 585 | BluetoothAgentPrivate *priv; | ||
601 | 586 | |||
602 | 587 | g_return_if_fail (BLUETOOTH_IS_AGENT (agent)); | ||
603 | 588 | |||
604 | 589 | priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
605 | 590 | |||
606 | 591 | priv->authorize_func = func; | ||
607 | 592 | priv->authorize_data = data; | ||
608 | 593 | } | ||
609 | 594 | |||
610 | 595 | void bluetooth_agent_set_cancel_func(BluetoothAgent *agent, | ||
611 | 596 | BluetoothAgentCancelFunc func, gpointer data) | ||
612 | 597 | { | ||
613 | 598 | BluetoothAgentPrivate *priv; | ||
614 | 599 | |||
615 | 600 | g_return_if_fail (BLUETOOTH_IS_AGENT (agent)); | ||
616 | 601 | |||
617 | 602 | priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
618 | 603 | |||
619 | 604 | priv->cancel_func = func; | ||
620 | 605 | priv->cancel_data = data; | ||
621 | 606 | } | ||
622 | 607 | |||
623 | 608 | GQuark bluetooth_agent_error_quark(void) | ||
624 | 609 | { | ||
625 | 610 | static GQuark quark = 0; | ||
626 | 611 | if (!quark) | ||
627 | 612 | quark = g_quark_from_static_string("agent"); | ||
628 | 613 | |||
629 | 614 | return quark; | ||
630 | 615 | } | ||
631 | 616 | |||
632 | 617 | #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } | ||
633 | 618 | |||
634 | 619 | GType bluetooth_agent_error_get_type(void) | ||
635 | 620 | { | ||
636 | 621 | static GType etype = 0; | ||
637 | 622 | if (etype == 0) { | ||
638 | 623 | static const GEnumValue values[] = { | ||
639 | 624 | ENUM_ENTRY(AGENT_ERROR_REJECT, "Rejected"), | ||
640 | 625 | { 0, 0, 0 } | ||
641 | 626 | }; | ||
642 | 627 | |||
643 | 628 | etype = g_enum_register_static("agent", values); | ||
644 | 629 | } | ||
645 | 630 | |||
646 | 631 | return etype; | ||
647 | 632 | } | ||
648 | 633 | |||
649 | 0 | 634 | ||
650 | === added directory '.pc/ssp-parameter-fix.patch/wizard' | |||
651 | === added file '.pc/ssp-parameter-fix.patch/wizard/main.c' | |||
652 | --- .pc/ssp-parameter-fix.patch/wizard/main.c 1970-01-01 00:00:00 +0000 | |||
653 | +++ .pc/ssp-parameter-fix.patch/wizard/main.c 2014-05-15 03:31:21 +0000 | |||
654 | @@ -0,0 +1,1001 @@ | |||
655 | 1 | /* | ||
656 | 2 | * | ||
657 | 3 | * BlueZ - Bluetooth protocol stack for Linux | ||
658 | 4 | * | ||
659 | 5 | * Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org> | ||
660 | 6 | * | ||
661 | 7 | * | ||
662 | 8 | * This program is free software; you can redistribute it and/or modify | ||
663 | 9 | * it under the terms of the GNU General Public License as published by | ||
664 | 10 | * the Free Software Foundation; either version 2 of the License, or | ||
665 | 11 | * (at your option) any later version. | ||
666 | 12 | * | ||
667 | 13 | * This program is distributed in the hope that it will be useful, | ||
668 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
669 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
670 | 16 | * GNU General Public License for more details. | ||
671 | 17 | * | ||
672 | 18 | * You should have received a copy of the GNU General Public License | ||
673 | 19 | * along with this program; if not, write to the Free Software | ||
674 | 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
675 | 21 | * | ||
676 | 22 | */ | ||
677 | 23 | |||
678 | 24 | #ifdef HAVE_CONFIG_H | ||
679 | 25 | #include <config.h> | ||
680 | 26 | #endif | ||
681 | 27 | |||
682 | 28 | #include <math.h> | ||
683 | 29 | #include <glib/gi18n.h> | ||
684 | 30 | #include <gtk/gtk.h> | ||
685 | 31 | #include <gdk/gdkkeysyms.h> | ||
686 | 32 | |||
687 | 33 | #include <bluetooth-client.h> | ||
688 | 34 | #include <bluetooth-client-private.h> | ||
689 | 35 | #include <bluetooth-chooser.h> | ||
690 | 36 | #include <bluetooth-agent.h> | ||
691 | 37 | #include <bluetooth-plugin-manager.h> | ||
692 | 38 | |||
693 | 39 | #include "pin.h" | ||
694 | 40 | |||
695 | 41 | #define AGENT_PATH "/org/bluez/agent/wizard" | ||
696 | 42 | |||
697 | 43 | /* We'll try to connect to the device repeatedly for that | ||
698 | 44 | * amount of time before we bail out */ | ||
699 | 45 | #define CONNECT_TIMEOUT 3.0 | ||
700 | 46 | |||
701 | 47 | #define W(x) GTK_WIDGET(gtk_builder_get_object(builder, x)) | ||
702 | 48 | |||
703 | 49 | enum { | ||
704 | 50 | PAGE_SEARCH, | ||
705 | 51 | PAGE_CONNECTING, | ||
706 | 52 | PAGE_SETUP, | ||
707 | 53 | PAGE_SSP_SETUP, | ||
708 | 54 | PAGE_FINISHING, | ||
709 | 55 | PAGE_SUMMARY | ||
710 | 56 | }; | ||
711 | 57 | |||
712 | 58 | typedef enum { | ||
713 | 59 | PAIRING_UI_NORMAL, | ||
714 | 60 | PAIRING_UI_KEYBOARD, | ||
715 | 61 | PAIRING_UI_ICADE | ||
716 | 62 | } PairingUIBehaviour; | ||
717 | 63 | |||
718 | 64 | static gboolean set_page_search_complete(void); | ||
719 | 65 | |||
720 | 66 | static BluetoothClient *client; | ||
721 | 67 | static BluetoothAgent *agent; | ||
722 | 68 | |||
723 | 69 | static gchar *target_address = NULL; | ||
724 | 70 | static gchar *target_name = NULL; | ||
725 | 71 | static guint target_max_digits = 0; | ||
726 | 72 | static PairingUIBehaviour target_ui_behaviour = PAIRING_UI_NORMAL; | ||
727 | 73 | static gboolean target_ssp = FALSE; | ||
728 | 74 | static gboolean create_started = FALSE; | ||
729 | 75 | static gboolean display_called = FALSE; | ||
730 | 76 | |||
731 | 77 | /* NULL means automatic, anything else is a pincode specified by the user */ | ||
732 | 78 | static gchar *user_pincode = NULL; | ||
733 | 79 | /* If TRUE, then we won't display the PIN code to the user when pairing */ | ||
734 | 80 | static gboolean automatic_pincode = FALSE; | ||
735 | 81 | static char *pincode = NULL; | ||
736 | 82 | |||
737 | 83 | static GtkBuilder *builder = NULL; | ||
738 | 84 | |||
739 | 85 | static GtkAssistant *window_assistant = NULL; | ||
740 | 86 | static GtkWidget *button_quit = NULL; | ||
741 | 87 | static GtkWidget *button_cancel = NULL; | ||
742 | 88 | static GtkWidget *page_search = NULL; | ||
743 | 89 | static GtkWidget *page_connecting = NULL; | ||
744 | 90 | static GtkWidget *page_setup = NULL; | ||
745 | 91 | static GtkWidget *page_ssp_setup = NULL; | ||
746 | 92 | static GtkWidget *page_finishing = NULL; | ||
747 | 93 | static GtkWidget *page_summary = NULL; | ||
748 | 94 | |||
749 | 95 | static GtkWidget *label_connecting = NULL; | ||
750 | 96 | static GtkWidget *spinner_connecting = NULL; | ||
751 | 97 | |||
752 | 98 | static GtkWidget *label_pin = NULL; | ||
753 | 99 | static GtkWidget *label_pin_help = NULL; | ||
754 | 100 | |||
755 | 101 | static GtkWidget *label_ssp_pin_help = NULL; | ||
756 | 102 | static GtkWidget *label_ssp_pin = NULL; | ||
757 | 103 | static GtkWidget *does_not_match_button = NULL; | ||
758 | 104 | static GtkWidget *matches_button = NULL; | ||
759 | 105 | |||
760 | 106 | static GtkWidget *label_finishing = NULL; | ||
761 | 107 | static GtkWidget *spinner_finishing = NULL; | ||
762 | 108 | |||
763 | 109 | static gboolean summary_failure = FALSE; | ||
764 | 110 | static GtkWidget *label_summary = NULL; | ||
765 | 111 | static GtkWidget *extra_config_vbox = NULL; | ||
766 | 112 | |||
767 | 113 | static BluetoothChooser *selector = NULL; | ||
768 | 114 | |||
769 | 115 | static GtkWidget *pin_dialog = NULL; | ||
770 | 116 | static GtkWidget *radio_auto = NULL; | ||
771 | 117 | static GtkWidget *radio_0000 = NULL; | ||
772 | 118 | static GtkWidget *radio_1111 = NULL; | ||
773 | 119 | static GtkWidget *radio_1234 = NULL; | ||
774 | 120 | static GtkWidget *radio_none = NULL; | ||
775 | 121 | static GtkWidget *radio_custom = NULL; | ||
776 | 122 | static GtkWidget *entry_custom = NULL; | ||
777 | 123 | |||
778 | 124 | /* Signals */ | ||
779 | 125 | void quit_callback(GtkWidget *assistant, gpointer data); | ||
780 | 126 | void prepare_callback(GtkWidget *assistant, GtkWidget *page, gpointer data); | ||
781 | 127 | void select_device_changed(BluetoothChooser *selector, const char *address, gpointer user_data); | ||
782 | 128 | gboolean entry_custom_event(GtkWidget *entry, GdkEventKey *event); | ||
783 | 129 | void set_user_pincode(GtkWidget *button); | ||
784 | 130 | void toggle_set_sensitive(GtkWidget *button, gpointer data); | ||
785 | 131 | void pin_option_button_clicked (GtkButton *button, gpointer data); | ||
786 | 132 | void entry_custom_changed(GtkWidget *entry); | ||
787 | 133 | void restart_button_clicked (GtkButton *button, gpointer user_data); | ||
788 | 134 | void does_not_match_cb (GtkButton *button, gpointer user_data); | ||
789 | 135 | void matches_cb (GtkButton *button, gpointer user_data); | ||
790 | 136 | |||
791 | 137 | static void | ||
792 | 138 | set_large_label (GtkLabel *label, const char *text) | ||
793 | 139 | { | ||
794 | 140 | char *str; | ||
795 | 141 | |||
796 | 142 | str = g_strdup_printf("<span font_desc=\"50\"> %s </span>", text); | ||
797 | 143 | gtk_label_set_markup(GTK_LABEL(label), str); | ||
798 | 144 | g_free(str); | ||
799 | 145 | } | ||
800 | 146 | |||
801 | 147 | static char * | ||
802 | 148 | get_random_pincode (guint num_digits) | ||
803 | 149 | { | ||
804 | 150 | if (num_digits == 0) | ||
805 | 151 | num_digits = PIN_NUM_DIGITS; | ||
806 | 152 | return g_strdup_printf ("%d", g_random_int_range (pow (10, num_digits - 1), | ||
807 | 153 | pow (10, num_digits))); | ||
808 | 154 | } | ||
809 | 155 | |||
810 | 156 | static char * | ||
811 | 157 | get_icade_pincode (char **pin_display_str) | ||
812 | 158 | { | ||
813 | 159 | GString *pin, *pin_display; | ||
814 | 160 | guint i; | ||
815 | 161 | static char *arrows[] = { | ||
816 | 162 | NULL, | ||
817 | 163 | "⬆", /* up = 1 */ | ||
818 | 164 | "⬇", /* down = 2 */ | ||
819 | 165 | "⬅", /* left = 3 */ | ||
820 | 166 | "➡" /* right = 4 */ | ||
821 | 167 | }; | ||
822 | 168 | |||
823 | 169 | pin = g_string_new (NULL); | ||
824 | 170 | pin_display = g_string_new (NULL); | ||
825 | 171 | |||
826 | 172 | for (i = 0; i < PIN_NUM_DIGITS; i++) { | ||
827 | 173 | int r; | ||
828 | 174 | char *c; | ||
829 | 175 | |||
830 | 176 | r = g_random_int_range (1, 4); | ||
831 | 177 | |||
832 | 178 | c = g_strdup_printf ("%d", r); | ||
833 | 179 | g_string_append (pin, c); | ||
834 | 180 | g_free (c); | ||
835 | 181 | |||
836 | 182 | g_string_append (pin_display, arrows[r]); | ||
837 | 183 | } | ||
838 | 184 | g_string_append (pin_display, "❍"); | ||
839 | 185 | |||
840 | 186 | *pin_display_str = g_string_free (pin_display, FALSE); | ||
841 | 187 | return g_string_free (pin, FALSE); | ||
842 | 188 | } | ||
843 | 189 | |||
844 | 190 | static gboolean | ||
845 | 191 | pincode_callback (GDBusMethodInvocation *invocation, | ||
846 | 192 | GDBusProxy *device, | ||
847 | 193 | gpointer user_data) | ||
848 | 194 | { | ||
849 | 195 | target_ssp = FALSE; | ||
850 | 196 | |||
851 | 197 | /* Only show the pincode page if the pincode isn't automatic */ | ||
852 | 198 | if (automatic_pincode == FALSE) | ||
853 | 199 | gtk_assistant_set_current_page (window_assistant, PAGE_SETUP); | ||
854 | 200 | g_debug ("Using pincode \"%s\"", pincode); | ||
855 | 201 | g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", pincode)); | ||
856 | 202 | |||
857 | 203 | return TRUE; | ||
858 | 204 | } | ||
859 | 205 | |||
860 | 206 | void | ||
861 | 207 | restart_button_clicked (GtkButton *button, | ||
862 | 208 | gpointer user_data) | ||
863 | 209 | { | ||
864 | 210 | /* Clean up old state */ | ||
865 | 211 | target_ssp = FALSE; | ||
866 | 212 | display_called = FALSE; | ||
867 | 213 | g_free (target_address); | ||
868 | 214 | target_address = NULL; | ||
869 | 215 | g_free (target_name); | ||
870 | 216 | target_name = NULL; | ||
871 | 217 | summary_failure = FALSE; | ||
872 | 218 | target_ui_behaviour = PAIRING_UI_NORMAL; | ||
873 | 219 | |||
874 | 220 | g_object_set (selector, | ||
875 | 221 | "device-category-filter", BLUETOOTH_CATEGORY_NOT_PAIRED_OR_TRUSTED, | ||
876 | 222 | NULL); | ||
877 | 223 | |||
878 | 224 | gtk_assistant_set_current_page (window_assistant, PAGE_SEARCH); | ||
879 | 225 | } | ||
880 | 226 | |||
881 | 227 | void | ||
882 | 228 | does_not_match_cb (GtkButton *button, | ||
883 | 229 | gpointer user_data) | ||
884 | 230 | { | ||
885 | 231 | GDBusMethodInvocation *invocation; | ||
886 | 232 | GError *error = NULL; | ||
887 | 233 | char *text; | ||
888 | 234 | |||
889 | 235 | summary_failure = TRUE; | ||
890 | 236 | gtk_assistant_set_current_page (window_assistant, PAGE_SUMMARY); | ||
891 | 237 | |||
892 | 238 | /* translators: | ||
893 | 239 | * The '%s' is the device name, for example: | ||
894 | 240 | * Pairing with 'Sony Bluetooth Headset' cancelled | ||
895 | 241 | */ | ||
896 | 242 | text = g_strdup_printf(_("Pairing with '%s' cancelled"), target_name); | ||
897 | 243 | gtk_label_set_text(GTK_LABEL(label_summary), text); | ||
898 | 244 | g_free(text); | ||
899 | 245 | |||
900 | 246 | invocation = g_object_get_data (G_OBJECT (button), "invocation"); | ||
901 | 247 | error = g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT, | ||
902 | 248 | "Agent callback cancelled"); | ||
903 | 249 | g_dbus_method_invocation_return_gerror (invocation, error); | ||
904 | 250 | g_error_free (error); | ||
905 | 251 | |||
906 | 252 | g_object_set_data (G_OBJECT(does_not_match_button), "invocation", NULL); | ||
907 | 253 | g_object_set_data (G_OBJECT(matches_button), "invocation", NULL); | ||
908 | 254 | } | ||
909 | 255 | |||
910 | 256 | void | ||
911 | 257 | matches_cb (GtkButton *button, | ||
912 | 258 | gpointer user_data) | ||
913 | 259 | { | ||
914 | 260 | GDBusMethodInvocation *invocation; | ||
915 | 261 | |||
916 | 262 | invocation = g_object_get_data (G_OBJECT (button), "invocation"); | ||
917 | 263 | gtk_widget_set_sensitive (does_not_match_button, FALSE); | ||
918 | 264 | gtk_widget_set_sensitive (matches_button, FALSE); | ||
919 | 265 | g_dbus_method_invocation_return_value (invocation, NULL); | ||
920 | 266 | |||
921 | 267 | g_object_set_data (G_OBJECT(does_not_match_button), "invocation", NULL); | ||
922 | 268 | g_object_set_data (G_OBJECT(matches_button), "invocation", NULL); | ||
923 | 269 | } | ||
924 | 270 | |||
925 | 271 | static gboolean | ||
926 | 272 | confirm_callback (GDBusMethodInvocation *invocation, | ||
927 | 273 | GDBusProxy *device, | ||
928 | 274 | guint pin, | ||
929 | 275 | gpointer user_data) | ||
930 | 276 | { | ||
931 | 277 | char *str, *label; | ||
932 | 278 | |||
933 | 279 | target_ssp = TRUE; | ||
934 | 280 | gtk_assistant_set_current_page (window_assistant, PAGE_SSP_SETUP); | ||
935 | 281 | |||
936 | 282 | gtk_widget_show (label_ssp_pin_help); | ||
937 | 283 | label = g_strdup_printf (_("Please confirm that the PIN displayed on '%s' matches this one."), | ||
938 | 284 | target_name); | ||
939 | 285 | gtk_label_set_markup(GTK_LABEL(label_ssp_pin_help), label); | ||
940 | 286 | g_free (label); | ||
941 | 287 | |||
942 | 288 | gtk_widget_show (label_ssp_pin); | ||
943 | 289 | str = g_strdup_printf ("%06d", pin); | ||
944 | 290 | set_large_label (GTK_LABEL (label_ssp_pin), str); | ||
945 | 291 | g_free (str); | ||
946 | 292 | |||
947 | 293 | g_object_set_data (G_OBJECT(does_not_match_button), "invocation", invocation); | ||
948 | 294 | g_object_set_data (G_OBJECT(matches_button), "invocation", invocation); | ||
949 | 295 | |||
950 | 296 | return TRUE; | ||
951 | 297 | } | ||
952 | 298 | |||
953 | 299 | static gboolean | ||
954 | 300 | display_callback (GDBusMethodInvocation *invocation, | ||
955 | 301 | GDBusProxy *device, | ||
956 | 302 | guint pin, | ||
957 | 303 | guint entered, | ||
958 | 304 | gpointer user_data) | ||
959 | 305 | { | ||
960 | 306 | gchar *text, *done, *code; | ||
961 | 307 | |||
962 | 308 | display_called = TRUE; | ||
963 | 309 | target_ssp = TRUE; | ||
964 | 310 | gtk_assistant_set_current_page (window_assistant, PAGE_SSP_SETUP); | ||
965 | 311 | |||
966 | 312 | code = g_strdup_printf("%06d", pin); | ||
967 | 313 | |||
968 | 314 | if (entered > 0) { | ||
969 | 315 | GtkEntry *entry; | ||
970 | 316 | gunichar invisible; | ||
971 | 317 | GString *str; | ||
972 | 318 | guint i; | ||
973 | 319 | |||
974 | 320 | entry = GTK_ENTRY (gtk_entry_new ()); | ||
975 | 321 | invisible = gtk_entry_get_invisible_char (entry); | ||
976 | 322 | g_object_unref (entry); | ||
977 | 323 | |||
978 | 324 | str = g_string_new (NULL); | ||
979 | 325 | for (i = 0; i < entered; i++) | ||
980 | 326 | g_string_append_unichar (str, invisible); | ||
981 | 327 | if (entered < strlen (code)) | ||
982 | 328 | g_string_append (str, code + entered); | ||
983 | 329 | |||
984 | 330 | done = g_string_free (str, FALSE); | ||
985 | 331 | } else { | ||
986 | 332 | done = g_strdup (""); | ||
987 | 333 | } | ||
988 | 334 | |||
989 | 335 | gtk_widget_show (label_pin_help); | ||
990 | 336 | |||
991 | 337 | gtk_label_set_markup(GTK_LABEL(label_ssp_pin_help), _("Please enter the following PIN:")); | ||
992 | 338 | text = g_strdup_printf("%s%s", done, code + entered); | ||
993 | 339 | set_large_label (GTK_LABEL (label_ssp_pin), text); | ||
994 | 340 | g_free(text); | ||
995 | 341 | |||
996 | 342 | g_free(done); | ||
997 | 343 | g_free(code); | ||
998 | 344 | |||
999 | 345 | g_dbus_method_invocation_return_value (invocation, NULL); | ||
1000 | 346 | |||
1001 | 347 | return TRUE; | ||
1002 | 348 | } | ||
1003 | 349 | |||
1004 | 350 | static gboolean | ||
1005 | 351 | cancel_callback (GDBusMethodInvocation *invocation, | ||
1006 | 352 | gpointer user_data) | ||
1007 | 353 | { | ||
1008 | 354 | gchar *text; | ||
1009 | 355 | |||
1010 | 356 | create_started = FALSE; | ||
1011 | 357 | |||
1012 | 358 | summary_failure = TRUE; | ||
1013 | 359 | gtk_assistant_set_current_page (window_assistant, PAGE_SUMMARY); | ||
1014 | 360 | |||
1015 | 361 | /* translators: | ||
1016 | 362 | * The '%s' is the device name, for example: | ||
1017 | 363 | * Pairing with 'Sony Bluetooth Headset' cancelled | ||
1018 | 364 | */ | ||
1019 | 365 | text = g_strdup_printf(_("Pairing with '%s' cancelled"), target_name); | ||
1020 | 366 | gtk_label_set_text(GTK_LABEL(label_summary), text); | ||
1021 | 367 | g_free(text); | ||
1022 | 368 | |||
1023 | 369 | g_dbus_method_invocation_return_value (invocation, NULL); | ||
1024 | 370 | |||
1025 | 371 | return TRUE; | ||
1026 | 372 | } | ||
1027 | 373 | |||
1028 | 374 | typedef struct { | ||
1029 | 375 | char *path; | ||
1030 | 376 | GTimer *timer; | ||
1031 | 377 | } ConnectData; | ||
1032 | 378 | |||
1033 | 379 | static void | ||
1034 | 380 | connect_callback (GObject *source_object, | ||
1035 | 381 | GAsyncResult *res, | ||
1036 | 382 | gpointer user_data) | ||
1037 | 383 | { | ||
1038 | 384 | ConnectData *data = (ConnectData *) user_data; | ||
1039 | 385 | gboolean success; | ||
1040 | 386 | |||
1041 | 387 | success = bluetooth_client_connect_service_finish (client, res, NULL); | ||
1042 | 388 | |||
1043 | 389 | if (success == FALSE && g_timer_elapsed (data->timer, NULL) < CONNECT_TIMEOUT) { | ||
1044 | 390 | bluetooth_client_connect_service (client, data->path, TRUE, NULL, connect_callback, data); | ||
1045 | 391 | return; | ||
1046 | 392 | } | ||
1047 | 393 | |||
1048 | 394 | if (success == FALSE) | ||
1049 | 395 | g_debug ("Failed to connect to device %s", data->path); | ||
1050 | 396 | |||
1051 | 397 | g_timer_destroy (data->timer); | ||
1052 | 398 | g_free (data->path); | ||
1053 | 399 | g_free (data); | ||
1054 | 400 | |||
1055 | 401 | gtk_assistant_set_current_page (window_assistant, PAGE_SUMMARY); | ||
1056 | 402 | } | ||
1057 | 403 | |||
1058 | 404 | static void | ||
1059 | 405 | create_callback (BluetoothClient *_client, | ||
1060 | 406 | const char *path, | ||
1061 | 407 | const GError *error, | ||
1062 | 408 | gpointer user_data) | ||
1063 | 409 | { | ||
1064 | 410 | ConnectData *data; | ||
1065 | 411 | |||
1066 | 412 | create_started = FALSE; | ||
1067 | 413 | |||
1068 | 414 | /* Create failed */ | ||
1069 | 415 | if (path == NULL) { | ||
1070 | 416 | char *text; | ||
1071 | 417 | |||
1072 | 418 | summary_failure = TRUE; | ||
1073 | 419 | gtk_assistant_set_current_page (window_assistant, PAGE_SUMMARY); | ||
1074 | 420 | |||
1075 | 421 | /* translators: | ||
1076 | 422 | * The '%s' is the device name, for example: | ||
1077 | 423 | * Setting up 'Sony Bluetooth Headset' failed | ||
1078 | 424 | */ | ||
1079 | 425 | text = g_strdup_printf(_("Setting up '%s' failed"), target_name); | ||
1080 | 426 | |||
1081 | 427 | g_warning ("Setting up '%s' failed: %s", target_name, error->message); | ||
1082 | 428 | |||
1083 | 429 | gtk_label_set_markup(GTK_LABEL(label_summary), text); | ||
1084 | 430 | g_free (text); | ||
1085 | 431 | |||
1086 | 432 | return; | ||
1087 | 433 | } | ||
1088 | 434 | |||
1089 | 435 | bluetooth_client_set_trusted(client, path, TRUE); | ||
1090 | 436 | |||
1091 | 437 | data = g_new0 (ConnectData, 1); | ||
1092 | 438 | data->path = g_strdup (path); | ||
1093 | 439 | data->timer = g_timer_new (); | ||
1094 | 440 | |||
1095 | 441 | bluetooth_client_connect_service (client, path, TRUE, NULL, connect_callback, data); | ||
1096 | 442 | gtk_assistant_set_current_page (window_assistant, PAGE_FINISHING); | ||
1097 | 443 | } | ||
1098 | 444 | |||
1099 | 445 | void | ||
1100 | 446 | quit_callback (GtkWidget *widget, | ||
1101 | 447 | gpointer data) | ||
1102 | 448 | { | ||
1103 | 449 | gtk_widget_destroy(GTK_WIDGET (window_assistant)); | ||
1104 | 450 | } | ||
1105 | 451 | |||
1106 | 452 | void prepare_callback (GtkWidget *assistant, | ||
1107 | 453 | GtkWidget *page, | ||
1108 | 454 | gpointer data) | ||
1109 | 455 | { | ||
1110 | 456 | gboolean complete = TRUE; | ||
1111 | 457 | |||
1112 | 458 | gtk_widget_hide (button_quit); | ||
1113 | 459 | gtk_widget_hide (button_cancel); | ||
1114 | 460 | |||
1115 | 461 | if (page == page_search) { | ||
1116 | 462 | complete = set_page_search_complete (); | ||
1117 | 463 | bluetooth_chooser_start_discovery(selector); | ||
1118 | 464 | } else { | ||
1119 | 465 | bluetooth_chooser_stop_discovery(selector); | ||
1120 | 466 | } | ||
1121 | 467 | |||
1122 | 468 | if (page == page_connecting) { | ||
1123 | 469 | char *text; | ||
1124 | 470 | |||
1125 | 471 | complete = FALSE; | ||
1126 | 472 | |||
1127 | 473 | gtk_spinner_start (GTK_SPINNER (spinner_connecting)); | ||
1128 | 474 | |||
1129 | 475 | /* translators: | ||
1130 | 476 | * The '%s' is the device name, for example: | ||
1131 | 477 | * Connecting to 'Sony Bluetooth Headset'... | ||
1132 | 478 | */ | ||
1133 | 479 | text = g_strdup_printf (_("Connecting to '%s'..."), target_name); | ||
1134 | 480 | gtk_label_set_text (GTK_LABEL (label_connecting), text); | ||
1135 | 481 | g_free (text); | ||
1136 | 482 | |||
1137 | 483 | gtk_widget_show (button_cancel); | ||
1138 | 484 | } else { | ||
1139 | 485 | gtk_spinner_stop (GTK_SPINNER (spinner_connecting)); | ||
1140 | 486 | } | ||
1141 | 487 | |||
1142 | 488 | if ((page == page_setup || page == page_connecting) && (create_started == FALSE)) { | ||
1143 | 489 | const char *path = AGENT_PATH; | ||
1144 | 490 | |||
1145 | 491 | /* Set the filter on the selector, so we can use it to get more | ||
1146 | 492 | * info later, in page_summary */ | ||
1147 | 493 | g_object_set (selector, | ||
1148 | 494 | "device-category-filter", BLUETOOTH_CATEGORY_ALL, | ||
1149 | 495 | NULL); | ||
1150 | 496 | |||
1151 | 497 | /* Do we pair, or don't we? */ | ||
1152 | 498 | if (automatic_pincode && pincode == NULL) { | ||
1153 | 499 | g_debug ("Not pairing as %s", automatic_pincode ? "pincode is NULL" : "automatic_pincode is FALSE"); | ||
1154 | 500 | path = NULL; | ||
1155 | 501 | } | ||
1156 | 502 | |||
1157 | 503 | g_object_ref(agent); | ||
1158 | 504 | bluetooth_client_create_device (client, target_address, | ||
1159 | 505 | path, create_callback, assistant); | ||
1160 | 506 | create_started = TRUE; | ||
1161 | 507 | } | ||
1162 | 508 | |||
1163 | 509 | if (page == page_setup) { | ||
1164 | 510 | complete = FALSE; | ||
1165 | 511 | |||
1166 | 512 | if (automatic_pincode == FALSE && target_ssp == FALSE) { | ||
1167 | 513 | char *help, *pincode_display; | ||
1168 | 514 | |||
1169 | 515 | g_free (pincode); | ||
1170 | 516 | pincode = NULL; | ||
1171 | 517 | pincode_display = NULL; | ||
1172 | 518 | |||
1173 | 519 | switch (target_ui_behaviour) { | ||
1174 | 520 | case PAIRING_UI_NORMAL: | ||
1175 | 521 | help = g_strdup_printf (_("Please enter the following PIN on '%s':"), target_name); | ||
1176 | 522 | break; | ||
1177 | 523 | case PAIRING_UI_KEYBOARD: | ||
1178 | 524 | help = g_strdup_printf (_("Please enter the following PIN on '%s' and press “Enter” on the keyboard:"), target_name); | ||
1179 | 525 | pincode = get_random_pincode (target_max_digits); | ||
1180 | 526 | pincode_display = g_strdup_printf ("%s⏎", pincode); | ||
1181 | 527 | break; | ||
1182 | 528 | case PAIRING_UI_ICADE: | ||
1183 | 529 | help = g_strdup (_("Please move the joystick of your iCade in the following directions:")); | ||
1184 | 530 | pincode = get_icade_pincode (&pincode_display); | ||
1185 | 531 | break; | ||
1186 | 532 | default: | ||
1187 | 533 | g_assert_not_reached (); | ||
1188 | 534 | } | ||
1189 | 535 | |||
1190 | 536 | if (pincode == NULL) | ||
1191 | 537 | pincode = get_random_pincode (target_max_digits); | ||
1192 | 538 | |||
1193 | 539 | gtk_label_set_markup(GTK_LABEL(label_pin_help), help); | ||
1194 | 540 | g_free (help); | ||
1195 | 541 | set_large_label (GTK_LABEL (label_pin), pincode_display ? pincode_display : pincode); | ||
1196 | 542 | g_free (pincode_display); | ||
1197 | 543 | } else { | ||
1198 | 544 | g_assert_not_reached (); | ||
1199 | 545 | } | ||
1200 | 546 | |||
1201 | 547 | gtk_widget_show (button_cancel); | ||
1202 | 548 | } | ||
1203 | 549 | |||
1204 | 550 | if (page == page_finishing) { | ||
1205 | 551 | char *text; | ||
1206 | 552 | |||
1207 | 553 | complete = FALSE; | ||
1208 | 554 | |||
1209 | 555 | gtk_spinner_start (GTK_SPINNER (spinner_finishing)); | ||
1210 | 556 | |||
1211 | 557 | /* translators: | ||
1212 | 558 | * The '%s' is the device name, for example: | ||
1213 | 559 | * Please wait while finishing setup on 'Sony Bluetooth Headset'... | ||
1214 | 560 | */ | ||
1215 | 561 | text = g_strdup_printf (_("Please wait while finishing setup on device '%s'..."), target_name); | ||
1216 | 562 | gtk_label_set_text (GTK_LABEL (label_finishing), text); | ||
1217 | 563 | g_free (text); | ||
1218 | 564 | |||
1219 | 565 | gtk_widget_show (button_quit); | ||
1220 | 566 | } else { | ||
1221 | 567 | gtk_spinner_stop (GTK_SPINNER (spinner_finishing)); | ||
1222 | 568 | } | ||
1223 | 569 | |||
1224 | 570 | if (page == page_summary && summary_failure == FALSE) { | ||
1225 | 571 | GList *widgets = NULL; | ||
1226 | 572 | GValue value = { 0, }; | ||
1227 | 573 | char **uuids, *text; | ||
1228 | 574 | |||
1229 | 575 | /* FIXME remove this code when bluetoothd has pair/unpair code */ | ||
1230 | 576 | g_object_set (G_OBJECT (selector), "device-selected", target_address, NULL); | ||
1231 | 577 | |||
1232 | 578 | bluetooth_chooser_get_selected_device_info (selector, "name", &value); | ||
1233 | 579 | text = g_strdup_printf (_("Successfully set up new device '%s'"), g_value_get_string (&value)); | ||
1234 | 580 | g_value_unset (&value); | ||
1235 | 581 | gtk_label_set_text (GTK_LABEL (label_summary), text); | ||
1236 | 582 | g_free (text); | ||
1237 | 583 | |||
1238 | 584 | if (bluetooth_chooser_get_selected_device_info (selector, "uuids", &value) != FALSE) { | ||
1239 | 585 | uuids = g_value_get_boxed (&value); | ||
1240 | 586 | widgets = bluetooth_plugin_manager_get_widgets (target_address, | ||
1241 | 587 | (const char **) uuids); | ||
1242 | 588 | g_value_unset (&value); | ||
1243 | 589 | } | ||
1244 | 590 | if (widgets != NULL) { | ||
1245 | 591 | GList *l; | ||
1246 | 592 | |||
1247 | 593 | for (l = widgets; l != NULL; l = l->next) { | ||
1248 | 594 | GtkWidget *widget = l->data; | ||
1249 | 595 | gtk_box_pack_start (GTK_BOX (extra_config_vbox), | ||
1250 | 596 | widget, | ||
1251 | 597 | FALSE, | ||
1252 | 598 | TRUE, | ||
1253 | 599 | 0); | ||
1254 | 600 | } | ||
1255 | 601 | g_list_free (widgets); | ||
1256 | 602 | gtk_widget_show_all (extra_config_vbox); | ||
1257 | 603 | } | ||
1258 | 604 | gtk_widget_show (button_quit); | ||
1259 | 605 | } | ||
1260 | 606 | |||
1261 | 607 | /* Setup the buttons some */ | ||
1262 | 608 | if (page == page_summary && summary_failure) { | ||
1263 | 609 | complete = FALSE; | ||
1264 | 610 | gtk_assistant_add_action_widget (GTK_ASSISTANT (assistant), W("restart_button")); | ||
1265 | 611 | gtk_widget_show (button_quit); | ||
1266 | 612 | } else { | ||
1267 | 613 | if (gtk_widget_get_parent (W("restart_button")) != NULL) | ||
1268 | 614 | gtk_assistant_remove_action_widget (GTK_ASSISTANT (assistant), W("restart_button")); | ||
1269 | 615 | } | ||
1270 | 616 | |||
1271 | 617 | if (page == page_ssp_setup) { | ||
1272 | 618 | if (display_called == FALSE) { | ||
1273 | 619 | complete = FALSE; | ||
1274 | 620 | gtk_assistant_add_action_widget (GTK_ASSISTANT (assistant), W("matches_button")); | ||
1275 | 621 | gtk_assistant_add_action_widget (GTK_ASSISTANT (assistant), W("does_not_match_button")); | ||
1276 | 622 | } else { | ||
1277 | 623 | gtk_widget_show (button_cancel); | ||
1278 | 624 | } | ||
1279 | 625 | } else { | ||
1280 | 626 | if (gtk_widget_get_parent (W("does_not_match_button")) != NULL) | ||
1281 | 627 | gtk_assistant_remove_action_widget (GTK_ASSISTANT (assistant), W("does_not_match_button")); | ||
1282 | 628 | if (gtk_widget_get_parent (W("matches_button")) != NULL) | ||
1283 | 629 | gtk_assistant_remove_action_widget (GTK_ASSISTANT (assistant), W("matches_button")); | ||
1284 | 630 | } | ||
1285 | 631 | |||
1286 | 632 | gtk_assistant_set_page_complete (GTK_ASSISTANT(assistant), | ||
1287 | 633 | page, complete); | ||
1288 | 634 | } | ||
1289 | 635 | |||
1290 | 636 | static gboolean | ||
1291 | 637 | set_page_search_complete (void) | ||
1292 | 638 | { | ||
1293 | 639 | char *name, *address; | ||
1294 | 640 | gboolean complete = FALSE; | ||
1295 | 641 | |||
1296 | 642 | address = bluetooth_chooser_get_selected_device (selector); | ||
1297 | 643 | name = bluetooth_chooser_get_selected_device_name (selector); | ||
1298 | 644 | |||
1299 | 645 | if (address == NULL) | ||
1300 | 646 | complete = FALSE; | ||
1301 | 647 | else if (name == NULL) | ||
1302 | 648 | complete = (user_pincode != NULL && strlen(user_pincode) >= 4); | ||
1303 | 649 | else | ||
1304 | 650 | complete = (user_pincode == NULL || strlen(user_pincode) >= 4); | ||
1305 | 651 | |||
1306 | 652 | g_free (address); | ||
1307 | 653 | g_free (name); | ||
1308 | 654 | |||
1309 | 655 | gtk_assistant_set_page_complete (GTK_ASSISTANT (window_assistant), | ||
1310 | 656 | page_search, complete); | ||
1311 | 657 | |||
1312 | 658 | return complete; | ||
1313 | 659 | } | ||
1314 | 660 | |||
1315 | 661 | gboolean | ||
1316 | 662 | entry_custom_event (GtkWidget *entry, GdkEventKey *event) | ||
1317 | 663 | { | ||
1318 | 664 | gunichar c; | ||
1319 | 665 | |||
1320 | 666 | if (event->length == 0) | ||
1321 | 667 | return FALSE; | ||
1322 | 668 | |||
1323 | 669 | /* Not a printable character? */ | ||
1324 | 670 | c = gdk_keyval_to_unicode (event->keyval); | ||
1325 | 671 | if (c == 0 || | ||
1326 | 672 | g_unichar_iscntrl (c) || | ||
1327 | 673 | g_unichar_isdigit (c)) | ||
1328 | 674 | return FALSE; | ||
1329 | 675 | |||
1330 | 676 | return TRUE; | ||
1331 | 677 | } | ||
1332 | 678 | |||
1333 | 679 | void | ||
1334 | 680 | entry_custom_changed (GtkWidget *entry) | ||
1335 | 681 | { | ||
1336 | 682 | g_free (user_pincode); | ||
1337 | 683 | user_pincode = g_strdup (gtk_entry_get_text(GTK_ENTRY(entry))); | ||
1338 | 684 | gtk_dialog_set_response_sensitive (GTK_DIALOG (pin_dialog), | ||
1339 | 685 | GTK_RESPONSE_ACCEPT, | ||
1340 | 686 | gtk_entry_get_text_length (GTK_ENTRY (entry)) >= 1); | ||
1341 | 687 | } | ||
1342 | 688 | |||
1343 | 689 | void | ||
1344 | 690 | toggle_set_sensitive (GtkWidget *button, | ||
1345 | 691 | gpointer data) | ||
1346 | 692 | { | ||
1347 | 693 | gboolean active; | ||
1348 | 694 | |||
1349 | 695 | active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); | ||
1350 | 696 | gtk_widget_set_sensitive(entry_custom, active); | ||
1351 | 697 | /* When selecting another PIN, make sure the "Close" button is sensitive */ | ||
1352 | 698 | if (!active) | ||
1353 | 699 | gtk_dialog_set_response_sensitive (GTK_DIALOG (pin_dialog), | ||
1354 | 700 | GTK_RESPONSE_ACCEPT, TRUE); | ||
1355 | 701 | else | ||
1356 | 702 | entry_custom_changed (entry_custom); | ||
1357 | 703 | } | ||
1358 | 704 | |||
1359 | 705 | void | ||
1360 | 706 | set_user_pincode (GtkWidget *button) | ||
1361 | 707 | { | ||
1362 | 708 | if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) | ||
1363 | 709 | return; | ||
1364 | 710 | |||
1365 | 711 | g_free (user_pincode); | ||
1366 | 712 | user_pincode = g_strdup (g_object_get_data (G_OBJECT (button), "pin")); | ||
1367 | 713 | } | ||
1368 | 714 | |||
1369 | 715 | void | ||
1370 | 716 | select_device_changed (BluetoothChooser *selector, | ||
1371 | 717 | const char *address, | ||
1372 | 718 | gpointer user_data) | ||
1373 | 719 | { | ||
1374 | 720 | GValue value = { 0, }; | ||
1375 | 721 | guint target_type = BLUETOOTH_TYPE_ANY; | ||
1376 | 722 | gboolean is_custom_pin = FALSE; | ||
1377 | 723 | int legacypairing; | ||
1378 | 724 | |||
1379 | 725 | if (gtk_assistant_get_current_page (GTK_ASSISTANT (window_assistant)) != PAGE_SEARCH) | ||
1380 | 726 | return; | ||
1381 | 727 | |||
1382 | 728 | set_page_search_complete (); | ||
1383 | 729 | |||
1384 | 730 | /* Device was deselected */ | ||
1385 | 731 | if (address == NULL) | ||
1386 | 732 | return; | ||
1387 | 733 | |||
1388 | 734 | if (bluetooth_chooser_get_selected_device_info (selector, "legacypairing", &value) != FALSE) { | ||
1389 | 735 | legacypairing = g_value_get_int (&value); | ||
1390 | 736 | if (legacypairing == -1) | ||
1391 | 737 | legacypairing = TRUE; | ||
1392 | 738 | } else { | ||
1393 | 739 | legacypairing = TRUE; | ||
1394 | 740 | } | ||
1395 | 741 | |||
1396 | 742 | g_free(target_address); | ||
1397 | 743 | target_address = g_strdup (address); | ||
1398 | 744 | |||
1399 | 745 | g_free(target_name); | ||
1400 | 746 | target_name = bluetooth_chooser_get_selected_device_name (selector); | ||
1401 | 747 | |||
1402 | 748 | target_type = bluetooth_chooser_get_selected_device_type (selector); | ||
1403 | 749 | target_ssp = !legacypairing; | ||
1404 | 750 | automatic_pincode = FALSE; | ||
1405 | 751 | target_ui_behaviour = PAIRING_UI_NORMAL; | ||
1406 | 752 | |||
1407 | 753 | g_free (pincode); | ||
1408 | 754 | pincode = NULL; | ||
1409 | 755 | |||
1410 | 756 | g_free (user_pincode); | ||
1411 | 757 | user_pincode = get_pincode_for_device (target_type, target_address, target_name, &target_max_digits); | ||
1412 | 758 | if (user_pincode != NULL && | ||
1413 | 759 | g_str_equal (user_pincode, "NULL") == FALSE) { | ||
1414 | 760 | if (g_str_equal (user_pincode, "KEYBOARD")) { | ||
1415 | 761 | target_ui_behaviour = PAIRING_UI_KEYBOARD; | ||
1416 | 762 | is_custom_pin = TRUE; | ||
1417 | 763 | } else if (g_str_equal (user_pincode, "ICADE")) { | ||
1418 | 764 | target_ui_behaviour = PAIRING_UI_ICADE; | ||
1419 | 765 | is_custom_pin = TRUE; | ||
1420 | 766 | } else { | ||
1421 | 767 | pincode = g_strdup (user_pincode); | ||
1422 | 768 | } | ||
1423 | 769 | } | ||
1424 | 770 | |||
1425 | 771 | if (is_custom_pin) | ||
1426 | 772 | automatic_pincode = FALSE; | ||
1427 | 773 | else | ||
1428 | 774 | automatic_pincode = user_pincode != NULL; | ||
1429 | 775 | |||
1430 | 776 | g_free (user_pincode); | ||
1431 | 777 | user_pincode = NULL; | ||
1432 | 778 | |||
1433 | 779 | gtk_entry_set_max_length (GTK_ENTRY (entry_custom), target_max_digits); | ||
1434 | 780 | } | ||
1435 | 781 | |||
1436 | 782 | void | ||
1437 | 783 | pin_option_button_clicked (GtkButton *button, | ||
1438 | 784 | gpointer data) | ||
1439 | 785 | { | ||
1440 | 786 | GtkWidget *radio; | ||
1441 | 787 | |||
1442 | 788 | gtk_window_set_transient_for (GTK_WINDOW (pin_dialog), | ||
1443 | 789 | GTK_WINDOW (window_assistant)); | ||
1444 | 790 | gtk_window_present (GTK_WINDOW (pin_dialog)); | ||
1445 | 791 | |||
1446 | 792 | /* When reopening, try to guess where the pincode was set */ | ||
1447 | 793 | if (user_pincode == NULL) | ||
1448 | 794 | radio = radio_auto; | ||
1449 | 795 | else if (g_str_equal (user_pincode, "0000")) | ||
1450 | 796 | radio = radio_0000; | ||
1451 | 797 | else if (g_str_equal (user_pincode, "1111")) | ||
1452 | 798 | radio = radio_1111; | ||
1453 | 799 | else if (g_str_equal (user_pincode, "1234")) | ||
1454 | 800 | radio = radio_1234; | ||
1455 | 801 | else if (g_str_equal (user_pincode, "NULL")) | ||
1456 | 802 | radio = radio_none; | ||
1457 | 803 | else { | ||
1458 | 804 | radio = radio_custom; | ||
1459 | 805 | gtk_entry_set_text (GTK_ENTRY (entry_custom), user_pincode); | ||
1460 | 806 | } | ||
1461 | 807 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); | ||
1462 | 808 | |||
1463 | 809 | gtk_dialog_run (GTK_DIALOG (pin_dialog)); | ||
1464 | 810 | gtk_widget_hide (pin_dialog); | ||
1465 | 811 | g_free (pincode); | ||
1466 | 812 | pincode = g_strdup (user_pincode); | ||
1467 | 813 | automatic_pincode = user_pincode != NULL; | ||
1468 | 814 | } | ||
1469 | 815 | |||
1470 | 816 | static int | ||
1471 | 817 | page_func (gint current_page, | ||
1472 | 818 | gpointer data) | ||
1473 | 819 | { | ||
1474 | 820 | if (current_page == PAGE_SEARCH) { | ||
1475 | 821 | if (target_ssp != FALSE || automatic_pincode != FALSE) | ||
1476 | 822 | return PAGE_CONNECTING; | ||
1477 | 823 | else | ||
1478 | 824 | return PAGE_SETUP; | ||
1479 | 825 | } | ||
1480 | 826 | if (current_page == PAGE_SETUP) | ||
1481 | 827 | return PAGE_SUMMARY; | ||
1482 | 828 | return current_page + 1; | ||
1483 | 829 | } | ||
1484 | 830 | |||
1485 | 831 | static gboolean | ||
1486 | 832 | create_wizard (void) | ||
1487 | 833 | { | ||
1488 | 834 | GtkAssistant *assistant; | ||
1489 | 835 | GError *err = NULL; | ||
1490 | 836 | |||
1491 | 837 | builder = gtk_builder_new (); | ||
1492 | 838 | if (gtk_builder_add_from_file (builder, "wizard.ui", NULL) == 0) { | ||
1493 | 839 | if (gtk_builder_add_from_file (builder, PKGDATADIR "/wizard.ui", &err) == 0) { | ||
1494 | 840 | g_warning ("Could not load UI from %s: %s", PKGDATADIR "/wizard.ui", err->message); | ||
1495 | 841 | g_error_free(err); | ||
1496 | 842 | return FALSE; | ||
1497 | 843 | } | ||
1498 | 844 | } | ||
1499 | 845 | |||
1500 | 846 | window_assistant = GTK_ASSISTANT(gtk_builder_get_object(builder, "assistant")); | ||
1501 | 847 | assistant = window_assistant; | ||
1502 | 848 | |||
1503 | 849 | gtk_assistant_set_forward_page_func (assistant, page_func, NULL, NULL); | ||
1504 | 850 | |||
1505 | 851 | /* The 2 custom buttons */ | ||
1506 | 852 | button_quit = W("quit_button"); | ||
1507 | 853 | button_cancel = W("cancel_button"); | ||
1508 | 854 | gtk_assistant_add_action_widget (assistant, button_quit); | ||
1509 | 855 | gtk_assistant_add_action_widget (assistant, button_cancel); | ||
1510 | 856 | gtk_widget_hide (button_quit); | ||
1511 | 857 | gtk_widget_hide (button_cancel); | ||
1512 | 858 | |||
1513 | 859 | /* Intro page, nothing to do */ | ||
1514 | 860 | |||
1515 | 861 | /* Search page */ | ||
1516 | 862 | page_search = W("page_search"); | ||
1517 | 863 | selector = BLUETOOTH_CHOOSER (gtk_builder_get_object (builder, "selector")); | ||
1518 | 864 | |||
1519 | 865 | /* Connecting page */ | ||
1520 | 866 | page_connecting = W("page_connecting"); | ||
1521 | 867 | label_connecting = W("label_connecting"); | ||
1522 | 868 | spinner_connecting = W("spinner_connecting"); | ||
1523 | 869 | |||
1524 | 870 | /* Setup page */ | ||
1525 | 871 | page_setup = W("page_setup"); | ||
1526 | 872 | label_pin_help = W("label_pin_help"); | ||
1527 | 873 | label_pin = W("label_pin"); | ||
1528 | 874 | |||
1529 | 875 | /* SSP Setup page */ | ||
1530 | 876 | page_ssp_setup = W("page_ssp_setup"); | ||
1531 | 877 | gtk_assistant_set_page_complete(assistant, page_ssp_setup, FALSE); | ||
1532 | 878 | label_ssp_pin_help = W("label_ssp_pin_help"); | ||
1533 | 879 | label_ssp_pin = W("label_ssp_pin"); | ||
1534 | 880 | does_not_match_button = W("does_not_match_button"); | ||
1535 | 881 | matches_button = W("matches_button"); | ||
1536 | 882 | |||
1537 | 883 | /* Finishing page */ | ||
1538 | 884 | page_finishing = W("page_finishing"); | ||
1539 | 885 | label_finishing = W("label_finishing"); | ||
1540 | 886 | spinner_finishing = W("spinner_finishing"); | ||
1541 | 887 | |||
1542 | 888 | /* Summary page */ | ||
1543 | 889 | page_summary = W("page_summary"); | ||
1544 | 890 | label_summary = W("label_summary"); | ||
1545 | 891 | extra_config_vbox = W("extra_config_vbox"); | ||
1546 | 892 | |||
1547 | 893 | /* PIN dialog */ | ||
1548 | 894 | pin_dialog = W("pin_dialog"); | ||
1549 | 895 | radio_auto = W("radio_auto"); | ||
1550 | 896 | radio_0000 = W("radio_0000"); | ||
1551 | 897 | radio_1111 = W("radio_1111"); | ||
1552 | 898 | radio_1234 = W("radio_1234"); | ||
1553 | 899 | radio_none = W("radio_none"); | ||
1554 | 900 | radio_custom = W("radio_custom"); | ||
1555 | 901 | entry_custom = W("entry_custom"); | ||
1556 | 902 | |||
1557 | 903 | g_object_set_data (G_OBJECT (radio_auto), "pin", NULL); | ||
1558 | 904 | g_object_set_data (G_OBJECT (radio_0000), "pin", "0000"); | ||
1559 | 905 | g_object_set_data (G_OBJECT (radio_1111), "pin", "1111"); | ||
1560 | 906 | g_object_set_data (G_OBJECT (radio_1234), "pin", "1234"); | ||
1561 | 907 | g_object_set_data (G_OBJECT (radio_none), "pin", "NULL"); | ||
1562 | 908 | g_object_set_data (G_OBJECT (radio_custom), "pin", ""); | ||
1563 | 909 | g_object_set_data (G_OBJECT (radio_custom), "entry", entry_custom); | ||
1564 | 910 | |||
1565 | 911 | gtk_builder_connect_signals(builder, NULL); | ||
1566 | 912 | |||
1567 | 913 | gtk_widget_show (GTK_WIDGET(assistant)); | ||
1568 | 914 | |||
1569 | 915 | gtk_assistant_update_buttons_state(GTK_ASSISTANT(assistant)); | ||
1570 | 916 | |||
1571 | 917 | return TRUE; | ||
1572 | 918 | } | ||
1573 | 919 | |||
1574 | 920 | static void | ||
1575 | 921 | activate_cb (GApplication *app, | ||
1576 | 922 | gpointer user_data) | ||
1577 | 923 | { | ||
1578 | 924 | gtk_window_present_with_time (GTK_WINDOW (user_data), GDK_CURRENT_TIME); | ||
1579 | 925 | } | ||
1580 | 926 | |||
1581 | 927 | static GOptionEntry options[] = { | ||
1582 | 928 | { NULL }, | ||
1583 | 929 | }; | ||
1584 | 930 | |||
1585 | 931 | int main (int argc, char **argv) | ||
1586 | 932 | { | ||
1587 | 933 | GtkApplication *app; | ||
1588 | 934 | GError *error = NULL; | ||
1589 | 935 | |||
1590 | 936 | bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); | ||
1591 | 937 | bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); | ||
1592 | 938 | textdomain(GETTEXT_PACKAGE); | ||
1593 | 939 | |||
1594 | 940 | if (gtk_init_with_args(&argc, &argv, NULL, | ||
1595 | 941 | options, GETTEXT_PACKAGE, &error) == FALSE) { | ||
1596 | 942 | if (error) { | ||
1597 | 943 | g_printerr("%s\n", error->message); | ||
1598 | 944 | g_error_free(error); | ||
1599 | 945 | } else | ||
1600 | 946 | g_printerr("An unknown error occurred\n"); | ||
1601 | 947 | |||
1602 | 948 | return 1; | ||
1603 | 949 | } | ||
1604 | 950 | |||
1605 | 951 | app = gtk_application_new ("org.gnome.Bluetooth.wizard", G_APPLICATION_FLAGS_NONE); | ||
1606 | 952 | if (g_application_register (G_APPLICATION (app), NULL, &error) == FALSE) { | ||
1607 | 953 | g_warning ("Could not register application: %s", error->message); | ||
1608 | 954 | g_error_free (error); | ||
1609 | 955 | return 1; | ||
1610 | 956 | } | ||
1611 | 957 | |||
1612 | 958 | if (g_application_get_is_remote (G_APPLICATION (app))) { | ||
1613 | 959 | g_application_activate (G_APPLICATION (app)); | ||
1614 | 960 | gdk_notify_startup_complete (); | ||
1615 | 961 | return 0; | ||
1616 | 962 | } | ||
1617 | 963 | |||
1618 | 964 | gtk_window_set_default_icon_name("bluetooth"); | ||
1619 | 965 | |||
1620 | 966 | client = bluetooth_client_new(); | ||
1621 | 967 | |||
1622 | 968 | agent = bluetooth_agent_new(); | ||
1623 | 969 | g_object_add_weak_pointer (G_OBJECT (agent), (gpointer *) (&agent)); | ||
1624 | 970 | |||
1625 | 971 | bluetooth_agent_set_pincode_func(agent, pincode_callback, NULL); | ||
1626 | 972 | bluetooth_agent_set_display_func(agent, display_callback, NULL); | ||
1627 | 973 | bluetooth_agent_set_cancel_func(agent, cancel_callback, NULL); | ||
1628 | 974 | bluetooth_agent_set_confirm_func(agent, confirm_callback, NULL); | ||
1629 | 975 | |||
1630 | 976 | bluetooth_agent_setup(agent, AGENT_PATH); | ||
1631 | 977 | |||
1632 | 978 | bluetooth_plugin_manager_init (); | ||
1633 | 979 | |||
1634 | 980 | if (create_wizard() == FALSE) | ||
1635 | 981 | return 1; | ||
1636 | 982 | gtk_application_add_window (app, | ||
1637 | 983 | GTK_WINDOW (window_assistant)); | ||
1638 | 984 | |||
1639 | 985 | g_signal_connect (app, "activate", | ||
1640 | 986 | G_CALLBACK (activate_cb), window_assistant); | ||
1641 | 987 | |||
1642 | 988 | g_application_run (G_APPLICATION (app), argc, argv); | ||
1643 | 989 | |||
1644 | 990 | bluetooth_plugin_manager_cleanup (); | ||
1645 | 991 | |||
1646 | 992 | if (agent != NULL) | ||
1647 | 993 | g_object_unref (agent); | ||
1648 | 994 | |||
1649 | 995 | g_object_unref(client); | ||
1650 | 996 | |||
1651 | 997 | g_object_unref(app); | ||
1652 | 998 | |||
1653 | 999 | return 0; | ||
1654 | 1000 | } | ||
1655 | 1001 | |||
1656 | 0 | 1002 | ||
1657 | === modified file 'debian/changelog' | |||
1658 | --- debian/changelog 2014-04-25 02:00:56 +0000 | |||
1659 | +++ debian/changelog 2014-05-15 03:31:21 +0000 | |||
1660 | @@ -1,3 +1,13 @@ | |||
1661 | 1 | gnome-bluetooth (3.8.2.1-0ubuntu6~test1) utopic; urgency=medium | ||
1662 | 2 | |||
1663 | 3 | * Add ssp parameter fix, fix the parameter entered in agent dbus API, | ||
1664 | 4 | also fix the wizard's UI to show the pin code correctly. | ||
1665 | 5 | Fixed Logitech Bluetooth Keyboard K760, Logitech Bluetooth Keyboard K810, | ||
1666 | 6 | HP Bluetooth Keyboard K4000 secure simple pairing failed issue. | ||
1667 | 7 | (LP: #1035431, #1291756) | ||
1668 | 8 | |||
1669 | 9 | -- Jian-Ding Chen (timchen119) <tim.chen119@canonical.com> Fri, 02 May 2014 16:50:57 +0800 | ||
1670 | 10 | |||
1671 | 1 | gnome-bluetooth (3.8.2.1-0ubuntu5) utopic; urgency=low | 11 | gnome-bluetooth (3.8.2.1-0ubuntu5) utopic; urgency=low |
1672 | 2 | 12 | ||
1673 | 3 | * debian/patches/99_add_microsoft_mice.patch: fix the problem that | 13 | * debian/patches/99_add_microsoft_mice.patch: fix the problem that |
1674 | 4 | 14 | ||
1675 | === modified file 'debian/patches/series' | |||
1676 | --- debian/patches/series 2014-02-25 16:32:43 +0000 | |||
1677 | +++ debian/patches/series 2014-05-15 03:31:21 +0000 | |||
1678 | @@ -7,3 +7,4 @@ | |||
1679 | 7 | git_leak_fixes.patch | 7 | git_leak_fixes.patch |
1680 | 8 | git_disconnect_callbacks.patch | 8 | git_disconnect_callbacks.patch |
1681 | 9 | git_reference_handling.patch | 9 | git_reference_handling.patch |
1682 | 10 | ssp-parameter-fix.patch | ||
1683 | 10 | 11 | ||
1684 | === added file 'debian/patches/ssp-parameter-fix.patch' | |||
1685 | --- debian/patches/ssp-parameter-fix.patch 1970-01-01 00:00:00 +0000 | |||
1686 | +++ debian/patches/ssp-parameter-fix.patch 2014-05-15 03:31:21 +0000 | |||
1687 | @@ -0,0 +1,86 @@ | |||
1688 | 1 | Description: ssp parameter fix | ||
1689 | 2 | * Add ssp parameter fix, fix the parameter entered in agent dbus API, | ||
1690 | 3 | also fix the wizard's UI to show the pin code correctly. | ||
1691 | 4 | Fixed Logitech Bluetooth Keyboard K760, Logitech Bluetooth Keyboard K810, | ||
1692 | 5 | HP Bluetooth Keyboard K4000 secure simple pairing failed issue. | ||
1693 | 6 | (LP: #1035431, #1291756) | ||
1694 | 7 | Author: Jian-Ding Chen (timchen119) <tim.chen119@canonical.com> | ||
1695 | 8 | Bug-Ubuntu: https://bugs.launchpad.net/bugs/1035431 | ||
1696 | 9 | Bug-Ubuntu: https://bugs.launchpad.net/bugs/1291756 | ||
1697 | 10 | Last-Update: 2014-04-29 | ||
1698 | 11 | |||
1699 | 12 | --- gnome-bluetooth-3.8.2.1.orig/lib/bluetooth-agent.c | ||
1700 | 13 | +++ gnome-bluetooth-3.8.2.1/lib/bluetooth-agent.c | ||
1701 | 14 | @@ -52,7 +52,7 @@ static const gchar introspection_xml[] = | ||
1702 | 15 | " <method name='DisplayPasskey'>" | ||
1703 | 16 | " <arg type='o' name='device' direction='in'/>" | ||
1704 | 17 | " <arg type='u' name='passkey' direction='in'/>" | ||
1705 | 18 | -" <arg type='y' name='entered' direction='in'/>" | ||
1706 | 19 | +" <arg type='q' name='entered' direction='in'/>" | ||
1707 | 20 | " </method>" | ||
1708 | 21 | " <method name='RequestConfirmation'>" | ||
1709 | 22 | " <arg type='o' name='device' direction='in'/>" | ||
1710 | 23 | @@ -164,7 +164,7 @@ static gboolean bluetooth_agent_request_ | ||
1711 | 24 | } | ||
1712 | 25 | |||
1713 | 26 | static gboolean bluetooth_agent_display_passkey(BluetoothAgent *agent, | ||
1714 | 27 | - const char *path, guint passkey, guint8 entered, | ||
1715 | 28 | + const char *path, guint passkey, guint16 entered, | ||
1716 | 29 | GDBusMethodInvocation *invocation) | ||
1717 | 30 | { | ||
1718 | 31 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | ||
1719 | 32 | @@ -339,9 +339,9 @@ handle_method_call (GDBusConnection | ||
1720 | 33 | } else if (g_strcmp0 (method_name, "DisplayPasskey") == 0) { | ||
1721 | 34 | char *path; | ||
1722 | 35 | guint32 passkey; | ||
1723 | 36 | - guint8 entered; | ||
1724 | 37 | + guint16 entered; | ||
1725 | 38 | |||
1726 | 39 | - g_variant_get (parameters, "(ouy)", &path, &passkey, &entered); | ||
1727 | 40 | + g_variant_get (parameters, "(ouq)", &path, &passkey, &entered); | ||
1728 | 41 | bluetooth_agent_display_passkey (agent, path, passkey, entered, invocation); | ||
1729 | 42 | g_free (path); | ||
1730 | 43 | } else if (g_strcmp0 (method_name, "RequestConfirmation") == 0) { | ||
1731 | 44 | --- gnome-bluetooth-3.8.2.1.orig/wizard/main.c | ||
1732 | 45 | +++ gnome-bluetooth-3.8.2.1/wizard/main.c | ||
1733 | 46 | @@ -303,7 +303,7 @@ display_callback (GDBusMethodInvocation | ||
1734 | 47 | guint entered, | ||
1735 | 48 | gpointer user_data) | ||
1736 | 49 | { | ||
1737 | 50 | - gchar *text, *done, *code; | ||
1738 | 51 | + gchar *text, *done, *code, *label; | ||
1739 | 52 | |||
1740 | 53 | display_called = TRUE; | ||
1741 | 54 | target_ssp = TRUE; | ||
1742 | 55 | @@ -329,18 +329,27 @@ display_callback (GDBusMethodInvocation | ||
1743 | 56 | |||
1744 | 57 | done = g_string_free (str, FALSE); | ||
1745 | 58 | } else { | ||
1746 | 59 | - done = g_strdup (""); | ||
1747 | 60 | + done = g_strdup_printf("%s", code); | ||
1748 | 61 | } | ||
1749 | 62 | |||
1750 | 63 | - gtk_widget_show (label_pin_help); | ||
1751 | 64 | + gtk_widget_show (label_ssp_pin); | ||
1752 | 65 | |||
1753 | 66 | - gtk_label_set_markup(GTK_LABEL(label_ssp_pin_help), _("Please enter the following PIN:")); | ||
1754 | 67 | - text = g_strdup_printf("%s%s", done, code + entered); | ||
1755 | 68 | + if (target_ui_behaviour == PAIRING_UI_KEYBOARD) { | ||
1756 | 69 | + label = g_strdup_printf (_("Please enter the following PIN on '%s' and press “Enter” on the keyboard:"), target_name); | ||
1757 | 70 | + text = g_strdup_printf("%s⏎", done); | ||
1758 | 71 | + } | ||
1759 | 72 | + else { | ||
1760 | 73 | + label = g_strdup_printf (_("Please enter the following PIN on '%s':"), target_name); | ||
1761 | 74 | + text = g_strdup_printf("%s", done); | ||
1762 | 75 | + } | ||
1763 | 76 | + | ||
1764 | 77 | + gtk_label_set_markup(GTK_LABEL(label_ssp_pin_help), label); | ||
1765 | 78 | set_large_label (GTK_LABEL (label_ssp_pin), text); | ||
1766 | 79 | g_free(text); | ||
1767 | 80 | |||
1768 | 81 | g_free(done); | ||
1769 | 82 | g_free(code); | ||
1770 | 83 | + g_free(label); | ||
1771 | 84 | |||
1772 | 85 | g_dbus_method_invocation_return_value (invocation, NULL); | ||
1773 | 86 | |||
1774 | 0 | 87 | ||
1775 | === modified file 'lib/bluetooth-agent.c' | |||
1776 | --- lib/bluetooth-agent.c 2013-07-03 16:07:57 +0000 | |||
1777 | +++ lib/bluetooth-agent.c 2014-05-15 03:31:21 +0000 | |||
1778 | @@ -52,7 +52,7 @@ | |||
1779 | 52 | " <method name='DisplayPasskey'>" | 52 | " <method name='DisplayPasskey'>" |
1780 | 53 | " <arg type='o' name='device' direction='in'/>" | 53 | " <arg type='o' name='device' direction='in'/>" |
1781 | 54 | " <arg type='u' name='passkey' direction='in'/>" | 54 | " <arg type='u' name='passkey' direction='in'/>" |
1783 | 55 | " <arg type='y' name='entered' direction='in'/>" | 55 | " <arg type='q' name='entered' direction='in'/>" |
1784 | 56 | " </method>" | 56 | " </method>" |
1785 | 57 | " <method name='RequestConfirmation'>" | 57 | " <method name='RequestConfirmation'>" |
1786 | 58 | " <arg type='o' name='device' direction='in'/>" | 58 | " <arg type='o' name='device' direction='in'/>" |
1787 | @@ -164,7 +164,7 @@ | |||
1788 | 164 | } | 164 | } |
1789 | 165 | 165 | ||
1790 | 166 | static gboolean bluetooth_agent_display_passkey(BluetoothAgent *agent, | 166 | static gboolean bluetooth_agent_display_passkey(BluetoothAgent *agent, |
1792 | 167 | const char *path, guint passkey, guint8 entered, | 167 | const char *path, guint passkey, guint16 entered, |
1793 | 168 | GDBusMethodInvocation *invocation) | 168 | GDBusMethodInvocation *invocation) |
1794 | 169 | { | 169 | { |
1795 | 170 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); | 170 | BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent); |
1796 | @@ -339,9 +339,9 @@ | |||
1797 | 339 | } else if (g_strcmp0 (method_name, "DisplayPasskey") == 0) { | 339 | } else if (g_strcmp0 (method_name, "DisplayPasskey") == 0) { |
1798 | 340 | char *path; | 340 | char *path; |
1799 | 341 | guint32 passkey; | 341 | guint32 passkey; |
1801 | 342 | guint8 entered; | 342 | guint16 entered; |
1802 | 343 | 343 | ||
1804 | 344 | g_variant_get (parameters, "(ouy)", &path, &passkey, &entered); | 344 | g_variant_get (parameters, "(ouq)", &path, &passkey, &entered); |
1805 | 345 | bluetooth_agent_display_passkey (agent, path, passkey, entered, invocation); | 345 | bluetooth_agent_display_passkey (agent, path, passkey, entered, invocation); |
1806 | 346 | g_free (path); | 346 | g_free (path); |
1807 | 347 | } else if (g_strcmp0 (method_name, "RequestConfirmation") == 0) { | 347 | } else if (g_strcmp0 (method_name, "RequestConfirmation") == 0) { |
1808 | 348 | 348 | ||
1809 | === modified file 'wizard/main.c' | |||
1810 | --- wizard/main.c 2013-07-03 16:07:57 +0000 | |||
1811 | +++ wizard/main.c 2014-05-15 03:31:21 +0000 | |||
1812 | @@ -303,7 +303,7 @@ | |||
1813 | 303 | guint entered, | 303 | guint entered, |
1814 | 304 | gpointer user_data) | 304 | gpointer user_data) |
1815 | 305 | { | 305 | { |
1817 | 306 | gchar *text, *done, *code; | 306 | gchar *text, *done, *code, *label; |
1818 | 307 | 307 | ||
1819 | 308 | display_called = TRUE; | 308 | display_called = TRUE; |
1820 | 309 | target_ssp = TRUE; | 309 | target_ssp = TRUE; |
1821 | @@ -329,18 +329,27 @@ | |||
1822 | 329 | 329 | ||
1823 | 330 | done = g_string_free (str, FALSE); | 330 | done = g_string_free (str, FALSE); |
1824 | 331 | } else { | 331 | } else { |
1832 | 332 | done = g_strdup (""); | 332 | done = g_strdup_printf("%s", code); |
1833 | 333 | } | 333 | } |
1834 | 334 | 334 | ||
1835 | 335 | gtk_widget_show (label_pin_help); | 335 | gtk_widget_show (label_ssp_pin); |
1836 | 336 | 336 | ||
1837 | 337 | gtk_label_set_markup(GTK_LABEL(label_ssp_pin_help), _("Please enter the following PIN:")); | 337 | if (target_ui_behaviour == PAIRING_UI_KEYBOARD) { |
1838 | 338 | text = g_strdup_printf("%s%s", done, code + entered); | 338 | label = g_strdup_printf (_("Please enter the following PIN on '%s' and press “Enter” on the keyboard:"), target_name); |
1839 | 339 | text = g_strdup_printf("%s⏎", done); | ||
1840 | 340 | } | ||
1841 | 341 | else { | ||
1842 | 342 | label = g_strdup_printf (_("Please enter the following PIN on '%s':"), target_name); | ||
1843 | 343 | text = g_strdup_printf("%s", done); | ||
1844 | 344 | } | ||
1845 | 345 | |||
1846 | 346 | gtk_label_set_markup(GTK_LABEL(label_ssp_pin_help), label); | ||
1847 | 339 | set_large_label (GTK_LABEL (label_ssp_pin), text); | 347 | set_large_label (GTK_LABEL (label_ssp_pin), text); |
1848 | 340 | g_free(text); | 348 | g_free(text); |
1849 | 341 | 349 | ||
1850 | 342 | g_free(done); | 350 | g_free(done); |
1851 | 343 | g_free(code); | 351 | g_free(code); |
1852 | 352 | g_free(label); | ||
1853 | 344 | 353 | ||
1854 | 345 | g_dbus_method_invocation_return_value (invocation, NULL); | 354 | g_dbus_method_invocation_return_value (invocation, NULL); |
1855 | 346 | 355 |
Looks fine to me. If it fixes the issues let's land it.