summaryrefslogtreecommitdiff
path: root/src/technology.c
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2010-10-07 20:03:48 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2010-10-07 20:07:43 +0200
commit6d935efb1a315faaa5eb049e77d7d96f90be5cfb (patch)
tree8e13c1e01fd8453abcd9a62b3df90a78ff43a054 /src/technology.c
parent6766d9764b7c8b1b0bcd8e85eced6e6e8a46699f (diff)
downloadconnman-6d935efb1a315faaa5eb049e77d7d96f90be5cfb.tar.gz
connman-6d935efb1a315faaa5eb049e77d7d96f90be5cfb.tar.bz2
connman-6d935efb1a315faaa5eb049e77d7d96f90be5cfb.zip
technology: Block devices based on technology rfkill status
Devices are blocked when their technology is blocked, i.e. all its devices are rfkilled. They all move back to the unblocked state when all the technology devices are no longer rfkilled.
Diffstat (limited to 'src/technology.c')
-rw-r--r--src/technology.c83
1 files changed, 67 insertions, 16 deletions
diff --git a/src/technology.c b/src/technology.c
index a8f994b8..0a585120 100644
--- a/src/technology.c
+++ b/src/technology.c
@@ -57,6 +57,7 @@ struct connman_technology {
GHashTable *rfkill_list;
GSList *device_list;
gint enabled;
+ gint blocked;
struct connman_technology_driver *driver;
void *driver_data;
@@ -497,20 +498,14 @@ int __connman_technology_add_device(struct connman_device *device)
g_hash_table_insert(device_table, device, technology);
- if (technology->device_list == NULL) {
- if (__connman_device_get_blocked(device) == TRUE)
- technology->state = CONNMAN_TECHNOLOGY_STATE_BLOCKED;
- else
- technology->state = CONNMAN_TECHNOLOGY_STATE_AVAILABLE;
+ if (g_atomic_int_get(&technology->blocked))
+ goto done;
- state_changed(technology);
- } else {
- if (technology->state == CONNMAN_TECHNOLOGY_STATE_BLOCKED &&
- __connman_device_get_blocked(device) == FALSE) {
- technology->state = CONNMAN_TECHNOLOGY_STATE_AVAILABLE;
- state_changed(technology);
- }
- }
+ technology->state = CONNMAN_TECHNOLOGY_STATE_AVAILABLE;
+
+ state_changed(technology);
+
+done:
technology->device_list = g_slist_append(technology->device_list,
device);
@@ -554,13 +549,16 @@ int __connman_technology_enable_device(struct connman_device *device)
DBG("device %p", device);
- type = __connman_device_get_service_type(device);
- __connman_notifier_enable(type);
-
technology = g_hash_table_lookup(device_table, device);
if (technology == NULL)
return -ENXIO;
+ if (g_atomic_int_get(&technology->blocked))
+ return -ERFKILL;
+
+ type = __connman_device_get_service_type(device);
+ __connman_notifier_enable(type);
+
if (g_atomic_int_exchange_and_add(&technology->enabled, 1) == 0) {
technology->state = CONNMAN_TECHNOLOGY_STATE_ENABLED;
state_changed(technology);
@@ -602,6 +600,18 @@ int __connman_technology_disable_device(struct connman_device *device)
return 0;
}
+static void technology_blocked(struct connman_technology *technology,
+ connman_bool_t blocked)
+{
+ GSList *list;
+
+ for (list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ __connman_device_set_blocked(device, blocked);
+ }
+}
+
int __connman_technology_add_rfkill(unsigned int index,
enum connman_service_type type,
connman_bool_t softblock,
@@ -609,6 +619,7 @@ int __connman_technology_add_rfkill(unsigned int index,
{
struct connman_technology *technology;
struct connman_rfkill *rfkill;
+ connman_bool_t blocked;
DBG("index %u type %d soft %u hard %u", index, type,
softblock, hardblock);
@@ -630,6 +641,17 @@ int __connman_technology_add_rfkill(unsigned int index,
g_hash_table_replace(technology->rfkill_list, &rfkill->index, rfkill);
+ blocked = (softblock || hardblock) ? TRUE : FALSE;
+ if (blocked == FALSE)
+ return 0;
+
+ if (g_atomic_int_exchange_and_add(&technology->blocked, 1) == 0) {
+ technology_blocked(technology, TRUE);
+
+ technology->state = CONNMAN_TECHNOLOGY_STATE_BLOCKED;
+ state_changed(technology);
+ }
+
return 0;
}
@@ -639,6 +661,7 @@ int __connman_technology_update_rfkill(unsigned int index,
{
struct connman_technology *technology;
struct connman_rfkill *rfkill;
+ connman_bool_t blocked;
DBG("index %u soft %u hard %u", index, softblock, hardblock);
@@ -653,6 +676,28 @@ int __connman_technology_update_rfkill(unsigned int index,
rfkill->softblock = softblock;
rfkill->hardblock = hardblock;
+ blocked = (softblock || hardblock) ? TRUE : FALSE;
+
+ if (blocked) {
+ guint n_blocked;
+
+ n_blocked =
+ g_atomic_int_exchange_and_add(&technology->blocked, 1);
+ if (n_blocked != g_hash_table_size(technology->rfkill_list) - 1)
+ return 0;
+
+ technology_blocked(technology, blocked);
+ technology->state = CONNMAN_TECHNOLOGY_STATE_BLOCKED;
+ state_changed(technology);
+ } else {
+ if (g_atomic_int_dec_and_test(&technology->blocked) == FALSE)
+ return 0;
+
+ technology_blocked(technology, blocked);
+ technology->state = CONNMAN_TECHNOLOGY_STATE_AVAILABLE;
+ state_changed(technology);
+ }
+
return 0;
}
@@ -670,6 +715,12 @@ int __connman_technology_remove_rfkill(unsigned int index)
g_hash_table_remove(rfkill_table, &index);
+ if (g_atomic_int_dec_and_test(&technology->blocked) == TRUE) {
+ technology_blocked(technology, FALSE);
+ technology->state = CONNMAN_TECHNOLOGY_STATE_AVAILABLE;
+ state_changed(technology);
+ }
+
return 0;
}