Hands-on Projects for the Linux Graphics Subsystem
|
InitInput() is implemented in xf86Init.c as:
/* * InitInput -- * Initialize all supported input devices. */ void InitInput(argc, argv) int argc; char **argv; { IDevPtr pDev; InputDriverPtr pDrv; InputInfoPtr pInfo; static InputInfoPtr coreKeyboard = NULL, corePointer = NULL; xf86Info.vtRequestsPending = FALSE; xf86Info.inputPending = FALSE; #ifdef XTESTEXT1 xtest_command_key = KEY_Begin + MIN_KEYCODE; #endif /* XTESTEXT1 */ if (serverGeneration == 1) { /* Call the PreInit function for each input device instance. */ for (pDev = xf86ConfigLayout.inputs; pDev && pDev->identifier; pDev++) { #ifdef USE_DEPRECATED_KEYBOARD_DRIVER /* XXX The keyboard driver is a special case for now. */ if (!xf86NameCmp(pDev->driver, "keyboard")) { xf86MsgVerb(X_WARNING, 0, "...keyboard driver \"keyboard\" is deprecated\n"); xf86MsgVerb(X_WARNING, 0, "...the next release of the Xorg server.\n"); xf86MsgVerb(X_WARNING, 0, "...new \"kbd\" driver for \"%s\".\n", pDev->identifier); continue; } #endif if ((pDrv = MatchInput(pDev)) == NULL) { xf86Msg(X_ERROR, "No Input driver matching `%s'\n", pDev->driver); /* XXX For now, just continue. */ continue; } if (!pDrv->PreInit) { xf86MsgVerb(X_WARNING, 0, "Input driver `%s' has no PreInit function (ignoring)\n", pDrv->driverName); continue; } pInfo = pDrv->PreInit(pDrv, pDev, 0); if (!pInfo) { xf86Msg(X_ERROR, "PreInit returned NULL for \"%s\"\n", pDev->identifier); continue; } else if (!(pInfo->flags & XI86_CONFIGURED)) { xf86Msg(X_ERROR, "PreInit failed for input device \"%s\"\n", pDev->identifier); xf86DeleteInput(pInfo, 0); continue; } if (pInfo->flags & XI86_CORE_KEYBOARD) { if (coreKeyboard) { xf86Msg(X_ERROR, "Attempt to register more than one core keyboard (%s)\n", pInfo->name); pInfo->flags &= ~XI86_CORE_KEYBOARD; } else { if (!(pInfo->flags & XI86_KEYBOARD_CAPABLE)) { /* XXX just a warning for now */ xf86Msg(X_WARNING, "%s: does not have core keyboard capabilities\n", pInfo->name); } coreKeyboard = pInfo; } } if (pInfo->flags & XI86_CORE_POINTER) { if (corePointer) { xf86Msg(X_ERROR, "Attempt to register more than one core pointer (%s)\n", pInfo->name); pInfo->flags &= ~XI86_CORE_POINTER; } else { if (!(pInfo->flags & XI86_POINTER_CAPABLE)) { /* XXX just a warning for now */ xf86Msg(X_WARNING, "%s: does not have core pointer capabilities\n", pInfo->name); } corePointer = pInfo; } } } if (!corePointer) { xf86Msg(X_WARNING, "No core pointer registered\n"); /* XXX register a dummy core pointer */ } #ifdef NEW_KBD if (!coreKeyboard) { xf86Msg(X_WARNING, "No core keyboard registered\n"); /* XXX register a dummy core keyboard */ } #endif } /* Initialise all input devices. */ pInfo = xf86InputDevs; while (pInfo) { xf86ActivateDevice(pInfo); pInfo = pInfo->next; } if (coreKeyboard) { xf86Info.pKeyboard = coreKeyboard->dev; xf86Info.kbdEvents = NULL; /* to prevent the internal keybord driver usage*/ } else { #ifdef USE_DEPRECATED_KEYBOARD_DRIVER /* Only set this if we're allowing the old driver. */ if (xf86Info.kbdProc != NULL) xf86Info.pKeyboard = AddInputDevice(xf86Info.kbdProc, TRUE); #endif } if (corePointer) xf86Info.pMouse = corePointer->dev; if (xf86Info.pKeyboard) RegisterKeyboardDevice(xf86Info.pKeyboard); miRegisterPointerDevice(screenInfo.screens[0], xf86Info.pMouse); #ifdef XINPUT xf86eqInit ((DevicePtr)xf86Info.pKeyboard, (DevicePtr)xf86Info.pMouse); #else mieqInit ((DevicePtr)xf86Info.pKeyboard, (DevicePtr)xf86Info.pMouse); #endif |
Global xf86info is defined and initialized in xf86Globals.c. It is of type xf86InfoRec.
|
Consider for instance the following part of an xorg.conf:
MatchInput() is implemented as:
static InputDriverPtr MatchInput(IDevPtr pDev) { int i; for (i = 0; i < xf86NumInputDrivers; i++) { if (xf86InputDriverList[i] && xf86InputDriverList[i]->driverName && xf86NameCmp(pDev->driver, xf86InputDriverList[i]->driverName) == 0) return xf86InputDriverList[i]; } return NULL; } |
xf86InputDriverList is defined in xf86Globals.c as:
InputDriverPtr *xf86InputDriverList = NULL; |
Where InputDriverPtr is defined in xf86Xinput.h as:
/* This holds the input driver entry and module information. */ typedef struct _InputDriverRec { int driverVersion; char * driverName; void (*Identify)(int flags); struct _LocalDeviceRec *(*PreInit)(struct _InputDriverRec *drv, IDevPtr dev, int flags); void (*UnInit)(struct _InputDriverRec *drv, struct _LocalDeviceRec *pInfo, int flags); pointer module; int refCount; } InputDriverRec, *InputDriverPtr; |
In a NutshellInitInput() calls MatchInput(), which returns pDrv of type InputDriverPtr, which points to the matching item of xf86InputDriverList[]. xf86InputDriverList[] is created by xf86InputDriverlistFromConfig(), called in InitOutput() as:
xf86LoadModules() calls xf86AddInputDriver(), which adds a new item to xf86InputDriverList[]. The following is this item for the example we follow, after xf86AddInputDriver() is called as seen in the next paragraphs:
(*) module is of type ModuleDescPtr returned by LoadModule(), which is called by xf86LoadModules(). The pDrv->PreInit function, in our case MousePreInit(), is called next from InitInput(). This fills and returns pInfo, which is of type InputInfoPtr. The InputInfoRec it points to, for the example we follow, is presented in the next example. The pInfo are linked in the xf86InputDevs list. This is the result of xf86AllocateInput() that is called from InitInput() to allocate a new pInfo. InitInput() calls next xf86ActivateDevice() for each pInfo of the xf86InputDevs list. xf86ActivateDevice() calls AddInputDevice(), which allocates dev, a DeviceIntPtr (points to a _DeviceIntRec) and then it calls RegisterPointerDevice() and RegisterKeyboardDevice() to register the core mouse and keyboard devices.
|
Two notes about section 3.2.5.1
I. The following fields of xf86Info
xf86Info.pKeyboard are filled from the following instructions of InitInput(): xf86Info.pKeyboard = coreKeyboard->dev; ... xf86Info.pMouse = corePointer->dev;where coreKeyboard and corePointer are the pInfo (of type InputInfoPtr) that are returned from the PreInit() functions of the mouse and keyboard drivers, which have the XI86_CORE_POINTER and XI86_CORE_KEYBOARD flags respectively set. II. The following lines of xf86ActivateDevice(), called by InitInput() fill dev (of type DeviceIntPtr) which was allocated previously in xf86ActivateDevice() by calling AddInputDevice() with argument the pInfo->device_control: if (local->flags & XI86_CORE_POINTER) RegisterPointerDevice(dev); else if (local->flags & XI86_CORE_KEYBOARD) RegisterKeyboardDevice(dev);assign some of the fields of dev (field deviceProc was set by _AddInputDevice). Among the fields in section 3.2.5.1 we are interested in processInputProc. As we see for instance in _RegisterPointerDevice() this becomes ProcessPointerEvent. Similarly for the keyboard in _RegisterKeyboardDevice it becomes ProcessKeyboardEvent.
|
xf86InputDriverlistFromConfig() is implemented as:
char ** xf86InputDriverlistFromConfig() { int count = 0; char **modulearray; IDevPtr idp; /* * make sure the config file has been parsed and that we have a * ModulePath set; if no ModulePath was given, use the default * ModulePath */ if (xf86configptr == NULL) { xf86Msg(X_ERROR, "Cannot access global config data structure\n"); return NULL; } /* * Walk the list of driver lines in active "InputDevice" sections to * determine now many implicitly loaded modules there are. */ if (xf86ConfigLayout.inputs) { idp = xf86ConfigLayout.inputs; while (idp->identifier) { if (!xf86BuiltinInputDriver(idp->driver)) count++; idp++; } } if (count == 0) return NULL; /* * allocate the memory and walk the list again to fill in the pointers */ modulearray = xnfalloc((count + 1) * sizeof(char*)); count = 0; idp = xf86ConfigLayout.inputs; while (idp->identifier) { if (!xf86BuiltinInputDriver(idp->driver)) { modulearray[count] = idp->driver; count++; } idp++; } modulearray[count] = NULL; /* Remove duplicates */ for (count = 0; modulearray[count] != NULL; count++) { int i; for (i = 0; i < count; i++) if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) { modulearray[count] = ""; break; } } return modulearray; } |
Recall from section 3.2.2.2 that xf86ConfigLayout is of type serverLayoutRec. xf86ConfigLayout is the data structure that is used at this point to represent the Layout section information. It collects the information parsed by xorg.conf and stored previously in the XF86ConfLayoutPtr field of the global XF86ConfigRec. This process is done in configLayout() (or in configImpliedLayout()).
typedef struct _serverlayoutrec { char * id; screenLayoutPtr screens; GDevPtr inactives; IDevPtr inputs; pointer options; } serverLayoutRec, *serverLayoutPtr; |
xf86InputDriverlistFromConfig() creates the modulearray[], a array of strings whose elements are the module names. The module names are the ones we find at the driver field of xf86ConfigLayout.inputs. For instance for the xorg.conf of the green boxed example the module name becomes "mouse".
xf86LoadModules() is used then to load all modules of the modulearray[]. This function was covered in a section 3.2.2.5. In a short xf86LoadModules() calls LoadModule() for each module found in the list. One of the main things LoadModule() does is call the module's setup routine as:
ret->TearDownData = ret->SetupProc(ret, options, errmaj, errmin); |
The first argument ret is obtained from NewModuleDesc() (called by LoadModule) and is of type ModuleDescPtr. ret is filled by LoadModule() and in the current example 'module' is the actual argument that substitutes ret (the formal parameter).
LoadModule() checks if the special data object <modulename>ModuleData is present. For the current example this found in mouse.c as:
_X_EXPORT XF86ModuleData mouseModuleData = { &xf86MouseVersionRec, xf86MousePlug, xf86MouseUnplug }; |
Since XF86ModuleData is defined in xf86Module.h as:
typedef struct { XF86ModuleVersionInfo * vers; ModuleSetupProc setup; ModuleTearDownProc teardown; } XF86ModuleData; |
we conclude that the mouse setup routine is xf86MousePlug().
xf86MousePlug() called by LoadModule() calls xf86AddInputDriver() to add a pointer to the mouse InputDriverRec to xf86InputDriverList[]:
xf86AddInputDriver(&MOUSE, module, 0); |
where MOUSE is defined in mouse.c as:
_X_EXPORT InputDriverRec MOUSE = { 1, "mouse", NULL, MousePreInit, /*MouseUnInit,*/NULL, NULL, 0 }; |
the last NULL value (the red one) after the xf86AddInputDriver() call is substituted by a pointer to the 'module'.
A common place to find the "mouse" module is: /usr/lib/xorg/modules/input//mouse_drv.so |
The previous steps are described in section 5.6 of the DESIGN document (Register Video and Input Drivers):
5.6 Register Video and Input Drivers This is done at the start of the first server generation only. When a driver module is loaded, the loader calls its Setup function. For video drivers, this function calls xf86AddDriver() to register the driver's DriverRec, which contains a small set of essential details and driver entry points required during the early phase of InitOutput(). xf86AddDriver() adds it to the global xf86DriverList[] array. The DriverRec contains the driver canonical name, the Identify(), Probe() and AvailableOptions() function entry points as well as a pointer to the driver's module (as returned from the loader when the driver was loaded) and a refer- ence count which keeps track of how many screens are using the driver. The entry driver entry points are those required prior to the driver allocating and filling in its ScrnInfoRec. For a static server, the xf86DriverList[] array is initialised at build time, and the loading of modules is not done. A similar procedure is used for input drivers. The input driver's Setup function calls xf86AddInputDriver() to register the driver's InputDriverRec, which contains a small set of essential details and driver entry points required during the early phase of InitInput(). xf86AddInputDriver() adds it to the global xf86InputDriverList[] array. For a static server, the xf86InputDriverList[] array is initialised at build time. Both the xf86DriverList[] and xf86InputDriverList[] arrays have been ini- tialised by the end of this stage. Once all the drivers are registered, their ChipIdentify() functions are called. |
What is a canonical file name? As the Loader Overview explains:
"The module name module is normally the module's canonical name, which doesn't contain any directory path information, or any object/library file prefixes of suffixes."
MousePreInit(), the module's PreInit() function is implemented as:
static InputInfoPtr MousePreInit(InputDriverPtr drv, IDevPtr dev, int flags) { InputInfoPtr pInfo; MouseDevPtr pMse; mousePrivPtr mPriv; MessageType protocolFrom = X_DEFAULT, deviceFrom = X_CONFIG; const char *protocol, *osProt = NULL; const char *device; MouseProtocolID protocolID; MouseProtocolPtr pProto; Bool detected; int i; if (!InitProtocols()) return NULL; if (!(pInfo = xf86AllocateInput(drv, 0))) return NULL; /* Initialise the InputInfoRec. */ pInfo->name = dev->identifier; pInfo->type_name = XI_MOUSE; pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; pInfo->device_control = MouseProc; pInfo->read_input = MouseReadInput; pInfo->motion_history_proc = xf86GetMotionEvents; pInfo->history_size = 0; pInfo->control_proc = NULL; pInfo->close_proc = NULL; pInfo->switch_mode = NULL; pInfo->conversion_proc = MouseConvert; pInfo->reverse_conversion_proc = NULL; pInfo->fd = -1; pInfo->dev = NULL; pInfo->private_flags = 0; pInfo->always_core_feedback = 0; pInfo->conf_idev = dev; /* Check if SendDragEvents has been disabled. */ if (!xf86SetBoolOption(dev->commonOptions, "SendDragEvents", TRUE)) { pInfo->flags &= ~XI86_SEND_DRAG_EVENTS; } /* Allocate the MouseDevRec and initialise it. */ /* * XXX This should be done by a function in the core server since the * MouseDevRec is defined in the os-support layer. */ if (!(pMse = xcalloc(sizeof(MouseDevRec), 1))) return pInfo; pInfo->private = pMse; pMse->Ctrl = MouseCtrl; pMse->PostEvent = MousePostEvent; pMse->CommonOptions = MouseCommonOptions; /* Find the protocol type. */ protocol = xf86SetStrOption(dev->commonOptions, "Protocol", NULL); if (protocol) { protocolFrom = X_CONFIG; } else if (osInfo->DefaultProtocol) { protocol = osInfo->DefaultProtocol(); protocolFrom = X_DEFAULT; } if (!protocol) { xf86Msg(X_ERROR, "%s: No Protocol specified\n", pInfo->name); return pInfo; } /* Default Mapping: 1 2 3 8 9 10 11 ... */ for (i = 0; i < MSE_MAXBUTTONS; i++) pMse->buttonMap[i] = 1 << (i > 2 && i < MSE_MAXBUTTONS-4 ? i+4 : i); protocolID = ProtocolNameToID(protocol); do { detected = TRUE; switch (protocolID) { case PROT_AUTO: if (osInfo->SetupAuto) { if ((osProt = osInfo->SetupAuto(pInfo,NULL))) { MouseProtocolID id = ProtocolNameToID(osProt); if (id == PROT_UNKNOWN || id == PROT_UNSUP) { protocolID = id; protocol = osProt; detected = FALSE; } } } break; case PROT_UNKNOWN: /* Check for a builtin OS-specific protocol, * and call its PreInit. */ if (osInfo->CheckProtocol && osInfo->CheckProtocol(protocol)) { if (!xf86CheckStrOption(dev->commonOptions, "Device", NULL) && HAVE_FIND_DEVICE && osInfo->FindDevice) { xf86Msg(X_WARNING, "%s: No Device specified, " "looking for one...\n", pInfo->name); if (!osInfo->FindDevice(pInfo, protocol, 0)) { xf86Msg(X_ERROR, "%s: Cannot find which device " "to use.\n", pInfo->name); } else deviceFrom = X_PROBED; } if (osInfo->PreInit) { osInfo->PreInit(pInfo, protocol, 0); } return pInfo; } xf86Msg(X_ERROR, "%s: Unknown protocol \"%s\"\n", pInfo->name, protocol); return pInfo; break; case PROT_UNSUP: xf86Msg(X_ERROR, "%s: Protocol \"%s\" is not supported on this " "platform\n", pInfo->name, protocol); return pInfo; break; default: break; } } while (!detected); if (!xf86CheckStrOption(dev->commonOptions, "Device", NULL) && HAVE_FIND_DEVICE && osInfo->FindDevice) { xf86Msg(X_WARNING, "%s: No Device specified, looking for one...\n", pInfo->name); if (!osInfo->FindDevice(pInfo, protocol, 0)) { xf86Msg(X_ERROR, "%s: Cannot find which device to use.\n", pInfo->name); } else { deviceFrom = X_PROBED; xf86MarkOptionUsedByName(dev->commonOptions, "Device"); } } device = xf86CheckStrOption(dev->commonOptions, "Device", NULL); if (device) xf86Msg(deviceFrom, "%s: Device: \"%s\"\n", pInfo->name, device); xf86Msg(protocolFrom, "%s: Protocol: \"%s\"\n", pInfo->name, protocol); if (!(pProto = GetProtocol(protocolID))) return pInfo; pMse->protocolID = protocolID; pMse->oldProtocolID = protocolID; /* hack */ pMse->autoProbe = FALSE; /* Collect the options, and process the common options. */ xf86CollectInputOptions(pInfo, pProto->defaults, NULL); xf86ProcessCommonOptions(pInfo, pInfo->options); /* XXX should handle this OS dependency elsewhere. */ #ifndef __OS2ELF__ /* OS/2 has a mouse handled by the OS - it cannot fail here */ /* Check if the device can be opened. */ pInfo->fd = xf86OpenSerial(pInfo->options); if (pInfo->fd == -1) { if (xf86GetAllowMouseOpenFail()) xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); else { xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name); if (pMse->mousePriv) xfree(pMse->mousePriv); xfree(pMse); pInfo->private = NULL; return pInfo; } } xf86CloseSerial(pInfo->fd); #endif pInfo->fd = -1; if (!(mPriv = (pointer) xcalloc(sizeof(mousePrivRec), 1))) return pInfo; pMse->mousePriv = mPriv; pMse->CommonOptions(pInfo); pMse->checkMovements = checkForErraticMovements; pMse->autoProbeMouse = autoProbeMouse; pMse->collectData = collectData; pMse->dataGood = autoGood; MouseHWOptions(pInfo); MouseSerialOptions(pInfo); pInfo->flags |= XI86_CONFIGURED; return pInfo; } |
xf86AllocateInput() is implemented as:
/* Allocate a new InputInfoRec and add it to the head xf86InputDevs. */ InputInfoPtr xf86AllocateInput(InputDriverPtr drv, int flags) { InputInfoPtr new; if (!(new = xcalloc(sizeof(InputInfoRec), 1))) return NULL; new->drv = drv; drv->refCount++; #ifdef XFree86LOADER new->module = DuplicateModule(drv->module, NULL); #else new->module = NULL; #endif new->next = xf86InputDevs; xf86InputDevs = new; return new; } |
InputInfoPtr is defined in xf86Xinput.h as:
/* This is to input devices what the ScrnInfoRec is to screens. */ typedef struct _LocalDeviceRec { struct _LocalDeviceRec *next; char * name; int flags; Bool (*device_control)(DeviceIntPtr device, int what); void (*read_input)(struct _LocalDeviceRec *local); int (*control_proc)(struct _LocalDeviceRec *local, xDeviceCtl *control); void (*close_proc)(struct _LocalDeviceRec *local); int (*switch_mode)(ClientPtr client, DeviceIntPtr dev, int mode); Bool (*conversion_proc)(struct _LocalDeviceRec *local, int first, int num, int v0, int v1, int v2, int v3, int v4, int v5, int *x, int *y); Bool (*reverse_conversion_proc)( struct _LocalDeviceRec *local, int x, int y, int *valuators); int fd; Atom atom; DeviceIntPtr dev; pointer private; int private_flags; pointer motion_history; ValuatorMotionProcPtr motion_history_proc; unsigned int history_size; /* only for configuration purpose */ unsigned int first; unsigned int last; int old_x; int old_y; float dxremaind; float dyremaind; char * type_name; IntegerFeedbackPtr always_core_feedback; IDevPtr conf_idev; InputDriverPtr drv; pointer module; pointer options; } LocalDeviceRec, *LocalDevicePtr, InputInfoRec, *InputInfoPtr; |
Example (continued)For the given "mouse" device the InputInfoRec (pointed by pInfo) has the following form:
Notes: xf86AllocateInput() is used to set the drv field of the InputInfoRec to the first argument of MousePreInit(). This is the return value of MatchInput() which is the xf86InputDriverList[] element with driverName "mouse". As mentioned previously in the current section this list is created by xf86InputDriverlistFromConfig() from xf86ConfigLayout.inputs->driver. This was filled by configInput() called by configLayout(). For a more detailed explanation see configInput at section 3.2.2.2. Some values have the predefined value zero since xf86AllocateInput() calls xcalloc() which fills with zero each byte of the current InputInfoRec. Zero value for a pointer is equivalent to NULL. Also xf86CollectInputOptions() and xf86ProcessCommonOptions(), called by MousePreInit() fills the 'options' field:
Field 'private' is of type MouseDevPtr. conf_idev is filled with the IDevPtr that points to the IDevRec which as seen in the first lines of InitInput() results from the xf86ConfigLayout.inputs with the given identifier. Field 'dev' is filled when xf86ActivateDevice() runs latter. Field 'atom' also is filled with xf86ActivateDevice(). module and drv fields were filled by xf86AllocateInput(). MSE_MAXBUTTONS is defined in xf86OSmouse.h to 24.
|
MouseDevPtr is defined in xf86OSmouse.h as:
typedef struct _MouseDevRec { PtrCtrlProcPtr Ctrl; PostMseEventProc PostEvent; MouseCommonOptProc CommonOptions; DeviceIntPtr device; const char * mseDevice; const char * protocol; MouseProtocolID protocolID; MouseProtocolID oldProtocolID; /* hack */ int class; int mseModel; int baudRate; int oldBaudRate; int sampleRate; int lastButtons; int threshold; /* acceleration */ int num; int den; int buttons; /* # of buttons */ int emulateState; /* automata state for 2 button mode */ Bool emulate3Buttons; Bool emulate3ButtonsSoft; int emulate3Timeout;/* Timeout for 3 button emulation */ Bool chordMiddle; Bool flipXY; int invX; int invY; int mouseFlags; /* Flags to Clear after opening * mouse dev */ int truebuttons; /* (not used) * Arg to maintain before * emulate3buttons timer callback */ int resolution; int negativeZ; /* button mask */ int positiveZ; /* button mask */ int negativeW; /* button mask */ int positiveW; /* button mask */ pointer buffer; /* usually an XISBuffer* */ int protoBufTail; unsigned char protoBuf[8]; unsigned char protoPara[8]; unsigned char inSync; /* driver in sync with datastream */ pointer mousePriv; /* private area */ InputInfoPtr pInfo; int origProtocolID; const char * origProtocol; Bool emulate3Pending;/* timer waiting */ CARD32 emulate3Expires;/* time to fire emulation code */ Bool emulateWheel; int wheelInertia; int wheelButton; int negativeX; /* Button values. Unlike the Z and */ int positiveX; /* W equivalents, these are button */ int negativeY; /* values rather than button masks. */ int positiveY; int wheelYDistance; int wheelXDistance; Bool autoProbe; checkMovementsProc checkMovements; autoProbeProc autoProbeMouse; collectDataProc collectData; dataGoodProc dataGood; int angleOffset; pointer pDragLock; /* drag lock area */ int xisbscale; /* buffer size for 1 event */ int wheelButtonTimeout;/* Timeout for the wheel button emulation */ CARD32 wheelButtonExpires; int doubleClickSourceButtonMask; int doubleClickTargetButton; int doubleClickTargetButtonMask; int doubleClickOldSourceState; int lastMappedButtons; int buttonMap[MSE_MAXBUTTONS]; } MouseDevRec, *MouseDevPtr; |
xf86ActivateDevice() is called then by InitInput() as:
/*********************************************************************** * * xf86ActivateDevice -- * * Initialize an input device. * *********************************************************************** */ void xf86ActivateDevice(LocalDevicePtr local) { DeviceIntPtr dev; if (local->flags & XI86_CONFIGURED) { int open_on_init; open_on_init = local->flags & (XI86_OPEN_ON_INIT | XI86_ALWAYS_CORE | XI86_CORE_POINTER | XI86_CORE_KEYBOARD); dev = AddInputDevice(local->device_control, open_on_init); if (dev == NULL) FatalError("Too many input devices"); local->atom = MakeAtom(local->type_name, strlen(local->type_name), TRUE); AssignTypeAndName (dev, local->atom, local->name); dev->public.devicePrivate = (pointer) local; local->dev = dev; xf86XinputFinalizeInit(dev); /* * XXX Can a single device instance be both core keyboard and * core pointer? If so, this should be changed. */ if (local->flags & XI86_CORE_POINTER) RegisterPointerDevice(dev); else if (local->flags & XI86_CORE_KEYBOARD) RegisterKeyboardDevice(dev); #ifdef XINPUT else RegisterOtherDevice(dev); #endif if (serverGeneration == 1) xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", local->name, local->type_name); } } |
It mainly calls AddInputDevice() , (which actually calls _AddInputDevice) as:
dev = AddInputDevice(local->device_control, open_on_init); |
DeviceIntPtr _AddInputDevice(DeviceProc deviceProc, Bool autoStart) { register DeviceIntPtr dev; if (inputInfo.numDevices >= MAX_DEVICES) return (DeviceIntPtr)NULL; dev = (DeviceIntPtr) xalloc(sizeof(DeviceIntRec)); if (!dev) return (DeviceIntPtr)NULL; dev->type = 0; dev->id = inputInfo.numDevices; dev->public.on = FALSE; dev->public.processInputProc = (ProcessInputProc)NoopDDA; dev->public.realInputProc = (ProcessInputProc)NoopDDA; dev->public.enqueueInputProc = EnqueueEvent; dev->deviceProc = deviceProc; dev->startup = autoStart; dev->sync.frozen = FALSE; dev->sync.other = NullGrab; dev->sync.state = NOT_GRABBED; dev->sync.event = (xEvent *) NULL; dev->sync.evcount = 0; dev->grab = NullGrab; dev->grabTime = currentTime; dev->fromPassiveGrab = FALSE; dev->key = (KeyClassPtr)NULL; dev->valuator = (ValuatorClassPtr)NULL; dev->button = (ButtonClassPtr)NULL; dev->focus = (FocusClassPtr)NULL; dev->proximity = (ProximityClassPtr)NULL; dev->kbdfeed = (KbdFeedbackPtr)NULL; dev->ptrfeed = (PtrFeedbackPtr)NULL; dev->intfeed = (IntegerFeedbackPtr)NULL; dev->stringfeed = (StringFeedbackPtr)NULL; dev->bell = (BellFeedbackPtr)NULL; dev->leds = (LedFeedbackPtr)NULL; dev->next = inputInfo.off_devices; #ifdef XKB dev->xkb_interest= NULL; #endif dev->nPrivates = 0; dev->devPrivates = NULL; dev->unwrapProc = NULL; inputInfo.off_devices = dev; return dev; } |
For AddInputDevice() we read at xfree86.org:
"This DIX function allocates the device structure, registers a callback function (which handles device init, close, on and off), and returns the input handle, which can be treated as opaque. It is called once for each input device. Once input handles for core keyboard and core pointer devices have been obtained from AddInputDevice(), they are registered as core devices by calling RegisterPointerDevice() and RegisterKeyboardDevice()."
For the example we follow in the green box the local->device_control (or pInfo->device_control) is function MouseProc(). The second argument are flags added by the xf86ActivateDevice() to the pInfo->flags. Because flag XI86_CORE_POINTER is added now (along with XI86_OPEN_ON_INIT, XI86_ALWAYS_CORE and XI86_CORE_KEYBOARD) RegisterPointerDevice() is also called from xf86ActivateDevice():
void _RegisterPointerDevice(DeviceIntPtr device) { inputInfo.pointer = device; #ifdef XKB device->public.processInputProc = CoreProcessPointerEvent; device->public.realInputProc = CoreProcessPointerEvent; if (!noXkbExtension) XkbSetExtension(device,ProcessPointerEvent); #else device->public.processInputProc = ProcessPointerEvent; device->public.realInputProc = ProcessPointerEvent; #endif device->ActivateGrab = ActivatePointerGrab; device->DeactivateGrab = DeactivatePointerGrab; if (!device->name) { char *p = "pointer"; device->name = (char *)xalloc(strlen(p) + 1); strcpy(device->name, p); } } |
Example (continued)DeviceIntPtr is defined in input.h as:
where _DeviceIntRec is defined in inputstr.h as:
For the current example thread after xf86ActivateDevice() runs and therefore both AddInputDevice() and RegisterPointerDevice() are called the _DeviceIntRec, pointed by DeviceIntPtr (dev) becomes:
Note: field 'public' is of type _DeviceRec, which is defined in input.h as:
|
Notice that DeviceIntPtr points to a DeviceIntRec, defined in inputstr.h as:
typedef struct _DeviceIntRec { DeviceRec public; DeviceIntPtr next; TimeStamp grabTime; Bool startup; /* true if needs to be turned on at server intialization time */ DeviceProc deviceProc; /* proc(DevicePtr, DEVICE_xx). It is used to initialize, turn on, or turn off the device */ Bool inited; /* TRUE if INIT returns Success */ GrabPtr grab; /* the grabber - used by DIX */ struct { Bool frozen; int state; GrabPtr other; /* if other grab has this frozen */ xEvent *event; /* saved to be replayed */ int evcount; } sync; Atom type; char *name; CARD8 id; CARD8 activatingKey; Bool fromPassiveGrab; GrabRec activeGrab; void (*ActivateGrab) ( DeviceIntPtr /*device*/, GrabPtr /*grab*/, TimeStamp /*time*/, Bool /*autoGrab*/); void (*DeactivateGrab)( DeviceIntPtr /*device*/); KeyClassPtr key; ValuatorClassPtr valuator; ButtonClassPtr button; FocusClassPtr focus; ProximityClassPtr proximity; KbdFeedbackPtr kbdfeed; PtrFeedbackPtr ptrfeed; IntegerFeedbackPtr intfeed; StringFeedbackPtr stringfeed; BellFeedbackPtr bell; LedFeedbackPtr leds; #ifdef XKB struct _XkbInterest * xkb_interest; #endif DevUnion *devPrivates; int nPrivates; DeviceUnwrapProc unwrapProc; } DeviceIntRec; |
By returning to InitInput() aftter xf86ActivateDevice() and since corePointer was previously set in the InitInput() code and variable corePointer became pInfo the following execute in InitInput() :
if (corePointer) xf86Info.pMouse = corePointer->dev; |
Global struct xf86Info is defined in xf86Globals.c as:
/* Globals that video drivers may not access */ xf86InfoRec xf86Info = { NULL, /* pKeyboard */ NULL, /* kbdProc */ NULL, /* kbdEvents */ -1, /* consoleFd */ -1, /* kbdFd */ -1, /* vtno */ -1, /* kbdType */ -1, /* kbdRate */ -1, /* kbdDelay */ -1, /* bell_pitch */ -1, /* bell_duration */ TRUE, /* autoRepeat */ 0, /* leds */ 0, /* xleds */ NULL, /* vtinit */ 0, /* scanPrefix */ FALSE, /* capsLock */ FALSE, /* numLock */ FALSE, /* scrollLock */ FALSE, /* modeSwitchLock */ FALSE, /* composeLock */ FALSE, /* vtSysreq */ SKWhenNeeded, /* ddxSpecialKeys */ FALSE, /* ActionKeyBindingsSet */ #if defined(SVR4) && defined(i386) FALSE, /* panix106 */ #endif #if defined(__OpenBSD__) || defined(__NetBSD__) 0, /* wskbdType */ #endif NULL, /* pMouse */ #ifdef XINPUT NULL, /* mouseLocal */ #endif -1, /* lastEventTime */ FALSE, /* vtRequestsPending */ FALSE, /* inputPending */ FALSE, /* dontVTSwitch */ FALSE, /* dontZap */ FALSE, /* dontZoom */ FALSE, /* notrapSignals */ FALSE, /* caughtSignal */ FALSE, /* sharedMonitor */ NULL, /* currentScreen */ #ifdef CSRG_BASED -1, /* screenFd */ -1, /* consType */ #endif #ifdef XKB NULL, /* xkbkeymap */ NULL, /* xkbkeycodes */ NULL, /* xkbtypes */ NULL, /* xkbcompat */ NULL, /* xkbsymbols */ NULL, /* xkbgeometry */ FALSE, /* xkbcomponents_specified */ NULL, /* xkbrules */ NULL, /* xkbmodel */ NULL, /* xkblayout */ NULL, /* xkbvariant */ NULL, /* xkboptions */ #endif FALSE, /* allowMouseOpenFail */ TRUE, /* vidModeEnabled */ FALSE, /* vidModeAllowNonLocal */ TRUE, /* miscModInDevEnabled */ FALSE, /* miscModInDevAllowNonLocal */ PCIOsConfig, /* pciFlags */ Pix24DontCare, /* pixmap24 */ X_DEFAULT, /* pix24From */ #if defined(i386) || defined(__i386__) FALSE, /* pc98 */ #endif TRUE, /* pmFlag */ LogNone, /* syncLog */ 0, /* estimateSizesAggressively */ FALSE, /* kbdCustomKeycodes */ FALSE, /* disableRandR */ X_DEFAULT /* randRFrom */ }; |
The usage of xf86Info pKeyboard and pMouse fields that are filled in InitInput() (see blue characters in the InitInput() source code above) can be found in section 3.2.5.1. |
For the mieqInit() call see section 3.2.5.1.
REFERENCES:
The DESIGN Document
Input Driver Specifications
Xorg Input HOWTO
The XFree86 Architecture
Distributed Multihead X design