[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#382425: [PATCH] discover: use sysfs for pcmcia



Hi,

trying to get rid of the old pcmcia-ioctl-interface in the kernel, I modified
discover to use sysfs for that. Please find the patch attached. It modifies
configure.ac, so autoreconf has to be used to generate the new configure.

Is this interesting? I hope so, it seems discover is the last more prominent
user of that old interface...

Regards,

   Wolfram

---

Finally get rid of these messages that discover uses the outdated pcmcia-ioctl
interface. For that, the sysfs-code was copied from PCI and adapted. That means
the ioctl-method is still there as a fallback.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 configure.ac           |    3 +
 sysdeps/linux/pcmcia.c |  147 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 148 insertions(+), 2 deletions(-)

Index: configure.ac
===================================================================
--- configure.ac.orig
+++ configure.ac
@@ -218,6 +218,7 @@ linux*)
         PATH_PROC_PCI="/proc/bus/pci/devices"
         PATH_PROC_PCI_DIR=`dirname $PATH_PROC_PCI`
         PATH_SYS_PCI="/sys/bus/pci/devices"
+        PATH_SYS_PCMCIA="/sys/bus/pcmcia/devices"
         PATH_PROC_SCSI="/proc/scsi/scsi"
         PATH_PROC_USB="/proc/bus/usb/devices"
         AC_DEFINE_UNQUOTED(PATH_PROC_IDE, "$PATH_PROC_IDE",
@@ -228,6 +229,8 @@ linux*)
                            [Define path to /proc/bus/pci.])
         AC_DEFINE_UNQUOTED(PATH_SYS_PCI, "$PATH_SYS_PCI",
                            [Define path to /sys/bus/pci/devices.])
