📄 usbdev.c
字号:
/****************************************Copyright (c)**************************************************** Guangzhou ZHIYUAN electronics Co.,LTD.** ** http://www.zyinside.com****--------------File Info-------------------------------------------------------------------------------** File Name: usbdev.c** Last modified Date: 2006.01.09** Last Version: V1.0 ** Description: usbdev.c, S3C2410 USB 设备驱动程序** usbdev.c, S3C2410 USB Device Driver**------------------------------------------------------------------------------------------------------** Created By: MingYuan Zheng 郑明远** Created date: 2006.01.09** Version: V1.0** Descriptions: The original version 初始版本****------------------------------------------------------------------------------------------------------** Modified by:** Modified date:** Version:** Description:**********************************************************************************************************/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include "config.h"
static ssize_t usbdev_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
static ssize_t usbdev_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
static int usbdev_open(struct inode *inode, struct file *filp);
static int usbdev_release(struct inode *inode, struct file *filp);
static int usbdev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long param);
void ep1_int_handler(void);
void ep2_int_handler(void);
void ep3_int_handler(void);
void ep4_int_handler(void);
/********************************************************************************************************
define announce
********************************************************************************************************/
MODULE_PARM(major, "i");
MODULE_LICENSE("Proprietary");
MODULE_DESCRIPTION("GuangZhou ZhiYuan Electronics Co.,LTD.\nhttp://www.zyinside.com");
MODULE_SUPPORTED_DEVICE("linux2.4.18 S3C2410 usbdev");
MODULE_AUTHOR("MingYuan Zheng");
#define MAJOR_NR major
/*********************************************************************************************************
** "全局和静态变量在这里定义"
** global variables and static variables define here
********************************************************************************************************/
/* device using count */
unsigned int usage = 0; /* 设备使用计数器 */
static int major = USBDEV_MAJOR_NR;
/* endpoint numbers except control endpoint */
#define NUMS_REC_ENDPOINTS 2 /* 除控制端点外端点数 */
#define NUMS_SEND_ENDPOINTS 2
/* endpoint used semaphore */
struct semaphore rec_sem[NUMS_REC_ENDPOINTS]; /* 端点占用信号量(用于互斥) */
struct semaphore send_sem[NUMS_SEND_ENDPOINTS];
/* endpoint interrupt semaphore */
struct semaphore rec_irq_sem[NUMS_REC_ENDPOINTS]; /* 端点中断信号量(用于数据收发) */
struct semaphore send_irq_sem[NUMS_SEND_ENDPOINTS];
/* endpoint size */ /* 端点FIFO大小 */
static int rec_fifo_size[NUMS_REC_ENDPOINTS] = {EP2_PACKET_SIZE, EP4_PACKET_SIZE};
static int send_fifo_size[NUMS_SEND_ENDPOINTS] = {EP1_PACKET_SIZE, EP3_PACKET_SIZE};
/* endpoint waiting queue */
wait_queue_head_t rec_queue[NUMS_REC_ENDPOINTS]; /* 端点等待队列 */
wait_queue_head_t send_queue[NUMS_SEND_ENDPOINTS];
/* endpoint timeout */
static int rec_timeout[NUMS_REC_ENDPOINTS]; /* 端点收发超时时间 */
static int send_timeout[NUMS_SEND_ENDPOINTS];
/* endpoint have finished receiving and trasmitting once */
static int b_send[NUMS_SEND_ENDPOINTS]; /* 端点是(1)否(0)完成一次数据收发 */
static int b_rec[NUMS_REC_ENDPOINTS];
/********************************************************************************************************/
static struct file_operations usbdev_fops = /* driver info */
{
owner: THIS_MODULE,
write: usbdev_write,
read: usbdev_read,
open: usbdev_open,
release: usbdev_release,
ioctl: usbdev_ioctl,
};
/*********************************************************************************************************
** Function name : usbdev_release
** Descriptions : release device
** Input : inode: information of device
** filp: pointer of file
** Output : 0: OK
** other: not OK
** Created by : MingYuan Zheng 郑明远
** Created Date : 2006-01-12
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
static int usbdev_release(struct inode *inode, struct file *filp)
{
int i;
MOD_DEC_USE_COUNT;
usage--;
/* re-initialize global variable */
for (i = 0; i < NUMS_REC_ENDPOINTS; i++)
{
rec_timeout[i] = 0; /* timeout time be setted to 0 超时时间置为0 */
send_timeout[i] = 0;
b_send[i] = 0; /* transmitted flash be setted to 0 已发送标志置为0 */
b_rec[i] = 0; /* received flash be setted to 0 已接收标志置为0 */
}
return(0);
}
/*********************************************************************************************************
** Function name : usbdev_write
** Descriptions : write device(transmit data to USB host by endpoint)
** Input : filp: pointer of file
** buf: buf to write data
** count: size for write
** f_pos: *f_pos = write point
** Output : write size
** Created by : MingYuan Zheng 郑明远
** Created Date : 2006-01-12
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
static ssize_t usbdev_write(struct file *filp, const char *buf, size_t count,
loff_t *f_pos)
{
unsigned int num,len;
unsigned int sendcnt = 0,i;
unsigned int epsize; /* endpoint buffer size */
unsigned char sendbuf[64];
unsigned int flag, bfinish = 0;
int ret;
num = (unsigned int)filp->private_data;
if ((num > NUMS_SEND_ENDPOINTS) || (num < 1))
{
return -ENODEV;
}
if (down_interruptible(&send_sem[num - 1])) /* occupy the endpoint */
{
return -ERESTARTSYS;
}
epsize = send_fifo_size[num - 1]; /* get FIFO size */
while(1)
{
/****************************************************
write the data to the FIFO of USB device
****************************************************/
local_irq_save(flag);
len = count - sendcnt;
if (len >= epsize)
{
copy_from_user(sendbuf, (unsigned char *)(buf + sendcnt), epsize);
len = USB_WriteEndpoint(num * 2 - 1, epsize, sendbuf); /* write FIFO */
}
else
{
copy_from_user(sendbuf, (unsigned char *)(buf + sendcnt), len);
len = USB_WriteEndpoint(num * 2 - 1, len, sendbuf); /* write FIFO */
}
sendcnt = sendcnt + len;
if (sendcnt >= count)
{ /* all data have been write into FIFO */
b_send[num - 1] = 0;
local_irq_restore(flag);
bfinish = 1;
}
b_send[num - 1] = 0;
local_irq_restore(flag);
/*****************************************************
wait the data be received by USB Host(PC)
*****************************************************/
if (send_timeout[num - 1] != 0)
{
local_irq_save(flag);
if (b_send[num - 1] == 0)
{
local_irq_restore(flag);
ret = interruptible_sleep_on_timeout(&send_queue[num - 1], send_timeout[num - 1] * HZ/1000);
if (ret <= 0)
{
printk("S3C2410 USB device ep%d send data timeout!\n", num);
up(&send_sem[num - 1]);
return sendcnt;
}
}
else
b_send[num - 1] = 0;
}
else
{
if (down_interruptible(&send_irq_sem[num - 1]))
{ /* can not wait the send_irq_sem*/
up(&send_sem[num - 1]);
return -ERESTARTSYS;
}
}
/******************************************************
all data has been received by USB host(such as PC)
******************************************************/
if (bfinish == 1)
{
up(&send_sem[num - 1]);
return sendcnt;
}//end of if (bfinish == 1)
}//end of while(1)
}
/*********************************************************************************************************
** Function name : usbdev_read
** Descriptions : read device (receive data from USB host by endpoint)
** Input : filp: pointer of file
** buf: buf for save data
** count: size for read
** f_pos: *f_pos = read point
** Output : read size
** Created by : MingYuan Zheng
** Created Date : 2005-5-17
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
static ssize_t usbdev_read(struct file *filp, char *buf, size_t count,
loff_t *f_pos)
{
unsigned int flag, num, len;
unsigned int epsize, reccnt = 0, i;
unsigned char recbuf[64], endpstatus;
int ret;
num = (unsigned int)filp->private_data;
if ((num > NUMS_REC_ENDPOINTS) ||(num < 1))
{
return -ENODEV;
}
if (down_interruptible(&rec_sem[num - 1])) /* occupy the endpoint */
{
return -ERESTARTSYS;
}
epsize = rec_fifo_size[num - 1]; /* get FIFO size */
while(1)
{
/*******************************************************
wait for the data(send from USB host(such as PC))
*******************************************************/
if (rec_timeout[num - 1] != 0)
{
local_irq_save(flag);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -