转自http://blog.csdn.net/aaronychen/article/details/3555885
我们先来了解下probe的过程
Driver的probe的调用顺序:
1 device_add(): 把device注册到相应的bus上去,并创建相应的device file,最后调用bus_attach_device()
2 bus_attach_device()调用device_attach(dev)
3 device_attach(): 调用bus_for_each_drv()遍历bus上的每个driver,当找到一个driver则用__device_attach()来判断是否匹配
4 __device_attach(): 直接调用driver_probe_device(drv, dev)
5 driver_probe_device(): 首先如果driver所在总线有match函数则先调用这个match来匹配,如不匹配则直接返回错误,否则接着调用really_probe(dev,drv)
6 really_probe(): 先判断dev所在总线是否有probe函数,有则调用它来匹配,失败则返回,正确则成功,如果总线没有probe则判断drv是否有probe函数,有则调用并匹配它.
7 drv->prob(): 一般它是一类设备的probe,在它里面它会调用具体某个drv的probe函数,这个函数是在我们的驱动程序里面注册的.
device_register()里会调用device_add(). 因此由 5 可知 系统会先调用总线上的match函数来匹配. 对于我们的总线就是usb_serial_bus, 它的match函数就是usb_serial_device_match(), 至于为什么是这条总线, 通过前面的代码分析, 我们知道我们的设备也好, 我们的驱动也好都是注册在这条总线上的.
下面我们就来分析usb_serial_device_match()
Bus.c:
static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
{
struct usb_serial_driver *driver;
const struct usb_serial_port *port;
/*
* drivers are already assigned to ports in serial_probe so it's
* a simple check here.
*/
port = to_usb_serial_port(dev); //获取usb_serial_port对象
if (!port)
return 0;
driver = to_usb_serial_driver(drv); //获取usb_serial_driver对象
if (driver == port->serial->type) //匹配否?
return 1;
return 0;
}
很显然,通过前面的分析可知, 这里肯定是匹配的.
接着通过上
面probe过程的6可知会调用总线的probe函数,这里就是usb_serial_device_probe
Bus.c:
static int usb_serial_device_probe (struct device *dev)
{
struct usb_serial_driver *driver;
struct usb_serial_port *port;
int retval = 0;
int minor;
port = to_usb_serial_port(dev);
if (!port) {
retval = -ENODEV;
goto exit;
}
driver = port->serial->type;
if (driver->port_probe) {
if (!try_module_get(driver->driver.owner)) {
dev_err(dev, "module get failed, exiting/n");
retval = -EIO;
goto exit;
}
retval = driver->port_probe (port);
module_put(driver->driver.owner);
if (retval)
goto exit;
}
minor = port->number;
tty_register_device (usb_serial_tty_driver, minor, dev); //呵呵, 这里总算把tty_driver和device绑定
//起来了
dev_info(&port->serial->dev->dev,
"%s converter now attached to ttyUSB%d/n",
driver->description, minor);
exit:
return retval;
}
到了这一步该设备就和tty_driver绑定在了一起了, 同时在/dev下也创建了相应的设备文件了, 也就是说应用层可以使用这个设备了.
这样整个对设备的probe过程才算真的完成了.
OK, 设备从USB口连上系统, 并被系统认出及probe的真个过程就基本完成了, 从此以后设备就进入了就绪状态. 下面我们就开始分析对设备的操作流程了.
要使用设备当然要先打开这个设备了, 应用层调用open系统调用来打开这个设备, 它最终会跑到我们tty_driver的open函数里面
static struct tty_operations serial_ops = {
.open = serial_open,
.close = serial_close,
.write = serial_write,
.write_room = serial_write_room,
.ioctl = serial_ioctl,
.set_termios = serial_set_termios,
.throttle = serial_throttle,
.unthrottle = serial_unthrottle,
.break_ctl = serial_break,
.chars_in_buffer = serial_chars_in_buffer,
.read_proc = serial_read_proc,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
};
这里就是serial_open了.
usb_serial.c:
static int serial_open (struct tty_struct *tty, struct file * filp)
{
struct usb_serial *serial;
struct usb_serial_port *port;
unsigned int portNumber;
int retval;
dbg("%s", __FUNCTION__);
/* get the serial object associated with this tty pointer */
serial = usb_serial_get_by_index(tty->index); //获取usb_serial对象, 根据上面的分析,不难理解
if (!serial) {
tty->driver_data = NULL;
return -ENODEV;
}
portNumber = tty->index - serial->minor;
port = serial->port[portNumber]; //获取设备对应的port对象, 这也不难理解了
if (!port)
return -ENODEV;
if (down_interruptible(&port->sem))
return -ERESTARTSYS;
++port->open_count; //跟踪打开次数
if (port->open_count == 1) {
/* set up our port structure making the tty driver
* remember our port object, and us it */
tty->driver_data = port; //赋值, 为以后的操作方便引用
port->tty = tty;
/* lock this module before we call it
* this may fail, which means we must bail out,
* safe because we are called with BKL held */
if (!try_module_get(serial->type->driver.owner)) {
retval = -ENODEV;
goto bailout_kref_put;
}
/* only call the device specific open if this
* is the first time the port is opened */
retval = serial->type->open(port, filp); //调用usb_serial_driver的open函数, 在前面分析过了
if (retval)
goto bailout_module_put;
}
up(&port->sem);
return 0;
bailout_module_put:
module_put(serial->type->driver.owner);
bailout_kref_put:
kref_put(&serial->kref, destroy_serial);
port->open_count = 0;
up(&port->sem);
return retval;
}
可以看到这个open动作主要就是保存一些信息,以方便后面使用, 接着调用usb_serial_driver的open函数, 这里该open是usb_serial_generic_open, 前面分析过了
generic.c:
int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
int result = 0;
dbg("%s - port %d", __FUNCTION__, port->number);
/* force low_latency on so that our tty_push actually forces the data through,
otherwise it is scheduled, and with high data rates (like with OHCI) data
can get lost. */
if (port->tty)
port->tty->low_latency = 1;
/* if we have a bulk interrupt, start reading from it */
//如果有bulk in的端点的话, 就提交这个端点的urb, 即让系统开始在这个端点上接收来自设备段
//发过来的数据, 当数据收到后会调用serial->type->read_bulk_callback函数.
if (serial->num_bulk_in) {
/* Start reading from the device */
usb_fill_bulk_urb (port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
((serial->type->read_bulk_callback) ?
serial->type->read_bulk_callback :
usb_serial_generic_read_bulk_callback),
port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL); //提交
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d/n", __FUNCTION__, result);
}
return result;
}
这个函数后, 系统就开始在bulk in的端点上接收数据了, 如果有数据到来的话就会调用我们的回调函数.
接下来我们来看这个回调函数:
Generic.c:
void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = port->serial;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
if (urb->status) { //这次通信的状态
dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
return;
}
usb_serial_debug_data(debug,& port->dev, __FUNCTION__, urb->actual_length, data);
tty = port->tty;
if (tty && urb->actual_length) {
//如果有数据接收到的话, 就把它存入tty驱动的缓冲中去
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
/* Continue trying to always read */
//继续下一个接收操作.
usb_fill_bulk_urb (port->read_urb, serial->dev,
usb_rcvbulkpipe (serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
((serial->type->read_bulk_callback) ?
serial->type->read_bulk_callback :
usb_serial_generic_read_bulk_callback), port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d/n", __FUNCTION__, result);
}
很明显, 这个回调就是把从设备端收到的数据push到相对上层的tty驱动中去, 随后tty子系统会把这些数据返回给用户.
OK, 看完接收过程后我们在来看下发送过程.
发送过程由用户发起, 用户可以调用write系统调用来发数据, 最后会跑到tty驱动的write函数中去.
Usb-serial.c:
static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
{
struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
if (!port)
goto exit;
dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
if (!port->open_count) {
dbg("%s - port not opened", __FUNCTION__);
goto exit;
}
/* pass on to the driver specific version of this function */
retval = port->serial->type->write(port, buf, count); //仅仅是调用usb_serial_driver的write函数
exit:
return retval;
}
这个函数,直接调用了usb_serial_driver的write函数.
Generic.c:
int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
int result;
unsigned char *data;
dbg("%s - port %d", __FUNCTION__, port->number);
if (count == 0) {
dbg("%s - write request of 0 bytes", __FUNCTION__);
return (0);
}
/* only do something if we have a bulk out endpoint */
//仅在有bulk out的端点上才能发送
if (serial->num_bulk_out) {
spin_lock(&port->lock);
if (port->write_urb_busy) {
spin_unlock(&port->lock);
dbg("%s - already writing", __FUNCTION__);
return 0;
}
port->write_urb_busy = 1;
spin_unlock(&port->lock);
//把要发送的数据, 发送的字节数存入urb中
count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
memcpy (port->write_urb->transfer_buffer, buf, count);
data = port->write_urb->transfer_buffer;
usb_serial_debug_data(debug,& port->dev, __FUNCTION__, count, data);
/* set up our urb */
usb_fill_bulk_urb (port->write_urb, serial->dev,
usb_sndbulkpipe (serial->dev,
port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count,
((serial->type->write_bulk_callback) ?
serial->type->write_bulk_callback :
usb_serial_generic_write_bulk_callback), port);
/* send the data out the bulk port */
port->write_urb_busy = 1;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC); //提交一个发送过程
if (result) {
dev_err(&port->dev, "%s - failed submitting write urb, error %d/n", __FUNCTION__, result);
/* don't have to grab the lock here, as we will retry if != 0 */
port->write_urb_busy = 0;
} else
result = count;
return result;
}
/* no bulk out, so return 0 bytes written */
return 0;
}
该函数把用户要发送的数据封装到一个urb中去, 并把该urb提交给系统以执行一个发送的操作, 发送完成后会调用serial->type->write_bulk_callback函数.
接着看这个回调函数:
Generic.c:
void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
dbg("%s - port %d", __FUNCTION__, port->number);
port->write_urb_busy = 0;
if (urb->status) {
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
return;
}
usb_serial_port_softint((void *)port); //请求传输更多的数据
schedule_work(&port->work); //调度一个工作
}
Usb-serial.c:
void usb_serial_port_softint(void *private)
{
struct usb_serial_port *port = private;
struct tty_struct *tty;
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port)
return;
tty = port->tty;
if (!tty)
return;
tty_wakeup(tty); //请求传输更多的数据
}
其实很简单,
其他的函数就不多做分析了,
看懂了这个模块后, 实际上对USB设备的驱动也就大体知道了其流程.