Upgrade libddekit and introduce devmand.

Devmand (Device manager daemon) is the daemon that will
dynamically manage services based on events received from
the system.
This commit is contained in:
Kees Jongenburger 2012-06-05 09:43:18 +00:00
parent 6b8821515d
commit ade7dc8ded
16 changed files with 1219 additions and 61 deletions

View file

@ -8,7 +8,7 @@ SUBDIR= add_route arp ash at awk \
cawf cd cdprobe checkhier cpp \
chmod chown ci cksum cleantmp clear cmp co \
comm compress cp crc cron crontab cut \
dd decomp16 DESCRIBE dev2name devsize df dhcpd \
dd decomp16 DESCRIBE dev2name devmand devsize df dhcpd \
dhrystone diff dirname diskctl dumpcore \
eject elvis env expand factor fbdctl \
find finger fingerd fix fold format fortune fsck.mfs \

15
commands/devmand/Makefile Normal file
View file

@ -0,0 +1,15 @@
PROG = devmand
SRCS = main.c lex.yy.c y.tab.c
lex.yy.c: usb_scan.l y.tab.h
${LEX} usb_scan.l
y.tab.c y.tab.h: usb.y
${YACC} -d usb.y
CLEANFILES = y.tab.c y.tab.h *.d lex.yy.c lex.yy.o main.o y.tab.o
MAN =
.include <bsd.prog.mk>

View file

@ -0,0 +1,45 @@
usb_driver usb_storage
{
binary = /usr/sbin/usb_storage;
id {
bInterfaceClass = 0x08;
}
devprefix = usbstor;
upscript = /etc/devmand/scripts/block;
downscript = /etc/devmand/scripts/block;
}
usb_driver usb_keyboard
{
binary = /usr/sbin/usb_hid;
id {
bInterfaceClass = 0x3;
bInterfaceProtocol = 0x1;
}
upscript = /etc/devmand/scripts/singlechar;
downscript = /etc/devmand/scripts/singlechar;
devprefix = usb_keyboard;
}
usb_driver usb_mouse
{
binary = /usr/sbin/usb_hid;
id {
bInterfaceClass = 0x3;
bInterfaceProtocol = 0x2;
}
upscript = /etc/devmand/scripts/singlechar;
downscript = /etc/devmand/scripts/singlechar;
devprefix = usb_mouse;
}
usb_driver usb_hid
{
binary = /usr/sbin/usb_hid;
id {
bInterfaceClass = 0x3;
}
upscript = /etc/devmand/scripts/singlechar;
downscript = /etc/devmand/scripts/singlechar;
devprefix = usb_keyboard;
}

847
commands/devmand/main.c Normal file
View file

