hal/hald/linux net_class_device.c, 1.20, 1.21 osspec.c, 1.51,
1.52 pcmcia_cs.h, NONE, 1.1 pcmcia_utils.c, NONE,
1.1 pcmcia_utils.h, NONE, 1.1
David Zeuthen
david at freedesktop.org
Tue Oct 26 10:35:23 PDT 2004
Update of /cvs/hal/hal/hald/linux
In directory gabe:/tmp/cvs-serv3665/hald/linux
Modified Files:
net_class_device.c osspec.c
Added Files:
pcmcia_cs.h pcmcia_utils.c pcmcia_utils.h
Log Message:
2004-10-26 David Zeuthen <davidz at redhat.com>
Patch from Dan Williams <dcbw at redhat.com> to add support for
integration with cardmgr.
* configure.in: Add --enable-pcmcia-support and --with-stab-file
options
* hald/Makefile.am: Conditionally include linux/pcmcia_utils.c
linux/pcmcia_utils.h linux/pcmcia_cs.h
* hald/linux/net_class_device.c
(net_class_pre_process): Check driver link and set net.linux.driver
properties (me); add appropriate PCMCIA properties if applicable
(net_class_accept): Only accept network devices with device links as
well as PCMCIA devices
(net_class_compute_udi): Fix a typo (me)
* hald/linux/osspec.c
(compute_coldplug_list): Accept network devices without device link
* hald/linux/pcmcia_cs.h: New file
* hald/linux/pcmcia_utils.c: New file
* hald/linux/pcmcia_utils.h: New file
Index: net_class_device.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/net_class_device.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- net_class_device.c 21 Oct 2004 21:27:44 -0000 1.20
+++ net_class_device.c 26 Oct 2004 17:35:21 -0000 1.21
@@ -58,6 +58,10 @@
#include "class_device.h"
#include "common.h"
+#if PCMCIA_SUPPORT_ENABLE
+#include "pcmcia_utils.h"
+#endif
+
/**
* @defgroup HalDaemonLinuxNet Network class
* @ingroup HalDaemonLinux
@@ -509,10 +513,14 @@
int media_type = 0;
const char *media;
char wireless_path[SYSFS_PATH_MAX];
+ char driver_path[SYSFS_PATH_MAX];
dbus_bool_t is_80211 = FALSE;
int ifindex;
int flags;
struct stat statbuf;
+#if PCMCIA_SUPPORT_ENABLE
+ pcmcia_stab_entry *entry;
+#endif
hal_device_property_set_string (d, "net.linux.sysfs_path", sysfs_path);
hal_device_property_set_string (d, "net.interface",
@@ -526,6 +534,16 @@
is_80211 = TRUE;
}
+ /* Check driver link (may be unavailable for PCMCIA devices) */
+ snprintf (driver_path, SYSFS_PATH_MAX, "%s/driver", sysfs_path);
+ if (stat (driver_path, &statbuf) == 0) {
+ char buf[256];
+ memset (buf, '\0', sizeof (buf));
+ if (readlink (driver_path, buf, sizeof (buf) - 1) > 0) {
+ hal_device_property_set_string (d, "net.linux.driver", get_last_element (buf));
+ }
+ }
+
attr = sysfs_get_classdev_attr (class_device, "address");
if (attr != NULL) {
address = g_strstrip (g_strdup (attr->value));
@@ -596,6 +614,69 @@
hal_device_property_set_string (d, "info.category", "net.80203");
hal_device_add_capability (d, "net.80203");
}
+
+#if PCMCIA_SUPPORT_ENABLE
+ /* Add PCMCIA specific entries for PCMCIA cards */
+ if ((entry = pcmcia_get_stab_entry_for_device (class_device->name))) {
+ pcmcia_card_info *info = pcmcia_card_info_get (entry->socket);
+ if (info && (info->socket >= 0)) {
+ const char *type;
+ HalDevice *parent;
+
+ hal_device_property_set_string (d, "info.bus", "pcmcia");
+ if (entry->driver)
+ hal_device_property_set_string (d, "net.linux.driver", entry->driver);
+
+ if (info->productid_1 && strlen (info->productid_1))
+ hal_device_property_set_string (d, "pcmcia.productid_1", info->productid_1);
+ if (info->productid_2 && strlen (info->productid_2))
+ hal_device_property_set_string (d, "pcmcia.productid_2", info->productid_2);
+ if (info->productid_3 && strlen (info->productid_3))
+ hal_device_property_set_string (d, "pcmcia.productid_3", info->productid_3);
+ if (info->productid_4 && strlen (info->productid_4))
+ hal_device_property_set_string (d, "pcmcia.productid_4", info->productid_4);
+
+ if ((type = pcmcia_card_type_string_from_type (info->type)))
+ hal_device_property_set_string (d, "pcmcia.function", type);
+
+ hal_device_property_set_int (d, "pcmcia.manfid_1", info->manfid_1);
+ hal_device_property_set_int (d, "pcmcia.manfid_2", info->manfid_2);
+ hal_device_property_set_int (d, "pcmcia.socket_number", info->socket);
+
+ /* Provide best-guess of vendor, goes in Vendor property;
+ * .fdi files can override this */
+ if (info->productid_1 != NULL) {
+ hal_device_property_set_string (d, "info.vendor", info->productid_1);
+ } else {
+ char namebuf[50];
+ snprintf (namebuf, sizeof(namebuf), "Unknown (0x%04x)", info->manfid_1);
+ hal_device_property_set_string (d, "info.vendor", namebuf);
+ }
+
+ /* Provide best-guess of name, goes in Product property;
+ * .fdi files can override this */
+ if (info->productid_2 != NULL) {
+ hal_device_property_set_string (d, "info.product", info->productid_2);
+ } else {
+ char namebuf[50];
+ snprintf (namebuf, sizeof(namebuf), "Unknown (0x%04x)", info->manfid_2);
+ hal_device_property_set_string (d, "info.product", namebuf);
+ }
+
+ /* Reparent PCMCIA devices to be under their socket */
+ parent = hal_device_store_match_key_value_int (hald_get_gdl (),
+ "pcmcia_socket.number",
+ info->socket);
+ if (parent)
+ hal_device_property_set_string (d, "info.parent",
+ hal_device_property_get_string (parent, "info.udi"));
+
+ }
+
+ pcmcia_card_info_free (info);
+ pcmcia_stab_entry_free (entry);
+ }
+#endif
}
static dbus_bool_t
@@ -604,6 +685,9 @@
{
gboolean accept;
struct sysfs_attribute *attr = NULL;
+#if PCMCIA_SUPPORT_ENABLE
+ pcmcia_stab_entry *entry = NULL;
+#endif
accept = TRUE;
@@ -630,12 +714,32 @@
}
/* 1 is the type for ethernet (incl. wireless) devices */
- if (attr->value[0] == '1') {
- accept = TRUE;
+ if (attr->value[0] != '1') {
+ accept = FALSE;
+ goto out;
+ }
+
+#if PCMCIA_SUPPORT_ENABLE
+ /* Allow 'net' devices without a sysdevice only if they
+ * are backed by real hardware (like PCMCIA cards).
+ */
+ if ((entry = pcmcia_get_stab_entry_for_device (class_device->name))) {
+ pcmcia_card_info *info = pcmcia_card_info_get (entry->socket);
+ if (info && (info->socket >= 0)) {
+ /* Ok, we're a PCMCIA card */
+ accept = TRUE;
+ } else {
+ accept = FALSE;
+ }
+
+ pcmcia_card_info_free (info);
+ pcmcia_stab_entry_free (entry);
goto out;
} else {
accept = FALSE;
+ goto out;
}
+#endif
out:
return accept;
@@ -658,7 +762,7 @@
if (append_num == -1)
format = "/org/freedesktop/Hal/devices/net-%s";
else
- format = "/org/freedesktop/Hal/devices_net-%s-%d";
+ format = "/org/freedesktop/Hal/devices/net-%s-%d";
snprintf (buf, 256, format,
hal_device_property_get_string (d, "net.address"),
Index: osspec.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/osspec.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- osspec.c 25 Oct 2004 15:35:49 -0000 1.51
+++ osspec.c 26 Oct 2004 17:35:21 -0000 1.52
@@ -458,10 +458,23 @@
gchar *normalized_target;
g_snprintf (path, SYSFS_PATH_MAX, "%s/class/%s/%s/device", sysfs_mount_path, f, f1);
- if ((target = g_file_read_link (path, NULL)) != NULL) {
+ /* Accept net devices without device links too, they may be coldplugged PCMCIA devices */
+ if (((target = g_file_read_link (path, NULL)) != NULL)
+#if PCMCIA_SUPPORT_ENABLE
+ || !strcmp (f, "net")
+#endif
+ )
+ {
g_snprintf (path1, SYSFS_PATH_MAX, "%s/class/%s/%s", sysfs_mount_path, f, f1);
- normalized_target = get_normalized_path (path1, target);
- g_free (target);
+ if (target) {
+ normalized_target = get_normalized_path (path1, target);
+ g_free (target);
+ }
+#if PCMCIA_SUPPORT_ENABLE
+ else {
+ normalized_target = g_strdup (path1);
+ }
+#endif
/*printf ("%s -> (%s, %s)\n", normalized_target, path1, f);*/
g_hash_table_insert (sysfs_to_class_in_devices_map,
--- NEW FILE: pcmcia_cs.h ---
/***************************************************************************
* CVSID: $Id: pcmcia_cs.h,v 1.1 2004/10/26 17:35:21 david Exp $
*
* PCMCIA Card utilities
*
* Copyright (C) 2003 Dan Williams <dcbw at redhat.com>
*
* Licensed under the Academic Free License version 2.0
*
* Most of this code was derived from pcmcia-cs code, originally
* developed by David A. Hinds <dahinds at users.sourceforge.net>.
* Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds.
* All Rights Reserved. It has been modified for integration into HAL
* by Dan Williams and is covered by the GPL version 2 license.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifndef PCMCIA_CS_H
#define PCMCIA_CS_H
#include <sys/types.h>
/* cs_types.h */
typedef u_short ioaddr_t;
typedef u_short socket_t;
typedef u_int event_t;
typedef u_char cisdata_t;
typedef u_short page_t;
struct client_t;
typedef struct client_t *client_handle_t;
struct window_t;
typedef struct window_t *window_handle_t;
struct region_t;
typedef struct region_t *memory_handle_t;
struct eraseq_t;
typedef struct eraseq_t *eraseq_handle_t;
#ifndef DEV_NAME_LEN
#define DEV_NAME_LEN 32
#endif
typedef char dev_info_t[DEV_NAME_LEN];
/* cs.h */
/* For AccessConfigurationRegister */
typedef struct conf_reg_t {
u_char Function;
u_int Action;
off_t Offset;
u_int Value;
} conf_reg_t;
/* Actions */
#define CS_READ 1
#define CS_WRITE 2
/* for AdjustResourceInfo */
typedef struct adjust_t {
u_int Action;
u_int Resource;
u_int Attributes;
union {
struct memory {
u_long Base;
u_long Size;
} memory;
struct io {
ioaddr_t BasePort;
ioaddr_t NumPorts;
u_int IOAddrLines;
} io;
struct irq {
u_int IRQ;
} irq;
} resource;
} adjust_t;
typedef struct servinfo_t {
char Signature[2];
u_int Count;
u_int Revision;
u_int CSLevel;
char *VendorString;
} servinfo_t;
typedef struct event_callback_args_t {
client_handle_t client_handle;
void *info;
void *mtdrequest;
void *buffer;
void *misc;
void *client_data;
struct bus_operations *bus;
} event_callback_args_t;
/* for GetConfigurationInfo */
typedef struct config_info_t {
u_char Function;
u_int Attributes;
u_int Vcc, Vpp1, Vpp2;
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, Option, ExtStatus;
u_int Present;
u_int CardValues;
u_int AssignedIRQ;
u_int IRQAttributes;
ioaddr_t BasePort1;
ioaddr_t NumPorts1;
u_int Attributes1;
ioaddr_t BasePort2;
ioaddr_t NumPorts2;
u_int Attributes2;
u_int IOAddrLines;
} config_info_t;
/* For GetFirst/NextClient */
typedef struct client_req_t {
socket_t Socket;
u_int Attributes;
} client_req_t;
#define CLIENT_THIS_SOCKET 0x01
/* For RegisterClient */
typedef struct client_reg_t {
dev_info_t *dev_info;
u_int Attributes;
u_int EventMask;
int (*event_handler)(event_t event, int priority,
event_callback_args_t *);
event_callback_args_t event_callback_args;
u_int Version;
} client_reg_t;
/* IntType field */
#define INT_CARDBUS 0x04
/* For GetMemPage, MapMemPage */
typedef struct memreq_t {
u_int CardOffset;
page_t Page;
} memreq_t;
/* For ModifyWindow */
typedef struct modwin_t {
u_int Attributes;
u_int AccessSpeed;
} modwin_t;
/* For RequestWindow */
typedef struct win_req_t {
u_int Attributes;
u_long Base;
u_int Size;
u_int AccessSpeed;
} win_req_t;
typedef struct cs_status_t {
u_char Function;
event_t CardState;
event_t SocketState;
} cs_status_t;
typedef struct error_info_t {
int func;
int retcode;
} error_info_t;
/* Special stuff for binding drivers to sockets */
typedef struct bind_req_t {
socket_t Socket;
u_char Function;
dev_info_t *dev_info;
} bind_req_t;
/* Flag to bind to all functions */
#define BIND_FN_ALL 0xff
typedef struct mtd_bind_t {
socket_t Socket;
u_int Attributes;
u_int CardOffset;
dev_info_t *dev_info;
} mtd_bind_t;
/* cistpl.h */
#define CISTPL_VERS_1 0x15
#define CISTPL_MANFID 0x20
#define CISTPL_FUNCID 0x21
typedef struct cistpl_longlink_t {
u_int addr;
} cistpl_longlink_t;
typedef struct cistpl_checksum_t {
u_short addr;
u_short len;
u_char sum;
} cistpl_checksum_t;
#define CISTPL_MAX_FUNCTIONS 8
typedef struct cistpl_longlink_mfc_t {
u_char nfn;
struct {
u_char space;
u_int addr;
} fn[CISTPL_MAX_FUNCTIONS];
} cistpl_longlink_mfc_t;
#define CISTPL_MAX_ALTSTR_STRINGS 4
typedef struct cistpl_altstr_t {
u_char ns;
u_char ofs[CISTPL_MAX_ALTSTR_STRINGS];
char str[254];
} cistpl_altstr_t;
#define CISTPL_MAX_DEVICES 4
typedef struct cistpl_device_t {
u_char ndev;
struct {
u_char type;
u_char wp;
u_int speed;
u_int size;
} dev[CISTPL_MAX_DEVICES];
} cistpl_device_t;
typedef struct cistpl_device_o_t {
u_char flags;
cistpl_device_t device;
} cistpl_device_o_t;
#define CISTPL_VERS_1_MAX_PROD_STRINGS 4
typedef struct cistpl_vers_1_t {
u_char major;
u_char minor;
u_char ns;
u_char ofs[CISTPL_VERS_1_MAX_PROD_STRINGS];
char str[254];
} cistpl_vers_1_t;
typedef struct cistpl_jedec_t {
u_char nid;
struct {
u_char mfr;
u_char info;
} id[CISTPL_MAX_DEVICES];
} cistpl_jedec_t;
typedef struct cistpl_manfid_t {
u_short manf;
u_short card;
} cistpl_manfid_t;
typedef struct cistpl_funcid_t {
u_char func;
u_char sysinit;
} cistpl_funcid_t;
typedef struct cistpl_funce_t {
u_char type;
u_char data[0];
} cistpl_funce_t;
typedef struct cistpl_bar_t {
u_char attr;
u_int size;
} cistpl_bar_t;
typedef struct cistpl_config_t {
u_char last_idx;
u_int base;
u_int rmask[4];
u_char subtuples;
} cistpl_config_t;
typedef struct cistpl_power_t {
u_char present;
u_char flags;
u_int param[7];
} cistpl_power_t;
typedef struct cistpl_timing_t {
u_int wait, waitscale;
u_int ready, rdyscale;
u_int reserved, rsvscale;
} cistpl_timing_t;
#define CISTPL_IO_MAX_WIN 16
typedef struct cistpl_io_t {
u_char flags;
u_char nwin;
struct {
u_int base;
u_int len;
} win[CISTPL_IO_MAX_WIN];
} cistpl_io_t;
typedef struct cistpl_irq_t {
u_int IRQInfo1;
u_int IRQInfo2;
} cistpl_irq_t;
#define CISTPL_MEM_MAX_WIN 8
typedef struct cistpl_mem_t {
u_char flags;
u_char nwin;
struct {
u_int len;
u_int card_addr;
u_int host_addr;
} win[CISTPL_MEM_MAX_WIN];
} cistpl_mem_t;
typedef struct cistpl_cftable_entry_t {
u_char index;
u_short flags;
u_char interface;
cistpl_power_t vcc, vpp1, vpp2;
cistpl_timing_t timing;
cistpl_io_t io;
cistpl_irq_t irq;
cistpl_mem_t mem;
u_char subtuples;
} cistpl_cftable_entry_t;
typedef struct cistpl_cftable_entry_cb_t {
u_char index;
u_int flags;
cistpl_power_t vcc, vpp1, vpp2;
u_char io;
cistpl_irq_t irq;
u_char mem;
u_char subtuples;
} cistpl_cftable_entry_cb_t;
typedef struct cistpl_device_geo_t {
u_char ngeo;
struct {
u_char buswidth;
u_int erase_block;
u_int read_block;
u_int write_block;
u_int partition;
u_int interleave;
} geo[CISTPL_MAX_DEVICES];
} cistpl_device_geo_t;
typedef struct cistpl_vers_2_t {
u_char vers;
u_char comply;
u_short dindex;
u_char vspec8, vspec9;
u_char nhdr;
u_char vendor, info;
char str[244];
} cistpl_vers_2_t;
typedef struct cistpl_org_t {
u_char data_org;
char desc[30];
} cistpl_org_t;
typedef struct cistpl_format_t {
u_char type;
u_char edc;
u_int offset;
u_int length;
} cistpl_format_t;
typedef union cisparse_t {
cistpl_device_t device;
cistpl_checksum_t checksum;
cistpl_longlink_t longlink;
cistpl_longlink_mfc_t longlink_mfc;
cistpl_vers_1_t version_1;
cistpl_altstr_t altstr;
cistpl_jedec_t jedec;
cistpl_manfid_t manfid;
cistpl_funcid_t funcid;
cistpl_funce_t funce;
cistpl_bar_t bar;
cistpl_config_t config;
cistpl_cftable_entry_t cftable_entry;
cistpl_cftable_entry_cb_t cftable_entry_cb;
cistpl_device_geo_t device_geo;
cistpl_vers_2_t vers_2;
cistpl_org_t org;
cistpl_format_t format;
} cisparse_t;
typedef struct tuple_t {
u_int Attributes;
cisdata_t DesiredTuple;
u_int Flags; /* internal use */
u_int LinkOffset; /* internal use */
u_int CISOffset; /* internal use */
cisdata_t TupleCode;
cisdata_t TupleLink;
cisdata_t TupleOffset;
cisdata_t TupleDataMax;
cisdata_t TupleDataLen;
cisdata_t *TupleData;
} tuple_t;
#define TUPLE_RETURN_COMMON 0x02
/* For ValidateCIS */
typedef struct cisinfo_t {
u_int Chains;
} cisinfo_t;
#define CISTPL_MAX_CIS_SIZE 0x200
/* For ReplaceCIS */
typedef struct cisdump_t {
u_int Length;
cisdata_t Data[CISTPL_MAX_CIS_SIZE];
} cisdump_t;
/* bulkmem.h */
typedef struct region_info_t {
u_int Attributes;
u_int CardOffset;
u_int RegionSize;
u_int AccessSpeed;
u_int BlockSize;
u_int PartMultiple;
u_char JedecMfr, JedecInfo;
memory_handle_t next;
} region_info_t;
/* ds.h */
typedef struct tuple_parse_t {
tuple_t tuple;
cisdata_t data[255];
cisparse_t parse;
} tuple_parse_t;
typedef struct win_info_t {
window_handle_t handle;
win_req_t window;
memreq_t map;
} win_info_t;
typedef struct bind_info_t {
dev_info_t dev_info;
u_char function;
struct dev_link_t *instance;
char name[DEV_NAME_LEN];
u_short major, minor;
void *next;
} bind_info_t;
typedef struct mtd_info_t {
dev_info_t dev_info;
u_int Attributes;
u_int CardOffset;
} mtd_info_t;
typedef union ds_ioctl_arg_t {
servinfo_t servinfo;
adjust_t adjust;
config_info_t config;
tuple_t tuple;
tuple_parse_t tuple_parse;
client_req_t client_req;
cs_status_t status;
conf_reg_t conf_reg;
cisinfo_t cisinfo;
region_info_t region;
bind_info_t bind_info;
mtd_info_t mtd_info;
win_info_t win_info;
cisdump_t cisdump;
} ds_ioctl_arg_t;
#define DS_GET_CONFIGURATION_INFO _IOWR('d', 3, config_info_t)
#define DS_GET_FIRST_TUPLE _IOWR('d', 4, tuple_t)
#define DS_GET_TUPLE_DATA _IOWR('d', 6, tuple_parse_t)
#define DS_PARSE_TUPLE _IOWR('d', 7, tuple_parse_t)
#endif
--- NEW FILE: pcmcia_utils.c ---
/***************************************************************************
* CVSID: $Id: pcmcia_utils.c,v 1.1 2004/10/26 17:35:21 david Exp $
*
* PCMCIA Card utilities
*
* Copyright (C) 2003 Dan Williams <dcbw at redhat.com>
*
* Licensed under the Academic Free License version 2.0
*
* Some of this code was derived from pcmcia-cs code, originally
* developed by David A. Hinds <dahinds at users.sourceforge.net>.
* Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds.
* All Rights Reserved. It has been modified for integration into HAL
* by Dan Williams and is covered by the GPL version 2 license.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "pcmcia_utils.h"
static char *pcmcia_card_types[] = {
"multifunction", "memory", "serial", "parallel",
"fixed disk", "video", "network", "AIMS", "SCSI"
};
static int pcmcia_major = -1;
static int pcmcia_lookup_dev(void)
{
FILE *f;
int n;
char s[32], t[32];
f = fopen("/proc/devices", "r");
if (f == NULL)
return -errno;
while (fgets(s, 32, f) != NULL) {
if (sscanf(s, "%d %s", &n, t) == 2)
if (strcmp("pcmcia", t) == 0)
break;
}
fclose(f);
if (strcmp ("pcmcia", t) == 0)
return n;
else
return -ENODEV;
}
int pcmcia_socket_open (int socket)
{
static char *paths[] = {
"/var/lib/pcmcia", "/var/run", "/dev", "/tmp", NULL
};
int fd;
char **p, fn[64];
dev_t dev;
if ((socket < 0) || (socket > PCMCIA_MAX_SOCKETS))
return -1;
if (pcmcia_major < 0)
{
pcmcia_major = pcmcia_lookup_dev();
if (pcmcia_major < 0) {
if (pcmcia_major == -ENODEV)
fprintf (stderr, "no pcmcia driver in /proc/devices\n");
else
fprintf (stderr, "could not open /proc/devices");
}
}
dev = (pcmcia_major<<8) + socket;
for (p = paths; *p; p++) {
sprintf(fn, "%s/hal-%d", *p, getpid());
if (mknod(fn, (S_IFCHR | S_IREAD | S_IWRITE), dev) == 0) {
fd = open(fn, O_RDONLY);
unlink(fn);
if (fd >= 0)
return fd;
if (errno == ENODEV)
break;
}
}
return -1;
}
int pcmcia_get_tuple(int fd, cisdata_t code, ds_ioctl_arg_t *arg)
{
arg->tuple.DesiredTuple = code;
arg->tuple.Attributes = TUPLE_RETURN_COMMON;
arg->tuple.TupleOffset = 0;
if ( (ioctl(fd, DS_GET_FIRST_TUPLE, arg) == 0)
&& (ioctl(fd, DS_GET_TUPLE_DATA, arg) == 0)
&& (ioctl(fd, DS_PARSE_TUPLE, arg) == 0))
return 0;
else
return -1;
}
pcmcia_card_info *pcmcia_card_info_get (int socket)
{
int fd;
pcmcia_card_info *info = NULL;
if ((socket < 0) || (socket > PCMCIA_MAX_SOCKETS))
return NULL;
fd = pcmcia_socket_open (socket);
if (fd >= 0) {
ds_ioctl_arg_t arg;
cistpl_vers_1_t *vers = &arg.tuple_parse.parse.version_1;
cistpl_manfid_t *manfid = &arg.tuple_parse.parse.manfid;
cistpl_funcid_t *funcid = &arg.tuple_parse.parse.funcid;
config_info_t config;
/* Ignore CardBus cards and empty slots */
if (ioctl(fd, DS_GET_CONFIGURATION_INFO, &config) == 0)
goto out;
if (config.IntType == INT_CARDBUS)
goto out;
if (pcmcia_get_tuple(fd, CISTPL_VERS_1, &arg) != 0)
goto out;
if (!(info = calloc (1, sizeof (pcmcia_card_info))))
goto out;
info->socket = socket;
if (vers->ns >= 1)
info->productid_1 = strdup (vers->str+vers->ofs[0]);
if (vers->ns >= 2)
info->productid_2 = strdup (vers->str+vers->ofs[1]);
if (vers->ns >= 3)
info->productid_3 = strdup (vers->str+vers->ofs[2]);
if (vers->ns >= 4)
info->productid_4 = strdup (vers->str+vers->ofs[3]);
if (pcmcia_get_tuple(fd, CISTPL_FUNCID, &arg) == 0)
info->type = funcid->func;
if (pcmcia_get_tuple(fd, CISTPL_MANFID, &arg) == 0) {
info->manfid_1 = manfid->manf;
info->manfid_2 = manfid->card;
}
close (fd);
}
out:
return (info);
}
void pcmcia_card_info_free (pcmcia_card_info *info)
{
if (!info) return;
info->socket = -1;
info->type = PCMCIA_TYPE_INVALID;
free (info->productid_1);
free (info->productid_2);
free (info->productid_3);
free (info->productid_4);
info->manfid_1 = -1;
info->manfid_2 = -1;
}
const char *pcmcia_card_type_string_from_type (const PCMCIA_card_type type)
{
/* basically, ensure we don't go out of the array's bounds */
if ((type < PCMCIA_TYPE_MULTIFUNCTION) || (type >= PCMCIA_TYPE_INVALID)) return NULL;
return pcmcia_card_types[type];
}
PCMCIA_card_type pcmcia_card_type_from_type_string (const char *string)
{
PCMCIA_card_type i;
if (!string) return PCMCIA_TYPE_INVALID;
for (i = PCMCIA_TYPE_MULTIFUNCTION; i < PCMCIA_TYPE_INVALID; i++) {
if (!strcmp (string, pcmcia_card_types[i]))
return i;
}
return PCMCIA_TYPE_INVALID;
}
static inline int whack_newline (char *buf)
{
int len;
if (!buf)
return 0;
len = strlen (buf);
if ((buf[len-1] == '\n') || (buf[len-1] == '\r')) {
buf[len-1] = '\0';
len--;
}
return len;
}
pcmcia_stab_entry *pcmcia_stab_entry_get (int socket)
{
FILE *f;
pcmcia_stab_entry *entry = NULL;
if ((socket < 0) || (socket > PCMCIA_MAX_SOCKETS))
return NULL;
if ((f = fopen (PCMCIA_STAB_FILE, "r"))) {
char buf[200];
while (fgets (buf, 200, f) && !feof (f)) {
char match[50];
buf[199] = '\0';
whack_newline (buf);
snprintf (match, 49, "Socket %d", socket);
if (!strncmp (buf, match, strlen (match))) {
/* Ok, found our socket */
if (fgets (buf, 200, f) && !feof (f)) {
buf[199] = '\0';
whack_newline (buf);
if (strncmp (buf, "Socket", 6)) {
/* Got our card */
int s;
char func[50];
char driver[50];
int g;
char dev[50];
if (sscanf (buf, "%d\t%s\t%s\t%d\t%s", &s, &func, &driver, &g, &dev) == 5) {
PCMCIA_card_type t = pcmcia_card_type_from_type_string (func);
if (t != PCMCIA_TYPE_INVALID) {
entry = calloc (1, sizeof (pcmcia_stab_entry));
entry->socket = s;
entry->type = t;
entry->driver = strdup (driver);
entry->dev = strdup (dev);
}
break;
}
}
}
}
}
fclose (f);
}
return (entry);
}
void pcmcia_stab_entry_free (pcmcia_stab_entry *entry)
{
if (!entry) return;
entry->socket = -1;
entry->type = PCMCIA_TYPE_INVALID;
free (entry->driver);
free (entry->dev);
}
pcmcia_stab_entry *pcmcia_get_stab_entry_for_device (const char *interface)
{
pcmcia_stab_entry *entry = NULL;
int i;
if (!interface) return 0;
for (i = 0; i < PCMCIA_MAX_SOCKETS; i++)
{
if ((entry = pcmcia_stab_entry_get (i)))
{
if (!strcmp (interface, entry->dev))
break;
pcmcia_stab_entry_free (entry);
}
}
return (entry);
}
--- NEW FILE: pcmcia_utils.h ---
/***************************************************************************
* CVSID: $Id: pcmcia_utils.h,v 1.1 2004/10/26 17:35:21 david Exp $
*
* PCMCIA Card utilities
*
* Copyright (C) 2003 Dan Williams <dcbw at redhat.com>
*
* Licensed under the Academic Free License version 2.0
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifndef PCMCIA_UTILS_H
#define PCMCIA_UTILS_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "pcmcia_cs.h"
#define PCMCIA_MAX_SOCKETS 8
typedef enum PCMCIA_card_type {
PCMCIA_TYPE_MULTIFUNCTION = 0,
PCMCIA_TYPE_MEMORY,
PCMCIA_TYPE_SERIAL,
PCMCIA_TYPE_PARALLEL,
PCMCIA_TYPE_FIXED_DISK,
PCMCIA_TYPE_VIDEO,
PCMCIA_TYPE_NETWORK,
PCMCIA_TYPE_AIMS,
PCMCIA_TYPE_SCSI,
PCMCIA_TYPE_INVALID /* should always be last */
} PCMCIA_card_type;
typedef struct pcmcia_stab_entry {
int socket;
PCMCIA_card_type type;
char *driver;
char *dev;
} pcmcia_stab_entry;
typedef struct pcmcia_card_info {
int socket;
PCMCIA_card_type type;
char *productid_1;
char *productid_2;
char *productid_3;
char *productid_4;
int manfid_1;
int manfid_2;
} pcmcia_card_info;
int pcmcia_socket_open (int socket);
int pcmcia_get_tuple(int fd, cisdata_t code, ds_ioctl_arg_t *arg);
const char *pcmcia_card_type_string_from_type (const PCMCIA_card_type type);
PCMCIA_card_type pcmcia_card_type_from_type_string (const char *string);
pcmcia_stab_entry *pcmcia_stab_entry_get (int socket);
void pcmcia_stab_entry_free (pcmcia_stab_entry *entry);
pcmcia_stab_entry *pcmcia_get_stab_entry_for_device (const char *interface);
pcmcia_card_info *pcmcia_card_info_get (int socket);
void pcmcia_card_info_free (pcmcia_card_info *info);
#endif
More information about the hal-commit
mailing list