Linux Kernel Programming by Examples(1)[Xeroo]

源代码在线查看: the input subsystem2.htm

软件大小: 61131 K
上传用户: wyly
关键词: Programming Examples Kernel Linux
下载地址: 免注册下载 普通下载 VIP

相关代码

				
				
				The Input Subsystem
								href="The Input Subsystem2_file/style.css" rel=stylesheet>
				
				
				The Input Subsystem
				References:B. Hards, "The Linux USB Input Subsystem, Part I", Linux 
				Journal 106, Feb. 2003, 20-25 B. Hards, "Using the Input Subsystem, Part 
				II", Linux Journal 107, Mar. 2003, 22-30 The source code in the 
				drivers/input subdirectory The include file 
				include/linux/input.h 				clear=all>
				The Input subsystem is an abstraction layer between input devices 
				(keyboard, mouse, joystick, and so on) and input handlers. The input devices 
				capture inputs from the user actions or from other sources and produce input 
				events. For instance a key press results in an input event. The input events go 
				through the Input core and are dispatched to the interested handlers. The Input 
				core provides a many-to-many mapping between input devices and event handlers. 
				
				An input event is a data structure with four field (see the file 
				include/linux/input.h), 
				
				  struct timeval time of the event; 
				  unsigned short type, the type of the event; 
				  unsigned short code, the code of the event (a sort of 
				  subtype); 
				  unsigned int value, a value number assigend to the event. 
				  There are hundreds of events. They are grouped in few event types. 
				For example "keys" events (EV_KEY), relative motion events (EV_REL), led events 
				(EV_LED). "Keys" event are really many. Relative axes and led events are just a 
				few. 
				There are three important data structures: 
				
				  input_dev, which represents an input device; 
				  input_handler, which represents an input handler; 
				  input_handle, which represents a connection between an input 
				  device and an input handler. 
				The input_dev contains several fields. In particular 
				
				  private, a pointer to private data; 
				  name, a string identifying the device; 
				  idbus, bus identifier; 
				  idvendor, idproduct, and idversion 
				  (in 2.5 these, together with idbus, are packed in an 
				  id structure); 
				  several bitmasks: evbit, keybit, etc.; 
				  a timer; 
				  several method pointers: open, close, 
				  event, upload_effect and erase_effect; 
				  handle, a pointer to an input_handle; 
				  next, a pointer to the next input_dev since the input devices 
				  are linked in a list. 
				The input_handler data structure contains 
				
				  the pointer to the private data; 
				  method pointers: event, connect and 
				  disconnect, as well as a pointer to file_operations; 
				  handle, a pointer to an input_handle; 
				  next, for the linked list of input_handler's. 
				
				Finally the input_handle contains 
				
				  the pointer to the private data; 
				  an integer open; 
				  dev, a pointer to an input_dev; 
				  handler, a pointer to an input_handler; 
				  two pointers, dnext and hnext, for the linked 
				  lists of input_handle's attached to a input_dev, and to a input_handler, 
				  respectively. 
				Input devices, input handlers and input handles are connected in a sparse 
				matrix structure, in which the input handles are the nodes of the matrix. The 
				devices are the entries to the columns of the matrix, and the handlers are the 
				entries to the rows. See the figure below. 
								align=center> 
				The Input Core 
				
				
				  input_event( dev, type, code, value ) reports events. It 
				  returns immediately if the device has not set the bit for the 
				  type. The it switches on the event type. Each event 
				  is handled only if the corresponding bit of the proper device bitset is set. 
				  Key events ... For absolute motion events the code entry of the 
				  device abs[] array is modified (with some fuzziness) before 
				  handling them. Relative motion events are skipped if the value is 
				  0. LED and sound events toggle the device led and 
				  snd, respectively, and call the device event() 
				  function if it exists defore handling. Repeat events set the code 
				  entry of the device rep[] array to value before 
				  handling. After these controls and preliminary things it dispatches the event 
				  to the list of handles attaches to the device: traversing the list 
				  dnext it calls the event() method for each open 
				  handle. 
				  input_repeat_key( dev ) It invokes the 
				  input_event() method with the device dev, a "key" 
				  event type, the code of the device repaet_key, and value 2 
				  input_open_device( handle ) is called when a handle' device 
				  is opened. It invokes the open method of the handle's device and 
				  increases the handle open counter. 
				  input_close_device( handle ) is called when the handle' 
				  device is closed. It invokes the close method of the handle's 
				  device and decreases the open counter. 
				  input_link_handle( handle ) inserts handle in the first 
				  position of both the device list (of the handle's dev) and the handler list 
				  (of the handle's handler). 
				  input_unlink_handle( handle ) remove the handle from both the 
				  device list and the handler list 
				  input_register_device( dev ) is called by an input device 
				  that wants to register with the input core. It initializes the device repeat 
				  timer to default values (in particular the timer function is 
				  input_repeat_key). Then it assignes the device number (the first 
				  free number). Finally it scans the list of input_handler trying to connect 
				  each handler with the device: if it succeeds it inserts the newly created 
				  handle. It increases input_number. 
				  input_unregister_device( dev ) is called by a device that 
				  drops from the input core. It deletes the repeat timer. For each handle in the 
				  device list of dev it unlinks the handle and disconnect it from 
				  the associated handler. Finally it removes the device and decreases 
				  input_number. 
				  input_register_handler( handler ) is called by an input 
				  handler that wants to register with the input core. It adds the handler to the 
				  list input_handler and add it to the input_table. 
				  Then it adds a handle for each device that can be connected to the handler. 
				  input_unregister_handler( handler ) is called by a handler to 
				  unregister from the input core. It disconnects the handler from all the 
				  devices to which it is connected. Then it removes the handler from the list 
				  input_handler and remove it from the input_table. 
				  input_open_file( inode, file ). This is the only file 
				  operation of the input core driver. [ STILL TO DO ] 
				Anatomy of a handler
				Sample input handlers are contained in the drivers/input subdirectory of 
				the source tree. They provide the user interfaces. Here we consider the event 
				handler evdev.c. Two data structures are used to store event device 
				and event informations: 
				
				  evdev, which contains, besides other things, an input_handle, 
				  a wait_queue_head, and a pointer to an evdev_list; 
				  evdev_list, with a buffer of input_event's, a fasync_struct 
				  pointer, a pointer to its evdev, and the next evdev_list pointer. The 
				evdev's are stored in a static evdev_table; 
				The user interface methods (API) are 
				
				  evdev_fasync( fd, file, on ). It gets the 
				  evdev_list stored in the file's 
				  private_data, and invokes the the fasync_helper with the 
				  evdev_list's fasync function [FIXME], 
				     fasync_helper(fd, file, on, &list->fasync); 
				  evdev_open( inode, file ). The inode's minor 
				  specifes which evdev to open. A new evdev_list structure is allocated and 
				  linked into the evdev's evdev_list, and the file 
				  private_data is made to point to the newly created evdev_list, 
				  
				     list->evdev = 
				  evdev_table[i];   list->next = 
				  evdev_table[i]->list;   evdev_table[i]->list = 
				  list;   file->private_data = list; After this 
				  bookkeeping, if the evdev was not already open (and if it exists), the 
				  input_core input_open_device is invoked with the evdev's 
				  handle. 
				  evdev_release( inode, file ). This does the opposite 
				  operations of the open method: if this was the last list of the evdev, the 
				  evdev is closed with the input_core (and possibly unregistered and deallocated 
				  if its exist flag is not set). Finally the evdev_list is freed. 
				  evdev_write( file, buffer, count ) allows the user process to write 
				  events into the evdev buffer. The user buffer must 
				  contain one or more struct input_event. count is the 
				  number of bytes used in the user buffer. 
				  evdev_read( file, buffer, count, ppos ). Reading is the 
				  reverse operation: events are copied from the evdev's buffer to 
				  the user buffer. There is one catch. If the evdev's 
				  buffer is empty the process is put to sleep. 
				  evdev_poll( file, wait ). 
				  evdev_ioctl( inode, file, cmd, arg ). 
				Finally the methods related to the input_core are 
				
				  evdev_event: given an input_handle, retrieves the associated 
				  evdev (contained in the private field), and its list of 
				  evdev_list's. Then for each evdev_list in the list, the event informations 
				  (time, type, code and value) are put on the next free slot of the 
				  buffer, and the fasync is signalled [FIXME]. Finally 
				  the processes on the evdev's wait_queue are waken up. 
				  evdev_connect( handler, dev ). Finds the first unused entry 
				  in the evdev_table, and allocates a new evdev for it. Initialize its 
				  wait_queue, its handle 
				     evdev->handle.dev = 
				  dev;   evdev->handle.handler = 
				  handler;   evdev->handle.private = evdev; 
				  and register with the input_core. 
				  evdev_disconnect( handle ). The evdev is contained in the 
				  handle's private field. If the evdev is open it is closed and the 
				  processes on its wait_queue are waken up. Otherwise it is unregistered, 
				  dropped from the evdev_table, and deallocated. 
				  evdev_init: register with the input_core; 
				  evdev_exit: unregister with the input_core. 
				Working through the code
				First, we start with examples of input devices. These are taken from Hard's 
				article, with minor changes to make them run on 2.4 kernels. 
				
				  				  href="http://www.geocities.com/marco_corvi/games/lkpe/input/example1.c">example1.c, 
				  basic register/unregister 
				  				  href="http://www.geocities.com/marco_corvi/games/lkpe/input/example2.c">example2.c, 
				  key event device 
				  				  href="http://www.geocities.com/marco_corvi/games/lkpe/input/example3.c">example3.c, 
				  motion event device Try these examples out. Here is the 				href="http://www.geocities.com/marco_corvi/games/lkpe/input/makefile">makefile. 
				
				Now the first exercise. Write a driver that generates led input events. You 
				can begin with examples 2 or 3 above, and replace the driver event type with 
				EV_LED, and set some ledbit. Give it a try before looking at a 
				solution, 				href="http://www.geocities.com/marco_corvi/games/lkpe/input/example4.c">example4.c, 
				led event device. 
				Second exercise. Now write a handler for the led device of the first 
				exercise. As a hint you may look at the joydev.c code in drivers/input 
				subdirectory of Linux. Here is a solution, 				href="http://www.geocities.com/marco_corvi/games/lkpe/input/leddev.c">leddev.c, 
				led event handler. And these are two user programs for it, 				href="http://www.geocities.com/marco_corvi/games/lkpe/input/ledtest.c">ledtest.c, 
								href="http://www.geocities.com/marco_corvi/games/lkpe/input/ledreset.c">ledreset.c. 
				Marco Corvi - 2003 
								language=JavaScript>var PUpage="76001084"; var PUprop="geocities"; 
				
				
				
								src="The Input Subsystem2_file/ygIELib9.js">
				
				var yviContents='http://us.toto.geo.yahoo.com/toto?s=76001084&l=NE&b=1&t=1057747069';yviR='us';yfiEA(0);
				
				
				
				
				
				geovisit();
								width=1 border=0> 				src="The Input Subsystem2_file/serv.gif" width=1> 
							

相关资源