usb_serial部分分析3
来源:互联网 发布:zara淘宝没有了 编辑:程序博客网 时间:2024/06/04 00:45
转自http://blog.csdn.net/aaronychen/article/details/3555885
generic.c:
static int generic_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
const struct usb_device_id *id_pattern;
id_pattern = usb_match_id(interface, generic_device_ids); //设备匹配
if (id_pattern != NULL)
return usb_serial_probe(interface, id); //进一步匹配
return -ENODEV;
}
如果接入系统的设备的vendor和product与我们驱动支持的设备列表匹配则调用usb_serial_probe来进一步匹配.
usb_serial_probe函数比较长, 我们一段段的来看
usb-serial.c:
int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev (interface);
struct usb_serial *serial = NULL;
struct usb_serial_port *port;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
struct usb_serial_driver *type = NULL;
int retval;
int minor;
int buffer_size;
int i;
int num_interrupt_in = 0;
int num_interrupt_out = 0;
int num_bulk_in = 0;
int num_bulk_out = 0;
int num_ports = 0;
int max_endpoints;
type = search_serial_device(interface); //获取该设备匹配的驱动
if (!type) {
dbg("none matched");
return -ENODEV;
}
......
}
首先是找到合适的驱动程序.
usb-serial.c:
static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
{
struct list_head *p;
const struct usb_device_id *id;
struct usb_serial_driver *t;
/* Check if the usb id matches a known device */
list_for_each(p, &usb_serial_driver_list) {
t = list_entry(p, struct usb_serial_driver, driver_list);
id = usb_match_id(iface, t->id_table); //看设备列表是否匹配
if (id != NULL) {
dbg("descriptor matches");
return t; //返回匹配的驱动
}
}
return NULL;
}
实际上这边的匹配和generic_probe里的匹配重复了, 因为他们的匹配的设备列表是同一个, 这边主要是为了得到匹配的驱动程序, 根据上面的代码分析我们可以知道这里匹配的驱动是usb_serial_generic_device.
接着看usb_serial_probe()
usb-serial.c:
....
serial = create_serial (dev, interface, type); //为该设备创建一个usb_serial对象
if (!serial) {
dev_err(&interface->dev, "%s - out of memory/n", __FUNCTION__);
return -ENOMEM;
}
/* if this device type has a probe function, call it */
if (type->probe) { //从上面分析的代码可知这里的probe函数没有赋值
const struct usb_device_id *id;
if (!try_module_get(type->driver.owner)) {
dev_err(&interface->dev, "module get failed, exiting/n");
kfree (serial);
return -EIO;
}
id = usb_match_id(interface, type->id_table);
retval = type->probe(serial, id);
module_put(type->driver.owner);
if (retval) {
dbg ("sub driver rejected device");
kfree (serial);
return retval;
}
}
....
这段代码可知, 主要是创建一个usb_serial的对象, 用于保存该设备的详细信息, 一般的驱动程序都会为自己匹配的设备创建一个描用于描述该设备的对象. 在以后的所有操作中如读写等都会直接从这个对象里获取相应的信息.
usb-serial.c:
static struct usb_serial * create_serial (struct usb_device *dev,
struct usb_interface *interface,
struct usb_serial_driver *driver)
{
struct usb_serial *serial;
serial = kmalloc (sizeof (*serial), GFP_KERNEL); //创造该对象
if (!serial) {
dev_err(&dev->dev, "%s - out of memory/n", __FUNCTION__);
return NULL;
}
//初始化该对象
memset (serial, 0, sizeof(*serial));
serial->dev = usb_get_dev(dev); //增加dev的引用计数
serial->type = driver;
serial->interface = interface;
kref_init(&serial->kref);
return serial;
}
这个函数就是用来创建usb_serial对象的,并把相关信息保存在里面.
继续看usb_serial_probe()
usb-serial.c:
....
/* descriptor matches, let's find the endpoints needed */
/* check out the endpoints */
//查找该设备使用的endpoint的描述符, 并检查是否正确
iface_desc = interface->cur_altsetting; //接口描述符
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint =& iface_desc->endpoint[i].desc; //端点描述符
if ((endpoint->bEndpointAddress& 0x80) &&
((endpoint->bmAttributes & 3) == 0x02)) {
/* we found a bulk in endpoint */ //bulk in 的端点
dbg("found bulk in on endpoint %d", i);
bulk_in_endpoint[num_bulk_in] = endpoint;
++num_bulk_in;
}
if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
((endpoint->bmAttributes & 3) == 0x02)) {
/* we found a bulk out endpoint */ //bulk out的端点
dbg("found bulk out on endpoint %d", i);
bulk_out_endpoint[num_bulk_out] = endpoint;
++num_bulk_out;
}
if ((endpoint->bEndpointAddress& 0x80) &&
((endpoint->bmAttributes & 3) == 0x03)) {
/* we found a interrupt in endpoint */ //中断 in 端点
dbg("found interrupt in on endpoint %d", i);
interrupt_in_endpoint[num_interrupt_in] = endpoint;
++num_interrupt_in;
}
if (((endpoint->bEndpointAddress& 0x80) == 0x00) &&
((endpoint->bmAttributes & 3) == 0x03)) {
/* we found an interrupt out endpoint */ //中断 out 端点
dbg("found interrupt out on endpoint %d", i);
interrupt_out_endpoint[num_interrupt_out] = endpoint;
++num_interrupt_out;
}
}
.....
该段代码主要是获取该设备使用的各个类型及方向的端点描述府, 并保存起来, 关于端点的类型与方向可以参考USB的规范.
继续看usb_serial_probe()
usb-serial.c:
....
#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
/* BEGIN HORRIBLE HACK FOR PL2303 */
/* this is needed due to the looney way its endpoints are set up */
if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
(le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
(le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID))) {
if (interface != dev->actconfig->interface[0]) {
/* check out the endpoints of the other interface*/
iface_desc = dev->actconfig->interface[0]->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if ((endpoint->bEndpointAddress & 0x80) &&
((endpoint->bmAttributes & 3) == 0x03)) {
/* we found a interrupt in endpoint */
dbg("found interrupt in for Prolific device on separate interface");
interrupt_in_endpoint[num_interrupt_in] = endpoint;
++num_interrupt_in;
}
}
}
/* Now make sure the PL-2303 is configured correctly.
* If not, give up now and hope this hack will work
* properly during a later invocation of usb_serial_probe
*/
if (num_bulk_in == 0 || num_bulk_out == 0) {
dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not/n");
kfree (serial);
return -ENODEV;
}
}
/* END HORRIBLE HACK FOR PL2303 */
#endif
上面这段代码主要是用于特定类型设备的(PL2303), 这里我们不用管他.
- usb_serial部分分析3
- usb_serial部分分析2
- usb_serial部分分析4
- usb_serial部分分析5
- usb_serial之repllog.exe不能自启动
- [HGE]-源码分析-3 Core部分
- cocos2dx 音频模块分析(3): 背景音乐部分
- icesword 驱动部分分析
- Icesword驱动部分分析
- Icesword 驱动部分分析
- icesword 驱动部分分析
- 第三部分 需求分析
- lighting sensor 部分分析
- 吃豆人部分代码分析
- listview 部分代码分析
- apache网络部分分析
- spring部分源码分析
- freediameter部分源码分析
- intellij IDEA创建nodejs项目---环境搭建
- Myeclipse2014的下载及破解教程
- Java求最大公约数和最小公倍数
- idea使用maven创建WebApp项目+项目搭建
- Fire Net
- usb_serial部分分析3
- iptables基础知识二
- sklearn官方文档学习笔记 管道和特征联合(Pipeline and FeatureUnion):组合估计器
- JVM系列四(大名鼎鼎的GC)
- nodejs,vscode的安装
- C++ vector 根据元素值删除
- Object类
- HTTP Content-type 对照表
- spring cloud 简单介绍