Drivers Pctv Input Devices

Products North America. Digital products. PCTV HD mini Stick; Hybrid products. PCTV HD Stick; PCTV HD Pro Stick; PCTV HD Card; Mac products. PCTV for Mac HD mini Stick. PCI device: Typical PCI cards used in PCs include: network cards, sound cards, modems, extra ports such as USB or serial, TV tuner cards and disk controllers. Historically video cards were typically PCI devices, but growing bandwidth requirements soon outgrew the capabilities of PCI.

1.1. The simplest example¶

Here comes a very simple example of an input device driver. The device hasjust one button and the button is accessible at i/o port BUTTON_PORT. Whenpressed or released a BUTTON_IRQ happens. The driver could look like:

1.2. What the example does¶

First it has to include the <linux/input.h> file, which interfaces to theinput subsystem. This provides all the definitions needed.

In the _init function, which is called either upon module load or whenbooting the kernel, it grabs the required resources (it should also checkfor the presence of the device).

Then it allocates a new input device structure with input_allocate_device()and sets up input bitfields. This way the device driver tells the otherparts of the input systems what it is - what events can be generated oraccepted by this input device. Our example device can only generate EV_KEYtype events, and from those only BTN_0 event code. Thus we only set thesetwo bits. We could have used:

as well, but with more than single bits the first approach tends to beshorter.

Then the example driver registers the input device structure by calling:

This adds the button_dev structure to linked lists of the input driver andcalls device handler modules _connect functions to tell them a new inputdevice has appeared. input_register_device() may sleep and therefore mustnot be called from an interrupt or with a spinlock held.

While in use, the only used function of the driver is:

which upon every interrupt from the button checks its state and reports itvia the:

call to the input system. There is no need to check whether the interruptroutine isn’t reporting two same value events (press, press for example) tothe input system, because the input_report_* functions check thatthemselves.

Then there is the:

call to tell those who receive the events that we’ve sent a complete report.This doesn’t seem important in the one button case, but is quite importantfor for example mouse movement, where you don’t want the X and Y valuesto be interpreted separately, because that’d result in a different movement.

1.3. dev->open() and dev->close()¶

In case the driver has to repeatedly poll the device, because it doesn’thave an interrupt coming from it and the polling is too expensive to be doneall the time, or if the device uses a valuable resource (eg. interrupt), itcan use the open and close callback to know when it can stop polling orrelease the interrupt and when it must resume polling or grab the interruptagain. To do that, we would add this to our example driver:

Note that input core keeps track of number of users for the device andmakes sure that dev->open() is called only when the first user connectsto the device and that dev->close() is called when the very last userdisconnects. Calls to both callbacks are serialized.

The open() callback should return a 0 in case of success or any nonzero valuein case of failure. The close() callback (which is void) must always succeed.

1.4. Basic event types¶

The most simple event type is EV_KEY, which is used for keys and buttons.It’s reported to the input system via:

See uapi/linux/input-event-codes.h for the allowable values of code (from 0 toKEY_MAX). Value is interpreted as a truth value, ie any nonzero value means keypressed, zero value means key released. The input code generates events onlyin case the value is different from before.

In addition to EV_KEY, there are two more basic event types: EV_REL andEV_ABS. They are used for relative and absolute values supplied by thedevice. A relative value may be for example a mouse movement in the X axis.The mouse reports it as a relative difference from the last position,because it doesn’t have any absolute coordinate system to work in. Absoluteevents are namely for joysticks and digitizers - devices that do work in anabsolute coordinate systems.

Having the device report EV_REL buttons is as simple as with EV_KEY, simplyset the corresponding bits and call the:

function. Events are generated only for nonzero value.

However EV_ABS requires a little special care. Before callinginput_register_device, you have to fill additional fields in the input_devstruct for each absolute axis your device has. If our button device had alsothe ABS_X axis:

Or, you can just say:

This setting would be appropriate for a joystick X axis, with the minimum of0, maximum of 255 (which the joystick must be able to reach, no problem ifit sometimes reports more, but it must be able to always reach the min andmax values), with noise in the data up to +- 4, and with a center flatposition of size 8.

