s5p4418调试usb camera设备结果分析与usb驱动简要分析

第一,开发环境

硬件:三星s5p4418

linux version:3.4.39

ubuntu:14.04

usb camera:whois

第二,usb camera调试结果分析

1,将usb camera驱动打入内核,插上usb camera,系统启动后会在kmesg中有如下提示:

<6>[    1.015000] usb 1-1: New USB device found, idVendor=0547, idProduct=1002      
<6>[    1.015000] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 
<6>[    1.015000] usb 1-1: Product: U02_Sensor                                      
<6>[    1.015000] usb 1-1: Manufacturer: Whois  

<6>[    1.138000] android_usb gadget: android_usb ready                             
<4>[    1.143000] ==========usb_whois_init start========                            
<4>[    1.148000] ==========whois probe start========                               
<6>[    1.155000] whois_usbcam 1-1:1.0: whois USB camera now attached to whoiscam0==
<6>[    1.165000] usbcore: registered new interface driver whois_usbcam             
<4>[    1.172000] ==========usb_whois_init end========   

表示内核启动过程首先usb host初始化完毕,检测到有一个新的usb设备,并通过握手获得usb从设备的verdorID和productID号,产品类型,产品的厂商名。

随后内核启动调用驱动

static int __init usb_whois_init(void)
{
    int result;
    printk("==========usb_whois_init start========\n");
    result = usb_register(&whois_driver);
    if (result)
        printk("usb_register failed. Error number %d", result);
    printk("==========usb_whois_init end========\n");
    return result;
}

module_init(usb_whois_init);

初始化驱动的过程就是注册USB驱动的过程,它会把驱动里的支持的厂商设备ID加到内核中,供内核使用。内核如果找到对应的设备,则加载相应的驱动。

这一点和设备-总线-驱动的设备模型有点不一样,不是通过设备名和驱动名称配对,probe的。

从上面kmsg的信息可以判断usb设备和驱动因为verdorID和productID号的一致,被内核匹配,并调用驱动的probe,进行探测,生成相应的设备节点。

此时在/dev下面可以看到节点;
whoiscam0

如果拔掉usb camera节点会消失。

usb 1-1: USB disconnect, device number 2                          
<6>[   14.370000] whois_usbcam 1-1:1.0: USB whoiscam0 now disconnected

如果再次插入usb camera可以看到:

usb 1-1: New USB device found, idVendor=0547, idProduct=1002      
<6>[   25.064000] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 
<6>[   25.071000] usb 1-1: Product: U02_Sensor                                      
<6>[   25.075000] usb 1-1: Manufacturer: Whois                                      
<4>[   25.081000] ==========whois probe start========                               
<6>[   25.088000] whois_usbcam 1-1:1.0: whois USB camera now attached to whoiscam0==
驱动的probe再次被调用。
此时在/dev下面可以看到设备的节点;
whoiscam0

为了能够让大家更清晰的看到usb驱动,我从内核里拷贝一个简单的usbled的驱动附在下面:

/*
 * USB LED driver
 */

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>

enum led_type {
	DELCOM_VISUAL_SIGNAL_INDICATOR,
	DREAM_CHEEKY_WEBMAIL_NOTIFIER,
};

<span style="color:#FF0000;">/* table of devices that work with this driver */
static const struct usb_device_id id_table[] = {
	{ USB_DEVICE(0x0fc5, 0x1223),
			.driver_info = DELCOM_VISUAL_SIGNAL_INDICATOR },
	{ USB_DEVICE(0x1d34, 0x0004),
			.driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },
	{ USB_DEVICE(0x1d34, 0x000a),
			.driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },
	{ },
};
MODULE_DEVICE_TABLE(usb, id_table);</span>

struct usb_led {
	struct usb_device	*udev;
	unsigned char		blue;
	unsigned char		red;
	unsigned char		green;
	enum led_type		type;
};


