/* * Copyright (c) 1999, 2000 Motoyuki Kasahara. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include "pccard.h" /* * Slot information table. */ typedef struct { char manufacturer[PCCARD_MAX_MANUFACTURER_LENGTH + 1]; char version[PCCARD_MAX_VERSION_LENGTH + 1]; char driver[PCCARD_MAX_DRIVER_LENGTH + 1]; char alias[PCCARD_MAX_ALIAS_LENGTH + 1]; int status; } PCCard_Slot; static PCCard_Slot *slot_table = NULL; /* * The number of slots the system has. */ static int number_of_slots = 0; /* * Use an alias file or not. */ static char *alias_file_name = NULL; /* * Message handlers. */ extern void (*pccard_output_error_message)(const char *, ...); extern void (*pccard_output_warning_message)(const char *, ...); extern void (*pccard_output_debug_message)(const char *, ...); /* * Debug flag. */ extern int pccard_debug_flag; /* * Open a socket for talking to pccardd, and get current status of slots. * If an error occurs, -1 is returned. Otherwise 0 is returned. */ int pccard_initialize_client(const char *file_name) { if (slot_table != NULL) pccard_finalize_client(); /* * Set alias file name if `file_name' is not NULL. */ if (file_name != NULL) { alias_file_name = (char *) malloc(strlen(file_name) + 1); if (alias_file_name == NULL) { pccard_output_error_message("memory exhausted"); return -1; } strcpy(alias_file_name, file_name); } /* * Open a socket. */ if (pccard_open_socket() == -1) return -1; /* * Get the number of slots the system has. */ number_of_slots = pccard_query_number_of_slots(); if (number_of_slots == -1) return -1; /* * Allocate memory for pccard table. */ slot_table = (PCCard_Slot *) malloc(sizeof(PCCard_Slot) * number_of_slots); if (slot_table == NULL) { pccard_output_error_message("memory exhausted"); return -1; } /* * Get all slots status. */ return pccard_synchronize(); } /* * Get status of all slots to syncrhonisze the slot table. * 0 is returned if it succeeds, -1 if doesn't. * * NOTE: If another application sends a message to pccardd, pccardd * turns to send messages to the application. To fix the situation, * we need to send a request to pccardd once. We should also ask * pccardd about status of all slots, because my slot table may be * out of date. */ int pccard_synchronize(void) { PCCard_Slot *slot_entry; char manufacturer[PCCARD_MAX_RESPONSE_LENGTH + 1]; char version[PCCARD_MAX_RESPONSE_LENGTH + 1]; char driver[PCCARD_MAX_RESPONSE_LENGTH + 1]; char alias[PCCARD_MAX_ALIAS_LENGTH + 1]; int status; int slot; /* * Get information of each slot. */ for (slot = 0; slot < number_of_slots; slot++) { slot_entry = slot_table + slot; if (pccard_query_slot_information(slot, manufacturer, version, driver, &status) == -1) return -1; if (status == PCCARD_STATUS_FILLED && alias_file_name != NULL && pccard_search_alias_file(alias_file_name, alias, manufacturer, version)) { memcpy(slot_entry->alias, alias, PCCARD_MAX_ALIAS_LENGTH); *(slot_entry->alias + PCCARD_MAX_ALIAS_LENGTH) = '\0'; } else { *(slot_entry->alias) = '\0'; } memcpy(slot_entry->manufacturer, manufacturer, PCCARD_MAX_MANUFACTURER_LENGTH); *(slot_entry->manufacturer + PCCARD_MAX_MANUFACTURER_LENGTH) = '\0'; memcpy(slot_entry->version, version, PCCARD_MAX_VERSION_LENGTH); *(slot_entry->version + PCCARD_MAX_VERSION_LENGTH) = '\0'; memcpy(slot_entry->driver, driver, PCCARD_MAX_DRIVER_LENGTH); *(slot_entry->driver + PCCARD_MAX_DRIVER_LENGTH) = '\0'; slot_entry->status = status; } return 0; } /* * Close the connection to pccard, and dispose slot status data. */ void pccard_finalize_client(void) { number_of_slots = 0; free(slot_table); slot_table = NULL; free(alias_file_name); alias_file_name = NULL; pccard_close_socket(); } /* * Return the alias file name. */ const char * pccard_alias_file_name(void) { return alias_file_name; } /* * Return the number of slots the system has. */ int pccard_number_of_slots(void) { return number_of_slots; } /* * Get manufacturer, version, driver name and status of the slot `slot'. * Upon return, `manufacturer', `version', `driver' and `status' are * set by this function. * * It returns -1 if `slot' is not valid, or this library is not * initialized yet. It sets an empty string to manufacturer, * version and driver name if `slot' is not active. */ int pccard_slot_information(int slot, const char **manufacturer, const char **version, const char **driver, int *status) { PCCard_Slot *slot_entry; if (slot_table == NULL) { pccard_output_error_message("pccard client is not initialized"); return -1; } if (slot < 0 || slot >= number_of_slots) { pccard_output_error_message("invalid slot number %d", slot); return -1; } slot_entry = slot_table + slot; *manufacturer = slot_entry->manufacturer; *version = slot_entry->version; *driver = slot_entry->driver; *status = slot_entry->status; return 0; } /* * Return manufacturer information of the slot `slot'. * It returns NULL if `slot' is not valid, or this library is not * initialized yet. It returns an empty string if `slot' is not * active. */ const char * pccard_manufacturer(int slot) { if (slot_table == NULL) { pccard_output_error_message("pccard client is not initialized"); return NULL; } if (slot < 0 || slot >= number_of_slots) { pccard_output_error_message("invalid slot number %d", slot); return NULL; } return (slot_table + slot)->manufacturer; } /* * Return version information of the slot `slot'. * It returns NULL if `slot' is not valid, or this library is not * initialized yet. It returns an empty string if `slot' is not * active. */ const char * pccard_version(int slot) { if (slot_table == NULL) { pccard_output_error_message("pccard client is not initialized"); return NULL; } if (slot < 0 || slot >= number_of_slots) { pccard_output_error_message("invalid slot number %d", slot); return NULL; } return (slot_table + slot)->version; } /* * Return a driver name of the slot `slot'. * It returns NULL if `slot' is not valid, or this library is not * initialized yet. It returns an empty string if `slot' is not * active. */ const char * pccard_driver(int slot) { if (slot_table == NULL) { pccard_output_error_message("pccard client is not initialized"); return NULL; } if (slot < 0 || slot >= number_of_slots) { pccard_output_error_message("invalid slot number %d", slot); return NULL; } return (slot_table + slot)->driver; } /* * Return current status of the slot `slot'. * It returns -1 if `slot' is not valid, or this library is not * initialized yet. */ int pccard_status(int slot) { if (slot_table == NULL) { pccard_output_error_message("pccard client is not initialized"); return -1; } if (slot < 0 || slot >= number_of_slots) { pccard_output_error_message("invalid slot number %d", slot); return -1; } return (slot_table + slot)->status; } /* * Return an alias name of the card inserted in `slot'. * It returns NULL if `slot' is not valid, or this library is not * initialized yet. It returns an empty string if `slot' is not * active, or if the inserted card has no alias. */ const char * pccard_alias(int slot) { if (slot_table == NULL) { pccard_output_error_message("pccard client is not initialized"); return NULL; } if (slot < 0 || slot >= number_of_slots) { pccard_output_error_message("invalid slot number %d", slot); return NULL; } return (slot_table + slot)->alias; } /* * Send an insert request to pccardd, and receive a response. * If it succeeds, 0 is returned. Otherwise -1 is returned. */ int pccard_insert(int slot) { if (slot_table == NULL) { pccard_output_error_message("pccard client is not initialized"); return -1; } if (slot < 0 || slot >= number_of_slots) { pccard_output_error_message("invalid slot number %d", slot); return -1; } if (pccard_query_insertion(slot) == -1) return -1; (slot_table + slot)->status = PCCARD_STATUS_INACTIVE2; if (pccard_debug_flag) { pccard_output_debug_message("status changed: slot=%d, status=%d", slot, PCCARD_STATUS_INACTIVE2); } return 0; } /* * Send a removal request to pccardd, and receive a response. * If it succeeds, 0 is returned. Otherwise -1 is returned. */ int pccard_remove(int slot) { if (slot_table == NULL) { pccard_output_error_message("pccard client is not initialized"); return -1; } if (slot < 0 || slot >= number_of_slots) { pccard_output_error_message("invalid slot number %d", slot); return -1; } if (pccard_query_removal(slot) == -1) return -1; (slot_table + slot)->status = PCCARD_STATUS_FILLED2; if (pccard_debug_flag) { pccard_output_debug_message("status changed: slot=%d, status=%d", slot, PCCARD_STATUS_FILLED2); } return 0; } /* * Wait and receive an update message from pccardd. * If it succeeds, 0 is returned. Otherwise -1 is returned. */ int pccard_update(void) { PCCard_Slot *slot_entry; char manufacturer[PCCARD_MAX_RESPONSE_LENGTH + 1]; char version[PCCARD_MAX_RESPONSE_LENGTH + 1]; char driver[PCCARD_MAX_RESPONSE_LENGTH + 1]; char alias[PCCARD_MAX_ALIAS_LENGTH + 1]; int status; int slot; if (slot_table == NULL) { pccard_output_error_message("pccard client is not initialized"); return -1; } /* * Get update information from pccardd. */ if (pccard_wait_response() == -1) return -1; if (pccard_status_changed(&slot, manufacturer, version, driver, &status) == -1) return -1; if (slot < 0 || slot >= number_of_slots) { pccard_output_error_message("received invalid slot number %d", slot); return -1; } /* * Update the slot table. */ slot_entry = slot_table + slot; if (status == PCCARD_STATUS_FILLED && alias_file_name != NULL && pccard_search_alias_file(alias_file_name, alias, manufacturer, version)) { memcpy(slot_entry->alias, alias, PCCARD_MAX_ALIAS_LENGTH); *(slot_entry->alias + PCCARD_MAX_ALIAS_LENGTH) = '\0'; } else { *(slot_entry->alias) = '\0'; } memcpy(slot_entry->manufacturer, manufacturer, PCCARD_MAX_MANUFACTURER_LENGTH); *(slot_entry->manufacturer + PCCARD_MAX_MANUFACTURER_LENGTH) = '\0'; memcpy(slot_entry->version, version, PCCARD_MAX_VERSION_LENGTH); *(slot_entry->version + PCCARD_MAX_VERSION_LENGTH) = '\0'; memcpy(slot_entry->driver, driver, PCCARD_MAX_DRIVER_LENGTH); *(slot_entry->driver + PCCARD_MAX_DRIVER_LENGTH) = '\0'; slot_entry->status = status; return slot; } /* * For test: */ #ifdef TEST #include void signal_handler(int sig) { pccard_finalize_client(); } int main() { int nslots; const char *manufacturer; const char *version; const char *driver; const char *status_string; int status; int slot; signal(SIGHUP, signal_handler); signal(SIGINT, signal_handler); signal(SIGQUIT, signal_handler); signal(SIGTERM, signal_handler); pccard_initialize_client(); nslots = pccard_number_of_slots(); if (nslots == 0) { fprintf(stderr, "no slot\n"); exit(1); } for (slot = 0; slot < nslots; slot++) { pccard_slot_information(slot, &manufacturer, &version, &driver, &status); printf("slot %d:\n", slot); printf(" manufacturer = %s\n", manufacturer); printf(" version = %s\n", version); printf(" driver = %s\n", driver); switch (status) { case PCCARD_STATUS_EMPTY: status_string = "empty"; break; case PCCARD_STATUS_FILLED: status_string = "filled"; break; case PCCARD_STATUS_INACTIVE: status_string = "inactive"; break; case PCCARD_STATUS_UNKNOWN: status_string = "unknown"; break; } printf(" status = %s\n\n", status_string); } pccard_finalize_client(); } #endif