konst, тут не видно open() и проверку на ошибки.
тестовый пример подробнее:
static const char teststr[] = "abcdefghijklmn";
void mshowerror(int err, const char* s) {
char t[128];
t[0] = 0;
strerror_r(err, t, sizeof(t));
printf("%s #%d: \"%s\"\n", s, err, t);
}
int main(int argc, char *argv[])
{
int fd, i;
unsigned char t[64];
fd = open("/dev/fscm", O_RDWR);
if (fd != -1) {
printf("opened\n");
memcpy(t, teststr, 8);
do {
i = write(fd, t, 8);
if (i <= 0) {
mshowerror(-errno, "error write");
break;
}
i = read(fd, t, 8);
if (i <= 0) {
mshowerror(-errno, "error read");
}
} while (0);
close(fd);
} else {
mshowerror(-errno, "error opening device");
}
return EXIT_SUCCESS;
}
Во-вторых, давай код модуля.
он же здоровый! вот на мой вкус критические места:
static int __init rs_init(void)
{
int i;
init_bh(SERIAL_BH, do_serial_bh);
init_timer(&serial_timer);
serial_timer.function = rs_timer;
mod_timer(&serial_timer, jiffies + RS_STROBE_TIME);
for (i = 0; i < NR_IRQS; i++) {
IRQ_ports[i] = 0;
IRQ_timeout[i] = 0;
}
show_serial_version();
/* Initialize the tty_driver structure */
memset(&serial_driver, 0, sizeof(struct tty_driver));
serial_driver.magic = TTY_DRIVER_MAGIC;
serial_driver.driver_name = "fscserial";
serial_driver.name = "fscm";
serial_driver.major = TTY_MAJOR;
serial_driver.minor_start = 111; // my own magic minor number
serial_driver.num = NR_PORTS;
serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
serial_driver.subtype = SERIAL_TYPE_NORMAL;
serial_driver.init_termios = tty_std_termios;
serial_driver.init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
serial_driver.flags = TTY_DRIVER_REAL_RAW;
serial_driver.refcount = &serial_refcount;
serial_driver.table = serial_table;
serial_driver.termios = serial_termios;
serial_driver.termios_locked = serial_termios_locked;
serial_driver.open = rs_open;
serial_driver.close = rs_close;
serial_driver.write = rs_write;
serial_driver.put_char = rs_put_char;
serial_driver.flush_chars = rs_flush_chars;
serial_driver.write_room = rs_write_room;
serial_driver.chars_in_buffer = rs_chars_in_buffer;
serial_driver.flush_buffer = rs_flush_buffer;
serial_driver.ioctl = rs_ioctl;
serial_driver.throttle = rs_throttle;
serial_driver.unthrottle = rs_unthrottle;
serial_driver.set_termios = rs_set_termios;
serial_driver.stop = rs_stop;
serial_driver.start = rs_start;
serial_driver.hangup = rs_hangup;
#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
serial_driver.break_ctl = rs_break;
#endif
#if (LINUX_VERSION_CODE >= 131343)
serial_driver.send_xchar = rs_send_xchar;
serial_driver.wait_until_sent = rs_wait_until_sent;
serial_driver.read_proc = rs_read_proc;
#endif
/*
* The callout device is just like normal device except for
* major number and the subtype code.
*/
callout_driver = serial_driver;
callout_driver.name = "fscm";
callout_driver.major = TTYAUX_MAJOR;
callout_driver.subtype = SERIAL_TYPE_CALLOUT;
#if (LINUX_VERSION_CODE >= 131343)
callout_driver.read_proc = 0;
callout_driver.proc_entry = 0;
#endif
if (tty_register_driver(&serial_driver))
panic("Couldn't register serial driver\n");
if (tty_register_driver(&callout_driver))
panic("Couldn't register callout driver\n");
probe_serial_pci();
return 0;
}
static int rs_open(struct tty_struct *tty, struct file * filp)
{
struct async_struct *info;
int retval, line;
unsigned long page;
MOD_INC_USE_COUNT;
line = MINOR(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= NR_PORTS)) {
MOD_DEC_USE_COUNT;
return -ENODEV;
}
retval = get_async_struct(line, &info);
if (retval) {
MOD_DEC_USE_COUNT;
return retval;
}
tty->driver_data = info;
info->tty = tty;
if (serial_paranoia_check(info, tty->device, "rs_open"))
return -ENODEV;
#if (LINUX_VERSION_CODE > 0x20100)
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
#endif
/*
* This relies on lock_kernel() stuff so wants tidying for 2.5
*/
if (!tmp_buf) {
page = get_zeroed_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
if (tmp_buf)
free_page(page);
else
tmp_buf = (unsigned char *) page;
}
/*
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
if (info->flags & ASYNC_CLOSING)
interruptible_sleep_on(&info->close_wait);
return -EAGAIN;
}
/*
* Start up serial port
*/
retval = startup(info);
if (retval)
return retval;
retval = block_til_ready(tty, filp, info);
if (retval)
return retval;
if ((info->state->count == 1) &&
(info->flags & ASYNC_SPLIT_TERMIOS)) {
if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
*tty->termios = info->state->normal_termios;
else
*tty->termios = info->state->callout_termios;
change_speed(info, 0);
}
info->session = current->session;
info->pgrp = current->pgrp;
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
return 0;
}