@ -0,0 +1,847 @@
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
#include <string.h>
#include <lib.h>
#include <sys/stat.h>
#include <assert.h>
#include <signal.h>
#include "usb_driver.h"
#include "proto.h"
#define CONTROL_FIFO_PATH "/var/tmp/devmand_control"
#define SERVICE_BINARY "/bin/service"
#define DEVMAN_TYPE_NAME "dev_type"
#define PATH_LEN 256
#define INVAL_MAJOR -1
static void main_loop();
static void handle_event();
static void cleanup();
static void parse_config();
static void display_usage();
static enum dev_type determine_type(char *path);
static int get_major();
static void create_pid_file();
static void put_major(int major);
static struct devmand_usb_driver* match_usb_driver(struct usb_device_id *id);
static struct devmand_driver_instance *find_instance(int dev_id);
#define dbg(fmt, ... ) \
if (args.verbose) \
printf("%8s:%4d: %13s()| "fmt"\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__ )
static LIST_HEAD(usb_driver_head, devmand_usb_driver) drivers =
LIST_HEAD_INITIALIZER(drivers);
static LIST_HEAD(usb_driver_inst_head, devmand_driver_instance) instances =
LIST_HEAD_INITIALIZER(instances);
static int _run = 1;
struct global_args {
int deamonize;
char *path;
char *config;
int major_offset;
int verbose;
};
enum dev_type {
DEV_TYPE_USB_DEVICE,
DEV_TYPE_USB_INTF,
DEV_TYPE_UNKOWN
};
extern FILE *yyin;
static struct global_args args = {0,NULL,NULL,25, 0};
static struct option options[] =
{
{"deamonize", no_argument, NULL, 'd'},
{"path", required_argument, NULL, 'p'},
{"config", required_argument, NULL, 'c'},
{"verbose", required_argument, NULL, 'v'},
{0,0,0,0} /* terminating entry */
};
static char major_bitmap[16]; /* can store up to 128 major number states */
/*===========================================================================*
* run_upscript *
*===========================================================================*/
int run_upscript(struct devmand_driver_instance *inst)
{
char cmdl[1024];
cmdl[0] = 0;
int ret;
snprintf(cmdl, 1024, "%s up %s %d %d",
inst->drv->upscript, inst->label, inst->major, inst->dev_id);
dbg("Running Upscript: \"%s\"", cmdl);
ret = system(cmdl);
if (ret != 0) {
return EINVAL;
}
return 0;
}
/*===========================================================================*
* run_cleanscript *
*===========================================================================*/
int run_cleanscript(struct devmand_usb_driver *drv)
{
char cmdl[1024];
cmdl[0] = 0;
int ret;
snprintf(cmdl, 1024, "%s clean %s ",
drv->upscript, drv->devprefix);
dbg("Running Upscript: \"%s\"", cmdl);
ret = system(cmdl);
if (ret != 0) {
return EINVAL;
}
return 0;
}
/*===========================================================================*
* run_downscript *
*===========================================================================*/
int run_downscript(struct devmand_driver_instance *inst)
{
char cmdl[1024];
cmdl[0] = 0;
int ret;
snprintf(cmdl, 1024, "%s down %s %d",
inst->drv->downscript, inst->label, inst->major);
dbg("Running Upscript: \"%s\"", cmdl);
ret = system(cmdl);
if (ret != 0) {
return EINVAL;
}
return 0;
}
/*===========================================================================*
* stop_driver *
*===========================================================================*/
int stop_driver(struct devmand_driver_instance *inst)
{
char cmdl[1024];
cmdl[0] = 0;
int ret;
snprintf(cmdl, 1024, "%s down %s %d",
SERVICE_BINARY, inst->label, inst->dev_id);
dbg("executing service: \"%s\"", cmdl);
ret = system(cmdl);
if (ret != 0)
{
return EINVAL;
}
printf("Stopped driver %s with label %s for device %d.\n",
inst->drv->binary, inst->label, inst->dev_id);
return 0;
}
/*===========================================================================*
* start_driver *
*===========================================================================*/
int start_driver(struct devmand_driver_instance *inst)
{
char cmdl[1024];
cmdl[0] = 0;
int ret;
/* generate label */
ret = snprintf(inst->label, 32, "%s%d", inst->drv->devprefix,
inst->dev_id);
if (ret < 0 || ret > DEVMAND_DRIVER_LABEL_LEN) {
dbg("label too long");
return ENOMEM;
}
snprintf(cmdl, 1024, "%s up %s -major %d -devid %d -label %s",
SERVICE_BINARY, inst->drv->binary, inst->major, inst->dev_id,
inst->label);
dbg("executing service: \"%s\"", cmdl);
ret = system(cmdl);
if (ret != 0) {
return EINVAL;
}
printf("Started driver %s with label %s for device %d.\n",
inst->drv->binary, inst->label, inst->dev_id);
return 0;
}
/*===========================================================================*
* find_instance *
*===========================================================================*/
static struct devmand_driver_instance *
find_instance(int dev_id)
{
struct devmand_driver_instance *inst;
LIST_FOREACH(inst, &instances, list) {
if (inst->dev_id == dev_id) {
return inst;
}
}
return NULL;
}
/*===========================================================================*
* match_usb_driver *
*===========================================================================*/
static int
match_usb_id(struct devmand_usb_match_id *mid, struct usb_device_id *id)
{
int res = 1;
unsigned long match = mid->match_flags;
struct usb_device_id *_id = &mid->match_id;
if (match & USB_MATCH_ID_VENDOR)
if (id->idVendor != _id->idVendor) res = 0;
if (match & USB_MATCH_ID_PRODUCT)
if (id->idProduct != _id->idProduct) res = 0;
if (match & USB_MATCH_BCD_DEVICE)
if (id->bcdDevice != _id->bcdDevice) res = 0;
if (match & USB_MATCH_DEVICE_PROTOCOL)
if (id->bDeviceProtocol != _id->bDeviceProtocol) res = 0;
if (match & USB_MATCH_DEVICE_SUBCLASS)
if (id->bDeviceSubClass != _id->bDeviceSubClass) res = 0;
if (match & USB_MATCH_DEVICE_PROTOCOL)
if (id->bDeviceProtocol != _id->bDeviceProtocol) res = 0;
if (match & USB_MATCH_INTERFACE_CLASS)
if (id->bInterfaceClass != _id->bInterfaceClass) res = 0;
if (match & USB_MATCH_INTERFACE_SUBCLASS)
if (id->bInterfaceSubClass != _id->bInterfaceSubClass) res = 0;
if (match & USB_MATCH_INTERFACE_PROTOCOL)
if (id->bInterfaceProtocol != _id->bInterfaceProtocol) res = 0;
if (match == 0UL) {
res = 0;
}
return res;
}
/*===========================================================================*
* match_usb_driver *
*===========================================================================*/
static struct devmand_usb_driver*
match_usb_driver(struct usb_device_id *id)
{
struct devmand_usb_driver *driver;
struct devmand_usb_match_id *mid;
LIST_FOREACH(driver, &drivers, list) {
LIST_FOREACH(mid, &driver->ids, list) {
if (match_usb_id(mid, id)) {
return driver;
}
}
}
return NULL;
}
/*===========================================================================*
* add_usb_match_id *
*===========================================================================*/
struct devmand_usb_driver * add_usb_driver(char *name)
{
struct devmand_usb_driver *udrv = (struct devmand_usb_driver*)
malloc(sizeof(struct devmand_usb_driver));
LIST_INSERT_HEAD(&drivers, udrv, list);
LIST_INIT(&udrv->ids);
udrv->name = name;
return udrv;
}
/*===========================================================================*
* add_usb_match_id *
*===========================================================================*/
struct devmand_usb_match_id *
add_usb_match_id
(struct devmand_usb_driver *drv)
{
struct devmand_usb_match_id *id = (struct devmand_usb_match_id*)
malloc(sizeof(struct devmand_usb_match_id));
memset(id, 0, sizeof(struct devmand_usb_match_id));
LIST_INSERT_HEAD(&drv->ids, id, list);
return id;
}
/*===========================================================================*
* parse_config *
*===========================================================================*/
static void parse_config()
{
yyin = fopen(args.config, "r");
if (yyin < 0) {
printf("Can not open config file: %d.\n", errno);
}
dbg("Parsing configfile... ");
yyparse();
dbg("Done.");
fclose(yyin);
}
/*===========================================================================*
* cleanup *
*===========================================================================*/
static void cleanup() {
int res;
struct devmand_driver_instance *inst;
/* destroy fifo */
dbg("cleaning up... ");
/* quit all running drivers */
LIST_FOREACH(inst, &instances, list) {
dbg("stopping driver %s", inst->label);
run_downscript (inst);
stop_driver(inst);
}
res = remove(CONTROL_FIFO_PATH);
if (res != 0) {
fprintf(stderr, "WARNING: could not remove control fifo");
}
unlink("/var/run/devmand.pid");
}
static void sig_int(int sig) {
dbg("devman: Received SIGINT... cleaning up.");
_run = 0;
}
/*===========================================================================*
* create_pid_file *
*===========================================================================*/
void create_pid_file()
{
FILE *fd;
fd = fopen("/var/run/devmand.pid", "r");
if(fd) {
fprintf(stderr, "devmand: /var/run/devmand.pid exists... "
"another devmand running?\n");
fclose(fd);
exit(1);
} else {
fd = fopen("/var/run/devmand.pid","w");
fprintf(fd, "%d", getpid());
fclose(fd);
}
}
/*===========================================================================*
* main *
*===========================================================================*/
int main(int argc, char *argv[])
{
int opt, optindex, res;
struct devmand_usb_driver *driver;
create_pid_file();
/* get command line arguments */
while ((opt = getopt_long(argc, argv, "vdc:p:h?", options, &optindex))
!= -1) {
switch (opt) {
case 'd':
args.deamonize = 1;
break;
case 'p':
args.path = optarg;
break;
case 'c':
args.config = optarg;
break;
case 'v':
args.verbose = 1;
break;
case 'h':
case '?':
default:
display_usage(argv[0]);
return 0;
}
}
/* is path set? */
if (args.path == NULL) {
args.path = "/sys/";
}
/* is path set? */
if (args.config == NULL) {
args.config = "/etc/devmand/devmand.cfg";
}
dbg("Options: deamonize: %s, path: %s",
args.deamonize?"true":"false", args.path);
/* create control socket if not exists */
res = mkfifo(CONTROL_FIFO_PATH, S_IWRITE);
if ( !((res == 0) || (res == EEXIST)) ) {
fprintf(stderr, "Could not create control FIFO (%d)\n", res);
exit(1);
}
parse_config();
LIST_FOREACH(driver, &drivers, list) {
run_cleanscript(driver);
}
signal(SIGINT, sig_int);
main_loop();
cleanup();
return 0;
}
/*===========================================================================*
* determine_type *
*===========================================================================*/
static enum dev_type determine_type (char *path)
{
FILE * fd;
char *mypath;
char buf[256];
int res;
mypath = (char *) calloc(1, strlen(path)+strlen(DEVMAN_TYPE_NAME)+1);
if (mypath == NULL) {
fprintf(stderr, "ERROR: out of mem\n");
exit(1);
}
strcat(mypath, path);
strcat(mypath, DEVMAN_TYPE_NAME);
fd = fopen(mypath, "r");
free(mypath);
if (fd == NULL) {
fprintf(stderr, "WARN: could not open %s\n", mypath);
return DEV_TYPE_UNKOWN;
}
res = fscanf(fd , "%s\n", buf);
fclose(fd);
if (res != 1) {
fprintf(stderr, "WARN: could not parse %s\n", mypath);
return DEV_TYPE_UNKOWN;
}
if (strcmp(buf, "USB_DEV") == 0) {
return DEV_TYPE_USB_DEVICE;
} else if (strcmp(buf, "USB_INTF") == 0) {
return DEV_TYPE_USB_INTF;
}
return DEV_TYPE_UNKOWN;
}
/*===========================================================================*
* read_hex_uint *
*===========================================================================*/
static int read_hex_uint(char *base_path, char *name, unsigned int* val )
{
char my_path[PATH_LEN];
FILE *fd;
memset(my_path,0,PATH_LEN);
int ret = 0;
strcat(my_path, base_path);
strcat(my_path, name);
fd = fopen(my_path, "r");
if (fd == NULL) {
fprintf(stderr, "WARN: could not open %s\n", my_path);
return EEXIST;
} else if (fscanf(fd, "0x%x\n", val ) != 1) {
fprintf(stderr, "WARN: could not parse %s\n", my_path);
ret = EINVAL;
}
fclose(fd);
return ret;
}
/*===========================================================================*
* get_major *
*===========================================================================*/
static int get_major() {
int i, ret = args.major_offset;
for (i=0; i < 16; i++) {
int j;
for (j = 0; j < 8; j++ ) {
if ((major_bitmap[i] & (1 << j))) {
major_bitmap[i] &= !(1 << j);
return ret;
}
ret++;
}
}
return INVAL_MAJOR;
}
/*===========================================================================*
* put_major *
*===========================================================================*/
static void put_major(int major) {
int i;
major -= args.major_offset;
assert(major >= 0);
for (i=0; i < 16; i++) {
int j;
for (j = 0; j < 8; j++ ) {
if (major==0) {
assert(!(major_bitmap[i] & (1 <<j)));
major_bitmap[i] |= (1 << j);
return;
}
major--;
}
}
}
/*===========================================================================*
* generate_usb_device_id *
*===========================================================================*/
static struct usb_device_id *
generate_usb_device_id(char * path, int is_interface)
{
struct usb_device_id *ret;
int res;
unsigned int val;
ret = (struct usb_device_id *)
calloc(1,sizeof (struct usb_device_id));
if (is_interface) {
res = read_hex_uint(path, "../idVendor", &val);
if (res) goto err;
ret->idVendor = val;
res = read_hex_uint(path, "../idProduct", &val);
if (res) goto err;
ret->idProduct = val;
#if 0
res = read_hex_uint(path, "../bcdDevice", &val);
if (res) goto err;
ret->bcdDevice = val;
#endif
res = read_hex_uint(path, "../bDeviceClass", &val);
if (res) goto err;
ret->bDeviceClass = val;
res = read_hex_uint(path, "../bDeviceSubClass", &val);
if (res) goto err;
ret->bDeviceSubClass = val;
res = read_hex_uint(path, "../bDeviceProtocol", &val);
if (res) goto err;
ret->bDeviceProtocol = val;
res = read_hex_uint(path, "/bInterfaceClass", &val);
if (res) goto err;
ret->bInterfaceClass = val;
res = read_hex_uint(path, "/bInterfaceSubClass", &val);
if (res) goto err;
ret->bInterfaceSubClass = val;
res = read_hex_uint(path, "/bInterfaceProtocol", &val);
if (res) goto err;
ret->bInterfaceProtocol = val;
}
return ret;
err:
free(ret);
return NULL;
}
/*===========================================================================*
* usb_intf_add_even *
*===========================================================================*/
static void usb_intf_add_event(char *path, int dev_id)
{
struct usb_device_id *id;
struct devmand_usb_driver *drv;
struct devmand_driver_instance *drv_inst;
int major, ret;
/* generate usb_match_id */
id = generate_usb_device_id(path,TRUE);
if (id == NULL) {
fprintf(stderr, "WARN: could not create usb_device id...\n"
" ommiting event\n");
free(id);
return;
}
/* find suitable driver */
drv = match_usb_driver(id);
free (id);
if (drv == NULL) {
dbg("INFO: could not find a suitable driver for %s", path);
return;
}
/* create instance */
drv_inst = (struct devmand_driver_instance *)
calloc(1,sizeof(struct devmand_driver_instance));
if (drv_inst == NULL) {
fprintf(stderr, "ERROR: out of memory");
return; /* maybe better quit here. */
}
/* allocate inode number, if device files needed */
major = get_major();
if (major == INVAL_MAJOR) {
fprintf(stderr, "WARN: ran out of major numbers\n"
" cannot start driver %s for %s\n",
drv->name, path);
return;
}
drv_inst->major = major;
drv_inst->drv = drv;
drv_inst->dev_id = dev_id;
/* start driver (invoke service) */
start_driver(drv_inst);
/*
* run the up action
*
* An up action can be any executable. Before running it devmand
* will set certain environment variables so the script can configure
* the device (or generate device files, etc). See up_action() for that.
*/
if (drv->upscript) {
ret = run_upscript(drv_inst);
if (ret) {
stop_driver(drv_inst);
fprintf(stderr, "devmand: warning, could not run up_action\n");
free(drv_inst);
return;
}
}
LIST_INSERT_HEAD(&instances,drv_inst,list);
}
/*===========================================================================*
* usb_intf_remove_event *
*===========================================================================*/
static void usb_intf_remove_event(char *path, int dev_id)
{
struct devmand_driver_instance *inst;
struct devmand_usb_driver *drv;
int ret;
/* find the driver instance */
inst = find_instance(dev_id);
if (inst == NULL) {
dbg("No driver running for id: %d", dev_id);
return;
}
drv = inst->drv;
/* run the down script */
if (drv->downscript) {
ret = run_downscript(inst);
if (ret) {
fprintf(stderr, "WARN: error running up_action");
}
}
/* stop the driver */
stop_driver(inst);
/* free major */
put_major(inst->major);
/* free instance */
LIST_REMOVE(inst,list);
free(inst);
}
/*===========================================================================*
* handle_event *
*===========================================================================*/
static void handle_event(char *event)
{
enum dev_type type;
char path[PATH_LEN];
char tmp_path[PATH_LEN];
int dev_id, res;
path[0]=0;
if (strncmp("ADD ", event, 4) == 0) {
/* read data from event */
res = sscanf(event, "ADD %s 0x%x", tmp_path, &dev_id);
if (res != 2) {
fprintf(stderr, "WARN: could not parse event: %s", event);
fprintf(stderr, "WARN: omitting event: %s", event);
}
strcpy(path, args.path);
strcat(path, tmp_path);
/* what kind of device is added? */
type = determine_type(path);
switch (type) {
case DEV_TYPE_USB_DEVICE:
dbg("USB device added: ommited....");
/* ommit usb devices for now */
break;
case DEV_TYPE_USB_INTF:
dbg("USB interface added: (%s, devid: = %d)",path, dev_id);
usb_intf_add_event(path, dev_id);
return;
default:
dbg("default");
fprintf(stderr, "WARN: ommiting event\n");
}
} else if (strncmp("REMOVE ", event, 7) == 0) {
/* read data from event */
res = sscanf(event,"REMOVE %s 0x%x", tmp_path, &dev_id);
if (res != 2) {
fprintf(stderr, "WARN: could not parse event: %s", event);
fprintf(stderr, "WARN: omitting event: %s", event);
}
usb_intf_remove_event(path, dev_id);
#if 0
strcpy(path, args.path);
strcat(path, tmp_path);
/* what kind of device is added? */
type = determine_type(path);
switch (type) {
case DEV_TYPE_USB_DEVICE:
/* ommit usb devices for now */
break;
case DEV_TYPE_USB_INTF:
usb_intf_remove_event(path, dev_id);
return;
default:
fprintf(stderr, "WARN: ommiting event\n");
}
#endif
}
}
/*===========================================================================*
* main_loop *
*===========================================================================*/
static void main_loop()
{
char ev_path[128];
char buf[256];
int len;
FILE* fd;
len = strlen(args.path);
/* init major numbers */
memset(&major_bitmap, 0xff, 16);
if (len > 128 - 7 /*len of "events" */) {
fprintf(stderr, "pathname to long\n");
exit(1);
}
strcpy(ev_path, args.path);
strcat(ev_path, "events");
while (_run) {
char *res;
fd = fopen(ev_path, "r");
if (fd == NULL) {
fprintf(stderr, "ERROR: could not open event file...\n");
exit(1);
}
res = fgets(buf, 256, fd);
fclose(fd);
if (res == NULL) {
/* TODO: wait for control events */
usleep(50000);
continue;
}
dbg("handle_event: %s", buf);
handle_event(buf);
}
}
/*===========================================================================*
* display_usage *
*===========================================================================*/
static void display_usage(const char *name)
{
printf("Usage: %s [-d|--deamonize] [{-p|--pathname} PATH_TO_SYS}"
" [{-c|--config} CONFIG_FILE]\n", name);
}

11
commands/devmand/proto.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef _DEVMAND_PROTO_H
#define _DEVMAND_PROTO_H
/* main.c */
struct devmand_usb_driver * add_usb_driver(char *name);
struct devmand_usb_match_id * add_usb_match_id();
/* y.tab.c */
int yyparse();
#endif

134
commands/devmand/usb.y Normal file
View file

@ -0,0 +1,134 @@
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "usb_driver.h"
#define YY_NO_INPUT
static struct devmand_usb_driver *current_drv;
static struct devmand_usb_match_id *current_id;
int yylex(void);
void yyerror(char *s)
{
fprintf(stderr,"parsing error: %s\n",s);
}
int yywrap()
{
return 1;
}
%}
%union {
char *string;
}
%start drivers
%token <string> USB_DRIVER DEV_PREFIX BINARY INTERFACE_CLASS INTERFACE_SUB_CLASS EQUALS DEV_TYPE BLOCK_DEV CHAR_DEV UPSCRIPT DOWNSCRIPT
SEMICOLON BRACKET_OPEN BRACKET_CLOSE STRING ID INTERFACE_PROTOCOL
%%
drivers :
driver
{
}
| drivers driver
{
};
driver :
USB_DRIVER STRING {current_drv = add_usb_driver($2);}
BRACKET_OPEN
usb_driver_statements BRACKET_CLOSE
{
};
usb_driver_statements:
usb_driver_statement
{
}
| usb_driver_statements usb_driver_statement
{
};
usb_driver_statement:
{current_id = add_usb_match_id(current_drv);}
ID BRACKET_OPEN usb_device_id_statements BRACKET_CLOSE
{
}
| BINARY EQUALS STRING SEMICOLON
{
current_drv->binary = $3;
}
| DEV_PREFIX EQUALS STRING SEMICOLON
{
current_drv->devprefix = $3;
}
| DEV_TYPE EQUALS BLOCK_DEV SEMICOLON
{
current_drv->dev_type = block_dev;
}
| DEV_TYPE EQUALS CHAR_DEV SEMICOLON
{
current_drv->dev_type = char_dev;
}
| UPSCRIPT EQUALS STRING SEMICOLON
{
current_drv->upscript = $3;
}
| DOWNSCRIPT EQUALS STRING SEMICOLON
{
current_drv->downscript = $3;
};
usb_device_id_statements:
usb_device_id_statement
{
}
|usb_device_id_statements usb_device_id_statement
{
};
usb_device_id_statement:
INTERFACE_CLASS EQUALS STRING SEMICOLON
{
int res;
unsigned int num;
current_id->match_flags |= USB_MATCH_INTERFACE_CLASS;
res = sscanf($3, "0x%x", &num);
if (res != 1) {
fprintf(stderr, "ERROR");
exit(1);
}
current_id->match_id.bInterfaceClass = num;
}
| INTERFACE_SUB_CLASS EQUALS STRING SEMICOLON
{
int res;
unsigned int num;
current_id->match_flags |= USB_MATCH_INTERFACE_SUBCLASS;
res = sscanf($3, "0x%x", &num);
if (res != 1) {
fprintf(stderr, "ERROR");
exit(1);
}
current_id->match_id.bInterfaceSubClass = num;
}
| INTERFACE_PROTOCOL EQUALS STRING SEMICOLON
{
int res;
unsigned int num;
current_id->match_flags |= USB_MATCH_INTERFACE_PROTOCOL;
res = sscanf($3, "0x%x", &num);
if (res != 1) {
fprintf(stderr, "ERROR");
exit(1);
}
current_id->match_id.bInterfaceProtocol = num;
};
%%

