一.spidev.c文件
看一个设备驱动的方法:
概览下重要的结构体spidev_data及全局变量device_list,bufsiz,SPIDEV_MAJOR...
module_init标识的入口初始化函数spidev_init,(module_exit标识的出口函数)
设备与设备驱动匹配时候调用的probe方法spidev_probe
设备驱动的操作函数集file_operations--->spidev_fops
先看open方法spidev_open
接着看读写方法spidev_read & spidev_write
再接着看ioctl方法-->spidev_ioctl
再看其他剩余的方法
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>
#include <asm/uaccess.h>
#define SPIDEV_MAJOR 153 //spidev主设备号
#define N_SPI_MINORS 32 /* ... up to 256 */
static DECLARE_BITMAP(minors, N_SPI_MINORS); //声明次设备位图
#define SPI_MODE_MASK (SPI_CPHA|SPI_CPOL|SPI_CS_HIGH|SPI_LSB_FIRST|SPI_3WIRE|SPI_LOOP|SPI_NO_CS|SPI_READY)
struct spidev_data {
dev_t devt; //设备号
spinlock_t spi_lock; //自旋锁
struct spi_device *spi; //spi设备结构体
struct list_head device_entry;
struct mutex buf_lock; //互斥锁
unsigned users; //使用者计数
u8 *buffer; //缓冲区
};
static LIST_HEAD(device_list); //声明spi设备链表
static DEFINE_MUTEX(device_list_lock); //定义互斥锁
static unsigned bufsiz = 4096; //最大传输缓冲区大小
module_param(bufsiz, uint, S_IRUGO);
MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");
static void spidev_complete(void *arg)
{
complete(arg); //调用complete
}
static ssize_t spidev_sync(struct spidev_data *spidev, struct spi_message *message)
{
DECLARE_COMPLETION_ONSTACK(done);
int status;
message->complete = spidev_complete; //设置spi消息的complete方法 回调函数
message->context = &done;
spin_lock_irq(&spidev->spi_lock);
if (spidev->spi == NULL) //判断是否有指定对应的spi设备
status = -ESHUTDOWN;
else
status = spi_async(spidev->spi, message); //spi异步同步
spin_unlock_irq(&spidev->spi_lock);
if (status == 0) {
wait_for_completion(&done); //等待传输完成
status = message->status; //获取spi消息传输事务状态
if (status == 0)
status = message->actual_length; //status等于传输的实际长度
}
return status; //返回实际传输长度
}
static inline ssize_t spidev_sync_write(struct spidev_data *spidev, size_t len)
{
struct spi_transfer t = {
.tx_buf = spidev->buffer, //发送缓冲区
.len = len, //发送数据长度
};
struct spi_message m;
spi_message_init(&m); //初始化spi消息(初始化spi传递事务队列)
spi_message_add_tail(&t, &m); //添加spr传递到该队列
return spidev_sync(spidev, &m); //同步读写
}
static inline ssize_t spidev_sync_read(struct spidev_data *spidev, size_t len)
{
struct spi_transfer t = {
.rx_buf = spidev->buffer, //接收缓冲区
.len = len, //接收数据长度
};
struct spi_message m;
spi_message_init(&m); //初始化spi消息(初始化spi传递事务队列)
spi_message_add_tail(&t, &m); //添加spr传递到该队列
return spidev_sync(spidev, &m); //同步读写
}
static ssize_t spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
struct spidev_data *spidev;
ssize_t status = 0;
if (count > bufsiz) //传输数据大于缓冲区容量
return -EMSGSIZE;
spidev = filp->private_data; //从文件私有数据指针获取spidev_data
mutex_lock(&spidev->buf_lock); //上互斥锁
status = spidev_sync_read(spidev, count); //同步读,返回传输数据长度
if (status > 0) {
unsigned long missing; //丢失的数据个数
missing = copy_to_user(buf, spidev->buffer, status); //内核空间复制到用户空间
if (missing == status) //丢失的数据个数等于要传输的数据个数
status = -EFAULT;
else
status = status - missing; //传输成功的数据个数
}
mutex_unlock(&spidev->buf_lock);//解互斥锁
return status; //返回读取成功的数据个数
}
static ssize_t spidev_write(struct file *filp, const char __user *buf,size_t count, loff_t *f_pos)
{
struct spidev_data *spidev;
ssize_t status = 0;
unsigned long missing;
if (count > bufsiz) //传输数据大于缓冲区容量
return -EMSGSIZE;
spidev = filp->private_data; //从文件私有数据指针获取spidev_data
mutex_lock(&spidev->buf_lock); //上互斥锁
missing = copy_from_user(spidev->buffer, buf, count); //用户空间复制到内核空间
if (missing == 0) { //传输失败个数为0
status = spidev_sync_write(spidev, count); //同步写,返回传输数据长度
}
else
status = -EFAULT;
mutex_unlock(&spidev->buf_lock);//解互斥锁
return status; //返回写数据的实际个数
}
static int spidev_message(struct spidev_data *spidev,struct spi_ioc_transfer *u_xfers, unsigned n_xfers)
{
struct spi_message msg;
struct spi_transfer *k_xfers;