If you don’t need absfuzz and absflat, you can set them to zero, which meanthat the thing is precise and always returns to exactly the center position(if it has any).

1.5. BITS_TO_LONGS(), BIT_WORD(), BIT_MASK()¶

These three macros from bitops.h help some bitfield computations:

1.6. The id* and name fields¶

The dev->name should be set before registering the input device by the inputdevice driver. It’s a string like ‘Generic button device’ containing auser friendly name of the device.

The id* fields contain the bus ID (PCI, USB, ...), vendor ID and device IDof the device. The bus IDs are defined in input.h. The vendor and device idsare defined in pci_ids.h, usb_ids.h and similar include files. These fieldsshould be set by the input device driver before registering it.

The idtype field can be used for specific information for the input devicedriver.

The id and name fields can be passed to userland via the evdev interface.

1.7. The keycode, keycodemax, keycodesize fields¶

These three fields should be used by input devices that have dense keymaps.The keycode is an array used to map from scancodes to input system keycodes.The keycode max should contain the size of the array and keycodesize thesize of each entry in it (in bytes).

Userspace can query and alter current scancode to keycode mappings usingEVIOCGKEYCODE and EVIOCSKEYCODE ioctls on corresponding evdev interface.When a device has all 3 aforementioned fields filled in, the driver mayrely on kernel’s default implementation of setting and querying keycodemappings.

1.8. dev->getkeycode() and dev->setkeycode()¶

getkeycode() and setkeycode() callbacks allow drivers to override defaultkeycode/keycodesize/keycodemax mapping mechanism provided by input coreand implement sparse keycode maps.

1.9. Key autorepeat¶

... is simple. It is handled by the input.c module. Hardware autorepeat isnot used, because it’s not present in many devices and even where it ispresent, it is broken sometimes (at keyboards: Toshiba notebooks). To enableautorepeat for your device, just set EV_REP in dev->evbit. All will behandled by the input system.

1.10. Other event types, handling output events¶

The other event types up to now are:

  • EV_LED - used for the keyboard LEDs.
  • EV_SND - used for keyboard beeps.

They are very similar to for example key events, but they go in the otherdirection - from the system to the input device driver. If your input devicedriver can handle these events, it has to set the respective bits in evbit,and also the callback routine:

Drivers Pctv Input Devices App

This callback routine can be called from an interrupt or a BH (although thatisn’t a rule), and thus must not sleep, and must not take too long to finish.

To write an input driver, you must first create your owninput module. The sample directory contains asample skeleton for creating a module. We recommend that youuse this as a starting point.

A module is represented by a data type calledinput_module_t. It contains various datafields and function pointers representing its interface.

input_module_t data type

Writing an input module consists of simply creating aninput_module_t representing your module andfilling in the relevant interface functions.

flags
Only one flag has been defined — MODULE_FLAG_INUSE, which indicates a valid module.
type
A combination (OR) of two descriptors:
  • driver class:
    • DEVI_CLASS_KBD — keyboard
    • DEVI_CLASS_REL — relative
    • DEVI_CLASS_ABS — absolute
  • driver layer that this module represents:
    • DEVI_MODULE_TYPE_FILTER — filter
    • DEVI_MODULE_TYPE_PROTO — protocol
    • DEVI_MODULE_TYPE_DEVICE — device
args
List of module parameters where each parameter isrepresented by a single character. If there's an optionalargument, the parameter has the format x: (the: means that the optional argument is expected).
data
Usually a pointer to a module's local data. This can beassigned in the init() module function.

In the sample directory

The code in the sample directory provides lots of commentsdetailing the steps required to initialize your module, andwhat to put in your module's functions.

You'll also find two modules:

  • samp_dev — an example of a device module.
  • samp_proto — the MS-mouse protocol code with lots of comments.

You'll also find a README file that providesfurther background info on how the system processes datafrom keyboard and absolute devices.

Input
In many embedded systems, a combination device/protocolmodule is called for. For details, see the section on“Writing a combination device/protocol module”in this chapter.

Device modules can pass data in any format they want up toprotocol modules. But protocol modules must pass data ina specific format to filter modules.