View file

@ -0,0 +1,52 @@
#ifndef DEVMAN_USB_DRIVER
#define DEVMAN_USB_DRIVER
#include <minix/usb.h>
#include <sys/queue.h>
#define USB_MATCH_ID_VENDOR (1 << 0)
#define USB_MATCH_ID_PRODUCT (1 << 1)
#define USB_MATCH_BCD_DEVICE (1 << 2)
#define USB_MATCH_DEVICE_CLASS (1 << 3)
#define USB_MATCH_DEVICE_SUBCLASS (1 << 4)
#define USB_MATCH_DEVICE_PROTOCOL (1 << 5)
#define USB_MATCH_INTERFACE_CLASS (1 << 6)
#define USB_MATCH_INTERFACE_SUBCLASS (1 << 7)
#define USB_MATCH_INTERFACE_PROTOCOL (1 << 8)
enum devmand_device_type {
char_dev,
block_dev
};
struct devmand_usb_match_id {
unsigned match_flags;
struct usb_device_id match_id;
LIST_ENTRY(devmand_usb_match_id) list;
};
#define DEVMAND_DRIVER_LABEL_LEN 32
struct devmand_driver_instance {
int dev_id;
int major;
char label[DEVMAND_DRIVER_LABEL_LEN];
struct devmand_usb_driver *drv;
LIST_ENTRY(devmand_driver_instance) list;
};
struct devmand_usb_driver {
char *name;
char *devprefix;
char *binary;
char *upscript;
char *downscript;
enum devmand_device_type dev_type;
LIST_HEAD(devid_head, devmand_usb_match_id) ids;
LIST_ENTRY(devmand_usb_driver) list;
};
struct devmand_usb_driver * add_usb_driver(char *name);
struct devmand_usb_match_id *add_usb_match_id(struct devmand_usb_driver *drv);
#endif

