USB系列-2-DNW源码

对DNW驱动源码进行简要分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/fs.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/uaccess.h>

#define SECBULK_MAJOR 102
#define SECBULK_MINOR 0
#define DRIVER_NAME "secbulk"

#define BULKOUT_BUFFER_SIZE 512

struct secbulk_dev
{
struct usb_device *udev;
struct mutex io_mutex;
char* bulkout_buffer;
__u8 bulk_out_endpointAddr;
};

static struct usb_class_driver secbulk_class;

static struct usb_device_id secbulk_table[]= {
{ USB_DEVICE(0x04e8, 0x1234)}, //c
{ }
};

static struct usb_driver secbulk_driver;
static void secbulk_disconnect(struct usb_interface *interface)
{
struct secbulk_dev *dev = NULL;
printk(KERN_INFO "secbulk:secbulk disconnected!\n");
dev = usb_get_intfdata(interface);
if( NULL != dev )
kfree(dev);
usb_deregister_dev(interface, &secbulk_class);
return;
}

static ssize_t secbulk_read(struct file *file, char __user *buf, size_t len, loff_t *loff)
{
return -EPERM;
}

static ssize_t secbulk_write(struct file *file, const char __user *buf, size_t len, loff_t *loff)
{
size_t to_write;
struct secbulk_dev *dev = file->private_data;
int ret;
int actual_length;
size_t total_writed;

total_writed = 0;
while(len > 0)
{
to_write = min(len, BULKOUT_BUFFER_SIZE);

if(copy_from_user(dev->bulkout_buffer, buf+total_writed, to_write)) //得到用户空间数据
{
printk(KERN_ERR "secbulk:copy_from_user failed!\n");
return -EFAULT;
}

ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), //构造批量传输信息,传输给usbCore处理
dev->bulkout_buffer,
to_write,
&actual_length,
3*HZ);
if(ret || actual_length!=to_write)
{
printk(KERN_ERR "secbulk:usb_bulk_msg failed!\n");
return -EFAULT;
}
len -= to_write;
total_writed += to_write;
}
return total_writed;
}

static int secbulk_open(struct inode *node, struct file *file)
{
struct usb_interface *interface;
struct secbulk_dev *dev;

interface = usb_find_interface(&secbulk_driver, iminor(node));
if(!interface)
return -ENODEV;

dev = usb_get_intfdata(interface);
dev->bulkout_buffer = kzalloc(BULKOUT_BUFFER_SIZE, GFP_KERNEL);
if(!(dev->bulkout_buffer))
return -ENOMEM;
if(!mutex_trylock(&dev->io_mutex))
return -EBUSY;
file->private_data = dev;
return 0;
}

static int secbulk_release(struct inode *node, struct file *file)
{
struct secbulk_dev *dev;

dev = (struct secbulk_dev*)(file->private_data);
kfree(dev->bulkout_buffer);
mutex_unlock(&dev->io_mutex);
return 0;
}

static struct file_operations secbulk_fops = {
.owner = THIS_MODULE,
.read = secbulk_read,
.write = secbulk_write,
.open = secbulk_open,
.release= secbulk_release,
};

static struct usb_class_driver secbulk_class = {
.name = "secbulk%d",
.fops = &secbulk_fops,
.minor_base= 100,
};

static int secbulk_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
int ret;
struct secbulk_dev *dev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int i;

printk(KERN_INFO "secbulk:secbulk probing...\n");

dev = kzalloc(sizeof(*dev), GFP_KERNEL); //分配一个指针空间,只是为了索引内核的空间
if(!dev)
{
ret = -ENOMEM;
goto error;
}

iface_desc = interface->cur_altsetting;
for(i=0; i < iface_desc->desc.bNumEndpoints; i++) //从USBCore传入的借口中得到得到输出端点
{
endpoint = &(iface_desc->endpoint[i].desc);
if(!dev->bulk_out_endpointAddr
&& usb_endpoint_is_bulk_out(endpoint))
{
printk(KERN_INFO "secbulk:bulk out endpoint found!\n");
dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
break;
}
}

if(!(dev->bulk_out_endpointAddr))
{
ret = -EBUSY;
goto error;
}

ret = usb_register_dev(interface, &secbulk_class); //将usb驱动注册成字符设备驱动提供给用户程序
if(ret)
{
printk(KERN_ERR "secbulk: usb_register_dev failed!\n");
return ret;
}
dev->udev = usb_get_dev(interface_to_usbdev(interface));

usb_set_intfdata(interface, dev);

mutex_init(&dev->io_mutex);
return 0;
error:
if(!dev)
kfree(dev);
return ret;
}

static struct usb_driver secbulk_driver= {
.name= "secbulk",
.probe= secbulk_probe,
.disconnect= secbulk_disconnect,
.id_table= secbulk_table,
.supports_autosuspend=0,
};
static int __init secbulk_init(void)
{
int result;
printk(KERN_INFO "secbulk:secbulk loaded\n");
result = usb_register(&secbulk_driver); //1 注册 secbulk_driver, 此处我们就注册了usb_driver,当插入USB后,
//会调用add_dev,然后将ID号与驱动支持的id进行对比,如果对比通过,就会调用probe
if(result)
{ printk(KERN_ERR "secbulk:usb_register failed: %d", result);
return result;
}
return 0;
}

static void __exit secbulk_exit(void)
{
usb_deregister(&secbulk_driver);
printk(KERN_INFO "secbulk:secbulk unloaded\n");
}

module_init(secbulk_init);
module_exit(secbulk_exit);
MODULE_LICENSE("GPL");

版权声明:本文为博主原创文章,转载需声明为转载内容并添加原文地址。

原文地址:https://coderdock.com

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2017-2020 Dock
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信