Add UNIX domain socket feature to pccardd. This makes pccard

related PAO3/ports such as gxcardmon work.

Reviewed by:	imp
Obtained from:	PAO3
This commit is contained in:
Hajimu UMEMOTO 2000-08-20 16:16:57 +00:00
parent 59e8700a14
commit e0faad6850
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=64878
7 changed files with 271 additions and 15 deletions

View file

@ -58,7 +58,7 @@
/*
* Slot states for PIOCGSTATE
*/
enum cardstate { noslot, empty, suspend, filled };
enum cardstate { noslot, empty, suspend, filled, inactive };
/*
* Descriptor structure for memory map.

View file

@ -318,7 +318,7 @@ pccard_event(struct slot *slt, enum card_event event)
* The slot and devices are disabled, but the
* data structures are not unlinked.
*/
if (slt->state == filled) {
if (slt->state == filled || slt->state == inactive) {
slt->state = empty;
disable_slot_to(slt);
}
@ -600,11 +600,13 @@ crdioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
if (!pwval) {
if (slt->state != filled)
return EINVAL;
pccard_event(slt, card_removed);
slt->state = inactive;
} else {
if (slt->state != empty)
if (slt->state != empty && slt->state != inactive)
return EINVAL;
pccard_event(slt, card_inserted);
}
pccard_event(slt, pwval == 0 ? card_removed : card_inserted);
break;
case PIOCSBEEP:
if (pccard_beep_select(*(int *)data)) {

View file

@ -1,7 +1,8 @@
# Makefile for pccardd
# $FreeBSD$
PROG= pccardd
SRCS= pccardd.c cardd.c file.c util.c readcis.c printcis.c
SRCS= pccardd.c cardd.c file.c util.c readcis.c printcis.c server.c
MAN8= pccardd.8
MAN5= pccard.conf.5
DPADD= ${LIBUTIL}

View file

@ -49,6 +49,8 @@ static void pr_cmd(struct cmd *);
static void read_ether(struct slot *);
static void read_ether_attr2(struct slot *sp);
struct slot *slots;
/*
* Dump configuration file data.
*/
@ -105,7 +107,7 @@ readslots(void)
{
char name[128];
int i, fd;
struct slot *slots, *sp;
struct slot *sp;
slots = NULL;
for (i = 0; i < MAXSLOT; i++) {
@ -158,6 +160,7 @@ slot_change(struct slot *sp)
}
switch (state.state) {
case empty:
case inactive:
case noslot:
/* Debounce potentially incorrectly reported removals */
if (state.laststate == filled || state.laststate == suspend)
@ -173,6 +176,8 @@ slot_change(struct slot *sp)
/* ignored */
break;
}
sp->state = state.state;
stat_changed(sp);
}
/*

View file

@ -139,6 +139,9 @@ struct slot {
#define AFLAGS (IO_ASSIGNED | MEM_ASSIGNED | IRQ_ASSIGNED)
#define CFLAGS (EADDR_CONFIGED | WL_CONFIGED)
EXTERN struct slot *slots, *current_slot;
EXTERN int slen;
EXTERN struct allocblk *pool_ioblks; /* I/O blocks in the pool */
EXTERN struct allocblk *pool_mem; /* Memory in the pool */
EXTERN int pool_irq[16]; /* IRQ allocations */
@ -170,9 +173,14 @@ char *newstr();
void reset_slot(struct slot *);
void *xmalloc(int);
/* file.c */
/* file.c functions */
void readfile(char *);
/* server.c functions */
void set_socket(int);
void stat_changed(struct slot *);
void process_client(void);
#define IOPORTS 0x400
#define MEMUNIT 0x1000
#define MEMSTART 0xA0000

View file

@ -35,12 +35,22 @@ static const char rcsid[] =
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#define EXTERN
#include "cardd.h"
char *config_file = "/etc/defaults/pccard.conf";
static char *pid_file = "/var/run/pccardd.pid";
/*
* pathname of UNIX-domain socket
*/
static char *socket_name = "/var/tmp/.pccardd";
static char *sock = 0;
static int server_sock;
/* SIGHUP signal handler */
static void
restart(void)
@ -49,6 +59,7 @@ restart(void)
bitstr_t bit_decl(mem_inuse, MEMBLKS);
int irq_inuse[16];
int i;
struct sockaddr_un sun;
bit_nclear(io_inuse, 0, IOPORTS-1);
bit_nclear(mem_inuse, 0, MEMBLKS-1);
@ -98,6 +109,22 @@ restart(void)
pool_irq[i] = 0;
}
}
close(server_sock);
if ((server_sock = socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0)
die("socket failed");
bzero(&sun, sizeof(sun));
sun.sun_family = AF_UNIX;
if (sock) {
socket_name = sock;
}
strcpy(sun.sun_path, socket_name);
slen = SUN_LEN(&sun);
(void)unlink(socket_name);
if (bind(server_sock, (struct sockaddr *) & sun, slen) < 0)
die("bind failed");
chown(socket_name, 0, 5); /* XXX - root.operator */
chmod(socket_name, 0660);
set_socket(server_sock);
}
/* SIGTERM/SIGINT signal handler */
@ -127,18 +154,20 @@ int doverbose = 0;
int
main(int argc, char *argv[])
{
struct slot *slots, *sp;
struct slot *sp;
int count, dodebug = 0;
int delay = 0;
int irq_arg[16];
int irq_specified = 0;
int i;
struct sockaddr_un sun;
#define COM_OPTS ":dvf:s:i:z"
bzero(irq_arg, sizeof(irq_arg));
debug_level = 0;
pccard_init_sleep = 5000000;
cards = last_card = 0;
while ((count = getopt(argc, argv, ":dvf:i:z")) != -1) {
while ((count = getopt(argc, argv, COM_OPTS)) != -1) {
switch (count) {
case 'd':
setbuf(stdout, 0);
@ -160,6 +189,9 @@ main(int argc, char *argv[])
irq_arg[i] = 1;
irq_specified = 1;
break;
case 's':
sock = optarg;
break;
case 'z':
delay = 1;
break;
@ -200,23 +232,44 @@ main(int argc, char *argv[])
logmsg("pccardd started", NULL);
write_pid();
if ((server_sock = socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0)
die("socket failed");
bzero(&sun, sizeof(sun));
sun.sun_family = AF_UNIX;
if (sock) {
socket_name = sock;
}
strcpy(sun.sun_path, socket_name);
slen = SUN_LEN(&sun);
(void)unlink(socket_name);
if (bind(server_sock, (struct sockaddr *) & sun, slen) < 0)
die("bind failed");
chown(socket_name, 0, 5); /* XXX - root.operator */
chmod(socket_name, 0660);
set_socket(server_sock);
(void)signal(SIGINT, dodebug ? term : SIG_IGN);
(void)signal(SIGTERM, term);
(void)signal(SIGHUP, (void (*)(int))restart);
for (;;) {
fd_set mask;
FD_ZERO(&mask);
fd_set rmask, emask;
FD_ZERO(&emask);
FD_ZERO(&rmask);
for (sp = slots; sp; sp = sp->next)
FD_SET(sp->fd, &mask);
count = select(32, 0, 0, &mask, 0);
FD_SET(sp->fd, &emask);
FD_SET(server_sock, &rmask);
count = select(32, &rmask, 0, &emask, 0);
if (count == -1) {
logerr("select");
continue;
}
if (count)
if (count) {
for (sp = slots; sp; sp = sp->next)
if (FD_ISSET(sp->fd, &mask))
if (FD_ISSET(sp->fd, &emask))
slot_change(sp);
if (FD_ISSET(server_sock, &rmask))
process_client();
}
}
}

View file

@ -0,0 +1,187 @@
/*
* pccardd UNIX-domain socket interface
* Copyright (C) 1996 by Tatsumi Hosokawa <hosokawa@mt.cs.keio.ac.jp>
*
* $Id: server.c,v 1.3 1999/02/07 08:02:44 kuriyama Exp $
*/
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <setjmp.h>
#include "cardd.h"
static void
cardnum(char *buf)
{
int i = 0;
struct slot *sp;
for (sp = slots; sp; sp = sp->next)
i++;
if (i > MAXSLOT)
i = MAXSLOT;
sprintf(buf, "%2d", i);
}
static struct slot *
find_slot(int slot)
{
struct slot *sp;
/* Search the list until we find the slot or get to the end */
for (sp = slots; sp && sp->slot != slot; sp = sp->next)
continue;
return ( sp );
}
static void
cardname(char *buf, int slot)
{
struct slot *sp;
char *manuf, *vers, *drv, *stat;
/* Look for the slot */
if ( (sp = find_slot(slot)) == NULL)
return;
/* Fill in the information in the buff */
if (sp->cis) {
manuf = sp->cis->manuf;
vers = sp->cis->vers;
if (sp->config && sp->config->driver &&
sp->config->driver->name)
drv = sp->config->driver->name;
else
drv = "";
} else
manuf = vers = drv = "";
switch (sp->state) {
case empty:
stat = "0";
break;
case filled:
stat = "1";
break;
case inactive:
stat = "2";
break;
default:
stat = "9";
}
sprintf(buf, "%d~%s~%s~%s~%s", slot, manuf, vers, drv, stat);
}
static void
cardpwr(int slot, int pwon)
{
struct slot *sp;
/* Look for the slot */
if ( (sp = find_slot(slot)) == NULL)
return;
if (ioctl(sp->fd, PIOCSVIR, &pwon) < 0)
logerr("invaild arguments for cardpwr");
}
static int sock = 0;
static int slen = 0;
static struct sockaddr_un sun;
void
set_socket(int s)
{
sock = s;
}
void
stat_changed(struct slot *sp)
{
int len;
char buf[512];
if (!slen)
return;
cardname(buf, sp->slot);
len = strlen(buf);
if (sendto(sock, buf, len, 0, (struct sockaddr *) & sun, slen) != len) {
logerr("sendto failed");
slen = 0;
}
}
void
process_client(void)
{
char buf[512], obuf[512];
int len;
int snum;
if (!sock)
return;
slen = sizeof(sun);
len = recvfrom(sock, buf, sizeof(buf),
0, (struct sockaddr *)&sun, &slen);
if (len < 0)
logerr("recvfrom failed");
buf[len] = '\0';
obuf[0] = '\0';
switch (buf[0]) { /* Protocol implementation */
case 'S': /* How many slots? */
cardnum(obuf);
break;
case 'N': /* Card name request */
sscanf(buf + 1, "%d", &snum);
if (snum >= 0 && snum <= MAXSLOT)
cardname(obuf, snum);
else
logerr("Illegal slot requests for N command");
break;
case 'P': /* Virtual insertion request */
sscanf(buf + 1, "%d", &snum);
if (snum >= 0 && snum <= MAXSLOT) {
logmsg("slot %d: spring has come", snum);
cardpwr(snum, 1);
} else
logerr("Illegal slot requests for P command");
break;
case 'Q': /* Virtual removal request */
sscanf(buf + 1, "%d", &snum);
if (snum >= 0 && snum <= MAXSLOT) {
logmsg("slot %d: hibernation", snum);
cardpwr(snum, 0);
} else
logerr("Illegal slot requests for Q command");
break;
default:
logerr("Unknown control message from socket");
break;
}
len = strlen(obuf);
if (len) {
if (sendto(sock, obuf, len, 0, (struct sockaddr *)&sun, slen)
!= len) {
logerr("sendto failed");
slen = 0;
}
} else if (sendto(sock, 0, 0, 0, (struct sockaddr *)&sun, slen)
!= len) {
logerr("sendto failed");
slen = 0;
}
}