USB1.1 Device Learning in Linux (6) _hid and input Subsystem (3)
http://cupidove.blog.163.com/blog/static/100566220119206136357/
Now go back to Input_attach_handler.
Error = Handler->connect (handler, dev, id);
Now you know what Handler->connect is, that's mousedev_connect.
Mousedev_connect in the/drivers/input/mousedev.c.
static int mousedev_connect (struct Input_handler *handler, struct Input_dev *dev, const struct INPUT_DEVICE_ID *id) { struct Mousedev *mousedev; int minor; int error; The mousedev_table array, looking for an empty position for (minor = 0; minor < mousedev_minors; minor++) if (!mousedev_table[minor]) Break Detect if the array is full if (minor = = mousedev_minors) { PRINTK (kern_err "mousedev:no more free Mousedev devices\n"); Return-enfile; } Create a mouse device Mousedev = mousedev_create (Dev, handler, minor); if (Is_err (Mousedev)) Return Ptr_err (Mousedev); Add to Mice device queue Error = Mixdev_add_device (Mousedev); if (Error) { Mousedev_destroy (Mousedev); return error; } return 0; } |
Since mice uses 31, the minor of our mouse device here is 32.
Now we can finally get into the input_register_handle in Mousedev_create.
Input_register_handle in the/drivers/input/input.c.
int Input_register_handle (struct input_handle *handle) { struct Input_handler *handler = handle->handler; struct Input_dev *dev = handle->dev; int error; /* * We take Dev->mutex prevent race with * Input_release_device (). */ Error = mutex_lock_interruptible (&dev->mutex); if (Error) return error; Connecting connectors to Devices List_add_tail_rcu (&handle->d_node, &dev->h_list); Mutex_unlock (&dev->mutex); Synchronize_rcu (); /* * Since We are supposed to is called from->connect () * which is mutually exclusive with->disconnect () * We can ' t be racing with Input_unregister_handle () * And so separate lock isn't needed here. */ Connection connectors and processing modules List_add_tail (&handle->h_node, &handler->h_list); Detect if the processing module has a start operation if (Handler->start) Handler->start (handle); return 0; } |
Registered mouse device data structure as follows back to Mousedev_connect, now to Mixdev_add_device
Mixdev_add_device in the/drivers/input/mousedev.c.
static int Mixdev_add_device (struct Mousedev *mousedev) { int retval; retval = mutex_lock_interruptible (&mousedev_mix->mutex); if (retval) return retval; Detect if a mouse device is available if (Mousedev_mix->open) { retval = Mousedev_open_device (Mousedev); if (retval) Goto out; Mousedev->mixdev_open = 1; } Get_device (&mousedev->dev); Add to Mice device queue List_add_tail (&mousedev->mixdev_node, &mousedev_mix_list); Out Mutex_unlock (&mousedev_mix->mutex); return retval; } |
Because there is no mouse device, so it will not go into the Mousedev_open_device
Here is the registration of the input subsystem is finished, combined with the data structure hid, the following figure
Back in the Hid_probe, the rest of the Hiddev and Hidraw have nothing to do with the mouse, so I don't analyze it.
To go back to Hub_port_connect_change, there is only one hub_power_remaining function, which is a function of current distribution, not enough understanding of current
Jump back into the hub_events
One last deal
if (!hdev->parent &&!hub->busy_bits[0])
USB_ENABLE_ROOT_HUB_IRQ (Hdev->bus);
Because this operation is not hub_irq_enable in UHCI, this function is not useful for UHCI.
Such a USB mouse from beginning to end of the registered achievement analysis okay
Finally, let's look at how the USB mouse data is obtained in Linux.
In Linux, the use of a device need to open first, when we opened the mouse character file came to the Input_open_file, as for the input subsystem principle, there is time I will write a detailed article to resolve
Input_open_file in the/drivers/input/input.c.
static int input_open_file (struct inode *inode, struct file *file) { calculates which processing module the secondary device number of this device belongs to struct Input_handler *handler = Input_table[iminor (inode) >> 5]; const struct File_operations *old_fops, *new_fops = NULL; int err; /* No Load-on-demand here? */ Detect if the processing module exists Detects if the set of operations for this processing module exists if (!handler | |!) ( New_fops = Fops_get (handler->fops))) Return-enodev; /* * that ' s _really_ odd. Usually NULL->open means "nothing special", * not "no device". Oh, so ... */ Detects whether the open operation of a new set of operations exists if (!new_fops->open) { Fops_put (New_fops); Return-enodev; } Replace the set of operations to replace the operation set of input with the processing module Old_fops = file->f_op; File->f_op = New_fops; To run the open operation in a new operation set Err = New_fops->open (inode, file); if (err) { Fops_put (FILE->F_OP); File->f_op = Fops_get (old_fops); } Fops_put (Old_fops); return err; } |
So the cat for the prince into the mouse processing module open
The Mousedev_open function is this open operation
Mousedev_open in the/drivers/input/mousedev.c.
Static int mousedev_open_device (Struct mousedev *mousedev) { br> int retval; retval = mutex_lock_interruptible (&mousedev->mutex); if (retval) return retval //detect if Mice device if (mousedev->minor == Mousedev_mix |