Search
lxdream.org :: lxdream/src/drivers/serial_unix.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/serial_unix.c
changeset 1081:ef31ae97bb8b
prev1079:691f9f621c5a
author nkeynes
date Tue Dec 01 18:18:15 2009 +1000 (11 years ago)
permissions -rw-r--r--
last change Fix compile-time warnings
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Host driver for a serial port attachment, that can be hooked to a character
     5  * device, fifo or named pipe.
     6  *
     7  * Copyright (c) 2009 Nathan Keynes.
     8  *
     9  * This program is free software; you can redistribute it and/or modify
    10  * it under the terms of the GNU General Public License as published by
    11  * the Free Software Foundation; either version 2 of the License, or
    12  * (at your option) any later version.
    13  *
    14  * This program is distributed in the hope that it will be useful,
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17  * GNU General Public License for more details.
    18  */
    20 #include <stdio.h>
    21 #include <stdlib.h>
    22 #include <fcntl.h>
    23 #include <sys/stat.h>
    25 #include "lxdream.h"
    26 #include "config.h"
    27 #include "ioutil.h"
    28 #include "serial.h"
    31 typedef struct serial_fd_device {
    32     struct serial_device dev;
    33     FILE *in;
    34     FILE *out;
    35     gboolean closeOnDestroy;
    36     io_listener_t listener;
    37 } *serial_fd_device_t;
    39 static void serial_fd_device_attach(serial_device_t dev);
    40 static void serial_fd_device_detach(serial_device_t dev);
    41 static void serial_fd_device_destroy(serial_device_t dev);
    42 static void serial_fd_device_set_line_speed(struct serial_device *dev, uint32_t bps);
    43 static void serial_fd_device_set_line_params(struct serial_device *dev, int flags);
    44 static void serial_fd_device_receive_data(struct serial_device *dev, uint8_t value);
    45 static gboolean serial_fd_device_transmit_data( int fd, void *dev);
    47 static gboolean serial_config_changed(void *data, struct lxdream_config_group *group, unsigned item,
    48                                       const gchar *oldval, const gchar *newval);
    50 struct lxdream_config_group serial_group =
    51     { "serial", serial_config_changed, NULL, NULL,
    52        {{ "device", N_("Serial device"), CONFIG_TYPE_FILE, "/dev/tty" },
    53         { NULL, CONFIG_TYPE_NONE }} };
    55 void serial_init()
    56 {
    57     const gchar *name = serial_group.params[0].value;
    58     if( name != NULL ) {
    59         serial_device_t dev = serial_fd_device_new_filename(name);
    60         if( dev != NULL ) {
    61             serial_attach_device( dev );
    62         }
    63     }
    64 }
    66 static gboolean serial_config_changed(void *data, struct lxdream_config_group *group, unsigned item,
    67                                       const gchar *oldval, const gchar *newval)
    68 {
    69     if( item == 0 ) {
    70         serial_destroy_device(serial_detach_device());
    71         serial_device_t dev = serial_fd_device_new_filename(newval);
    72         if( dev != NULL ) {
    73             serial_attach_device( dev );
    74         }
    75     }
    76     return TRUE;
    77 }
    81 serial_device_t serial_fd_device_new_filename( const gchar *filename )
    82 {
    83     FILE *out = fopen( filename, "w+" );
    84     FILE *in;
    85     struct stat st;
    87     if( out == NULL ) {
    88         return NULL;
    89     }
    91     if( fstat( fileno(out), &st ) != 0 ) {
    92         fclose(out);
    93         return NULL;
    94     }
    96     if( S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode) ) {
    97         in = out;
    98     } else {
    99         in = NULL;
   100     }
   102     return (serial_device_t)serial_fd_device_new_file(in, out, TRUE);
   103 }
   105 serial_device_t serial_fd_device_new_console()
   106 {
   107     return serial_fd_device_new_file( stdin, stdout, FALSE );
   108 }
   110 serial_device_t serial_fd_device_new_file( FILE *in, FILE *out, gboolean closeOnDestroy )
   111 {
   112     if( in != NULL )
   113         fcntl( fileno(in), F_SETFL, O_NONBLOCK );
   115     serial_fd_device_t dev = (serial_fd_device_t)malloc(sizeof(struct serial_fd_device));
   116     if( dev == NULL ) {
   117         if( closeOnDestroy ) {
   118             if( in != NULL )
   119                 fclose(in);
   120             if( out != NULL && out != in )
   121                 fclose(out);
   122         }
   123         return NULL;
   124     }
   126     dev->dev.attach = serial_fd_device_attach;
   127     dev->dev.detach = serial_fd_device_detach;
   128     dev->dev.destroy = serial_fd_device_destroy;
   129     dev->dev.set_line_speed = serial_fd_device_set_line_speed;
   130     dev->dev.set_line_params = serial_fd_device_set_line_params;
   131     dev->dev.receive_data = serial_fd_device_receive_data;
   132     dev->in = in;
   133     dev->out = out;
   134     dev->closeOnDestroy = closeOnDestroy;
   135     return (serial_device_t)dev;
   136 }
   138 static void serial_fd_device_attach(serial_device_t dev)
   139 {
   140     serial_fd_device_t fddev = (serial_fd_device_t)dev;
   141     if( fddev->in != NULL )
   142         fddev->listener = io_register_listener( fileno(fddev->in), serial_fd_device_transmit_data, fddev, NULL );
   143 }
   145 static void serial_fd_device_detach(serial_device_t dev)
   146 {
   147     serial_fd_device_t fddev = (serial_fd_device_t)dev;
   148     if( fddev->in != NULL )
   149         io_unregister_listener( fddev->listener );
   150 }
   152 static void serial_fd_device_destroy(serial_device_t dev)
   153 {
   154     serial_fd_device_t fddev = (serial_fd_device_t)dev;
   155     if( fddev->closeOnDestroy ) {
   156         if( fddev->in != NULL )
   157             fclose(fddev->in);
   158         if( fddev->out != NULL && fddev->out != fddev->in )
   159             fclose(fddev->out);
   160     }
   161     fddev->in = NULL;
   162     fddev->out = NULL;
   163     free(fddev);
   164 }
   165 static void serial_fd_device_set_line_speed(struct serial_device *dev, uint32_t bps)
   166 {
   167     /* Do nothing for now */
   168 }
   169 static void serial_fd_device_set_line_params(struct serial_device *dev, int flags)
   170 {
   171     /* Do nothing for now */
   172 }
   173 static void serial_fd_device_receive_data(struct serial_device *dev, uint8_t value)
   174 {
   175     serial_fd_device_t fddev = (serial_fd_device_t)dev;
   176     if( fddev->out != NULL )
   177         fputc( value, fddev->out );
   178 }
   180 static gboolean serial_fd_device_transmit_data( int fd, void *dev )
   181 {
   182     serial_fd_device_t fddev = (serial_fd_device_t)dev;
   183     char buf[4096];
   184     size_t len = fread(buf, 1, sizeof(buf), fddev->in);
   185     if( len > 0 ) {
   186         serial_transmit_data(buf, len);
   187     }
   188     return TRUE;
   189 }
.