/
usb_moded-udev.c
153 lines (134 loc) · 3.68 KB
/
usb_moded-udev.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <unistd.h>
#include <poll.h>
#include <libudev.h>
#include <glib.h>
#include "usb_moded-log.h"
#include "usb_moded-config.h"
#include "usb_moded-hw-ab.h"
#include "usb_moded.h"
/* global variables */
struct udev *udev;
struct udev_monitor *mon;
struct udev_device *dev;
/* static function definitions */
gpointer monitor_udev(gpointer data) __attribute__ ((noreturn));
/* TODO: write udev property parsing in seperate function to avoid code duplication */
gboolean hwal_init(void)
{
GThread * thread;
const gchar *udev_path = NULL;
const char *tmp;
/* Create the udev object */
udev = udev_new();
if (!udev)
{
log_err("Can't create udev\n");
return 0;
}
udev_path = find_udev_path();
if(udev_path)
dev = udev_device_new_from_syspath(udev, udev_path);
else
dev = udev_device_new_from_syspath(udev, "/sys/class/power_supply/usb");
if (!dev)
{
log_err("Unable to find $power_supply device.");
return 0;
}
mon = udev_monitor_new_from_netlink (udev, "udev");
if (!mon)
{
log_err("Unable to monitor the 'present' value\n");
return 0;
}
udev_monitor_filter_add_match_subsystem_devtype(mon, "power_supply", NULL);
udev_monitor_enable_receiving (mon);
/* check if we are already connected */
tmp = udev_device_get_property_value(dev, "POWER_SUPPLY_PRESENT");
if(!tmp)
tmp = udev_device_get_property_value(dev, "POWER_SUPPLY_ONLINE");
if(!tmp)
{
log_err("No usable power supply indicator\n");
return 0;
}
if(!strcmp(tmp, "1"))
{
/* power supply type might not exist */
tmp = udev_device_get_property_value(dev, "POWER_SUPPLY_TYPE");
if(!tmp)
{
/* power supply type might not exist also :( Send connected event but this will not be able
to discriminate between charger/cable */
log_warning("Fallback since cable detecion cannot be accurate. Will connect on any voltage on usb.\n");
set_usb_connected(TRUE);
}
if(!strcmp(tmp, "USB")||!strcmp(tmp, "USB_CDP"))
{
log_debug("UDEV:USB cable connected\n");
set_usb_connected(TRUE);
}
}
thread = g_thread_create(monitor_udev, NULL, FALSE, NULL);
if(thread)
return 1;
else
{
log_debug("thread not created succesfully\n");
return 0;
}
}
gpointer monitor_udev(gpointer data)
{
const char *tmp;
while(1)
{
dev = udev_monitor_receive_device (mon);
if (dev)
{
if(!strcmp(udev_device_get_action(dev), "change"))
{
tmp = udev_device_get_property_value(dev, "POWER_SUPPLY_ONLINE");
if(!tmp)
tmp = udev_device_get_property_value(dev, "POWER_SUPPLY_PRESENT");
if(!tmp)
{
log_err("No usable power supply indicator\n");
exit(1);
}
if(!strcmp(tmp, "1"))
{
log_debug("UDEV:power supply present\n");
/* POWER_SUPPLY_TYPE is USB if usb cable is connected, USB_CDP for charging hub or USB_DCP for charger */
tmp = udev_device_get_property_value(dev, "POWER_SUPPLY_TYPE");
if(!tmp)
{
/* power supply type might not exist also :( Send connected event but this will not be able
to discriminate between charger/cable */
log_warning("Fallback since cable detecion cannot be accurate. Will connect on any voltage on usb.\n");
set_usb_connected(TRUE);
}
if(!strcmp(tmp, "USB")||!strcmp(tmp, "USB_CDP"))
{
log_debug("UDEV:USB cable connected\n");
set_usb_connected(TRUE);
}
}
else
{
log_debug("UDEV:USB cable disconnected\n");
set_usb_connected(FALSE);
}
}
udev_device_unref(dev);
}
}
}
void hwal_cleanup(void)
{
udev_monitor_unref(mon);
udev_unref(udev);
}