[新增] 华清 源码
This commit is contained in:
22
usb/ex1/Makefile
Executable file
22
usb/ex1/Makefile
Executable file
@ -0,0 +1,22 @@
|
||||
ifeq ($(KERNELRELEASE),)
|
||||
|
||||
ifeq ($(ARCH),arm)
|
||||
KERNELDIR ?= /home/farsight/fs4412/linux-3.14.25-fs4412
|
||||
ROOTFS ?= /nfs/rootfs
|
||||
else
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
endif
|
||||
PWD := $(shell pwd)
|
||||
|
||||
modules:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
|
||||
modules_install:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) INSTALL_MOD_PATH=$(ROOTFS) modules_install
|
||||
clean:
|
||||
rm -rf *.o *.ko .*.cmd *.mod.* modules.order Module.symvers .tmp_versions
|
||||
else
|
||||
|
||||
obj-m := pdiusbd12.o
|
||||
|
||||
endif
|
||||
|
||||
297
usb/ex1/pdiusbd12.c
Executable file
297
usb/ex1/pdiusbd12.c
Executable file
@ -0,0 +1,297 @@
|
||||
#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");
|
||||
17
usb/ex1/pdiusbd12.h
Executable file
17
usb/ex1/pdiusbd12.h
Executable file
@ -0,0 +1,17 @@
|
||||
#ifndef _PDIUSBD12_H
|
||||
#define _PDIUSBD12_H
|
||||
|
||||
struct d12key {
|
||||
unsigned char key[8];
|
||||
};
|
||||
|
||||
struct d12led {
|
||||
unsigned char led[8];
|
||||
};
|
||||
|
||||
#define PDIUSBD12_MAGIC 'p'
|
||||
|
||||
#define PDIUSBD12_GET_KEY _IOR(PDIUSBD12_MAGIC, 0, struct d12key)
|
||||
#define PDIUSBD12_SET_LED _IOW(PDIUSBD12_MAGIC, 1, struct d12led)
|
||||
|
||||
#endif
|
||||
72
usb/ex1/test.c
Executable file
72
usb/ex1/test.c
Executable file
@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "pdiusbd12.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fd;
|
||||
int ret;
|
||||
unsigned char key[8];
|
||||
unsigned char led[8];
|
||||
unsigned int count, i;
|
||||
|
||||
fd = open("/dev/pdiusbd12", O_RDWR);
|
||||
if (fd == -1)
|
||||
goto fail;
|
||||
|
||||
while (1) {
|
||||
ret = ioctl(fd, PDIUSBD12_GET_KEY, key);
|
||||
if (ret == -1) {
|
||||
if (errno == ETIMEDOUT)
|
||||
continue;
|
||||
else
|
||||
goto fail;
|
||||
}
|
||||
switch (key[0]) {
|
||||
case 0x00:
|
||||
puts("KEYn released");
|
||||
break;
|
||||
case 0x01:
|
||||
puts("KEY2 pressed");
|
||||
break;
|
||||
case 0x02:
|
||||
puts("KEY3 pressed");
|
||||
break;
|
||||
case 0x04:
|
||||
puts("KEY4 pressed");
|
||||
break;
|
||||
case 0x08:
|
||||
puts("KEY5 pressed");
|
||||
break;
|
||||
case 0x10:
|
||||
puts("KEY6 pressed");
|
||||
break;
|
||||
case 0x20:
|
||||
puts("KEY7 pressed");
|
||||
break;
|
||||
case 0x40:
|
||||
puts("KEY8 pressed");
|
||||
break;
|
||||
case 0x80:
|
||||
puts("KEY9 pressed");
|
||||
break;
|
||||
}
|
||||
|
||||
if (key[0] != 0) {
|
||||
led[0] = key[0];
|
||||
ret = ioctl(fd, PDIUSBD12_SET_LED, key);
|
||||
if (ret == -1)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
fail:
|
||||
perror("usb test");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user