Use new kernel notifications to determine if USB mass storage is available.
The usb_mass_storage switch no longer exists in our 2.6.35 kernel.
Instead we will consider mass storage to be available if both USB is connected
and the USB mass storage function is enable.
Change-Id: I730d1b3cb3cac664fc2abcdc36cd39856a08404a
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 4f803fc..7ce25b0 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -55,7 +55,43 @@
mVolumes = new VolumeCollection();
mActiveContainers = new AsecIdCollection();
mBroadcaster = NULL;
- mUsbMassStorageConnected = false;
+ mUsbMassStorageEnabled = false;
+ mUsbConnected = false;
+
+ readInitialState();
+}
+
+void VolumeManager::readInitialState() {
+ FILE *fp;
+ char state[255];
+
+ /*
+ * Read the initial mass storage enabled state
+ */
+ if ((fp = fopen("/sys/devices/virtual/usb_composite/usb_mass_storage/enable", "r"))) {
+ if (fgets(state, sizeof(state), fp)) {
+ mUsbMassStorageEnabled = !strncmp(state, "1", 1);
+ } else {
+ SLOGE("Failed to read usb_mass_storage enabled state (%s)", strerror(errno));
+ }
+ fclose(fp);
+ } else {
+ SLOGD("USB mass storage support is not enabled in the kernel");
+ }
+
+ /*
+ * Read the initial USB connected state
+ */
+ if ((fp = fopen("/sys/devices/virtual/switch/usb_configuration/state", "r"))) {
+ if (fgets(state, sizeof(state), fp)) {
+ mUsbConnected = !strncmp(state, "1", 1);
+ } else {
+ SLOGE("Failed to read usb_configuration switch (%s)", strerror(errno));
+ }
+ fclose(fp);
+ } else {
+ SLOGD("usb_configuration switch is not enabled in the kernel");
+ }
}
VolumeManager::~VolumeManager() {
@@ -116,17 +152,12 @@
return 0;
}
-void VolumeManager::notifyUmsConnected(bool connected) {
+void VolumeManager::notifyUmsAvailable(bool available) {
char msg[255];
- if (connected) {
- mUsbMassStorageConnected = true;
- } else {
- mUsbMassStorageConnected = false;
- }
snprintf(msg, sizeof(msg), "Share method ums now %s",
- (connected ? "available" : "unavailable"));
-
+ (available ? "available" : "unavailable"));
+ SLOGD(msg);
getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
msg, false);
}
@@ -141,17 +172,37 @@
return;
}
- if (!strcmp(name, "usb_mass_storage")) {
-
- if (!strcmp(state, "online")) {
- notifyUmsConnected(true);
- } else {
- notifyUmsConnected(false);
+ bool oldAvailable = massStorageAvailable();
+ if (!strcmp(name, "usb_configuration")) {
+ mUsbConnected = !strcmp(state, "1");
+ SLOGD("USB %s", mUsbConnected ? "connected" : "disconnected");
+ bool newAvailable = massStorageAvailable();
+ if (newAvailable != oldAvailable) {
+ notifyUmsAvailable(newAvailable);
}
} else {
SLOGW("Ignoring unknown switch '%s'", name);
}
}
+void VolumeManager::handleUsbCompositeEvent(NetlinkEvent *evt) {
+ const char *function = evt->findParam("FUNCTION");
+ const char *enabled = evt->findParam("ENABLED");
+
+ if (!function || !enabled) {
+ SLOGW("usb_composite event missing function/enabled info");
+ return;
+ }
+
+ if (!strcmp(function, "usb_mass_storage")) {
+ bool oldAvailable = massStorageAvailable();
+ mUsbMassStorageEnabled = !strcmp(enabled, "1");
+ SLOGD("usb_mass_storage function %s", mUsbMassStorageEnabled ? "enabled" : "disabled");
+ bool newAvailable = massStorageAvailable();
+ if (newAvailable != oldAvailable) {
+ notifyUmsAvailable(newAvailable);
+ }
+ }
+}
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
const char *devpath = evt->findParam("DEVPATH");
@@ -726,10 +777,7 @@
return -1;
}
- if (mUsbMassStorageConnected)
- *avail = true;
- else
- *avail = false;
+ *avail = massStorageAvailable();
return 0;
}
@@ -758,9 +806,9 @@
if (!strcmp(cmd, "ums")) {
if (!strcmp(arg, "connect")) {
- notifyUmsConnected(true);
+ notifyUmsAvailable(true);
} else if (!strcmp(arg, "disconnect")) {
- notifyUmsConnected(false);
+ notifyUmsAvailable(false);
} else {
errno = EINVAL;
return -1;