Rind před 5 roky
revize
e1d07b6e4c
4 změnil soubory, kde provedl 352 přidání a 0 odebrání
  1. 24 0
      Makefile
  2. 187 0
      drvmain.c
  3. 112 0
      kfile.c
  4. 29 0
      kfile.h

+ 24 - 0
Makefile

@@ -0,0 +1,24 @@
+# ccflags-y += -O2
+TARGET_MODULE:=gfaspi
+PWD := $(shell pwd)
+
+$(TARGET_MODULE)-objs := drvmain.o kfile.o
+obj-m := $(TARGET_MODULE).o
+
+
+# all: default
+
+default:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+clean:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
+
+
+depend .depend dep:
+	$(CC) -M *.c > .depend
+
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif

+ 187 - 0
drvmain.c

@@ -0,0 +1,187 @@
+#include <linux/init.h>
+#include <linux/kernel.h>    // printk()
+#include <linux/kobject.h>   // struct kobject
+#include <linux/errno.h>     // error codes
+#include <linux/module.h>    // THIS_MODULE
+#include <linux/sysfs.h>
+#include <linux/syscalls.h>
+#include <asm/ioctls.h>
+#include <linux/spi/spidev.h>
+#include "kfile.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("GfA");
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define _SPI_DEVICE				"/dev/spidev1.0"
+static struct file *g_fdSpiDev	= NULL;
+
+/////////////////////////////////////////////////////////////////////////////
+
+static int temp = 0;
+static struct kobject *pKoGfa = NULL, *pKoTiva = NULL;
+
+/////////////////////////////////////////////////////////////////////////////
+
+static ssize_t tivaTempShow(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	printk(KERN_ALERT "tivaTemp - Read!!!\n");
+	return sprintf(buf, "%d", ++temp);
+}
+
+static ssize_t tivaTempStore(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	printk(KERN_ALERT "tivaTemp - Write!!!\n");
+	sscanf(buf, "%d", &temp);
+	return count;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static struct kobj_attribute tivaTempAtt = __ATTR(temp, 0660, tivaTempShow, tivaTempStore);
+
+/////////////////////////////////////////////////////////////////////////////
+
+static int drv_init(void)
+{
+	long ret;
+	uint8_t mode = SPI_MODE_3;
+	uint8_t bits = 8;
+	uint32_t speed = 1000000;
+
+	/////////////////////////////////////////////////////////////////////////
+
+	do
+	{
+		if(!(pKoGfa = kobject_create_and_add("gfa", /*kernel_kobj*/NULL)))
+		{
+			printk(KERN_ALERT "kobject_create_and_add failed\n");
+			break;
+		}
+
+		if(!(pKoTiva = kobject_create_and_add("tiva", pKoGfa)))
+		{
+			printk(KERN_ALERT "kobject_create_and_add failed\n");
+			break;
+		}
+
+		/////////////////////////////////////////////////////////////////////
+
+		if(sysfs_create_file(pKoTiva, &tivaTempAtt.attr))
+		{
+			printk(KERN_ALERT "sysfs_create_file failed\n");
+			break;
+		}
+
+		/////////////////////////////////////////////////////////////////////
+
+		if(!(g_fdSpiDev = kf_open(_SPI_DEVICE, O_RDWR, 0)))
+		{
+			printk(KERN_ALERT "file_open failed\n");
+			break;
+		}
+
+		/////////////////////////////////////////////////////////////////////
+
+		ret = kf_ioctl(g_fdSpiDev, SPI_IOC_WR_MODE, (unsigned long)&mode);
+		if(ret < 0)
+		{
+			printk(KERN_ALERT "can't set spi mode\n");
+			break;
+		}
+
+		mode = 0;
+		ret = kf_ioctl(g_fdSpiDev, SPI_IOC_RD_MODE, (unsigned long)&mode);
+		if(ret < 0)
+		{
+			printk(KERN_ALERT "can't get spi mode\n");
+			break;
+		}
+
+		ret = kf_ioctl(g_fdSpiDev, SPI_IOC_WR_BITS_PER_WORD, (unsigned long)&bits);
+		if(ret < 0)
+		{
+			printk(KERN_ALERT "can't set bits per word\n");
+			break;
+		}
+
+		bits = 0;
+		ret = kf_ioctl(g_fdSpiDev, SPI_IOC_RD_BITS_PER_WORD, (unsigned long)&bits);
+		if(ret < 0)
+		{
+			printk(KERN_ALERT "can't get bits per word\n");
+			break;
+		}
+
+		ret = kf_ioctl(g_fdSpiDev, SPI_IOC_WR_MAX_SPEED_HZ, (unsigned long)&speed);
+		if(ret < 0)
+		{
+			printk(KERN_ALERT "can't set max speed hz\n");
+			break;
+		}
+
+		speed = 0;
+		ret = kf_ioctl(g_fdSpiDev, SPI_IOC_RD_MAX_SPEED_HZ, (unsigned long)&speed);
+		if(ret < 0)
+		{
+			printk(KERN_ALERT "can't get max speed hz\n");
+			break;
+		}
+
+		/////////////////////////////////////////////////////////////////////
+
+		printk(KERN_ALERT "mode:  %hhu\n", mode);
+		printk(KERN_ALERT "bits:  %hhu\n", bits);
+		printk(KERN_ALERT "speed: %u\n", speed);
+		printk(KERN_ALERT "%s\n", __FUNCTION__);
+		return 0;
+	}
+	while(0);
+
+	/////////////////////////////////////////////////////////////////////////
+
+	if(g_fdSpiDev)
+		kf_close(g_fdSpiDev);
+
+	if(pKoTiva)
+	{
+		sysfs_remove_file(pKoTiva, &tivaTempAtt.attr);
+		kobject_put(pKoTiva);
+		pKoTiva = NULL;
+	}
+
+	if(pKoGfa)
+	{
+		kobject_put(pKoGfa);
+		pKoGfa = NULL;
+	}
+
+	return -ENOMEM;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static void drv_exit(void)
+{
+	if(g_fdSpiDev)
+		kf_close(g_fdSpiDev);
+
+	if(pKoTiva)
+	{
+		sysfs_remove_file(pKoTiva, &tivaTempAtt.attr);
+		kobject_put(pKoTiva);
+	}
+
+	if(pKoGfa)
+		kobject_put(pKoGfa);
+
+	printk(KERN_ALERT "%s\n", __FUNCTION__);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+module_init(drv_init);
+module_exit(drv_exit);

+ 112 - 0
kfile.c

@@ -0,0 +1,112 @@
+#include <linux/kernel.h>    // printk()
+#include <linux/syscalls.h>
+#include "kfile.h"
+
+static mm_segment_t g_oldfs;
+
+/////////////////////////////////////////////////////////////////////////////
+
+static long _vfs_ioctl(struct file *pf, unsigned int cmd, unsigned long arg)
+{
+	int ret = -ENOTTY;
+
+	if(pf->f_op->unlocked_ioctl)
+	{
+		ret = pf->f_op->unlocked_ioctl(pf, cmd, arg);
+
+		if(ret == -ENOIOCTLCMD)
+			ret = -ENOTTY;
+	}
+ 
+ 	return ret;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+struct file* kf_open(const char *path, int flags, int rights)
+{
+    struct file *pf = NULL;
+//    mm_segment_t oldfs;
+    int err = 0;
+
+    g_oldfs = get_fs();
+    set_fs(get_ds());
+    pf = filp_open(path, flags, rights);
+//    set_fs(oldfs);
+
+    if(IS_ERR(pf))
+    {
+        err = PTR_ERR(pf);
+		set_fs(g_oldfs);
+        return NULL;
+    }
+
+    return pf;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void kf_close(struct file *pf)
+{
+	if(pf)
+	{
+    	filp_close(pf, NULL);
+		set_fs(g_oldfs);
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int kf_read(struct file *pf, unsigned long long offset, unsigned char *data, unsigned int size)
+{
+	int ret;
+//	mm_segment_t oldfs;
+
+//	oldfs = get_fs();
+//	set_fs(get_ds());
+
+	ret = vfs_read(pf, data, size, &offset);
+
+//	set_fs(oldfs);
+	return ret;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int kf_write(struct file *pf, unsigned long long offset, unsigned char *data, unsigned int size)
+{
+	int ret;
+//	mm_segment_t oldfs;
+
+//	oldfs = get_fs();
+//	set_fs(get_ds());
+
+	ret = vfs_write(pf, data, size, &offset);
+
+//	set_fs(oldfs);
+	return ret;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+long kf_ioctl(struct file *pf, unsigned int cmd, unsigned long arg)
+{
+	long ret;
+//	mm_segment_t oldfs;
+
+//	oldfs = get_fs();
+//	set_fs(get_ds());
+
+	ret = _vfs_ioctl(pf, cmd, arg);
+
+//	set_fs(oldfs);
+	return ret;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int kf_sync(struct file *pf)
+{
+	vfs_fsync(pf, 0);
+	return 0;
+}

+ 29 - 0
kfile.h

@@ -0,0 +1,29 @@
+// kfile.h :
+//
+
+#if !defined(AGD_KFILE_H__A71FB716_AC33_40F3_95C0_3E47923E77B4__INCLUDED_)
+#define AGD_KFILE_H__A71FB716_AC33_40F3_95C0_3E47923E77B4__INCLUDED_
+
+#ifdef __cplusplus
+extern "C" {
+#endif	//	__cplusplus
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// https://stackoverflow.com/questions/1184274/read-write-files-within-a-linux-kernel-module
+//
+/////////////////////////////////////////////////////////////////////////////
+// kofile.h - Declarations:
+
+struct file*	kf_open(const char *path, int flags, int rights);
+void			kf_close(struct file *pf);
+int				kf_read(struct file *pf, unsigned long long offset, unsigned char *data, unsigned int size);
+int				kf_write(struct file *pf, unsigned long long offset, unsigned char *data, unsigned int size);
+long			kf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+int				kf_sync(struct file *pf);
+
+/////////////////////////////////////////////////////////////////////////////
+#ifdef __cplusplus
+}
+#endif	//	__cplusplus
+#endif	//	!defined(AGD_KFILE_H__A71FB716_AC33_40F3_95C0_3E47923E77B4__INCLUDED_)