diff --git a/char_dev.c b/char_dev.c new file mode 100644 index 0000000..ad17e6f --- /dev/null +++ b/char_dev.c @@ -0,0 +1,74 @@ + +static char device_buffer[1]; +static int major; +static uint8_t buff_empty=1; +static uint8_t buff_start; +static uint8_t buff_end; + + +static uint8_t buffer[BUFFER_SIZE]; + +static uint8_t readBuffer(void){ + uint8_t ret; + if(buff_empty){ + return 0; + } + ret=buffer[buff_end]; + buff_end++; + if(buff_end==BUFFER_SIZE){ + buff_end=0; + } + if(buff_end==buff_start){ + buff_empty=1; + } + return ret; +} + +static uint8_t writeToBuffer(uint8_t data){ + if(buff_start==buff_end && !buff_empty){ + /*overrun*/ + printk("<1>%s: Buffer overrun!\n",MOD_NAME); + return 1; + } + buffer[buff_start]=data; + buff_start++; + if(buff_start==BUFFER_SIZE){ + buff_start=0; + } + buff_empty=0; + return 0; +} + +static ssize_t device_read(struct file *filp, char __user *buffer, size_t length, loff_t *offset){ + uint8_t val; + if(!buff_empty){ + val = readBuffer(); + DEBUG_OUT("<1>%s: device_read invoked writing: mem[%x]=%02x\n",MOD_NAME,buffer,val); + if( copy_to_user(buffer,&val,1)<0 ){ + printk("<1>%s: Device read error!\n",MOD_NAME); + return 0; + } + return 1; + } + return 0; +} + +static ssize_t device_write(struct file *filp, const char __user *buff, size_t len, loff_t *off){ + int ret; + DEBUG_OUT("<1>%s: device_write invoked\n",MOD_NAME); + if(len!=1){ + return -EINVAL; + } + ret = copy_from_user(device_buffer, buff, len); + if( ret<0 ){ + printk("<1>%s: Device write error!\n",MOD_NAME); + return 0; + } + return len; +} + +struct file_operations fops = { + read: device_read, + write: device_write, +}; + diff --git a/common.h b/common.h new file mode 100644 index 0000000..2ade2dc --- /dev/null +++ b/common.h @@ -0,0 +1,8 @@ + +#ifndef _COMMON_H +#define _COMMON_H + +#define MOD_NAME "usb_gpio" +enum pin_commands {CMD_IN, CMD_OUTH, CMD_OUTL, CMD_H, CMD_L, CMD_READ}; + +#endif //_COMMON_H diff --git a/ftdi_daemon.c b/ftdi_daemon.c index 48ef1cb..b92d8f5 100644 --- a/ftdi_daemon.c +++ b/ftdi_daemon.c @@ -6,6 +6,8 @@ uint8_t USB_GPIO_DDR; uint8_t USB_GPIO_PORT; uint8_t USB_GPIO_PIN; +FILE* fd; + volatile uint8_t main_loop=1; static int vendor=0x0403, device=0x6001; @@ -165,7 +167,7 @@ static int cmd_fsm(char c){ case CMD_READ: ret = get_value((unsigned)pin); DEBUG_OUT("Value of %d is %d\n", pin,ret); - fputc((char)ret,stdout); + fputc((char)ret,fd); return 0; } } @@ -174,14 +176,16 @@ static int cmd_fsm(char c){ int main(void){ int ret=ftdi_chip_init(); + fd=fopen("/dev/usb_gpio","rw"); if(ret!=0){ return ret; } for(;main_loop;){ - //kernel will write commands to the stdin - ret = fgetc(stdin); + //kernel will write commands to the device file + ret = fgetc(fd); if( ret!=EOF ){ + DEBUG_OUT("read %02x\n",ret); cmd_fsm(ret); }else{ //main_loop=0; diff --git a/ftdi_daemon.h b/ftdi_daemon.h index aa2bc5f..e65084d 100644 --- a/ftdi_daemon.h +++ b/ftdi_daemon.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "common.h" diff --git a/gpio_callbacks.c b/gpio_callbacks.c index 94b7d64..d86967b 100644 --- a/gpio_callbacks.c +++ b/gpio_callbacks.c @@ -1,20 +1,49 @@ static int get_value(struct gpio_chip *gc, unsigned offset){ + int ret; + DEBUG_OUT("<1>%s: GET_VALUE of pin%d ",MOD_NAME,offset); - return 0; + + ret=writeToBuffer(offset); + ret|=writeToBuffer(CMD_READ); + + return -ret; } static void set_value(struct gpio_chip *chip, unsigned offset, int value){ DEBUG_OUT("<1>%s: SET_VALUE of pin%d to %d",MOD_NAME,offset,value); + + writeToBuffer(offset); + if(value){ + writeToBuffer(CMD_H); + }else{ + writeToBuffer(CMD_L); + } } static int set_in(struct gpio_chip *chip, unsigned offset){ + int ret=0; + DEBUG_OUT("<1>%s: SET_INPUT of pin%d ",MOD_NAME,offset); - return 0; + + ret=writeToBuffer(offset); + ret|=writeToBuffer(CMD_IN); + + return -ret; } static int set_out(struct gpio_chip *chip, unsigned offset, int value){ + int ret; + DEBUG_OUT("<1>%s: SET_OUTPUT of pin%d to %d",MOD_NAME,offset,value); - return 0; + + ret=writeToBuffer(offset); + if(value){ + ret|=writeToBuffer(CMD_OUTH); + }else{ + ret|=writeToBuffer(CMD_OUTL); + } + + return -ret; } diff --git a/usb_gpio.c b/usb_gpio.c index f23ad23..806ce40 100644 --- a/usb_gpio.c +++ b/usb_gpio.c @@ -3,12 +3,14 @@ static struct gpio_chip ft232_chip; static struct subprocess_info *sub_info; +#include "char_dev.c" #include "gpio_callbacks.c" static void usb_gpio_exit(void) { if( gpiochip_remove(&ft232_chip)<0 ){ printk("<1>%s: Couldn't free GPIO-pins!\n",MOD_NAME); } + unregister_chrdev(major, MOD_NAME); printk("<1>%s: Bye!\n",MOD_NAME); } @@ -23,6 +25,14 @@ static int usb_gpio_init(void) { printk("<1>%s: Loading... \n",MOD_NAME); + major = register_chrdev(0, MOD_NAME, &fops); + if(major<0){ + printk("<1>%s: Can't register character device!\n",MOD_NAME); + } + printk("<1>%s: Assigned device major #%d minor #0!\n",MOD_NAME,major); + printk("<1>%s: Create device file with: \"mknod /dev/usb_gpio c %d 0\"\n",MOD_NAME,major); + + //GPIO registration ft232_chip.label = MOD_NAME; //Callback functions @@ -44,15 +54,18 @@ static int usb_gpio_init(void) { if (ret){ printk("<1>%s: Can't register chip!\n",MOD_NAME); } - - //Call the user space handler - sub_info = call_usermodehelper_setup( argv[0], argv, envp, GFP_ATOMIC ); - if (sub_info == NULL){ - return -ENOMEM; - } + return ret; + //Call the user space handler + /*sub_info = call_usermodehelper_setup( argv[0], argv, envp, GFP_ATOMIC ); + if (sub_info == NULL){ + return -ENOMEM; + } - // the helper will run in the background until the module decides to kill it - return call_usermodehelper_exec( sub_info, UMH_NO_WAIT ); + // the helper will run in the background until the module decides to kill it + ret=call_usermodehelper_exec( sub_info, UMH_NO_WAIT ); + if(ret<0){ + printk("<1>%s: Couldn't run userspace helper process (%s)!\n",MOD_NAME,); + }*/ } module_init(usb_gpio_init); diff --git a/usb_gpio.h b/usb_gpio.h index f146e4b..4ba63fc 100644 --- a/usb_gpio.h +++ b/usb_gpio.h @@ -11,10 +11,14 @@ #include #include +#include +#include + #include "usb_gpio_util.h" #include "common.h" #define NUM_OF_GPIO 8 +#define BUFFER_SIZE 1024 #ifndef CONFIG_GENERIC_GPIO #error This module needs generic gpio support (CONFIG_GENERIC_GPIO)