/*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#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 <signal.h>
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
syntax highlighted by Code2HTML, v. 0.9.1