+        AC_DEFINE_UNQUOTED(PATH_SYS_PCMCIA, "$PATH_SYS_PCMCIA",
+                           [Define path to /sys/bus/pcmcia/devices.])
         AC_DEFINE_UNQUOTED(PATH_PROC_SCSI, "$PATH_PROC_SCSI",
                            [Define path to /proc/scsi/scsi.])
         AC_DEFINE_UNQUOTED(PATH_PROC_USB, "$PATH_PROC_USB",
Index: sysdeps/linux/pcmcia.c
===================================================================
--- sysdeps/linux/pcmcia.c.orig
+++ sysdeps/linux/pcmcia.c
@@ -72,6 +72,8 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <ctype.h>
+#include <string.h>
+#include <dirent.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -79,13 +81,18 @@
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
-
+#include <discover/sysdep.h>
 #include <discover/device.h>
 #include <discover/utils.h>
 
 /* XXX: There's no reason for this to be global. */
 static int major = 0;
 
+static int cmpstringp(const void *p1, const void *p2)
+{
+   return strcmp(* (char * const *) p1, * (char * const *) p2);
+}
+
 static int lookup_dev(char *name){
     FILE *f;
     int n;
@@ -153,7 +160,7 @@ _discover_sysdep_init(discover_sysdep_da
 }
 
 discover_sysdep_data_t *
-_discover_get_pcmcia_raw(void)
+_discover_get_pcmcia_raw_ioctl(void)
 {
     int fd, ns;
     ds_ioctl_arg_t arg;
@@ -198,6 +205,142 @@ _discover_get_pcmcia_raw(void)
     return head;
 }
 
+discover_sysdep_data_t *
+_discover_get_pcmcia_raw_sys(void)
+{
+    discover_sysdep_data_t *head = NULL, *node, *last = NULL;
+    FILE *f;
+    DIR *pcmciaDir;
+    struct dirent *pcmcia_device_entry;
+    unsigned int len;
+    char *device_dir, *vendor, *model, *p;
+    char **device_dir_list = NULL;
+    size_t device_dir_list_len, device_dir_index;
+    char path[256];
+    int ret;
+
+    /* Open the directory containing all the PCMCIA device dirs. */
+    pcmciaDir = opendir(PATH_SYS_PCMCIA);
+    if (pcmciaDir == NULL)
+        return _discover_get_pcmcia_raw_ioctl();
+
+    /* 
+     * The order of links in PATH_SYS_PCMCIA is not sorted.  Since 
+     * module load order can affect things like device naming, 
+     * we should collect the device directory names and sort them.  
+     */
+
+    for (pcmcia_device_entry = readdir(pcmciaDir); pcmcia_device_entry;
+         pcmcia_device_entry = readdir(pcmciaDir)) {
+        device_dir = strdup(pcmcia_device_entry->d_name);
+        if (device_dir == NULL)
+            continue;
+        if (device_dir[0] == '.') {
+            free(device_dir);
+            continue;
+        }
+
+        if (device_dir_list == NULL) {
+            device_dir_list = (char **)malloc(sizeof(char *));
+            device_dir_list_len = 1;
+        } else {
+            device_dir_list = 
+                (char **)realloc(device_dir_list,
+                                 sizeof(char *) * ++device_dir_list_len);
+        }
+
+        if (device_dir_list != NULL) {
+            device_dir_list[device_dir_list_len - 1] = device_dir;
+        } else {
+            free(device_dir);
+        }
+    }
+
+    closedir(pcmciaDir);
+
+    if (device_dir_list == NULL)
+        return _discover_get_pcmcia_raw_ioctl();
+
+    /* Do a sort. */
+    qsort(device_dir_list, device_dir_list_len, sizeof(char *), cmpstringp);
+
+    /* Loop through the PCMCIA device dirs. */
+    vendor = model = NULL;
+    for (device_dir_index = 0; device_dir_index < device_dir_list_len;
+         device_dir_index++) {
+        device_dir = device_dir_list[device_dir_index];
+        if (device_dir == NULL)
+            continue;
+
+        /* Clean up from tne last loop, if necessary. */
+        if (vendor) {
+            free(vendor);
+            vendor = NULL;
+        }
+        if (model) {
+            free(model);
+            model = NULL;
+        }
+
+        snprintf(path, 256, "%s/%s/manf_id", PATH_SYS_PCMCIA, device_dir);
+	 printf("%s\n", path);
+        f = fopen(path, "r");
+        if (!f) continue;
+        ret = getline(&vendor, &len, f);
+        fclose(f);
+	if (ret < 0) continue;
+        vendor[6] = '\0';
+        for (p = vendor; *(p + 2) != '\0'; p++) *p = *(p + 2);
+        *p = '\0';
+
+        snprintf(path, 256, "%s/%s/card_id", PATH_SYS_PCMCIA, device_dir);
+        f = fopen(path, "r");
+        if (!f) continue;
+        ret = getline(&model, &len, f);
+        fclose(f);
+	if (ret < 0) continue;
+        model[6] = '\0';
+        for (p = model; *(p + 2) != '\0'; p++) *p = *(p + 2);
+        *p = '\0';
+
+        /* Create a new sysdep node and populate it. */
+        node = _discover_sysdep_data_new();
+        if (!node) continue;
+        _discover_sysdep_init(node);
+
+        node->vendor = vendor;
+        node->model = model;
+
+        vendor = model = NULL;
+
+        /* Stick the new node in the list. */
+        if (head == NULL) {
+            head = node;
+            last = head;
+        } else {
+            last->next = node;
+            last = node;
+        }
+
+        /* Clean up the directory list memory as we go. */
+        free(device_dir);
+    }
+
+    free(device_dir_list);
+    return head;
+}
+
+
+discover_sysdep_data_t *
+_discover_get_pcmcia_raw(void)
+{
+    if (!access(PATH_SYS_PCMCIA, R_OK))
+        return _discover_get_pcmcia_raw_sys();
+    else
+        return _discover_get_pcmcia_raw_ioctl();
+}
+
+
 /*
  * Local variables:
  * c-file-style: "progeny"

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

Attachment: signature.asc
Description: Digital signature


Reply to: