linux下控制usb设备,LINUX下USB1.1设备学习小记(4)_uhci(4)

启动主机控制器和根集线器之后,现在来注册根集线器

register_root_hub负责根集线器的注册

register_root_hub在/drivers/usb/core/hcd.c中

static int register_root_hub(struct usb_hcd *hcd)

{

struct device *parent_dev = hcd->self.controller;

struct usb_device *usb_dev = hcd->self.root_hub;

const int devnum = 1;

int retval;

//设置设备的设备号为1

usb_dev->devnum = devnum;

//uhci总线的设备计数器+1

usb_dev->bus->devnum_next = devnum + 1;

//初始化设备位表

memset (&usb_dev->bus->devmap.devicemap, 0,sizeof usb_dev->bus->devmap.devicemap);

//占用设备表的第1位

set_bit (devnum, usb_dev->bus->devmap.devicemap);

//设置设备状态为USB_STATE_ADDRESS

usb_set_device_state(usb_dev, USB_STATE_ADDRESS);

mutex_lock(&usb_bus_list_lock);

//设置端点0包的最大值

usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);

//取得设备描述符

retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);

//检测返回的描述符大小和设备描述符的大小是否一致

if (retval != sizeof usb_dev->descriptor)

{

mutex_unlock(&usb_bus_list_lock);

dev_dbg (parent_dev, "can't read %s device descriptor %d\n",

usb_dev->dev.bus_id, retval);

return (retval < 0) ? retval : -EMSGSIZE;

}

//建立设备

retval = usb_new_device (usb_dev);

if (retval)

{

dev_err (parent_dev, "can't register root hub for %s, %d\n",usb_dev->dev.bus_id, retval);

}

mutex_unlock(&usb_bus_list_lock);

if (retval == 0)

{

spin_lock_irq (&hcd_root_hub_lock);

//设置注册标识为1

hcd->rh_registered = 1;

spin_unlock_irq (&hcd_root_hub_lock);

/* Did the HC die before the root hub was registered? */

if (hcd->state == HC_STATE_HALT)

usb_hc_died (hcd); /* This time clean up */

}

return retval;

}

usb_get_device_descriptor负责取得设备的设备描述符,设备描述符的结构如下

struct usb_device_descriptor {

__u8  bLength;    //描述符的长度

__u8  bDescriptorType;  //描述符的类型

__le16 bcdUSB;    //表示usb设备所遵循的usb规范

__u8  bDeviceClass;   //表示usb设备所属的标准设备类

__u8  bDeviceSubClass;  //表示usb设备所属的标准设备子类

__u8  bDeviceProtocol;  //表示usb设备所使用的设备类协议

__u8  bMaxPacketSize0;  //表示0号端点包的最大大小

__le16 idVendor;    //表示usb设备的生厂商id

__le16 idProduct;    //表示usb设备的产品id

__le16 bcdDevice;    //表示usb设备的版本号

__u8  iManufacturer;   //表示生产商字符串描述符的索引值

__u8  iProduct;    //表示产品字符串描述符的索引值

__u8  iSerialNumber;   //表示设备序列号字符串描述符的索引值

__u8  bNumConfigurations; //表示usb设备的配置数

} __attribute__ ((packed));

usb_get_device_descriptor在/drivers/usb/core/messgae.c中

int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)

{

struct usb_device_descriptor *desc;

int ret;

if (size > sizeof(*desc))

return -EINVAL;

//分配设备描述符所需要的空间

desc = kmalloc(sizeof(*desc), GFP_NOIO);

if (!desc)

return -ENOMEM;

//取得描述符,类型为设备

ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);

if (ret >= 0)

//拷贝设备描述符到usb_device中

memcpy(&dev->descriptor, desc, size);

kfree(desc);

return ret;

}

usb_get_descripto的用途为取得描述符

usb_get_descriptor在/drivers/usb/core/messgae.c中

int usb_get_descriptor(struct usb_device *dev, unsigned char type,

unsigned char index, void *buf, int size)

{

int i;

int result;

//buf清0

memset(buf, 0, size); /* Make sure we parse really received data */

//重试3次

for (i = 0; i < 3; ++i)

{

/* retry on length 0 or error; some devices are flakey */

//发送控制消息

result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),

USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,

(type << 8) + index, 0, buf, size,

USB_CTRL_GET_TIMEOUT);

if (result <= 0 && result != -ETIMEDOUT)

continue;

if (result > 1 && ((u8 *)buf)[1] != type)

{

result = -EPROTO;

continue;

}

break;

}

return result;

}

usb_control_msg的用途为发送控制消息

usb_control_msg在/drivers/usb/core/messgae.c中

int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,

__u8 requesttype, __u16 value, __u16 index, void *data,

__u16 size, int timeout)

{

struct usb_ctrlrequest *dr;

int ret;

//为控制请求结构分配空间

dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);

if (!dr)

return -ENOMEM;

//组建8字节的控制请求字段

dr->bRequestType = requesttype;

dr->bRequest = request;

dr->wValue = cpu_to_le16p(&value);

dr->wIndex = cpu_to_le16p(&index);

dr->wLength = cpu_to_le16p(&size);

/* dbg("usb_control_msg"); */

//发送控制消息

ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);

kfree(dr);

return ret;

}

这8字节的数据眼熟么?~  还记得在前面提到的setup事务中的数据包的内容么? 正是这8字节的数据,眼泪啊,到了这里,终于接触到传输了

usb_internal_control_msg的用途为组建一个urb结构并发送他,urb这个结构在usb设备插入前都不会讲解,因为在host自己对自己的访问中,urb只起到了一个花瓶的作用,走走过场,并没有真正发送出去

usb_internal_control_msg在/drivers/usb/core/messgae.c中

static int usb_internal_control_msg(struct usb_device *usb_dev,

unsigned int pipe,

struct usb_ctrlrequest *cmd,

void *data, int len, int timeout)

{

struct urb *urb;

int retv;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值