|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-124AC7EE-E227-5358-A755-628FFE257250" xml:lang="en"><title>HAL Handler Implementation</title><shortdesc>Describes how to implement or change a new HAL handler |
|
13 when you create a base port. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
14 <p>A HAL handler gets or sets hardware-specific settings, for example, |
|
15 the display contrast.</p> |
|
16 <p>A HAL handler is normally implemented in the kernel extension or |
|
17 a driver that provides the hardware-specific functionality. </p> |
|
18 <p>The easiest way to see the general pattern for implementing HAL |
|
19 handlers is to look at a real example. We will use the screen (i.e. |
|
20 video or LCD) driver for the template reference board, which is implemented |
|
21 in <filepath>...\template_variant\specific\lcd.cpp</filepath>. </p> |
|
22 <section id="GUID-B0EF5EC5-E7DA-5700-A187-4B8D14A3956A"><title>HAL |
|
23 handler function signature</title> <p>The HAL handler function has |
|
24 a signature that is defined by the <xref href="GUID-A65A16CA-488D-3A16-A034-F01C9C0B9D15.dita"><apiname>THalFunc</apiname></xref> typedef |
|
25 that is exported in <filepath>epoc32\include\kernel\kernel.h</filepath>. </p> <p>For example: </p> <codeblock id="GUID-0C6E606C-7916-50D3-8E89-D27BC3EB8C54" xml:space="preserve">TInt halFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)</codeblock> </section> |
|
26 <section id="GUID-217DAB35-D227-5FB7-8342-7EFD69E6CDBC"><title>Registering |
|
27 the HAL handler</title> <p>Before the handler can do anything, the |
|
28 extension or driver must register its handler for a specific HAL group. |
|
29 It does so by calling: </p> <codeblock id="GUID-0B935CC7-DA21-56A7-9BBE-F90B61EACDE0" xml:space="preserve">Kern::AddHalEntry(group, handler_func, ptr);</codeblock> <p>where: </p> <ul> |
|
30 <li id="GUID-17F56160-DFE5-5703-959F-EE93C748F74D"><p> <codeph>group</codeph> is the number of the <xref href="GUID-9AE254D4-AA60-579E-8D9D-F2797106A413.dita#GUID-9AE254D4-AA60-579E-8D9D-F2797106A413/GUID-366CC4B8-C6BD-5DCC-B55D-6D87CD5C8E64">HAL group attribute</xref> for which the HAL handler is being registered. </p> </li> |
|
31 <li id="GUID-C6D34824-AD21-514E-BC4E-EE1323E5A9C9"><p> <codeph>handler_func</codeph> is a pointer to the HAL handler function. </p> </li> |
|
32 <li id="GUID-195CE0E3-9658-51D4-B5FA-10B0263FBE60"><p> <codeph>ptr</codeph> is a pointer that is passed to the HAL handler function when it |
|
33 is called. This is usually a pointer to an object that can handle |
|
34 the specified HAL attribute. </p> </li> |
|
35 </ul> <p><note> A group can only have one handler, any attempt to |
|
36 register another handler returns an error. Typically, a driver will |
|
37 register its handler during its initialisation phase. </note></p> <p>Nearly all the functionality of the template screen driver is implemented |
|
38 in a single class, the LCD power handler object; its <codeph>DLcdPowerHandler::Create()</codeph> function is called as part of startup processing. It is this function |
|
39 that registers the HAL handler: </p> <codeblock id="GUID-09BCD8E9-60DB-5805-9A32-F5652C434AEE" xml:space="preserve">... |
|
40 // install the HAL function |
|
41 r=Kern::AddHalEntry(EHalGroupDisplay,halFunction,this); |
|
42 if (r!=KErrNone) |
|
43 return r; |
|
44 ... |
|
45 </codeblock> <p>Note that the third parameter is, in general, an optional |
|
46 pointer. It is a pointer to the current object, i.e. the <codeph>DLcdPowerHandler</codeph> object. It is this pointer that is passed on to the HAL handler |
|
47 function as its first argument. </p> </section> |
|
48 <section id="GUID-DAE573D1-EAA1-530F-93D4-0F4F8BC7EA60"><title>Common |
|
49 implementation pattern</title> <p>Using the template screen driver |
|
50 as an example, the driver provides the HAL handler for dealing with |
|
51 information related to the display HAL group, <xref href="GUID-7F299BFC-D8A5-3A5A-B8DA-39BF42C99DC6.dita"><apiname>EHalGroupDisplay</apiname></xref>. The HAL handler is the function: </p> <codeblock id="GUID-646A151D-79E3-54A8-8D52-D732C3E5F5AE" xml:space="preserve">LOCAL_C TInt halFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2) |
|
52 { |
|
53 DLcdPowerHandler* pH=(DLcdPowerHandler*)aPtr; |
|
54 return pH->HalFunction(aFunction,a1,a2); |
|
55 } |
|
56 </codeblock> <p>This is a stand-alone function. The first parameter <codeph>aPtr</codeph> is the pointer that was originally passed to the kernel |
|
57 when the HAL handler was registered via the <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-8C8DCE9D-0094-3909-8FDA-2F3134D0BC88"><apiname>Kern::AddHalEntry()</apiname></xref> call, and in this case, points to the LCD's power handler object. |
|
58 In this example, the main implementation of the HAL handler is the |
|
59 member function <codeph>HalFunction()</codeph> of the <codeph>DLcdPowerHandler</codeph> instance. </p> <p>Whether you use this kind of technique depends |
|
60 on the way your drivers are implemented, but it is a pattern that |
|
61 is also used by the digitiser and the keyboard driver, as well as |
|
62 by the Symbian implemented HAL handlers. </p> <p>The other parameters |
|
63 passed to the HAL handler function, i.e. <codeph>aFunction</codeph>, <codeph>a1</codeph>, and <codeph>a2</codeph> are the ones passed |
|
64 into a call to <xref href="GUID-9EF04FB9-B36F-3A6F-AF3F-F2238BD181E9.dita#GUID-9EF04FB9-B36F-3A6F-AF3F-F2238BD181E9/GUID-7F07C14C-E69A-3277-8BFF-0CE2A820166D"><apiname>UserSvr::HalFunction()</apiname></xref>, which itself |
|
65 is called by the various accessory functions; see <xref href="GUID-9D4B8CDF-60D7-5952-AAAF-94A3C1E8908F.dita">the Architecture</xref> of User-Side Hardware Abstraction (HAL) component. </p> <p>It's useful to note that a single HAL handler may end up being |
|
66 called as a result of calls to different accessory functions. For |
|
67 example, <codeph>ProcessDisplayCurrentModeInfo()</codeph> and <codeph>GetBacklightPresent()</codeph> are accessory functions that result |
|
68 in a call to the screen driver's HAL handler. </p> <p>To further distinguish |
|
69 between the different characteristics represented by a group, each |
|
70 group has an associated set of function-ids. The function id is the |
|
71 second parameter passed to the HAL handler function, and the most |
|
72 common pattern for an implementation is to code a simple switch statement |
|
73 based on this value. For example, the function-ids associated with |
|
74 the <xref href="GUID-7F299BFC-D8A5-3A5A-B8DA-39BF42C99DC6.dita"><apiname>EHalGroupDisplay</apiname></xref> are represented by the set |
|
75 of enum values defined by the <xref href="GUID-BB011D9B-105F-345C-9FC0-39B0BA509394.dita"><apiname>TDisplayHalFunction</apiname></xref> enum. This is a fragment taken from the template screen driver: </p> <codeblock id="GUID-F1CA7147-4659-572E-8AEB-437B7E9CA2CF" xml:space="preserve">TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2) |
|
76 { |
|
77 TInt r=KErrNone; |
|
78 switch(aFunction) |
|
79 { |
|
80 case EDisplayHalScreenInfo: |
|
81 { |
|
82 TPckgBuf<TScreenInfoV01> vPckg; |
|
83 ScreenInfo(vPckg()); |
|
84 Kern::InfoCopy(*(TDes8*)a1,vPckg); |
|
85 break; |
|
86 } |
|
87 |
|
88 case EDisplayHalWsRegisterSwitchOnScreenHandling: |
|
89 iWsSwitchOnScreen=(TBool)a1; |
|
90 break; |
|
91 |
|
92 case EDisplayHalWsSwitchOnScreen: |
|
93 WsSwitchOnScreen(); |
|
94 break; |
|
95 |
|
96 case EDisplayHalMaxDisplayContrast: |
|
97 { |
|
98 TInt mc=KMaxDisplayContrast; |
|
99 kumemput32(a1,&mc,sizeof(mc)); |
|
100 break; |
|
101 } |
|
102 ... |
|
103 default: |
|
104 r=KErrNotSupported; |
|
105 break; |
|
106 } |
|
107 ... |
|
108 }</codeblock> <p>If the HAL handler function does not deal with |
|
109 a specific function-id, then it returns <codeph>KErrNotSupported</codeph>. </p> <p>The meaning of the parameters <codeph>a1</codeph> and <codeph>a2</codeph> passed to the HAL handler depends on the group and function-id; |
|
110 see the list: <xref href="GUID-857F981E-711B-5CA8-AB37-5C700A6140FA.dita">HAL Groups and Handlers</xref> and <xref href="GUID-E49A8036-EACF-5181-91DA-AE89D3B6E815.dita">HAL Attributes and |
|
111 Function IDs</xref> for the more detail. </p> <p id="GUID-D75D3A65-590D-5716-84A7-0195DFCD1656"><b>Dealing with the |
|
112 HAL::GetAll() function</b> </p> <p>Calls that come through the <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-EF03B832-E9AA-32CF-903F-DFFA63A3E9AB"><apiname>HAL::GetAll()</apiname></xref> function must be dealt with by the HAL handler |
|
113 implementation in a particular way. </p> <p> <codeph>GetAll()</codeph> calls the HAL handler and passes -1. The HAL handler must return |
|
114 the HAL attribute value when it is passed a -1 as its parameter unless |
|
115 the handler requires additional parameters. If the handler expects |
|
116 more than one parameter then it must return the error code <codeph>KErrArgument</codeph>. </p> <p>For example, using a <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-573C49D6-7763-37AE-B2B2-4C8FB1327E21"><apiname>HAL::Get()</apiname></xref> request with the attribute <xref href="GUID-DEEDAD63-57EB-3FFC-9D1C-5AD32C424879.dita"><apiname>EDisplayBrightness</apiname></xref> returns the brightness for the <i>specified</i> device (screen). </p> <codeblock id="GUID-27357ABD-D38C-5B09-85B7-3B33440FC911" xml:space="preserve">HALArg = 0; |
|
117 ret = HAL::Get(screen, HAL::EDisplayBrightness, HALArg);</codeblock> <p>The information cannot be retrieved by the <codeph>GetAll()</codeph> function. </p> <p>When the HAL handler is expecting a value that |
|
118 specifies a particular mode or setting but receives a -1 the HAL handler |
|
119 must return the error code <xref href="GUID-0BEA3647-7888-3612-A2D3-7E27AC405E29.dita"><apiname>KErrArgument</apiname></xref> to indicate |
|
120 that an additional parameter was expected. </p><p>See <xref href="GUID-85AB6B6F-216E-3716-8A86-D0C44EE8008E.dita"><apiname>>THalImplementation</apiname></xref> and <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-EF03B832-E9AA-32CF-903F-DFFA63A3E9AB"><apiname>HAL::GetAll()</apiname></xref>.</p> </section> |
|
121 <section id="GUID-01D6179B-F1B6-5186-A96E-A1A5EDDC7A7A"><title>Context |
|
122 of the call to the HAL handler</title> <p>The HAL handler itself is |
|
123 only called by the kernel, and is the end result of a sequence that |
|
124 starts either with a call to the user interface functions provided |
|
125 by the HAL class (<xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-9454F1B2-D525-3D6D-A872-C6457CACD4FC"><apiname>HAL::Set()</apiname></xref>, <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-573C49D6-7763-37AE-B2B2-4C8FB1327E21"><apiname>HAL::Get()</apiname></xref> or <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-EF03B832-E9AA-32CF-903F-DFFA63A3E9AB"><apiname>HAL::GetAll()</apiname></xref>), or with a call to the kernel |
|
126 side <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-DA115709-A225-3E2A-BCCD-6E2BB15979B9"><apiname>Kern::HalFunction()</apiname></xref>. </p> <p>The handler runs |
|
127 on the kernel side in the context of the calling thread with no kernel |
|
128 mutexes or fast mutexes held; the calling thread is not placed into |
|
129 a critical section. It is the responsibility of the handler to do |
|
130 any thread synchronisation required. The handler returns a <xref href="GUID-7A2A43EC-6125-3BFE-834B-23C37F7B40D5.dita"><apiname>TInt</apiname></xref>, which is passed back to the user side, or the caller |
|
131 of <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-DA115709-A225-3E2A-BCCD-6E2BB15979B9"><apiname>Kern::HalFunction()</apiname></xref>. </p> </section> |
|
132 <section id="GUID-9C3570E1-50F6-5178-B9A1-99BCBB01ECA3"><title>Platform |
|
133 security</title> <p>If you are providing or porting a HAL handler, |
|
134 you need to be aware of platform security issues. In principle, for |
|
135 each call into the HAL handler, you need to check the capabilities |
|
136 of the caller's process. </p> <p>Recall that <xref href="GUID-9AE254D4-AA60-579E-8D9D-F2797106A413.dita#GUID-9AE254D4-AA60-579E-8D9D-F2797106A413/GUID-366CC4B8-C6BD-5DCC-B55D-6D87CD5C8E64">function-ids</xref> are used to distinguish between the different |
|
137 requests made on a given HAL handler. Different requests may require |
|
138 different capabilities, although many requests require no special |
|
139 capabilities. This means that each function-id is associated with |
|
140 a capability, and means that code that is dealing with a request associated |
|
141 with a specific function-id, must check the associated capability. </p> <p>For example, the screen (i.e. video or LCD) driver must check |
|
142 that the caller has the <xref href="GUID-C607209F-6FC5-31DE-8034-E5B799B857A8.dita"><apiname>ECapabilityWriteDeviceData</apiname></xref> capability before proceeding with a request to set the device's |
|
143 backlight on. This is a capability that grants write access to settings |
|
144 that control the behaviour of the device. </p> <codeblock id="GUID-AC4567DA-400E-53FB-8D90-E3D537AF68A3" xml:space="preserve">TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2) |
|
145 { |
|
146 TInt r=KErrNone; |
|
147 switch(aFunction) |
|
148 { |
|
149 ... |
|
150 case EDisplayHalSetBacklightOn: |
|
151 if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetBacklightOn"))) |
|
152 { |
|
153 return KErrPermissionDenied; |
|
154 ) |
|
155 ... |
|
156 break; |
|
157 ... |
|
158 }</codeblock> <p>To find the capabilities associated with function-ids, |
|
159 see the <xref href="GUID-E49A8036-EACF-5181-91DA-AE89D3B6E815.dita">HAL |
|
160 Attributes and Related Function IDs Tables</xref> section. Capabilities |
|
161 are documented as part of the API reference for each function-id. </p> </section> |
|
162 </conbody></concept> |