<span style="color:#FF0000;">static int led_probe(struct usb_interface *interface,
		     const struct usb_device_id *id)</span>
{
	struct usb_device *udev = interface_to_usbdev(interface);
	struct usb_led *dev = NULL;
	int retval = -ENOMEM;

	dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL);
	if (dev == NULL) {
		dev_err(&interface->dev, "out of memory\n");
		goto error_mem;
	}

	dev->udev = usb_get_dev(udev);
	dev->type = id->driver_info;

	usb_set_intfdata(interface, dev);

	retval = device_create_file(&interface->dev, &dev_attr_blue);
	if (retval)
		goto error;
	retval = device_create_file(&interface->dev, &dev_attr_red);
	if (retval)
		goto error;
	retval = device_create_file(&interface->dev, &dev_attr_green);
	if (retval)
		goto error;

	if (dev->type == DREAM_CHEEKY_WEBMAIL_NOTIFIER) {
		unsigned char *enable;

		enable = kmemdup("\x1f\x02\0\x5f\0\0\x1a\x03", 8, GFP_KERNEL);
		if (!enable) {
			dev_err(&interface->dev, "out of memory\n");
			retval = -ENOMEM;
			goto error;
		}

		retval = usb_control_msg(udev,
					usb_sndctrlpipe(udev, 0),
					0x09,
					0x21,
					0x200,
					0,
					enable,
					8,
					2000);

		kfree(enable);
		if (retval != 8)
			goto error;
	}

	dev_info(&interface->dev, "USB LED device now attached\n");
	return 0;

error:
	device_remove_file(&interface->dev, &dev_attr_blue);
	device_remove_file(&interface->dev, &dev_attr_red);
	device_remove_file(&interface->dev, &dev_attr_green);
	usb_set_intfdata(interface, NULL);
	usb_put_dev(dev->udev);
	kfree(dev);
error_mem:
	return retval;
}

static void led_disconnect(struct usb_interface *interface)
{
	struct usb_led *dev;

	dev = usb_get_intfdata(interface);

	device_remove_file(&interface->dev, &dev_attr_blue);
	device_remove_file(&interface->dev, &dev_attr_red);
	device_remove_file(&interface->dev, &dev_attr_green);

	/* first remove the files, then set the pointer to NULL */
	usb_set_intfdata(interface, NULL);

	usb_put_dev(dev->udev);

	kfree(dev);

	dev_info(&interface->dev, "USB LED now disconnected\n");
}

static struct usb_driver led_driver = {
	.name =		"usbled",
	<span style="color:#FF0000;"><strong>.probe =	led_probe,</strong></span>
	.disconnect =	led_disconnect,
	<span style="color:#FF0000;"><strong>.id_table =	id_table,</strong></span>
};

module_usb_driver(led_driver);

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

第三,linux下usb驱动简单分析

1,在USB设备组织结构中,从上到下分为设备(device)、配置(config)、接口(interface)和端点(endpoint)四个层次。USB设备程序绑定到接口上。
对于这四个层次的简单描述如下:
      设备通常具有一个或多个的配置
      配置经常具有一个或多个的接口
      接口没有或具有一个以上的端点

1) USB设备:对应数据结构struct usb_device

2) 配置:struct usb_host_config (任一时刻,只能有一个配置生效)

3)USB接口:struct usb_interface (USB 核心将其传递给USB设备驱动,并由USB设备驱动负责后续的控制。一个USB接口代表一个基本功能,每个USB驱动控制一个接口。所以一个物理上的硬件设备可能需要 一个以上的驱动程序。)

4)端点: struct usb_host_endpoint ,它所包含的真实端点信息在另一个结构中:struct usb_endpoint_descriptor(端点描述符,包含所有的USB特定数据)。

2,USB设备的probe和断开

当有USB设备插入时,usb host会获取设备的verdorID和productID号,对比加载到内核的usb设备驱动所支持的verdorID和productID号然后找到相应的驱动,并进行probe操作(创立节点等)。如果usb设备被拔出,则执行相应的断开操作:如

.disconnect =	led_disconnect,
参考:http://blog.csdn.net/myarrow/article/details/7013198

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值