This protocol module:Must format data into a:
Keyboardstruct packet_kbd
Relativestruct packet_rel
Absolutestruct packet_abs

See the header <devi.h> for the format of these structures.All these structures have a timestamp field; you fill them inusing the library call clk_get().

When writing keyboard device modules, keep in mind that theprotocol/filter layers will expect make-and-break scan codesindicating when a key is pressed down and released. Theeasiest thing to do is to map the scan codes your devicesends to the standard PC scan codes. This way you won't haveto make any filter-layer changes — it will all justwork like a normal PC keyboard. Standard PC scan codes areavailable in any PC hardware book.

When passing up a struct packet_kbd to the filter layer, all youneed to do is:

  1. Fill in the key_scan field of the struct _keyboard_datawith the scan code.
  2. Fill in the flags field with KEY_SCAN_VALID.
Drivers pctv input devices download

The keyboard filter layer will read in a keyboarddefinition file and interpret the scan codes itreceives based on the contents of this file.

The keyboard definition files are typically kept in thelocation$PHOTON_PATH/keyboard, where$PHOTON_PATH depends on you systemconfiguration (e.g. this might be /usr/photon on your machine).In this directory there's a file calledsample.kdef, which provides a sample definition file. The .kdeffiles are compiled into .kbd files using the utilities kbcvtand mkkbd.

Both of these utilities are shipped with Photon for QNX 4.

You shouldn't have to play around with these mapping filesvery much if you map your scan codes appropriately. The onlyplace where you might need to modify these files is if your keyboardhas special keys. In this case, you would start with a standard definitionfile (e.g. en_US_101.kdef), and add your uniquescan codes.

When the driver starts up and initializes the keyboard filter module,the module will try to load in a mapping definition file.It uses the following algorithm to look for the file:

  1. The module tries to open the keyboard configuration file/etc/system/trap/.KEYBOARD.If this file exists, the module just reads thekeyboard filename from it.
  2. If the keyboard mapping filename is empty, the moduletries to take it from the KBD environmentvariable.
  3. If the keyboard mapping filename is still empty, themodule assigns the standard US keyboard definition file(en_US_101.kbd) to it.
  4. The module tries to find this file in the %PHOTON%/keyboard directory.
  5. If the PHOTON environment variable isn'tdefined, the module tries to open it in the /usr/photon/keyboard directory.

The elo directory contains an example of atouchscreen protocol module.

Absolute devices (e.g. touchscreens) need to be calibrated.They typically generate “raw” coordinates thatmust be translated into actual screen coordinates. Thescreen coordinates they're translated into depend on thescreen resolution.

The device/protocol layer module receives raw coordinates fromthe touchscreen device, formats a packet_abs structure, and passes itup to the absolute filter.

Input

The absolute filter module takes care of translating rawcoordinates into screen coordinates. To do this, the moduletries to locate and read in a calibration file on startup via:

  1. Command-line option to the absolute filter (-ffilename)
  2. ABSF environment variable
  3. /etc/system/config/calib.hostname

Calibration file format

The format of this file is as follows:

where:

XL
X screen coordinate of upper left side (typically 0).
YL
Y screen coordinate of upper left side (typically 0).
XH
X screen coordinate of lower right side (typically X screen resolution − 1).
YH
Y screen coordinate of lower right side (typically Y screen resolution − 1).
XRL
Raw touchscreen X coordinate at upper left side.
XRH
Raw touchscreen X coordinate at lower right side.
YRL
Raw touchscreen Y coordinate at upper left side.
YRH
Raw touchscreen Y coordinate at lower right size.
SWAP
Whether to swap X or Y axes (0 is no, 1 is yes.) It's safe to leave this as 0.

This calibration file is typically generated by the Photontouchscreen calibration application, calib.When the utility starts, it sends a message to the devi- driver asking it to switch toraw mode, and then solicits coordinate info by asking the user totouch the screen at all four corners and the middle. Afterdoing this, calib formats the absf file, sends acalibration message to the devi-* driver, and writes the file.

The hirun directory contains examples of amouse device (kb.c) and protocol (msoft.c, ps2.s, msys.c) modules.