View file

@ -0,0 +1,43 @@
/* -*- indented-text -*- */
%option noinput
%option nounput
%{
#include "y.tab.h"
#include <string.h>
#if 0
#define ECHO fwrite(yytext, yyleng, 1, yyout)
#else
#define ECHO
#endif
%}
BO [{]
BC [}]
NL [\n]
SC [;]
CHAR [0-9a-zA-Z_/\-\*\.]
EQ [=]
SPACE [\032]
%%
usb_driver { ECHO; return USB_DRIVER;}
devprefix { ECHO; return DEV_PREFIX;}
devtype { ECHO; return DEV_TYPE;}
char { ECHO; return BLOCK_DEV;}
block { ECHO; return CHAR_DEV;}
binary { ECHO; return BINARY;}
bInterfaceClass { ECHO; return INTERFACE_CLASS;}
bInterfaceSubClass { ECHO; return INTERFACE_SUB_CLASS;}
bInterfaceProtocol { ECHO; return INTERFACE_PROTOCOL;}
id { ECHO; return ID;}
upscript { ECHO; return UPSCRIPT;}
downscript { ECHO; return DOWNSCRIPT;}
{EQ} { ECHO; return EQUALS;}
{SC} { ECHO; return SEMICOLON;}
{BO} { ECHO; return BRACKET_OPEN;}
{BC} { ECHO; return BRACKET_CLOSE;}
{CHAR}+ { ECHO; yylval.string = (char *)strdup(yytext); return STRING;}
. ;
%%

