PageRenderTime 55ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/usr/src/cmd/hal/hald/device.c

https://bitbucket.org/a3217055/illumos-2
C | 1352 lines | 981 code | 307 blank | 64 comment | 197 complexity | 85dca327133449fdca10bcde284395fb MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, AGPL-3.0, BSD-3-Clause, LGPL-2.0, 0BSD, BSD-2-Clause, BSD-3-Clause-No-Nuclear-License-2014, AGPL-1.0, GPL-2.0
  1. /***************************************************************************
  2. * CVSID: $Id$
  3. *
  4. * device.c : HalDevice methods
  5. *
  6. * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
  7. * Copyright (C) 2004 Novell, Inc.
  8. *
  9. * Licensed under the Academic Free License version 2.1
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. **************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include <config.h>
  28. #endif
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include "hald.h"
  32. #include "device.h"
  33. #include "hald_marshal.h"
  34. #include "logger.h"
  35. #include "hald_runner.h"
  36. static GObjectClass *parent_class;
  37. enum {
  38. PROPERTY_CHANGED,
  39. CAPABILITY_ADDED,
  40. CALLOUTS_FINISHED,
  41. CANCELLED,
  42. LAST_SIGNAL
  43. };
  44. static guint signals[LAST_SIGNAL] = { 0 };
  45. #ifdef HALD_MEMLEAK_DBG
  46. int dbg_hal_device_object_delta = 0;
  47. #endif
  48. static void
  49. hal_device_finalize (GObject *obj)
  50. {
  51. HalDevice *device = HAL_DEVICE (obj);
  52. runner_device_finalized (device);
  53. #ifdef HALD_MEMLEAK_DBG
  54. dbg_hal_device_object_delta--;
  55. printf ("************* in finalize for udi=%s\n", device->udi);
  56. #endif
  57. g_slist_foreach (device->properties, (GFunc) hal_property_free, NULL);
  58. g_slist_free (device->properties);
  59. g_free (device->udi);
  60. if (parent_class->finalize)
  61. parent_class->finalize (obj);
  62. }
  63. static void
  64. hal_device_class_init (HalDeviceClass *klass)
  65. {
  66. GObjectClass *obj_class = (GObjectClass *) klass;
  67. parent_class = g_type_class_peek_parent (klass);
  68. obj_class->finalize = hal_device_finalize;
  69. signals[PROPERTY_CHANGED] =
  70. g_signal_new ("property_changed",
  71. G_TYPE_FROM_CLASS (klass),
  72. G_SIGNAL_RUN_LAST,
  73. G_STRUCT_OFFSET (HalDeviceClass,
  74. property_changed),
  75. NULL, NULL,
  76. hald_marshal_VOID__STRING_BOOL_BOOL,
  77. G_TYPE_NONE, 3,
  78. G_TYPE_STRING,
  79. G_TYPE_BOOLEAN,
  80. G_TYPE_BOOLEAN);
  81. signals[CAPABILITY_ADDED] =
  82. g_signal_new ("capability_added",
  83. G_TYPE_FROM_CLASS (klass),
  84. G_SIGNAL_RUN_LAST,
  85. G_STRUCT_OFFSET (HalDeviceClass,
  86. capability_added),
  87. NULL, NULL,
  88. hald_marshal_VOID__STRING,
  89. G_TYPE_NONE, 1,
  90. G_TYPE_STRING);
  91. signals[CALLOUTS_FINISHED] =
  92. g_signal_new ("callouts_finished",
  93. G_TYPE_FROM_CLASS (klass),
  94. G_SIGNAL_RUN_LAST,
  95. G_STRUCT_OFFSET (HalDeviceClass,
  96. callouts_finished),
  97. NULL, NULL,
  98. hald_marshal_VOID__VOID,
  99. G_TYPE_NONE, 0);
  100. signals[CANCELLED] =
  101. g_signal_new ("cancelled",
  102. G_TYPE_FROM_CLASS (klass),
  103. G_SIGNAL_RUN_LAST,
  104. G_STRUCT_OFFSET (HalDeviceClass,
  105. cancelled),
  106. NULL, NULL,
  107. hald_marshal_VOID__VOID,
  108. G_TYPE_NONE, 0);
  109. }
  110. static void
  111. hal_device_init (HalDevice *device)
  112. {
  113. static int temp_device_counter = 0;
  114. device->udi = g_strdup_printf ("/org/freedesktop/Hal/devices/temp/%d",
  115. temp_device_counter++);
  116. device->num_addons = 0;
  117. device->num_addons_ready = 0;
  118. }
  119. GType
  120. hal_device_get_type (void)
  121. {
  122. static GType type = 0;
  123. if (!type) {
  124. static GTypeInfo type_info = {
  125. sizeof (HalDeviceClass),
  126. NULL, NULL,
  127. (GClassInitFunc) hal_device_class_init,
  128. NULL, NULL,
  129. sizeof (HalDevice),
  130. 0,
  131. (GInstanceInitFunc) hal_device_init,
  132. NULL
  133. };
  134. type = g_type_register_static (G_TYPE_OBJECT,
  135. "HalDevice",
  136. &type_info,
  137. 0);
  138. }
  139. return type;
  140. }
  141. HalDevice *
  142. hal_device_new (void)
  143. {
  144. HalDevice *device;
  145. device = g_object_new (HAL_TYPE_DEVICE, NULL, NULL);
  146. #ifdef HALD_MEMLEAK_DBG
  147. dbg_hal_device_object_delta++;
  148. #endif
  149. return device;
  150. }
  151. /** Merge all properties from source where the key starts with
  152. * source_namespace and put them onto target replacing source_namespace
  153. * with target_namespace
  154. *
  155. * @param target Device to put properties onto
  156. * @param source Device to retrieve properties from
  157. * @param target_namespace Replace source namespace with this namespace
  158. * @param source_namespace Source namespace that property keys must match
  159. */
  160. void
  161. hal_device_merge_with_rewrite (HalDevice *target,
  162. HalDevice *source,
  163. const char *target_namespace,
  164. const char *source_namespace)
  165. {
  166. GSList *iter;
  167. size_t source_ns_len;
  168. source_ns_len = strlen (source_namespace);
  169. /* doesn't handle info.capabilities */
  170. /* device_property_atomic_update_begin (); */
  171. for (iter = source->properties; iter != NULL; iter = iter->next) {
  172. HalProperty *p = iter->data;
  173. int type;
  174. const char *key;
  175. int target_type;
  176. gchar *target_key;
  177. key = hal_property_get_key (p);
  178. /* only care about properties that match source namespace */
  179. if (strncmp(key, source_namespace, source_ns_len) != 0)
  180. continue;
  181. target_key = g_strdup_printf("%s%s", target_namespace,
  182. key+source_ns_len);
  183. type = hal_property_get_type (p);
  184. /* only remove target if it exists with a different type */
  185. target_type = hal_device_property_get_type (target, key);
  186. if (target_type != HAL_PROPERTY_TYPE_INVALID && target_type != type)
  187. hal_device_property_remove (target, key);
  188. switch (type) {
  189. case HAL_PROPERTY_TYPE_STRING:
  190. hal_device_property_set_string (
  191. target, target_key,
  192. hal_property_get_string (p));
  193. break;
  194. case HAL_PROPERTY_TYPE_INT32:
  195. hal_device_property_set_int (
  196. target, target_key,
  197. hal_property_get_int (p));
  198. break;
  199. case HAL_PROPERTY_TYPE_UINT64:
  200. hal_device_property_set_uint64 (
  201. target, target_key,
  202. hal_property_get_uint64 (p));
  203. break;
  204. case HAL_PROPERTY_TYPE_BOOLEAN:
  205. hal_device_property_set_bool (
  206. target, target_key,
  207. hal_property_get_bool (p));
  208. break;
  209. case HAL_PROPERTY_TYPE_DOUBLE:
  210. hal_device_property_set_double (
  211. target, target_key,
  212. hal_property_get_double (p));
  213. break;
  214. default:
  215. HAL_WARNING (("Unknown property type %d", type));
  216. break;
  217. }
  218. g_free (target_key);
  219. }
  220. /* device_property_atomic_update_end (); */
  221. }
  222. void
  223. hal_device_merge (HalDevice *target, HalDevice *source)
  224. {
  225. GSList *iter;
  226. GSList *caps;
  227. /* device_property_atomic_update_begin (); */
  228. for (iter = source->properties; iter != NULL; iter = iter->next) {
  229. HalProperty *p = iter->data;
  230. int type;
  231. const char *key;
  232. int target_type;
  233. key = hal_property_get_key (p);
  234. type = hal_property_get_type (p);
  235. /* handle info.capabilities in a special way */
  236. if (strcmp (key, "info.capabilities") == 0)
  237. continue;
  238. /* only remove target if it exists with a different type */
  239. target_type = hal_device_property_get_type (target, key);
  240. if (target_type != HAL_PROPERTY_TYPE_INVALID && target_type != type)
  241. hal_device_property_remove (target, key);
  242. switch (type) {
  243. case HAL_PROPERTY_TYPE_STRING:
  244. hal_device_property_set_string (
  245. target, key,
  246. hal_property_get_string (p));
  247. break;
  248. case HAL_PROPERTY_TYPE_INT32:
  249. hal_device_property_set_int (
  250. target, key,
  251. hal_property_get_int (p));
  252. break;
  253. case HAL_PROPERTY_TYPE_UINT64:
  254. hal_device_property_set_uint64 (
  255. target, key,
  256. hal_property_get_uint64 (p));
  257. break;
  258. case HAL_PROPERTY_TYPE_BOOLEAN:
  259. hal_device_property_set_bool (
  260. target, key,
  261. hal_property_get_bool (p));
  262. break;
  263. case HAL_PROPERTY_TYPE_DOUBLE:
  264. hal_device_property_set_double (
  265. target, key,
  266. hal_property_get_double (p));
  267. break;
  268. default:
  269. HAL_WARNING (("Unknown property type %d", type));
  270. break;
  271. }
  272. }
  273. /* device_property_atomic_update_end (); */
  274. caps = hal_device_property_get_strlist (source, "info.capabilities");
  275. for (iter = caps; iter != NULL; iter = iter->next) {
  276. if (!hal_device_has_capability (target, iter->data))
  277. hal_device_add_capability (target, iter->data);
  278. }
  279. }
  280. gboolean
  281. hal_device_matches (HalDevice *device1, HalDevice *device2,
  282. const char *namespace)
  283. {
  284. int len;
  285. GSList *iter;
  286. len = strlen (namespace);
  287. for (iter = device1->properties; iter != NULL; iter = iter->next) {
  288. HalProperty *p;
  289. const char *key;
  290. int type;
  291. p = (HalProperty *) iter->data;
  292. key = hal_property_get_key (p);
  293. type = hal_property_get_type (p);
  294. if (strncmp (key, namespace, len) != 0)
  295. continue;
  296. if (!hal_device_has_property (device2, key))
  297. return FALSE;
  298. switch (type) {
  299. case HAL_PROPERTY_TYPE_STRING:
  300. if (strcmp (hal_property_get_string (p),
  301. hal_device_property_get_string (device2,
  302. key)) != 0)
  303. return FALSE;
  304. break;
  305. case HAL_PROPERTY_TYPE_INT32:
  306. if (hal_property_get_int (p) !=
  307. hal_device_property_get_int (device2, key))
  308. return FALSE;
  309. break;
  310. case HAL_PROPERTY_TYPE_UINT64:
  311. if (hal_property_get_uint64 (p) !=
  312. hal_device_property_get_uint64 (device2, key))
  313. return FALSE;
  314. break;
  315. case HAL_PROPERTY_TYPE_BOOLEAN:
  316. if (hal_property_get_bool (p) !=
  317. hal_device_property_get_bool (device2, key))
  318. return FALSE;
  319. break;
  320. case HAL_PROPERTY_TYPE_DOUBLE:
  321. if (hal_property_get_double (p) !=
  322. hal_device_property_get_double (device2, key))
  323. return FALSE;
  324. break;
  325. default:
  326. HAL_WARNING (("Unknown property type %d", type));
  327. break;
  328. }
  329. }
  330. return TRUE;
  331. }
  332. const char *
  333. hal_device_get_udi (HalDevice *device)
  334. {
  335. return device->udi;
  336. }
  337. void
  338. hal_device_set_udi (HalDevice *device, const char *udi)
  339. {
  340. if (device->udi != NULL)
  341. g_free (device->udi);
  342. device->udi = g_strdup (udi);
  343. }
  344. void
  345. hal_device_add_capability (HalDevice *device, const char *capability)
  346. {
  347. if (hal_device_property_strlist_add (device, "info.capabilities", capability))
  348. g_signal_emit (device, signals[CAPABILITY_ADDED], 0, capability);
  349. }
  350. gboolean
  351. hal_device_has_capability (HalDevice *device, const char *capability)
  352. {
  353. GSList *caps;
  354. GSList *iter;
  355. gboolean matched = FALSE;
  356. caps = hal_device_property_get_strlist (device, "info.capabilities");
  357. if (caps == NULL)
  358. return FALSE;
  359. for (iter = caps; iter != NULL; iter = iter->next) {
  360. if (strcmp (iter->data, capability) == 0) {
  361. matched = TRUE;
  362. break;
  363. }
  364. }
  365. return matched;
  366. }
  367. gboolean
  368. hal_device_has_property (HalDevice *device, const char *key)
  369. {
  370. g_return_val_if_fail (device != NULL, FALSE);
  371. g_return_val_if_fail (key != NULL, FALSE);
  372. return hal_device_property_find (device, key) != NULL;
  373. }
  374. int
  375. hal_device_num_properties (HalDevice *device)
  376. {
  377. g_return_val_if_fail (device != NULL, -1);
  378. return g_slist_length (device->properties);
  379. }
  380. HalProperty *
  381. hal_device_property_find (HalDevice *device, const char *key)
  382. {
  383. GSList *iter;
  384. g_return_val_if_fail (device != NULL, NULL);
  385. g_return_val_if_fail (key != NULL, NULL);
  386. for (iter = device->properties; iter != NULL; iter = iter->next) {
  387. HalProperty *p = iter->data;
  388. if (strcmp (hal_property_get_key (p), key) == 0)
  389. return p;
  390. }
  391. return NULL;
  392. }
  393. char *
  394. hal_device_property_to_string (HalDevice *device, const char *key)
  395. {
  396. HalProperty *prop;
  397. prop = hal_device_property_find (device, key);
  398. if (!prop)
  399. return NULL;
  400. return hal_property_to_string (prop);
  401. }
  402. void
  403. hal_device_property_foreach (HalDevice *device,
  404. HalDevicePropertyForeachFn callback,
  405. gpointer user_data)
  406. {
  407. GSList *iter;
  408. g_return_if_fail (device != NULL);
  409. g_return_if_fail (callback != NULL);
  410. for (iter = device->properties; iter != NULL; iter = iter->next) {
  411. HalProperty *p = iter->data;
  412. gboolean cont;
  413. cont = callback (device, p, user_data);
  414. if (cont == FALSE)
  415. return;
  416. }
  417. }
  418. int
  419. hal_device_property_get_type (HalDevice *device, const char *key)
  420. {
  421. HalProperty *prop;
  422. g_return_val_if_fail (device != NULL, HAL_PROPERTY_TYPE_INVALID);
  423. g_return_val_if_fail (key != NULL, HAL_PROPERTY_TYPE_INVALID);
  424. prop = hal_device_property_find (device, key);
  425. if (prop != NULL)
  426. return hal_property_get_type (prop);
  427. else
  428. return HAL_PROPERTY_TYPE_INVALID;
  429. }
  430. const char *
  431. hal_device_property_get_string (HalDevice *device, const char *key)
  432. {
  433. HalProperty *prop;
  434. g_return_val_if_fail (device != NULL, NULL);
  435. g_return_val_if_fail (key != NULL, NULL);
  436. prop = hal_device_property_find (device, key);
  437. if (prop != NULL)
  438. return hal_property_get_string (prop);
  439. else
  440. return NULL;
  441. }
  442. const char *
  443. hal_device_property_get_as_string (HalDevice *device, const char *key, char *buf, size_t bufsize)
  444. {
  445. HalProperty *prop;
  446. g_return_val_if_fail (device != NULL, NULL);
  447. g_return_val_if_fail (key != NULL, NULL);
  448. g_return_val_if_fail (buf != NULL, NULL);
  449. prop = hal_device_property_find (device, key);
  450. if (prop != NULL) {
  451. switch (hal_property_get_type (prop)) {
  452. case HAL_PROPERTY_TYPE_STRING:
  453. strncpy (buf, hal_property_get_string (prop), bufsize);
  454. break;
  455. case HAL_PROPERTY_TYPE_INT32:
  456. snprintf (buf, bufsize, "%d", hal_property_get_int (prop));
  457. break;
  458. case HAL_PROPERTY_TYPE_UINT64:
  459. snprintf (buf, bufsize, "%llu", (long long unsigned int) hal_property_get_uint64 (prop));
  460. break;
  461. case HAL_PROPERTY_TYPE_DOUBLE:
  462. snprintf (buf, bufsize, "%f", hal_property_get_double (prop));
  463. break;
  464. case HAL_PROPERTY_TYPE_BOOLEAN:
  465. strncpy (buf, hal_property_get_bool (prop) ? "true" : "false", bufsize);
  466. break;
  467. case HAL_PROPERTY_TYPE_STRLIST:
  468. /* print out as "\tval1\tval2\val3\t" */
  469. {
  470. GSList *iter;
  471. guint i;
  472. if (bufsize > 0)
  473. buf[0] = '\t';
  474. i = 1;
  475. for (iter = hal_property_get_strlist (prop);
  476. iter != NULL && i < bufsize;
  477. iter = g_slist_next (iter)) {
  478. guint len;
  479. const char *str;
  480. str = (const char *) iter->data;
  481. len = strlen (str);
  482. strncpy (buf + i, str, bufsize - i);
  483. i += len;
  484. if (i < bufsize) {
  485. buf[i] = '\t';
  486. i++;
  487. }
  488. }
  489. }
  490. break;
  491. }
  492. return buf;
  493. } else {
  494. buf[0] = '\0';
  495. return NULL;
  496. }
  497. }
  498. dbus_int32_t
  499. hal_device_property_get_int (HalDevice *device, const char *key)
  500. {
  501. HalProperty *prop;
  502. g_return_val_if_fail (device != NULL, -1);
  503. g_return_val_if_fail (key != NULL, -1);
  504. prop = hal_device_property_find (device, key);
  505. if (prop != NULL)
  506. return hal_property_get_int (prop);
  507. else
  508. return -1;
  509. }
  510. dbus_uint64_t
  511. hal_device_property_get_uint64 (HalDevice *device, const char *key)
  512. {
  513. HalProperty *prop;
  514. g_return_val_if_fail (device != NULL, -1);
  515. g_return_val_if_fail (key != NULL, -1);
  516. prop = hal_device_property_find (device, key);
  517. if (prop != NULL)
  518. return hal_property_get_uint64 (prop);
  519. else
  520. return -1;
  521. }
  522. dbus_bool_t
  523. hal_device_property_get_bool (HalDevice *device, const char *key)
  524. {
  525. HalProperty *prop;
  526. g_return_val_if_fail (device != NULL, FALSE);
  527. g_return_val_if_fail (key != NULL, FALSE);
  528. prop = hal_device_property_find (device, key);
  529. if (prop != NULL)
  530. return hal_property_get_bool (prop);
  531. else
  532. return FALSE;
  533. }
  534. double
  535. hal_device_property_get_double (HalDevice *device, const char *key)
  536. {
  537. HalProperty *prop;
  538. g_return_val_if_fail (device != NULL, -1.0);
  539. g_return_val_if_fail (key != NULL, -1.0);
  540. prop = hal_device_property_find (device, key);
  541. if (prop != NULL)
  542. return hal_property_get_double (prop);
  543. else
  544. return -1.0;
  545. }
  546. gboolean
  547. hal_device_property_set_string (HalDevice *device, const char *key,
  548. const char *value)
  549. {
  550. HalProperty *prop;
  551. /* check if property already exists */
  552. prop = hal_device_property_find (device, key);
  553. if (prop != NULL) {
  554. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRING)
  555. return FALSE;
  556. /* don't bother setting the same value */
  557. if (value != NULL &&
  558. strcmp (hal_property_get_string (prop), value) == 0)
  559. return TRUE;
  560. hal_property_set_string (prop, value);
  561. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  562. key, FALSE, FALSE);
  563. } else {
  564. prop = hal_property_new_string (key, value);
  565. device->properties = g_slist_prepend (device->properties, prop);
  566. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  567. key, FALSE, TRUE);
  568. }
  569. return TRUE;
  570. }
  571. gboolean
  572. hal_device_property_set_int (HalDevice *device, const char *key,
  573. dbus_int32_t value)
  574. {
  575. HalProperty *prop;
  576. /* check if property already exists */
  577. prop = hal_device_property_find (device, key);
  578. if (prop != NULL) {
  579. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_INT32)
  580. return FALSE;
  581. /* don't bother setting the same value */
  582. if (hal_property_get_int (prop) == value)
  583. return TRUE;
  584. hal_property_set_int (prop, value);
  585. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  586. key, FALSE, FALSE);
  587. } else {
  588. prop = hal_property_new_int (key, value);
  589. device->properties = g_slist_prepend (device->properties, prop);
  590. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  591. key, FALSE, TRUE);
  592. }
  593. return TRUE;
  594. }
  595. gboolean
  596. hal_device_property_set_uint64 (HalDevice *device, const char *key,
  597. dbus_uint64_t value)
  598. {
  599. HalProperty *prop;
  600. /* check if property already exists */
  601. prop = hal_device_property_find (device, key);
  602. if (prop != NULL) {
  603. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_UINT64)
  604. return FALSE;
  605. /* don't bother setting the same value */
  606. if (hal_property_get_uint64 (prop) == value)
  607. return TRUE;
  608. hal_property_set_uint64 (prop, value);
  609. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  610. key, FALSE, FALSE);
  611. } else {
  612. prop = hal_property_new_uint64 (key, value);
  613. device->properties = g_slist_prepend (device->properties, prop);
  614. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  615. key, FALSE, TRUE);
  616. }
  617. return TRUE;
  618. }
  619. gboolean
  620. hal_device_property_set_bool (HalDevice *device, const char *key,
  621. dbus_bool_t value)
  622. {
  623. HalProperty *prop;
  624. /* check if property already exists */
  625. prop = hal_device_property_find (device, key);
  626. if (prop != NULL) {
  627. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_BOOLEAN)
  628. return FALSE;
  629. /* don't bother setting the same value */
  630. if (hal_property_get_bool (prop) == value)
  631. return TRUE;
  632. hal_property_set_bool (prop, value);
  633. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  634. key, FALSE, FALSE);
  635. } else {
  636. prop = hal_property_new_bool (key, value);
  637. device->properties = g_slist_prepend (device->properties, prop);
  638. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  639. key, FALSE, TRUE);
  640. }
  641. return TRUE;
  642. }
  643. gboolean
  644. hal_device_property_set_double (HalDevice *device, const char *key,
  645. double value)
  646. {
  647. HalProperty *prop;
  648. /* check if property already exists */
  649. prop = hal_device_property_find (device, key);
  650. if (prop != NULL) {
  651. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_DOUBLE)
  652. return FALSE;
  653. /* don't bother setting the same value */
  654. if (hal_property_get_double (prop) == value)
  655. return TRUE;
  656. hal_property_set_double (prop, value);
  657. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  658. key, FALSE, FALSE);
  659. } else {
  660. prop = hal_property_new_double (key, value);
  661. device->properties = g_slist_prepend (device->properties, prop);
  662. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  663. key, FALSE, TRUE);
  664. }
  665. return TRUE;
  666. }
  667. gboolean
  668. hal_device_copy_property (HalDevice *from_device, const char *from, HalDevice *to_device, const char *to)
  669. {
  670. gboolean rc;
  671. rc = FALSE;
  672. if (hal_device_has_property (from_device, from)) {
  673. switch (hal_device_property_get_type (from_device, from)) {
  674. case HAL_PROPERTY_TYPE_STRING:
  675. rc = hal_device_property_set_string (
  676. to_device, to, hal_device_property_get_string (from_device, from));
  677. break;
  678. case HAL_PROPERTY_TYPE_INT32:
  679. rc = hal_device_property_set_int (
  680. to_device, to, hal_device_property_get_int (from_device, from));
  681. break;
  682. case HAL_PROPERTY_TYPE_UINT64:
  683. rc = hal_device_property_set_uint64 (
  684. to_device, to, hal_device_property_get_uint64 (from_device, from));
  685. break;
  686. case HAL_PROPERTY_TYPE_BOOLEAN:
  687. rc = hal_device_property_set_bool (
  688. to_device, to, hal_device_property_get_bool (from_device, from));
  689. break;
  690. case HAL_PROPERTY_TYPE_DOUBLE:
  691. rc = hal_device_property_set_double (
  692. to_device, to, hal_device_property_get_double (from_device, from));
  693. break;
  694. }
  695. }
  696. return rc;
  697. }
  698. gboolean
  699. hal_device_property_remove (HalDevice *device, const char *key)
  700. {
  701. HalProperty *prop;
  702. prop = hal_device_property_find (device, key);
  703. if (prop == NULL)
  704. return FALSE;
  705. device->properties = g_slist_remove (device->properties, prop);
  706. hal_property_free (prop);
  707. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  708. key, TRUE, FALSE);
  709. return TRUE;
  710. }
  711. gboolean
  712. hal_device_property_set_attribute (HalDevice *device,
  713. const char *key,
  714. enum PropertyAttribute attr,
  715. gboolean val)
  716. {
  717. HalProperty *prop;
  718. prop = hal_device_property_find (device, key);
  719. if (prop == NULL)
  720. return FALSE;
  721. return TRUE;
  722. }
  723. void
  724. hal_device_print (HalDevice *device)
  725. {
  726. GSList *iter;
  727. fprintf (stderr, "device udi = %s\n", hal_device_get_udi (device));
  728. for (iter = device->properties; iter != NULL; iter = iter->next) {
  729. HalProperty *p = iter->data;
  730. int type;
  731. const char *key;
  732. key = hal_property_get_key (p);
  733. type = hal_property_get_type (p);
  734. switch (type) {
  735. case HAL_PROPERTY_TYPE_STRING:
  736. fprintf (stderr, " %s = '%s' (string)\n", key,
  737. hal_property_get_string (p));
  738. break;
  739. case HAL_PROPERTY_TYPE_INT32:
  740. fprintf (stderr, " %s = %d 0x%x (int)\n", key,
  741. hal_property_get_int (p),
  742. hal_property_get_int (p));
  743. break;
  744. case HAL_PROPERTY_TYPE_UINT64:
  745. fprintf (stderr, " %s = %llu 0x%llx (uint64)\n", key,
  746. (long long unsigned int) hal_property_get_uint64 (p),
  747. (long long unsigned int) hal_property_get_uint64 (p));
  748. break;
  749. case HAL_PROPERTY_TYPE_DOUBLE:
  750. fprintf (stderr, " %s = %g (double)\n", key,
  751. hal_property_get_double (p));
  752. break;
  753. case HAL_PROPERTY_TYPE_BOOLEAN:
  754. fprintf (stderr, " %s = %s (bool)\n", key,
  755. (hal_property_get_bool (p) ? "true" :
  756. "false"));
  757. break;
  758. default:
  759. HAL_WARNING (("Unknown property type %d", type));
  760. break;
  761. }
  762. }
  763. fprintf (stderr, "\n");
  764. }
  765. typedef struct {
  766. char *key;
  767. HalDevice *device;
  768. HalDeviceAsyncCallback callback;
  769. gpointer user_data;
  770. guint prop_signal_id;
  771. guint timeout_id;
  772. } AsyncMatchInfo;
  773. static void
  774. destroy_async_match_info (AsyncMatchInfo *ai)
  775. {
  776. g_free (ai->key);
  777. g_signal_handler_disconnect (ai->device, ai->prop_signal_id);
  778. g_source_remove (ai->timeout_id);
  779. g_object_unref (ai->device);
  780. g_free (ai);
  781. }
  782. static void
  783. prop_changed_cb (HalDevice *device, const char *key,
  784. gboolean removed, gboolean added, gpointer user_data)
  785. {
  786. AsyncMatchInfo *ai = user_data;
  787. if (strcmp (key, ai->key) != 0)
  788. return;
  789. /* the property is no longer there */
  790. if (removed)
  791. goto cleanup;
  792. ai->callback (ai->device, ai->user_data, TRUE);
  793. cleanup:
  794. destroy_async_match_info (ai);
  795. }
  796. static gboolean
  797. async_wait_timeout (gpointer user_data)
  798. {
  799. AsyncMatchInfo *ai = (AsyncMatchInfo *) user_data;
  800. ai->callback (ai->device, ai->user_data, FALSE);
  801. destroy_async_match_info (ai);
  802. return FALSE;
  803. }
  804. void
  805. hal_device_async_wait_property (HalDevice *device,
  806. const char *key,
  807. HalDeviceAsyncCallback callback,
  808. gpointer user_data,
  809. int timeout)
  810. {
  811. HalProperty *prop;
  812. AsyncMatchInfo *ai;
  813. /* check if property already exists */
  814. prop = hal_device_property_find (device, key);
  815. if (prop != NULL || timeout==0) {
  816. callback (device, user_data, prop != NULL);
  817. return;
  818. }
  819. ai = g_new0 (AsyncMatchInfo, 1);
  820. ai->device = g_object_ref (device);
  821. ai->key = g_strdup (key);
  822. ai->callback = callback;
  823. ai->user_data = user_data;
  824. ai->prop_signal_id = g_signal_connect (device, "property_changed",
  825. G_CALLBACK (prop_changed_cb),
  826. ai);
  827. ai->timeout_id = g_timeout_add (timeout, async_wait_timeout, ai);
  828. }
  829. void
  830. hal_device_callouts_finished (HalDevice *device)
  831. {
  832. g_signal_emit (device, signals[CALLOUTS_FINISHED], 0);
  833. }
  834. /** Used when giving up on a device, e.g. if no device file appeared
  835. */
  836. void
  837. hal_device_cancel (HalDevice *device)
  838. {
  839. HAL_INFO (("udi=%s", device->udi));
  840. g_signal_emit (device, signals[CANCELLED], 0);
  841. }
  842. GSList *
  843. hal_device_property_get_strlist (HalDevice *device,
  844. const char *key)
  845. {
  846. HalProperty *prop;
  847. g_return_val_if_fail (device != NULL, NULL);
  848. g_return_val_if_fail (key != NULL, NULL);
  849. prop = hal_device_property_find (device, key);
  850. if (prop != NULL)
  851. return hal_property_get_strlist (prop);
  852. else
  853. return NULL;
  854. }
  855. const char *
  856. hal_device_property_get_strlist_elem (HalDevice *device,
  857. const char *key,
  858. guint index)
  859. {
  860. GSList *strlist;
  861. GSList *i;
  862. strlist = hal_device_property_get_strlist (device, key);
  863. if (strlist == NULL)
  864. return NULL;
  865. i = g_slist_nth (strlist, index);
  866. if (i == NULL)
  867. return NULL;
  868. return (const char *) i->data;
  869. }
  870. gboolean
  871. hal_device_property_strlist_append (HalDevice *device,
  872. const char *key,
  873. const char *value)
  874. {
  875. HalProperty *prop;
  876. /* check if property already exists */
  877. prop = hal_device_property_find (device, key);
  878. if (prop != NULL) {
  879. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
  880. return FALSE;
  881. hal_property_strlist_append (prop, value);
  882. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  883. key, FALSE, FALSE);
  884. } else {
  885. prop = hal_property_new_strlist (key);
  886. hal_property_strlist_append (prop, value);
  887. device->properties = g_slist_prepend (device->properties, prop);
  888. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  889. key, FALSE, TRUE);
  890. }
  891. return TRUE;
  892. }
  893. gboolean
  894. hal_device_property_strlist_prepend (HalDevice *device,
  895. const char *key,
  896. const char *value)
  897. {
  898. HalProperty *prop;
  899. /* check if property already exists */
  900. prop = hal_device_property_find (device, key);
  901. if (prop != NULL) {
  902. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
  903. return FALSE;
  904. hal_property_strlist_prepend (prop, value);
  905. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  906. key, FALSE, FALSE);
  907. } else {
  908. prop = hal_property_new_strlist (key);
  909. hal_property_strlist_prepend (prop, value);
  910. device->properties = g_slist_prepend (device->properties, prop);
  911. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  912. key, FALSE, TRUE);
  913. }
  914. return TRUE;
  915. }
  916. gboolean
  917. hal_device_property_strlist_remove_elem (HalDevice *device,
  918. const char *key,
  919. guint index)
  920. {
  921. HalProperty *prop;
  922. /* check if property already exists */
  923. prop = hal_device_property_find (device, key);
  924. if (prop == NULL)
  925. return FALSE;
  926. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
  927. return FALSE;
  928. if (hal_property_strlist_remove_elem (prop, index)) {
  929. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  930. key, FALSE, FALSE);
  931. return TRUE;
  932. }
  933. return FALSE;
  934. }
  935. gboolean
  936. hal_device_property_strlist_clear (HalDevice *device,
  937. const char *key)
  938. {
  939. HalProperty *prop;
  940. /* check if property already exists */
  941. prop = hal_device_property_find (device, key);
  942. if (prop == NULL) {
  943. prop = hal_property_new_strlist (key);
  944. device->properties = g_slist_prepend (device->properties, prop);
  945. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  946. key, FALSE, TRUE);
  947. return TRUE;
  948. }
  949. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
  950. return FALSE;
  951. if (hal_property_strlist_clear (prop)) {
  952. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  953. key, FALSE, FALSE);
  954. return TRUE;
  955. }
  956. return FALSE;
  957. }
  958. gboolean
  959. hal_device_property_strlist_add (HalDevice *device,
  960. const char *key,
  961. const char *value)
  962. {
  963. HalProperty *prop;
  964. gboolean res;
  965. res = FALSE;
  966. /* check if property already exists */
  967. prop = hal_device_property_find (device, key);
  968. if (prop != NULL) {
  969. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
  970. goto out;
  971. res = hal_property_strlist_add (prop, value);
  972. if (res) {
  973. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  974. key, FALSE, FALSE);
  975. }
  976. } else {
  977. prop = hal_property_new_strlist (key);
  978. hal_property_strlist_prepend (prop, value);
  979. device->properties = g_slist_prepend (device->properties, prop);
  980. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  981. key, FALSE, TRUE);
  982. res = TRUE;
  983. }
  984. out:
  985. return res;
  986. }
  987. gboolean
  988. hal_device_property_strlist_remove (HalDevice *device,
  989. const char *key,
  990. const char *value)
  991. {
  992. HalProperty *prop;
  993. /* check if property already exists */
  994. prop = hal_device_property_find (device, key);
  995. if (prop == NULL)
  996. return FALSE;
  997. if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
  998. return FALSE;
  999. if (hal_property_strlist_remove (prop, value)) {
  1000. g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
  1001. key, FALSE, FALSE);
  1002. }
  1003. return TRUE;
  1004. }
  1005. gboolean
  1006. hal_device_property_strlist_is_empty (HalDevice *device,
  1007. const char *key)
  1008. {
  1009. GSList *strlist;
  1010. if ( hal_device_has_property (device, key)) {
  1011. strlist = hal_device_property_get_strlist (device, key);
  1012. if (strlist == NULL )
  1013. return TRUE;
  1014. if (g_slist_length (strlist) > 0)
  1015. return FALSE;
  1016. else
  1017. return TRUE;
  1018. }
  1019. return FALSE;
  1020. }
  1021. void
  1022. hal_device_inc_num_addons (HalDevice *device)
  1023. {
  1024. device->num_addons++;
  1025. }
  1026. gboolean
  1027. hal_device_inc_num_ready_addons (HalDevice *device)
  1028. {
  1029. if (hal_device_are_all_addons_ready (device)) {
  1030. HAL_ERROR (("In hal_device_inc_num_ready_addons for udi=%s but all addons are already ready!",
  1031. device->udi));
  1032. return FALSE;
  1033. }
  1034. device->num_addons_ready++;
  1035. return TRUE;
  1036. }
  1037. gboolean
  1038. hal_device_are_all_addons_ready (HalDevice *device)
  1039. {
  1040. if (device->num_addons_ready == device->num_addons) {
  1041. return TRUE;
  1042. } else {
  1043. return FALSE;
  1044. }
  1045. }