Since these modules cover all the main types of relativedevices, you probably won't need to develop something newfrom scratch. If you need to implement support for anydevice that's not completely supported by this driver, youcan simply copy the files from this directory into a new oneand modify them.

Note that Microsoft and Mouse Systems class devices don't have a device module — they justuse /dev/serN to get raw data from a serial communication port.A PS/2 mouse shares the 8042 controller device driver (kb.c) with a standardkeyboard.

The protocol layer module receives raw coordinates fromthe mouse, formats a packet_rel structure, andthen passes it up to the relative filter.

The relative filter module implements an accelerationalgorithm, converts raw data received from the protocollevel according to the current speed parameter, and emitsthis data in the form of events to Photon.

The main part of developing a new module involvesimplementing several standard callback functions, combined“under the roof” of the module's instance ofthe input_module_t structure.

Consider implementing the following callbacks:

init()
Should be called for a one-time initialization of amodule's state after it's loaded.
reset()
Used to reset a module's and/or device's state. Youwould call it when the module is linked into an event busline; if necessary, it could be called from your code as areaction to any sort of device trouble.
input()
You usually implement this callback function in protocolmodules as part of the device-to-interface data channel.
output()
Usually called by higher-layer modules asking for datato be sent to the device. You can use this callback forpassing commands to control an input device.
pulse()
Usually implemented in device class modules. Thiscallback is automatically activated each time that aregistered interrupt handler wants to notify a device moduleabout input activity.
parm()
Called by the Input Runtime System to parse anycommand-line parameters given to the module.
devctrl()
Used by modules in an event bus line to send commands toeach other. This callback may also be called as a responseto the external devctl() call. You can use thiscallback for reconfiguring a driver on the fly.
shutdown()
Called when the Input Runtime System is shutting down.

Which callbacks are required?

To decide which callback functions should be implemented ina module, you'll need to consider the module's purpose. Ingeneral, a device module must have the followingfunctions:

  • pulse() (if it doesn't use an interrupt handler)
  • init()
  • parm()
  • devctrl()

A protocol module, in turn, must have at least theinput() function (and optionallyinit(), parm(), anddevctrl()).

Callback sequence

Drivers pctv input devices input

At startup, the Input Runtime System always calls a module'scallback functions in the following sequence:

Pctv

init()parm()reset()

If you're writing a driver for a custom type of device whereit doesn't make sense to split up the functionality ofdevice and protocol, you can write acombination module.

Drivers Pctv Input Devices Download

To do this, you simply proceed as you would when writing a“normal” driver: fill in your callbacks, talkto your device, interpret its protocol, etc.

In addition, there are two things you have to do:

  1. In the type field, put in DEVI_MODULE_TYPE_DEVICE DEVI_MODULE_TYPE_PROTOin addition to the DEVI_CLASS_ manifest.
  2. When you've interpreted the data from your device,package up a struct packet_* (depending onyour class of device) and send it up.

Because the devi-* framework is multithreaded,you should be aware of a possible reentrancy issue. When adevi-* driver is invoked, a module may bespecified multiple times, where each invocation will belongto a separate event bus line.

An example is the keyboard controller device module(kb). This module can communicate with akeyboard and with a PS/2 mouse. We would invoke the driveras follows:

Drivers Pctv Input Devices

Here we'll have two event bus lines: one for the keyboard andone for the mouse. Upon initialization, the input frameworkwill use the static kb data structure (input_module_t) for one ofthe bus lines and dynamically allocate/copy another one for theother bus line.

Drivers Pctv Input Devices Usb

If you keep your module-specific data confinedto the private data member of the module structure, you won't haveany problems with reentrancy. But if your module contains globalvariables, then you'll have to use some sort of mutual exclusionmechanism for protection.

Note that you don't have to ensure that theinit(), reset(), and parm()callbacks are reentrant, because they're always called froma single thread upon initialization. (However, if for somereason you need to call them when the runtime system is up,then you'd have to ensure that they're reentrant.) Thecallbacks used at runtime (e.g. the pulse()callback) are the ones at risk.

For more information, see the keyboard controller module code (hirun/kb.c).

Comments are closed.