View file

@ -7,9 +7,10 @@
struct ddekit_minix_msg_q;
void ddekit_minix_queue_msg(message *m);
void ddekit_minix_queue_msg(message *m, int ipc_status);
void ddekit_minix_rcv(struct ddekit_minix_msg_q * mq, message *m);
void ddekit_minix_rcv
(struct ddekit_minix_msg_q * mq, message *m, int *ipc_status);
struct ddekit_minix_msg_q *ddekit_minix_create_msg_q(unsigned from,
unsigned to);

View file

@ -32,7 +32,7 @@ int ddekit_release_mem(ddekit_addr_t start, ddekit_addr_t count);
*
* \return value read from port
*/
unsigned char dde_kit_inb(ddekit_addr_t port);
unsigned char ddekit_inb(ddekit_addr_t port);
/**
* Read I/O port (2-byte)
@ -41,7 +41,7 @@ unsigned char dde_kit_inb(ddekit_addr_t port);
*
* \return value read from port
*/
unsigned short dde_kit_inw(ddekit_addr_t port);
unsigned short ddekit_inw(ddekit_addr_t port);
/**
* Read I/O port (4-byte)
@ -50,7 +50,7 @@ unsigned short dde_kit_inw(ddekit_addr_t port);
*
* \return value read from port
*/
unsigned long dde_kit_inl(ddekit_addr_t port);
unsigned long ddekit_inl(ddekit_addr_t port);
/**
* Write I/O port (byte)
@ -58,7 +58,7 @@ unsigned long dde_kit_inl(ddekit_addr_t port);
* \param port port to write
* \param val value to write
*/
void dde_kit_outb(ddekit_addr_t port, unsigned char val);
void ddekit_outb(ddekit_addr_t port, unsigned char val);
/**
* Write I/O port (2-byte)
@ -66,7 +66,7 @@ void dde_kit_outb(ddekit_addr_t port, unsigned char val);
* \param port port to write
* \param val value to write
*/
void dde_kit_outw(ddekit_addr_t port, unsigned short val);
void ddekit_outw(ddekit_addr_t port, unsigned short val);
/**
* Write I/O port (4-byte)
@ -74,7 +74,7 @@ void dde_kit_outw(ddekit_addr_t port, unsigned short val);
* \param port port to write
* \param val value to write
*/
void dde_kit_outl(ddekit_addr_t port, unsigned long val);
void ddekit_outl(ddekit_addr_t port, unsigned long val);
#endif

