diff options
Diffstat (limited to 'daemon/UEvent.cpp')
-rw-r--r-- | daemon/UEvent.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/daemon/UEvent.cpp b/daemon/UEvent.cpp new file mode 100644 index 0000000..282e965 --- /dev/null +++ b/daemon/UEvent.cpp | |||
@@ -0,0 +1,75 @@ | |||
1 | /** | ||
2 | * Copyright (C) ARM Limited 2013-2014. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include "UEvent.h" | ||
10 | |||
11 | #include <linux/netlink.h> | ||
12 | #include <string.h> | ||
13 | #include <sys/socket.h> | ||
14 | #include <unistd.h> | ||
15 | |||
16 | #include "Logging.h" | ||
17 | |||
18 | static const char EMPTY[] = ""; | ||
19 | static const char ACTION[] = "ACTION="; | ||
20 | static const char DEVPATH[] = "DEVPATH="; | ||
21 | static const char SUBSYSTEM[] = "SUBSYSTEM="; | ||
22 | |||
23 | UEvent::UEvent() : mFd(-1) { | ||
24 | } | ||
25 | |||
26 | UEvent::~UEvent() { | ||
27 | if (mFd >= 0) { | ||
28 | close(mFd); | ||
29 | } | ||
30 | } | ||
31 | |||
32 | bool UEvent::init() { | ||
33 | mFd = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); | ||
34 | if (mFd < 0) { | ||
35 | logg->logMessage("%s(%s:%i): socket failed", __FUNCTION__, __FILE__, __LINE__); | ||
36 | return false; | ||
37 | } | ||
38 | |||
39 | struct sockaddr_nl sockaddr; | ||
40 | memset(&sockaddr, 0, sizeof(sockaddr)); | ||
41 | sockaddr.nl_family = AF_NETLINK; | ||
42 | sockaddr.nl_groups = 1; // bitmask: (1 << 0) == kernel events, (1 << 1) == udev events | ||
43 | sockaddr.nl_pid = 0; | ||
44 | if (bind(mFd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != 0) { | ||
45 | logg->logMessage("%s(%s:%i): bind failed", __FUNCTION__, __FILE__, __LINE__); | ||
46 | return false; | ||
47 | } | ||
48 | |||
49 | return true; | ||
50 | } | ||
51 | |||
52 | bool UEvent::read(UEventResult *const result) { | ||
53 | ssize_t bytes = recv(mFd, result->mBuf, sizeof(result->mBuf), 0); | ||
54 | if (bytes <= 0) { | ||
55 | logg->logMessage("%s(%s:%i): recv failed", __FUNCTION__, __FILE__, __LINE__); | ||
56 | return false; | ||
57 | } | ||
58 | |||
59 | result->mAction = EMPTY; | ||
60 | result->mDevPath = EMPTY; | ||
61 | result->mSubsystem = EMPTY; | ||
62 | |||
63 | for (int pos = 0; pos < bytes; pos += strlen(result->mBuf + pos) + 1) { | ||
64 | char *const str = result->mBuf + pos; | ||
65 | if (strncmp(str, ACTION, sizeof(ACTION) - 1) == 0) { | ||
66 | result->mAction = str + sizeof(ACTION) - 1; | ||
67 | } else if (strncmp(str, DEVPATH, sizeof(DEVPATH) - 1) == 0) { | ||
68 | result->mDevPath = str + sizeof(DEVPATH) - 1; | ||
69 | } else if (strncmp(str, SUBSYSTEM, sizeof(SUBSYSTEM) - 1) == 0) { | ||
70 | result->mSubsystem = str + sizeof(SUBSYSTEM) - 1; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | return true; | ||
75 | } | ||