![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
OverviewAs of Release 4.0, a distinction is made between those drivers that must support the sessions interface and those that need not. Those that must support this interface are said to be sessions-aware.
General Information for Sessions-Aware DriversThe new session-compliant user interface device drivers (touchscreen, buttons, sessions, ...) present their data as events that have a common header that is defined in <linux/include/linux/itsy_event.h>: typedef struct { The current classes are: and the event flags are: Events are normally created as a result of the user interacting with the hardware, such as pressing a button or the touchscreen. Some drivers additionally support synthetic events that are created programatically and passed to the driver, usually via the write() system call. These events are marked with the ITSY_EVENT_FLAG_SYNTHETIC flag by the driver. If the program that created the synthetic event has super user privileges, the ITSY_EVENT_FLAG_SUSER flag is set in the event. As mentioned in the sessions overview, events are delivered to processes that belong to the foreground session, and are not visible to processes in background sessions. However, there are times when a program may want to get events even when it is in the background (i.e., it is being executed by a process that belongs to a background session). This is accomplished by opening the appropriate raw device, making all the events from that device visible, regardless of whether the program is in the background or foreground. One type of program that would use this functionality is an application that records user interactions for later playback. This would be useful for demos or for macro creation. Some drivers also support a grab operation that allows a program to grab a resource (or set of resources) from the driver. For example, a voice recorder program may grab a specific button so the user can always record a voice memo regardless of which program is foreground. Grabbed events are only available to the grabber and to readers of the raw device. Grabbed events are marked with the ITSY_EVENT_FLAG_GRABBED flag so raw readers will know that they are from a grabbed resource. The following sections provide details for the various session-compliant Itsy device drivers:
The Analog-to-Digital Converter DriverThe UCB1200/1300 codec supports 4 analog to digital convertors (ADCs). The first one is connected to the battery on Itsy v1 and the battery's voltage can be read throught /dev/battery or /dev/adc (on a v2 the battery level can be obtained through /dev/battmon, see the Battery Monitor device driver documentation). The include file is <linux/itsy_adc.h>. The supported ioctls are: ADC_0_GET, ADC_1_GET, ADC_2_GET, ADC_3_GET. The adc returns values in the range of 0 to 1023. Here is an example: ioctl(fd, ADC_1_GET, &adc1); The Audio DriverThe Itsy audio driver supports interrupt-driven audio I/O via the Philips UCB1200/1300 codec. Both an Itsy-specific native API and the standard OSS "open sound system" API are supported. Clients may issue ioctl requests from either API, or even a mixture of both. It is recommended that clients use the OSS interface when possible for portability, and use the native interface only for operations that are not supported by OSS. Documentation for the OSS API is available from www.opensound.com. The standard Linux include file for the OSS interface is <sys/soundcard.h>. Unlike the OSS model, which generally allows only one active client, the Itsy audio driver supports any number of simultaneous clients for both microphone input and speaker output. Microphone input is replicated for all active input clients, and speaker output is mixed for all active output clients. In the current implementation, audio output from all clients in background sessions is attenuated by approximately 12 dB, resulting in substantial volume reduction. Note that the UCB1200/1300 hardware supports only a single sampling rate for both input and output. The current driver supports per-client output rates, and transparently performs sampling-rate conversion when necessary. This sample-rate conversion uses a crude linear interpolation approach; for better results, perform your own mixing in user-space by running sox or some other tool. The current implementation is also fairly inefficient, but since audio processing generally consumes less than 1% of the 200MHz Itsy CPU, we are not terribly motivated to optimize it. Sample-rate conversion is not yet implemented for microphone input; this will be supported in a future release. However, a client can use the native AUDIO_LOCK_RATE ioctl to maintain a desired rate. Subsequent requests to change the microphone sample rate by other clients will fail. The Itsy audio driver OSS implementation is intended to be complete. Although some of the less common ioctls have not been exhaustively tested, we have successfully compiled and used many applications such as sox without modification. However, memory-mapping the microphone buffer via the mmap() system call is supported only via the native API; it is currently unimplemented for OSS. The Battery DriverThe battery device (only valid on v1) provides information about the current state of the Itsy batteries. The include file is <linux/itsy_adc.h>. A single ioctl, BATTERY_GET, is supported. It returns the voltage of the battery in opaque internal units that must be converted to volts through calibration: ioctl(fd, BATTERY_GET, &bat); The Battery Monitor DriverVersion 2 itsies have a Dallas Semiconductor Smart Battery Monitor (DS2437) that provides detailed information on the state of the battery. The include file is <linux/itsy_battmon.h>. The device doesn't support reads or writes, only the ioctl interface. You should read the include file for full details.
Ioctlsioctl(fd, BATTMON_DETECT, &id);/* Detect the battery monitor and return its 64b ROM code */ ioctl(fd, BATTMON_GET_TEMP, &temp); /* Return temperature, it may take up to one second */ ioctl(fd, BATTMON_GET_VOLTAGE, &vdd); /* Return Vdd voltage (battery voltage) */ ioctl(fd, BATTMON_VET_VAD_VOLTAGE, &vad); /* Return Vad voltage (external voltage) */ ioctl(fd, BATTMON_READ_CURRENT, &cur); /* Return the value of the current register (updated 32/sec) */ ioctl(fd, BATTMON_READ_NET_CURRENT, *netcur); /* Return value of net current (ICA) register. This register is 0 when the battery is fully discharged, 100 when fully charged */ ioctl(fd, BATTMON_WRITE_NET_CURRENT, netcur); /* Set value of net current (ICA) register */ ioctl(fd, BATTMON_READ_CHARGING_CURRENT, &chargecur); /* Returns the value of the charging current (CCA) register. The CCA represents the total charging current the battery has encountered in its lifetime */ ioctl(fd, BATTMON_WRITE_CHARGING_CURRENT, chargecur); /* Set the value of CCA register */ ioctl(fd, BATTMON_READ_DISCHARGING_CURRENT, &dischargecur); /* Returns the value of the discharging current (DCA) register. The DCA represents the total discharging current the battery has encountered in its lifetime */ ioctl(fd, BATTMON_WRITE_DISCHARGING_CURRENT, dischargecur); /* Set the value of the DCA register */ ioctl(fd, BATTMON_READ_RTC, &rtc); /* Return value of RTC register. The timestamp is in units of 1 sec */ ioctl(fd, BATTMON_WRITE_RTC, rtc); /* Set the value of the RTC register */ ioctl(fd, BATTMON_READ_DISCONNECT_TIME, &disctime); /* Returns the value of the disconnect-timestamp register */ ioctl(fd, BATTMON_READ_EOC_TIME, &eoctime); /* Returns the value of the end-of-charge (EOC) register. */ The following ioctls are not directly related to the battery monitor but this seemed like the right driver to implement them. ioctl(fd, BATTMON_SET_CHARGE_RATE, rate); /* If rate != 0, set fast charge rate (500ma current). Else set slow charge rate (100ma current) */ ioctl(fd, BATTMON_GET_CHARGE_RATE, &rate); /* Returns value of charge rate as defined above */ ioctl(fd, BATTMON_SET_CORE_VOLTAGE, corev); /* If corev != 0, set core voltage to high (1.5 V) else set core voltage to low (1.23 V) */ ioctl(fd, BATTMON_GET_CORE_VOLTAGE, &corev); /* Returns value of core voltage as defined above */ The Buttons DriverThe Itsy buttons driver supports interrupt-driven button input, and additionally provides a polling-based interface for backwards compatibility with earlier drivers. The driver supports blocking and non-blocking I/O, select, asynchronous notifications, and synthetic events. Preliminary support for grabs has been implemented, but it has not been adequately tested. The include file is <linux/itsy_buttons.h>. The primary buttons devices are interrupt-driven and generate session-filtered button events that can be extracted via the read() system call: /dev/buttons buttons device A button event looks like: typedef struct { As with all itsy events, the common header field includes a timestamp and other generic information. There is only one button event type; the field common.type is always ITSY_EVENT_BUTTONS_STATE. The state field is a bitmask containing the state of each button: 0=up, 1=down. The header file <linux/buttons.h> defines symbolic names for various button masks, such as BUTTON_SIDE_TOP, BUTTON_CURSOR_RIGHT, and BUTTON_CURSOR_ANY. The backwards-compatible button devices have a polling interface (but are internally interrupt-driven). To poll the current device state, invoke the read() system call with a single unsigned long (32 bits): /dev/buttons.poll backwards-compatible polling interface
The ulong read from a polling button device is a button bitmask with the same format described above. (The use of 32 vs. 16 bits is for backwards compatibility). The buttons devices support the following ioctls, all of which are related to "grab" operations. Although grabs are implemented, they have not been adequately tested. In particular, grabs may not be properly reflected in the state obtained via the polling devices. ushort mask; On the V2 hardware, particular pairs of buttons share interrupts. Therefore, while any button is held down, the driver "polls" for any button state changes. Using the following ioctls, the polling rate, measured in jiffies, can be set by an application (but it will apply across all sessions). The polling can also be turned off or on (polling uses up a fair bit of time). ulong poll_rate; The buttons are debounced in software. Synthetic itsy_button_event events can be written to any of the buttons devices, and will be buffered for the session specified in the "sid" field. If set to the special value ITSY_SESSION_ID_FOREGROUND, the event will be sent to the current foreground session. Like real events, synthetic events are session-filtered appropriately during subsequent read() system calls by clients. The Clock Speed DriverThe processor clock can run at one of eleven clock levels, from 59.0 to 206.4Mhz (in approx 15Mhz increments). The code refers to the hardware index (0..10) rather than the actual clock speed. See Table 8.2 in the SA1100 manual concerning the clock configuration for more information. In addition, you can enable/disable "clock switching". When swtiching is enabled, the CPU runs at 2x the DRAM clock speed until the processor needs to wait for a memory operation, at which time it runs at the DRAM clock speed until the operation is completed. With clock switching disabled, the CPU always runs at the DRAM clock speed (e.g. from 30-103MHz). When the clock speed is changed, individual devices can (and should) be suspended during the speed change. You should only use the following IOCTL's:
The Display Driver. Supports framebuffer allocation, framebuffer memory maping, framebuffer deallocation, LCD control (on, off, static), etc. There are no framebuffer related events. The include file is: <linux/itsy_fb.h> and the devices are: /dev/fb /* access visible
framebuffer */
Allocating a new framebufferOpening /dev/fbclone automatically allocates a new framebuffer. This framebuffer can be accessed by memory mapping (via the mmap() system call) the file descriptor returned when /dev/fbclone is opened. The framebuffer is automatically deallocated when there are no more references to it; i.e., when all outstanding opens are closed or the process terminates.Example: /* ... other includes related to I/O */ /* The open call allocates a new framebuffer */ /* get framebuffer information. For example,
/* The first fbLcdParams.pixelDataOffset
bytes are used
Ioctlsioctl(fd, FB_LCD_ON, 0L);/* Turns the LCD on */ ioctl(fd, FB_LCD_OFF, 0L); /* Turns the LCD off */ ioctl(fd, FB_LCD_STATIC, 0L); /* Makes the LCD go into static mode */ ioctl(fd, FB_LCD_SHOW, 0L); /* Show (i.e. make this the visible framebuffer for this * session) the framebuffer represented by the file * descriptor "fd". */ ioctl(fd, FB_LCD_PARAMS, fbLcdParams); /* Get framebuffer info (w, h, depth, etc) */ The Backlight DriverThe Epson LCD display on Itsy v2 units has a built-in LED based backlight. The hardware interface only supports on/off, but different brightness levels are supported through software by turning the LEDs on and off very quickly. For example, given a cycling frequency of 50Hz and a level of 70%, then every 20ms the LEDs are turned on for 14ms and off for 6ms. The include file is <linux/itsy_bl.h>. The device doesn't support reads or writes, only the ioctl interface.
Ioctlsioctl(fd, BL_STATE_GET, &state);/* Returns 1 if the backlight is on, 0 if off */ ioctl(fd, BL_STATE_SET, state); /* Turn backlight on (state=1) or off (state=0) */ ioctl(fd, BL_FREQ_SET, freq); /* Set the cycling frequency */ ioctl(fd, BL_FREQ_GET, &freq); /* Returns the cycling frequency */ ioctl(fd, BL_LEVEL_GET, &level); /* Returns the backlight level */ ioctl(fd, BL_LEVEL_SET, level); /* Sets the backlight level */ The Keyboard DriverAny ASCII characters written to /dev/kbd will be processed as if they have been entered through the keyboard (this is what scribble uses). /dev/kbdr is the raw interface, it interprets the input characters as keycodes (see linux/include/key_map.h), this is what the screen keyboard uses. The Power Button DriverThe Itsy powerbutton driver supports interrupt-driven input for the distinguished physical powerbutton; i.e., the round white button on the face of the current Itsy prototypes (on the v2 Itsy units, the button is the one not part of the four-button cursor pad). This button is special because it is directly connected to an Itsy interrupt line; other button input is mediated by the codec. Like the ordinary buttons device, the powerbutton device generates itsy_buttons_event events that can be extracted via the read() system call. This driver is also responsible for supporting the low-power SA1100 sleep mode. In earlier releases, this button was used exclusively for entering and leaving sleep mode. This is still the default behavior, but the current driver provides additional flexibility, allowing clients to directly manage the button and its association with sleep mode. The include file is <linux/itsy_powerbutton.h>. By default, sleep mode is entered when the powerbutton is pressed. Each client may independently specify whether or not to respect this default. The device will enable the default sleep-mode behavior only when all clients agree to support it. A client may query or change its own local decision about entering sleep mode via the POWERBUTTON_GET_SLEEP and POWERBUTTON_SET_SLEEP ioctls. The global decision (across all clients) may be queried using POWERBUTTON_GET_SLEEP_ALL. Sleep mode can be requested directly from the POWERBUTTON_ENTER_SLEEP_MODE ioctl. Its argument, if non-zero, represents the amount of time it should sleep for (otherwise it will sleep until the powerbutton is pressed). Itsy v2 units also support the POWERBUTTON_ENTER_DEEP_SLEEP_MODE ioctl (a lower-power sleep mode that does not preserve the contents of DRAM). The supported ioctls are: ioctl(fd, POWERBUTTON_SET_SLEEP, 0); The Rock 'n' Scroll DriverReturns the most recent values generated by the two-axis ADXL202 accelerometer, http://www.analog.com/iMEMS/products/ADXL202.html. Read: When the caller is part of the foreground session, 8 or more bytes of data of the following form are returned: #define ADXL_SAMPLE_COUNT 1000struct ADXL_SAMPLE { int free; /* Index of first free entry */ int overflow; /* Buffer full so sample had to be flushed */ struct { unsigned int time; /* OS timer value */ unsigned int gpios; /* GPIO input values */ } samples[ ADXL_SAMPLE_COUNT ];}
Each time there is an edge transition on one or both of the gpio pins associated with the device, an interrupt occurs and an entry in the samples array is made. Each sample is of the form:
Since entries are also made when other IRQ_GPIO11_27 interrupts occur, there may be entries with no signal change. Correct operation requires that there be only one reader of this device per session. When the caller is not part of the foreground session, 0 bytes are returned. Select: Returns following the next interrupt sample generation. The Real Time Clock DriverThe real time clock driver provides three types of functions.
The Serial DriverThe serial driver conforms to the serial interface for Linux. It also provides the sleep functions: For the most recently active port
The Session Pseudo-DeviceThe Itsy session driver manages information about active Itsy sessions. It exports both kernel and character-device interfaces. The include file is <linux/itsy_session.h>. The kernel interface contains various operations to query, set, and receive callback notifications regarding sessions and changes in foreground/background status. The operation itsy_session_from_task() should be used by all session-compliant drivers to obtain the session identifier associated with a Linux task. Function-level documentation for this kernel interface is available in the include file. The normal device interface can be used by clients to obtain information about session events. It is expected that a distinguished session manager client will register itself (via the SESSION_SET_MANAGER ioctl, described below). In our current distribution, the gmanager application serves as the session manager. The manager is allowed to change the foreground session, and may also receive targeted messages from other clients (sent via the SESSION_MANAGER_REQUEST ioctl). The driver currently supports non-blocking I/O and select (support for blocking reads is planned) on the following devices: /dev/session sessions device Session events can be extracted via the read() system call, and look like: typedef struct { As with all itsy events, the common header field includes a timestamp and other generic information. The field common.type specifies the type of session event associated with the session id specified by the sid field: /* session event types */ FOREGROUND sid became foreground
session The session device supports the following ioctls: int sid; ioctl(fd, SESSION_GET_ID, &sid); typedef struct { itsy_session_info info; ioctl(fd, SESSION_GET_INFO, &info); typedef struct { itsy_session_data data; data.sid = sid_to_query; typedef struct { itsy_session_ids ids; ioctl(fd, SESSION_GET_IDS, &ids); The following ioctl is used to register or unregister the caller as the distinguished session manager: ioctl(fd, SESSION_SET_MANAGER, 0); The following manager operations are used to send Unix signals to all processes associated with the specified session id. They fail with EPERM unless the caller is the distinguished manager: ioctl(fd, SESSION_SIG_SUSPEND, sid); typedef struct { The manager request operation is used by session clients to send a request to the session manager (if one exists). The sender field is automatically set to the client's session id. The operation and data fields are opaque, and are intended to be interpreted in a manager-specific way.
itsy_session_request r;
Touchscreen DriverSupports blocking and non-blocking I/O, select, asynchronous notifications, synthetic events and grabs. The include file is: <linux/itsy_ts.h> and the touchscreen devices are: /dev/ts regular device Touchscreen events look like: typedef struct { typedef struct { Where: This is an energy efficient driver. When the touchscreen is not being pressed, it sets an interrupt so the driver can be notified when the touchscreen is pressed (and allows the MCP to go to sleep is no other device needs it). While the touchscreen in being pressed, events are created at a specified rate (default is 50/sec). When the pen (or finger) stops touching the screen, an event is created with the last (x,y) coordinates and zero pressure. The rate can be changed on a per-session basis. When a session opens the touchscreen driver for the first time, its rate is set to the default (50/sec; this can be changed by a process with super-user privileges). The session rate can be changed with the TS_SET_RATE ioctl. Every time this session becomes the foreground session, the touchscreen rate will be set to the session's specified rate. The coordinates read from the touchscreen hardware do not match the screen coordinates. The touchscreen driver maintains calibration information that is used to convert the hardware coordinates to the event coordinates read by programs. There is a global calibration and a per-client calibration (i.e., one for each open file descriptor). When a program opens the touchscreen driver, the per-client calibration is set to the global calibration. The program can later change its calibration with an ioctl. The following calibration structure is used to get or set the calibration: typedef struct { The calibration algorithm is: if (xyswap) { Note: the minp field is reserved for future use. The touchscreen driver supports the following ioctls: ts_calibration cal; ioctl(fd, TS_SET_DEFAULT_CALIBRATION, &cal) sets global calibration
int rate; /* calibration rate in events/sec */ ioctl(fd, TS_SET_DEFAULT_RATE, rate) sets global rate
The touchscreen driver supports one grabber at a time. The grabber is established by opening /dev/tsgrab and grab areas are added or deleted through ioctls. The following structure is used: typedef struct { Where p0 gives the coordinates of the upper left coordinate (and p1 of the lower right coordinate) of the rectangular area to be grabbed. Touchscreen events with x,y coordinates contained in a grabbed rectangular area (there can be more than one) are only seen by the grabber and by raw clients. The grab ioctls are: ts_grab_area garea; ioctl(fd, TS_ADD_GRAB_AREA, &garea); ioctl(fd, TS_DELETE_GRAB_AREA, id); ioctl(fd, TS_GET_GRABBER, &grabber_flag); |
![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The Itsy Project
is a joint effort of the Western Research Lab and the Systems Research Center