View file

@ -58,3 +58,8 @@ error "_MINIX_MACHINE has incorrect value (0)"
#define DEFAULT_STACK_LIMIT (64 * 1024 * 1024)
#endif /* _MINIX_SYS_CONFIG_H */
/* Added by release script */
#ifndef _VCS_REVISION
#define _VCS_REVISION "116fcea"
#endif

View file

@ -30,7 +30,7 @@ static void ddekit_dispatcher_thread_init(void);
/****************************************************************************/
static void dispatcher_thread(void *unused) {
/*
/*
* Gets all messages and dispatches them.
*
* NOTE: this thread runs only when no other ddekit is
@ -40,6 +40,7 @@ static void dispatcher_thread(void *unused) {
message m;
int r;
int i;
int ipc_status;
_ddekit_thread_set_myprio(0);
@ -47,17 +48,17 @@ static void dispatcher_thread(void *unused) {
/* Trigger a timer interrupt at each loop iteration */
_ddekit_timer_update();
/* Wait for messages */
if ((r = sef_receive(ANY, &m)) != 0) {
if ((r = sef_receive_status(ANY, &m, &ipc_status)) != 0) {
ddekit_panic("ddekit", "sef_receive failed", r);
}
_ddekit_timer_interrupt();
_ddekit_thread_wakeup_sleeping();
if (is_notify(m.m_type)) {
switch (_ENDPOINT_P(m.m_source)) {
case HARDWARE:
@ -77,15 +78,15 @@ static void dispatcher_thread(void *unused) {
}
} else {
/*
/*
* I don't know how to handle this msg,
* but maybe we have a msg queue which can
* handle this msg.
*/
ddekit_minix_queue_msg(&m);
}
ddekit_minix_queue_msg(&m, ipc_status);
}
}
}
@ -114,9 +115,9 @@ void ddekit_init(void)
ddekit_init_irqs();
ddekit_init_timers();
ddekit_dispatcher_thread_init();
exit_sem = ddekit_sem_init(0);
}

