#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/usb.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/uaccess.h>
#include "pdiusbd12.h"
#define PDIUSBD12_MAJOR 256
#define PDIUSBD12_MINOR 10
#define PDIUSBD12_DEV_NAME "pdiusbd12"
struct pdiusbd12_dev {
int pipe_ep1_out;
int pipe_ep1_in;
int pipe_ep2_out;
int pipe_ep2_in;
int maxp_ep1_out;
int maxp_ep1_in;
int maxp_ep2_out;
int maxp_ep2_in;
struct urb *ep2inurb;
int errors;
unsigned int ep2inlen;
unsigned char ep1inbuf[16];
unsigned char ep1outbuf[16];
unsigned char ep2inbuf[64];
unsigned char ep2outbuf[64];
struct usb_device *usbdev;
wait_queue_head_t wq;
struct cdev cdev;
dev_t dev;
};
static unsigned int minor = PDIUSBD12_MINOR;
static int pdiusbd12_open(struct inode *inode, struct file *filp)
{
struct pdiusbd12_dev *pdiusbd12;
pdiusbd12 = container_of(inode->i_cdev, struct pdiusbd12_dev, cdev);
filp->private_data = pdiusbd12;
return 0;
}
static int pdiusbd12_release(struct inode *inode, struct file *filp)
{
struct pdiusbd12_dev *pdiusbd12;
pdiusbd12 = container_of(inode->i_cdev, struct pdiusbd12_dev, cdev);
usb_kill_urb(pdiusbd12->ep2inurb);
return 0;
}
void usb_read_complete(struct urb * urb)
{
struct pdiusbd12_dev *pdiusbd12 = urb->context;
switch (urb->status) {
case 0:
pdiusbd12->ep2inlen = urb->actual_length;
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
default:
pdiusbd12->ep2inlen = 0;
break;
}
pdiusbd12->errors = urb->status;
wake_up_interruptible(&pdiusbd12->wq);
}
static ssize_t pdiusbd12_read(struct file *filp, char __user *buf, size_t count, loff_t *f_ops)
{
int ret;
struct usb_device *usbdev;
struct pdiusbd12_dev *pdiusbd12 = filp->private_data;
count = count > sizeof(pdiusbd12->ep2inbuf) ? sizeof(pdiusbd12->ep1inbuf) : count;
ret = count;
usbdev = pdiusbd12->usbdev;
usb_fill_bulk_urb(pdiusbd12->ep2inurb, usbdev, pdiusbd12->pipe_ep2_in, pdiusbd12->ep2inbuf, ret, usb_read_complete, pdiusbd12);
if (usb_submit_urb(pdiusbd12->ep2inurb, GFP_KERNEL))
return -EIO;
interruptible_sleep_on(&pdiusbd12->wq);
if (pdiusbd12->errors)
return pdiusbd12->errors;
else {
if (copy_to_user(buf, pdiusbd12->ep2inbuf, pdiusbd12->ep2inlen))
return -EFAULT;
else
return pdiusbd12->ep2inlen;
}
}
static ssize_t pdiusbd12_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops)
{
int len;
ssize_t ret = 0;
struct pdiusbd12_dev *pdiusbd12 = filp->private_data;
count = count > sizeof(pdiusbd12->ep2outbuf) ? sizeof(pdiusbd12->ep2outbuf) : count;
if (copy_from_user(pdiusbd12->ep2outbuf, buf, count))
return -EFAULT;
ret = usb_bulk_msg(pdiusbd12->usbdev, pdiusbd12->pipe_ep2_out, pdiusbd12->ep2outbuf, count, &len, 10 * HZ);
if (ret)
return ret;
else
return len;
}
long pdiusbd12_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret;
int len;
struct pdiusbd12_dev *pdiusbd12 = filp->private_data;
if (_IOC_TYPE(cmd) != PDIUSBD12_MAGIC)
return -ENOTTY;
switch (cmd) {
case PDIUSBD12_GET_KEY:
ret = usb_interrupt_msg(pdiusbd12->usbdev, pdiusbd12->pipe_ep1_in, pdiusbd12->ep1inbuf, 8, &len, 10 * HZ);
if (ret)
return ret;
else {
if (copy_to_user((unsigned char __user *)arg, pdiusbd12->ep1inbuf, len))
return -EFAULT;
else
return 0;
}
break;
case PDIUSBD12_SET_LED:
if (copy_from_user(pdiusbd12->ep1outbuf, (unsigned char __user *)arg, 8))
return -EFAULT;
ret = usb_interrupt_msg(pdiusbd12->usbdev, pdiusbd12->pipe_ep1_out, pdiusbd12->ep1outbuf, 8, &len, 10 * HZ);
if (ret)
return ret;
else
return 0;
default:
return -ENOTTY;
}
return 0;
}
static struct file_operations pdiusbd12_ops = {
.owner = THIS_MODULE,
.open = pdiusbd12_open,
.release = pdiusbd12_release,
.read = pdiusbd12_read,
.write = pdiusbd12_write,
.unlocked_ioctl = pdiusbd12_ioctl,
};
int pdiusbd12_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
static struct pdiusbd12_dev *pdiusbd12;
struct usb_device *usbdev;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
int ret = 0;
pdiusbd12 = kmalloc(sizeof(struct pdiusbd12_dev), GFP_KERNEL);
if (!pdiusbd12)
return -ENOMEM;
usbdev = interface_to_usbdev(intf);
interface = intf->cur_altsetting;
if (interface->desc.bNumEndpoints != 4) {
ret = -ENODEV;
goto out_no_dev;
}
/* EP1 Interrupt IN */
endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & 0x80)) { /* IN */
ret = -ENODEV;
goto out_no_dev;
}
if ((endpoint->bmAttributes & 0x7F) != 3) { /* Interrupt */
ret = -ENODEV;
goto out_no_dev;
}
pdiusbd12->pipe_ep1_in = usb_rcvintpipe(usbdev, endpoint->bEndpointAddress);
pdiusbd12->maxp_ep1_in = usb_maxpacket(usbdev, pdiusbd12->pipe_ep1_in, usb_pipeout(pdiusbd12->pipe_ep1_in));
/* EP1 Interrupt Out */
endpoint = &interface->endpoint[1].desc;
if (endpoint->bEndpointAddress & 0x80) { /* OUT */
ret = -ENODEV;
goto out_no_dev;
}
if ((endpoint->bmAttributes & 0x7F) != 3) { /* Interrupt */
ret = -ENODEV;
goto out_no_dev;
}
pdiusbd12->pipe_ep1_out = usb_sndintpipe(usbdev, endpoint->bEndpointAddress);
pdiusbd12->maxp_ep1_out = usb_maxpacket(usbdev, pdiusbd12->pipe_ep1_out, usb_pipeout(pdiusbd12->pipe_ep1_out));
/* EP2 Bulk IN */
endpoint = &interface->endpoint[2].desc;
if (!(endpoint->bEndpointAddress & 0x80)) { /* IN */
ret = -ENODEV;
goto out_no_dev;
}
if ((endpoint->bmAttributes & 0x7F) != 2) { /* Bulk */
ret = -ENODEV;
goto out_no_dev;
}
pdiusbd12->pipe_ep2_in = usb_rcvintpipe(usbdev, endpoint->bEndpointAddress);
pdiusbd12->maxp_ep2_in = usb_maxpacket(usbdev, pdiusbd12->pipe_ep2_in, usb_pipeout(pdiusbd12->pipe_ep2_in));
endpoint = &interface->endpoint[3].desc;
if (endpoint->bEndpointAddress & 0x80) { /* OUT */
ret = -ENODEV;
goto out_no_dev;
}
if ((endpoint->bmAttributes & 0x7F) != 2) { /* Bulk */
ret = -ENODEV;
goto out_no_dev;
}
pdiusbd12->pipe_ep2_out = usb_sndintpipe(usbdev, endpoint->bEndpointAddress);
pdiusbd12->maxp_ep2_out = usb_maxpacket(usbdev, pdiusbd12->pipe_ep2_out, usb_pipeout(pdiusbd12->pipe_ep2_out));
pdiusbd12->ep2inurb = usb_alloc_urb(0, GFP_KERNEL);
pdiusbd12->usbdev = usbdev;
usb_set_intfdata(intf, pdiusbd12);
pdiusbd12->dev = MKDEV(PDIUSBD12_MAJOR, minor++);
ret = register_chrdev_region (pdiusbd12->dev, 1, PDIUSBD12_DEV_NAME);
if (ret < 0)
goto out_reg_region;
cdev_init(&pdiusbd12->cdev, &pdiusbd12_ops);
pdiusbd12->cdev.owner = THIS_MODULE;
ret = cdev_add(&pdiusbd12->cdev, pdiusbd12->dev, 1);
if (ret)
goto out_cdev_add;
init_waitqueue_head(&pdiusbd12->wq);
return 0;
out_cdev_add:
unregister_chrdev_region(pdiusbd12->dev, 1);
out_reg_region:
usb_free_urb(pdiusbd12->ep2inurb);
out_no_dev:
kfree(pdiusbd12);
return ret;
}
void pdiusbd12_disconnect(struct usb_interface *intf)
{
struct pdiusbd12_dev *pdiusbd12 = usb_get_intfdata(intf);
cdev_del(&pdiusbd12->cdev);
unregister_chrdev_region(pdiusbd12->dev, 1);
usb_kill_urb(pdiusbd12->ep2inurb);
usb_free_urb(pdiusbd12->ep2inurb);
kfree(pdiusbd12);
}
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x8888, 0x000b) },
{ }
};
MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver pdiusbd12_driver =
{
.name = "pdiusbd12",
.id_table = id_table,
.probe = pdiusbd12_probe,
.disconnect = pdiusbd12_disconnect,
};
module_usb_driver(pdiusbd12_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kevin Jiang <jiangxg@farsight.com.cn>");
MODULE_DESCRIPTION("PDIUSBD12 driver");
没有合适的资源?快使用搜索试试~ 我知道了~
嵌入式linux驱动 开发教程-源代码.7z
共149个文件
c:74个
makefile:45个
h:29个
需积分: 37 70 下载量 56 浏览量
2019-06-18
10:29:12
上传
评论 3
收藏 24KB 7Z 举报
温馨提示
《嵌入式Linux驱动开发教程》完整的源代码下载。没有密码,解压直接编译即可以使用。
资源推荐
资源详情
资源评论
收起资源包目录
嵌入式linux驱动 开发教程-源代码.7z (149个子文件)
pdiusbd12.c 7KB
vser.c 6KB
vser.c 6KB
vser.c 6KB
vser.c 6KB
vser.c 6KB
vser.c 6KB
vser.c 5KB
ch368.c 5KB
fsrtc.c 5KB
vser.c 5KB
mpu6050.c 5KB
fspwm.c 5KB
vser.c 4KB
fsadc.c 4KB
fsled.c 4KB
fskey.c 4KB
fsled.c 4KB
fsled.c 4KB
vser.c 4KB
vnet.c 4KB
vser.c 4KB
vdsk.c 3KB
vdsk.c 3KB
fsled.c 3KB
vser.c 3KB
vser.c 3KB
vser.c 3KB
vser.c 3KB
vfb.c 3KB
memcpy.c 2KB
vser.c 2KB
test.c 2KB
vfb.c 2KB
vser.c 2KB
fsdev.c 2KB
fsdev.c 2KB
fskey.c 2KB
test.c 2KB
vser.c 2KB
model.c 2KB
test.c 1KB
test.c 1KB
test.c 1KB
vser.c 1KB
test.c 956B
pltdrv.c 891B
pltdev.c 873B
test.c 857B
vser.c 803B
test.c 781B
vser.c 777B
test.c 769B
test.c 765B
test.c 765B
test.c 765B
test.c 751B
test.c 735B
test.c 713B
test.c 656B
test.c 638B
test.c 591B
vdev.c 587B
vbus.c 583B
test.c 557B
test.c 531B
test.c 525B
vdrv.c 520B
vser.c 505B
foo.c 446B
vser.c 414B
dep.c 258B
vser.c 200B
bar.c 64B
i2c-dev.h 10KB
music.h 885B
music.h 885B
ch368.h 372B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
vser.h 357B
fsrtc.h 311B
pdiusbd12.h 300B
mpu6050.h 258B
fsadc.h 249B
fsled.h 234B
fspwm.h 205B
vnet.h 171B
共 149 条
- 1
- 2
资源评论
生如~夏花
- 粉丝: 4243
- 资源: 51
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功