View file

@ -8,7 +8,7 @@
#define DDEBUG DDEKIT_DEBUG_INITCALL
#endif
#include "debug.h"
#include "debug.h"
static struct __ddekit_initcall_s head = {0,0,0};

View file

@ -19,6 +19,7 @@ struct ddekit_minix_msg_q {
unsigned from, to;
message messages[MESSAGE_QUEUE_SIZE];
int ipc_status[MESSAGE_QUEUE_SIZE];
ddekit_sem_t *msg_w_sem, *msg_r_sem;
int msg_r_pos, msg_w_pos;
@ -26,8 +27,8 @@ struct ddekit_minix_msg_q {
};
static struct ddekit_minix_msg_q * _list = NULL;
static void _ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq,
message *m);
static void _ddekit_minix_queue_msg
(struct ddekit_minix_msg_q *mq, message *m, int ipc_status);
/*****************************************************************************
* ddekit_minix_create_msg_q *
@ -37,7 +38,7 @@ ddekit_minix_create_msg_q(unsigned from, unsigned to)
{
struct ddekit_minix_msg_q *mq = (struct ddekit_minix_msg_q *)
ddekit_simple_malloc(sizeof(struct ddekit_minix_msg_q));
mq->from = from;
mq->to = to;
mq->msg_w_pos = 0;
@ -49,10 +50,10 @@ ddekit_minix_create_msg_q(unsigned from, unsigned to)
/* TODO: check for overlapping message ranges */
mq->next = _list;
_list = mq;
DDEBUG_MSG_VERBOSE("created msg_q from %x to %x\n", from , to);
return mq;
return mq;
}
/*****************************************************************************
@ -81,8 +82,12 @@ void ddekit_minix_deregister_msg_q(struct ddekit_minix_msg_q *mq)
/*****************************************************************************
* _ddekit_minix_queue_msg *
****************************************************************************/
static void
_ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq, message *m)
static void
_ddekit_minix_queue_msg (
struct ddekit_minix_msg_q *mq,
message *m,
int ipc_status
)
{
int full;
full = ddekit_sem_down_try(mq->msg_w_sem);
@ -95,7 +100,7 @@ _ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq, message *m)
m->m_type = TASK_REPLY;
m->REP_STATUS = EAGAIN;
result = asynsend(m->m_source, m);
if (result != 0) {
ddekit_panic("unable to send reply to %d: %d\n",
m->m_source, result);
@ -104,7 +109,7 @@ _ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq, message *m)
} else {
/* queue the message */
memcpy(&mq->messages[mq->msg_w_pos], m, sizeof(message));
mq->ipc_status[mq->msg_w_pos] = ipc_status;
if (++mq->msg_w_pos == MESSAGE_QUEUE_SIZE) {
mq->msg_w_pos = 0;
}
@ -117,10 +122,10 @@ _ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq, message *m)
/*****************************************************************************
* ddekit_minix_queue_msg *
****************************************************************************/
void ddekit_minix_queue_msg(message *m)
void ddekit_minix_queue_msg(message *m, int ipc_status)
{
struct ddekit_minix_msg_q *it, *mq = NULL;
for (it = _list; it !=NULL ; it = it->next) {
if (m->m_type >= it->from && m->m_type <= it->to) {
mq = it;
@ -131,25 +136,29 @@ void ddekit_minix_queue_msg(message *m)
DDEBUG_MSG_VERBOSE("no q for msgtype %x\n", m->m_type);
return;
}
_ddekit_minix_queue_msg(mq,m);
_ddekit_minix_queue_msg(mq, m, ipc_status);
}
/*****************************************************************************
* ddekit_minix_rcv *
****************************************************************************/
void ddekit_minix_rcv(struct ddekit_minix_msg_q *mq, message *m)
void ddekit_minix_rcv (
struct ddekit_minix_msg_q *mq,
message *m,
int *ipc_status
)
{
DDEBUG_MSG_VERBOSE("waiting for message");
ddekit_sem_down(mq->msg_r_sem);
memcpy(m, &mq->messages[mq->msg_r_pos], sizeof(message));
*ipc_status = mq->ipc_status[mq->msg_r_pos];
if (++mq->msg_r_pos == MESSAGE_QUEUE_SIZE) {
mq->msg_r_pos = 0;
}
DDEBUG_MSG_VERBOSE("unqueing message");
ddekit_sem_up(mq->msg_w_sem);
}

View file

@ -52,18 +52,17 @@ static void _ddekit_usb_completion(struct usb_urb *mx_urb)
if (mx_urb->type == USB_TRANSFER_ISO) {
d_urb->start_frame = mx_urb->start_frame;
memcpy(d_urb->iso_desc, mx_urb->buffer + d_urb->size,
d_urb->number_of_packets * sizeof(struct usb_iso_packet_desc));
}
memcpy(d_urb->data, mx_urb->buffer, d_urb->size);
/* free mx_urb */
ddekit_simple_free(mx_urb);
/* 'give back' URB */
d_usb_driver->completion(d_urb->priv);
}
@ -139,11 +138,9 @@ int ddekit_usb_submit_urb(struct ddekit_usb_urb *d_urb)
{
int res;
unsigned urb_size = USB_URBSIZE(d_urb->size, d_urb->number_of_packets);
/* create mx urb out of d_urb */
struct usb_urb *mx_urb = (struct usb_urb*)
ddekit_simple_malloc(urb_size);
mx_urb->urb_size = urb_size;
mx_urb->dev_id = d_urb->dev->id;
@ -162,18 +159,15 @@ int ddekit_usb_submit_urb(struct ddekit_usb_urb *d_urb)
if (mx_urb->type == USB_TRANSFER_ISO) {
mx_urb->number_of_packets = d_urb->number_of_packets;
mx_urb->start_frame = d_urb->start_frame;
memcpy(mx_urb->buffer + d_urb->size, d_urb->iso_desc,
d_urb->number_of_packets * sizeof(struct usb_iso_packet_desc));
}
memcpy(mx_urb->buffer, d_urb->data, d_urb->size);
d_urb->ddekit_priv = mx_urb;
/* submit mx_urb */
res = usb_send_urb(mx_urb);
return res;
}
@ -197,14 +191,15 @@ static void _ddekit_usb_thread()
struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE,
USB_BASE + 0x1000);
message m;
int ipc_status;
while (1) {
ddekit_minix_rcv(mq, &m);
usb_handle_msg(&mx_usb_driver,&m);
ddekit_minix_rcv(mq, &m, &ipc_status);
usb_handle_msg(&mx_usb_driver, &m);
}
}
/*****************************************************************************
* ddekit_usb_init *
****************************************************************************/
@ -213,7 +208,6 @@ int ddekit_usb_init
ddekit_usb_malloc_fn *unused,
ddekit_usb_free_fn *_unused)
{
/* start usb_thread */
d_usb_driver = drv;
usb_init("dde");

View file

@ -415,7 +415,7 @@ static void cancle_urb(message *msg)
endpoint_t ep = msg->m_source;
struct minix_usb_driver *drv;
msg->USB_RESULT = -1;
msg->m_type = USB_REPLY;
@ -425,7 +425,7 @@ static void cancle_urb(message *msg)
return;
} else {
struct ddekit_usb_urb *d_urb = NULL;
d_urb = find_pending_urb(drv, msg->USB_URB_ID);
if (d_urb != NULL) {
@ -436,7 +436,7 @@ static void cancle_urb(message *msg)
msg->USB_RESULT = ENODEV;
}
}
send(ep, msg);
}
@ -468,9 +468,9 @@ static void completion_callback(void *priv)
mx_urb->actual_length = d_urb->actual_length;
mx_urb->error_count = d_urb->error_count;
mx_urb->transfer_flags = d_urb->transfer_flags;
remove_from_pending_urbs(drv, d_urb);
/* copy out URB */
res = sys_safecopyto(drv->ep, ctx->gid, 0,
(vir_bytes) ((char*)mx_urb) + sizeof(void*),
@ -486,7 +486,7 @@ static void completion_callback(void *priv)
msg.m_type = USB_COMPLETE_URB;
msg.USB_URB_ID = ctx->urb_id;
asynsend3(drv->ep, &msg, AMF_NOREPLY);
/* free stuff */
my_free(ctx);
my_free(mx_urb);
@ -725,10 +725,10 @@ static void devman_thread(void *unused)
{
struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(DEVMAN_BASE,
DEVMAN_BASE + 0xff);
int ipc_status;
message m;
while (1) {
ddekit_minix_rcv(mq, &m);
ddekit_minix_rcv(mq, &m, &ipc_status);
devman_handle_msg(&m);
}
}
@ -742,6 +742,7 @@ static void _ddekit_usb_thread(void * unused)
USB_BASE + 0xff);
message m;
int ipc_status;
/* create devman thread */
ddekit_thread_t * dmth;
@ -749,7 +750,7 @@ static void _ddekit_usb_thread(void * unused)
dmth = ddekit_thread_create(devman_thread, NULL, "devman_thread");
while (1) {
ddekit_minix_rcv(mq, &m);
ddekit_minix_rcv(mq, &m, &ipc_status);
handle_msg(&m);
}
}