From dd09c5a28c99312ae2e2eb03ec28f2cc56bcc6d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=82=A6=E8=AF=B6?= Date: Tue, 17 May 2022 17:01:23 +0800 Subject: [PATCH] new HarmonyAppProvison configuration file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 张悦诶 --- .../connectivity/http-request.md | 4 + .../connectivity/socket-connection.md | 4 + .../dfx/hiappevent-guidelines.md | 2 +- .../apis/js-apis-abilityAccessCtrl.md | 18 +- .../reference/apis/js-apis-call.md | 38 +- .../reference/apis/js-apis-contact.md | 160 +++---- .../reference/apis/js-apis-convertxml.md | 107 ++--- .../reference/apis/js-apis-display.md | 29 +- .../reference/apis/js-apis-faultLogger.md | 8 +- .../reference/apis/js-apis-hidebug.md | 95 +++- .../reference/apis/js-apis-http.md | 24 +- .../reference/apis/js-apis-net-connection.md | 60 +-- .../reference/apis/js-apis-observer.md | 38 +- .../reference/apis/js-apis-process.md | 39 +- .../reference/apis/js-apis-radio.md | 40 +- .../apis/js-apis-resource-manager.md | 110 +++-- .../reference/apis/js-apis-screenshot.md | 12 +- .../reference/apis/js-apis-sim.md | 40 +- .../reference/apis/js-apis-sms.md | 22 +- .../reference/apis/js-apis-socket.md | 78 ++-- .../reference/apis/js-apis-usb.md | 104 ++--- .../reference/apis/js-apis-webSocket.md | 38 +- .../reference/apis/js-apis-webgl.md | 14 +- .../reference/apis/js-apis-webgl2.md | 14 +- .../reference/apis/js-apis-window.md | 434 +++++++++--------- .../OpenHarmony-c-coding-style-guide.md | 4 +- .../driver/driver-hdf-development.md | 8 +- .../driver/driver-peripherals-external-des.md | 31 +- .../driver/driver-peripherals-sensor-des.md | 2 - .../driver/driver-peripherals-touch-des.md | 6 +- .../driver/driver-platform-adc-des.md | 8 +- .../driver/driver-platform-adc-develop.md | 62 ++- .../driver/driver-platform-dac-des.md | 13 +- .../driver/driver-platform-dac-develop.md | 19 +- .../driver/driver-platform-gpio-des.md | 27 +- .../driver/driver-platform-gpio-develop.md | 64 ++- .../driver/driver-platform-hdmi-des.md | 28 +- .../driver/driver-platform-hdmi-develop.md | 30 +- .../driver/driver-platform-i2c-develop.md | 69 ++- .../driver/driver-platform-i3c-develop.md | 10 +- .../driver/driver-platform-mipicsi-develop.md | 72 ++- .../driver/driver-platform-mipidsi-des.md | 37 +- .../driver/driver-platform-mipidsi-develop.md | 64 ++- .../driver/driver-platform-mmc-develop.md | 62 ++- .../driver/driver-platform-pin-des.md | 28 +- .../driver/driver-platform-pwm-develop.md | 56 +-- .../driver-platform-regulator-develop.md | 16 +- .../driver/driver-platform-rtc-des.md | 53 ++- .../driver/driver-platform-rtc-develop.md | 69 ++- .../driver/driver-platform-spi-des.md | 57 ++- .../driver/driver-platform-spi-develop.md | 66 ++- .../driver/driver-platform-uart-des.md | 63 +-- .../driver/driver-platform-uart-develop.md | 71 ++- .../driver/driver-platform-watchdog-des.md | 29 +- .../driver-platform-watchdog-develop.md | 61 ++- en/readme/update.md | 8 +- .../ability/context-userguide.md | 87 +++- .../application-dev/ability/fa-formability.md | 7 +- .../ability/figures/contextIntroduction.png | Bin 56717 -> 52284 bytes .../ability/stage-formextension.md | 7 +- zh-cn/application-dev/media/audio-capturer.md | 4 + zh-cn/application-dev/media/audio-renderer.md | 6 + .../media/figures/audio-capturer-state.png | Bin 0 -> 29079 bytes .../media/figures/audio-renderer-state.png | Bin 0 -> 37947 bytes .../application-dev/quick-start/Readme-CN.md | 1 + .../quick-start/app-provision-structure.md | 58 ++- ...module-structure.md => stage-structure.md} | 67 +-- .../quick-start/start-overview.md | 5 +- .../quick-start/start-with-ets-low-code.md | 26 +- .../quick-start/start-with-ets.md | 21 +- .../quick-start/start-with-js-low-code.md | 26 +- .../quick-start/start-with-js.md | 22 +- .../apis/js-apis-application-ability.md | 4 +- ...is-application-abilityLifecycleCallback.md | 153 ++++++ .../js-apis-application-applicationContext.md | 71 +++ .../apis/js-apis-application-context.md | 58 +-- .../security/accesstoken-overview.md | 47 +- .../driver/driver-peripherals-audio-des.md | 168 +++---- .../driver/driver-peripherals-camera-des.md | 54 +-- .../driver/driver-peripherals-external-des.md | 50 +- .../driver-peripherals-face_auth-des.md | 2 +- .../driver/driver-peripherals-lcd-des.md | 2 +- .../driver/driver-peripherals-light-des.md | 34 +- .../driver/driver-peripherals-pinauth-des.md | 26 +- .../driver/driver-peripherals-sensor-des.md | 22 +- .../driver/driver-peripherals-touch-des.md | 6 +- .../driver/driver-peripherals-usb-des.md | 106 ++--- .../driver/driver-peripherals-vibrator-des.md | 48 +- zh-cn/device-dev/driver/driver-peripherals.md | 19 +- .../driver/driver-platform-adc-des.md | 19 +- .../driver/driver-platform-adc-develop.md | 74 +-- .../driver/driver-platform-dac-des.md | 16 +- .../driver/driver-platform-dac-develop.md | 116 ++--- .../driver/driver-platform-gpio-des.md | 6 +- .../driver/driver-platform-gpio-develop.md | 96 ++-- .../driver/driver-platform-hdmi-des.md | 24 +- .../driver/driver-platform-hdmi-develop.md | 117 +++-- .../driver/driver-platform-i2c-des.md | 26 +- .../driver/driver-platform-i2c-develop.md | 104 ++--- .../driver/driver-platform-i3c-des.md | 48 +- .../driver/driver-platform-i3c-develop.md | 125 +++-- .../driver/driver-platform-mipicsi-des.md | 8 +- .../driver/driver-platform-mipicsi-develop.md | 60 +-- .../driver/driver-platform-mipidsi-des.md | 8 +- .../driver/driver-platform-mipidsi-develop.md | 74 +-- .../driver/driver-platform-mmc-develop.md | 134 +++--- .../driver/driver-platform-pin-des.md | 88 ++-- .../driver/driver-platform-pin-develop.md | 31 +- .../driver/driver-platform-rtc-des.md | 173 ++++--- .../driver/driver-platform-rtc-develop.md | 120 ++--- ...1\345\212\250\344\272\244\344\272\222.png" | Bin 29822 -> 31702 bytes ...le\345\255\220\347\263\273\347\273\237.md" | 8 +- ...66\345\255\220\347\263\273\347\273\237.md" | 8 +- ...42\345\255\220\347\263\273\347\273\237.md" | 8 +- ...45\345\255\220\347\263\273\347\273\237.md" | 2 +- 115 files changed, 2868 insertions(+), 2557 deletions(-) create mode 100644 zh-cn/application-dev/media/figures/audio-capturer-state.png create mode 100644 zh-cn/application-dev/media/figures/audio-renderer-state.png rename zh-cn/application-dev/quick-start/{module-structure.md => stage-structure.md} (97%) create mode 100644 zh-cn/application-dev/reference/apis/js-apis-application-abilityLifecycleCallback.md create mode 100644 zh-cn/application-dev/reference/apis/js-apis-application-applicationContext.md diff --git a/en/application-dev/connectivity/http-request.md b/en/application-dev/connectivity/http-request.md index ee4610f46c..edad275307 100644 --- a/en/application-dev/connectivity/http-request.md +++ b/en/application-dev/connectivity/http-request.md @@ -71,3 +71,7 @@ httpRequest.request( } ); ``` + +## Samples +The following sample is provided to help you better understand how to develop the HTTP data request feature: +- [`Http`: HTTP Data Request (eTS) (API 8)](https://gitee.com/openharmony/app_samples/tree/master/Network/Http) diff --git a/en/application-dev/connectivity/socket-connection.md b/en/application-dev/connectivity/socket-connection.md index 98b82c8064..5f50f7bdcc 100644 --- a/en/application-dev/connectivity/socket-connection.md +++ b/en/application-dev/connectivity/socket-connection.md @@ -122,3 +122,7 @@ The implementation is similar for UDPSocket and TCPSocket. The following uses th tcp.off('close'); }, 30 * 1000); ``` + +## Samples +The following sample is provided to help you better understand how to develop the socket connection feature: +- [`Socket`: Socket Connection (eTS) (API 8)](https://gitee.com/openharmony/app_samples/tree/master/Network/Socket) diff --git a/en/application-dev/dfx/hiappevent-guidelines.md b/en/application-dev/dfx/hiappevent-guidelines.md index 17c5998788..b4d267de31 100644 --- a/en/application-dev/dfx/hiappevent-guidelines.md +++ b/en/application-dev/dfx/hiappevent-guidelines.md @@ -75,4 +75,4 @@ In this example, an application event is logged after the application startup ex The following sample is provided to help you better understand how to develop the application event logging feature: -- [`JsDotTest`: Event Logging Test (JavaScript) (API 7)](https://gitee.com/openharmony/app_samples/tree/master/DFX/JsDotTest) +- [`JsDotTest`: Event Logging Test (JavaScript) (API 8)](https://gitee.com/openharmony/app_samples/tree/master/DFX/JsDotTest) diff --git a/en/application-dev/reference/apis/js-apis-abilityAccessCtrl.md b/en/application-dev/reference/apis/js-apis-abilityAccessCtrl.md index 9f81d3aab8..874341bd76 100644 --- a/en/application-dev/reference/apis/js-apis-abilityAccessCtrl.md +++ b/en/application-dev/reference/apis/js-apis-abilityAccessCtrl.md @@ -1,11 +1,11 @@ # Ability Access Control -> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The initial APIs of this module are supported since API version 8. Newly added APIs will be marked with a superscript to indicate their earliest API version. ## Modules to Import -``` +```js import abilityAccessCtrl from '@ohos.abilityAccessCtrl' ``` @@ -26,7 +26,7 @@ Creates an **AtManager** instance, which is used for ability access control. **Example** -``` +```js var AtManager = abilityAccessCtrl.createAtManager(); ``` @@ -57,7 +57,7 @@ Checks whether an application has been granted the specified permission. This AP **Example** -``` +```js var AtManager = abilityAccessCtrl.createAtManager(); let tokenID = 0; let promise = AtManager.verifyAccessToken(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS"); @@ -92,7 +92,7 @@ Grants a user granted permission to an application. This API uses a promise to r **Example** -``` +```js var AtManager = abilityAccessCtrl.createAtManager(); let tokenID = 0; let promise = AtManager.grantUserGrantedPermission(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS"); @@ -124,7 +124,7 @@ Grants a user granted permission to an application. This API uses an asynchronou **Example** -``` +```js var AtManager = abilityAccessCtrl.createAtManager(); let tokenID = 0; let permissionFlag = 1; @@ -159,7 +159,7 @@ Revokes a user granted permission given to an application. This API uses a promi **Example** -``` +```js var AtManager = abilityAccessCtrl.createAtManager(); let tokenID = 0; let permissionFlag = 1; @@ -190,7 +190,7 @@ Revokes a user granted permission given to an application. This API uses an asyn **Example** -``` +```js var AtManager = abilityAccessCtrl.createAtManager(); let tokenID = 0; AtManager.revokeUserGrantedPermission(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS",permissionFlag, data => { @@ -223,7 +223,7 @@ Obtains the flags of the specified permission of a given application. This API u **Example** -``` +```js var AtManager = abilityAccessCtrl.createAtManager(); let tokenID = 0; let promise = AtManager.getPermissionFlags(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS"); diff --git a/en/application-dev/reference/apis/js-apis-call.md b/en/application-dev/reference/apis/js-apis-call.md index 4d2b6c07f8..cda24e954d 100644 --- a/en/application-dev/reference/apis/js-apis-call.md +++ b/en/application-dev/reference/apis/js-apis-call.md @@ -7,7 +7,7 @@ ## Modules to Import -``` +```js import call from '@ohos.telephony.call'; ``` @@ -30,7 +30,7 @@ Initiates a call. This API uses an asynchronous callback to return the execution **Example** -``` +```js call.dial("138xxxxxxxx", (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -57,7 +57,7 @@ Initiates a call. You can set call options as needed. This API uses an asynchron **Example** -``` +```js call.dial("138xxxxxxxx", { extras: false }, (err, data) => { @@ -91,7 +91,7 @@ Initiates a call. You can set call options as needed. This API uses a promise to **Example** -``` +```js let promise = call.dial("138xxxxxxxx", { extras: false }); @@ -121,7 +121,7 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **Example** -``` +```js call.makeCall("138xxxxxxxx", err => { console.log(`makeCall callback: err->${JSON.stringify(err)}`); }); @@ -152,7 +152,7 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **Example** -``` +```js let promise = call.makeCall("138xxxxxxxx"); promise.then(() => { console.log(`makeCall success`); @@ -177,7 +177,7 @@ Checks whether a call is in progress. This API uses an asynchronous callback to **Example** -``` +```js call.hasCall((err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -200,7 +200,7 @@ Checks whether a call is in progress. This API uses a promise to return the resu **Example** -``` +```js let promise = call.hasCall(); promise.then(data => { console.log(`hasCall success, promise: data->${JSON.stringify(data)}`); @@ -226,7 +226,7 @@ Obtains the call status. This API uses an asynchronous callback to return the re **Example** -``` +```js call.getCallState((err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -249,7 +249,7 @@ Obtains the call status. This API uses a promise to return the result. **Example** -``` +```js let promise = call.getCallState(); promise.then(data => { console.log(`getCallState success, promise: data->${JSON.stringify(data)}`); @@ -272,7 +272,7 @@ Checks whether a device supports voice calls. This API works in synchronous mode | ------- | ------------------------------------------------------------ | | boolean | - **true**: The device supports voice calls.
- **false**: The device does not support voice calls.| -``` +```js let result = call.hasVoiceCapability(); console.log(`hasVoiceCapability: ${JSON.stringify(result)}`); ``` @@ -294,7 +294,7 @@ Checks whether the call number of the SIM card in the specified slot is an emerg **Example** -``` +```js call.isEmergencyPhoneNumber("138xxxxxxxx", (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -319,7 +319,7 @@ Checks whether the call number of the SIM card in the specified slot is an emerg **Example** -``` +```js call.isEmergencyPhoneNumber("112", {slotId: 1}, (err, value) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -349,7 +349,7 @@ Checks whether the call number of the SIM card in the specified slot is an emerg **Example** -``` +```js let promise = call.isEmergencyPhoneNumber("138xxxxxxxx", {slotId: 1}); promise.then(data => { console.log(`isEmergencyPhoneNumber success, promise: data->${JSON.stringify(data)}`); @@ -375,7 +375,7 @@ Formats a phone number based on the specified ISO country code. This API uses an **Example** -``` +```js call.formatPhoneNumber("138xxxxxxxx", (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -400,7 +400,7 @@ Formats a phone number based on specified formatting options. This API uses an a **Example** -``` +```js call.formatPhoneNumber("138xxxxxxxx",{ countryCode: "CN" }, (err, data) => { @@ -432,7 +432,7 @@ Formats a phone number based on specified formatting options. This API uses a pr **Example** -``` +```js let promise = call.formatPhoneNumber("138xxxxxxxx", { countryCode: "CN" }); @@ -465,7 +465,7 @@ All country codes are supported. **Example** -``` +```js call.formatPhoneNumberToE164("138xxxxxxxx",{ countryCode: "CN" }, (err, data) => { @@ -501,7 +501,7 @@ All country codes are supported. **Example** -``` +```js let promise = call.formatPhoneNumberToE164("138xxxxxxxx", { countryCode: "CN" }); diff --git a/en/application-dev/reference/apis/js-apis-contact.md b/en/application-dev/reference/apis/js-apis-contact.md index 9a4574e069..610f802066 100644 --- a/en/application-dev/reference/apis/js-apis-contact.md +++ b/en/application-dev/reference/apis/js-apis-contact.md @@ -7,7 +7,7 @@ ## Modules to Import -``` +```js import contact from '@ohos.contact'; ``` @@ -29,7 +29,7 @@ Adds a contact. This API uses an asynchronous callback to return the result. **Example** - ``` + ```js contact.addContact({ fullName: {fullName: 'xxx'}, phoneNumbers: [{phoneNumber: '138xxxxxxxx'}] @@ -65,7 +65,7 @@ Adds a contact. This API uses a promise to return the result. **Example** - ``` + ```js let promise = contact.addContact({ name: {fullName: 'xxx'}, phoneNumbers: [{phoneNumber: '138xxxxxxxx'}] @@ -96,7 +96,7 @@ Deletes a contact based on the specified contact key. This API uses an asynchron **Example** - ``` + ```js contact.deleteContact('xxx', (err) => { if (err) { console.log(`deleteContact callback: err->${JSON.stringify(err)}`); @@ -129,7 +129,7 @@ Deletes a contact based on the specified contact key. This API uses a promise to **Example** - ``` + ```js let promise = contact.deleteContact('xxx'); promise.then(() => { console.log(`deleteContact success`); @@ -157,7 +157,7 @@ Updates a contact based on the specified contact information. This API uses an a **Example** - ``` + ```js contact.updateContact({ name: {fullName: 'xxx'}, phoneNumbers: [{phoneNumber: '138xxxxxxxx'}] @@ -190,7 +190,7 @@ Updates a contact based on the specified contact information and attributes. Thi **Example** - ``` + ```js contact.updateContact({ fullName: {fullName: 'xxx'}, phoneNumbers: [{phoneNumber: '138xxxxxxxx'}] @@ -229,7 +229,7 @@ Updates a contact based on the specified contact information and attributes. Thi **Example** - ``` + ```js let promise = contact.updateContact({ fullName: {fullName: 'xxx'}, phoneNumbers: [{phoneNumber: '138xxxxxxxx'}] @@ -262,7 +262,7 @@ Checks whether the ID of this contact is in the local address book. This API use **Example** - ``` + ```js contact.isLocalContact(/*id*/1, (err, data) => { if (err) { console.log(`isLocalContact callback: err->${JSON.stringify(err)}`); @@ -295,7 +295,7 @@ Checks whether the ID of this contact is in the local address book. This API use **Example** - ``` + ```js let promise = contact.isLocalContact(/*id*/1); promise.then((data) => { console.log(`isLocalContact success: data->${JSON.stringify(data)}`); @@ -323,7 +323,7 @@ Checks whether a contact is included in my card. This API uses an asynchronous c **Example** - ``` + ```js contact.isMyCard(/*id*/1, (err, data) => { if (err) { console.log(`isMyCard callback: err->${JSON.stringify(err)}`); @@ -356,7 +356,7 @@ Checks whether a contact is included in my card. This API uses a promise to retu **Example** - ``` + ```js let promise = contact.isMyCard(/*id*/1); promise.then((data) => { console.log(`isMyCard success: data->${JSON.stringify(data)}`); @@ -383,7 +383,7 @@ Queries my card. This API uses an asynchronous callback to return the result. **Example** - ``` + ```js contact.queryMyCard((err, data) => { if (err) { console.log(`queryMyCard callback: err->${JSON.stringify(err)}`); @@ -412,7 +412,7 @@ Queries my card based on the specified contact attributes. This API uses an asyn **Example** - ``` + ```js contact.queryMyCard({ attributes:['ATTR_EMAIL', 'ATTR_NAME'] }, (err, data) => { @@ -447,7 +447,7 @@ Queries my card based on the specified contact attributes. This API uses a promi **Example** - ``` + ```js let promise = contact.queryMyCard({ attributes:['ATTR_EMAIL', 'ATTR_NAME'] }); @@ -478,7 +478,7 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **Example** - ``` + ```js contact.selectContact((err, data) => { if (err) { console.log(`selectContact callback: err->${JSON.stringify(err)}`); @@ -508,7 +508,7 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **Example** - ``` + ```js let promise = contact.selectContact(); promise.then((data) => { console.log(`selectContact success: data->${JSON.stringify(data)}`); @@ -536,7 +536,7 @@ Queries a contact based on the specified key. This API uses an asynchronous call **Example** - ``` + ```js contact.queryContact('xxx', (err, data) => { if (err) { console.log(`queryContact callback: err->${JSON.stringify(err)}`); @@ -566,7 +566,7 @@ Queries contacts based on the specified key and application. This API uses an as **Example** - ``` + ```js contact.queryContact('xxx', { holderId: 0 }, (err, data) => { @@ -598,7 +598,7 @@ Queries contacts based on the specified key and attributes. This API uses an asy **Example** - ``` + ```js contact.queryContact('xxx', { attributes: ["ATTR_EMAIL", "ATTR_NAME"] }, (err, data) => { @@ -631,7 +631,7 @@ Queries contacts based on the specified key, application, and attributes. This A **Example** - ``` + ```js contact.queryContact('xxx', { holderId: 0 }, { @@ -670,7 +670,7 @@ Queries contacts based on the specified key, application, and attributes. This A **Example** - ``` + ```js let promise = contact.queryContact('xxx', { holderId: 0 }, { @@ -701,7 +701,7 @@ Queries all contacts. This API uses an asynchronous callback to return the resul **Example** - ``` + ```js contact.queryContacts((err, data) => { if (err) { console.log(`queryContacts callback: err->${JSON.stringify(err)}`); @@ -730,7 +730,7 @@ Queries all contacts based on the specified application. This API uses an asynch **Example** - ``` + ```js contact.queryContacts({ holderId: 0 }, (err, data) => { @@ -761,7 +761,7 @@ Queries all contacts based on the specified attributes. This API uses an asynchr **Example** - ``` + ```js contact.queryContacts({ attributes: ["ATTR_EMAIL", "ATTR_NAME"] }, (err, data) => { @@ -793,7 +793,7 @@ Queries all contacts based on the specified application and attributes. This API **Example** - ``` + ```js contact.queryContacts({ holderId: 0 }, { @@ -831,7 +831,7 @@ Queries all contacts based on the specified application and attributes. This API **Example** - ``` + ```js let promise = contact.queryContacts({ holderId: 0 }, { @@ -863,7 +863,7 @@ Queries contacts based on the specified phone number. This API uses an asynchron **Example** - ``` + ```js contact.queryContactsByPhoneNumber('138xxxxxxxx', (err, data) => { if (err) { console.log(`queryContactsByPhoneNumber callback: err->${JSON.stringify(err)}`); @@ -893,7 +893,7 @@ Queries contacts based on the specified phone number and application. This API u **Example** - ``` + ```js contact.queryContactsByPhoneNumber('138xxxxxxxx', { holderId: 0 }, (err, data) => { @@ -925,7 +925,7 @@ Queries contacts based on the specified phone number and attributes. This API us **Example** - ``` + ```js contact.queryContactsByPhoneNumber('138xxxxxxxx', { attributes: ["ATTR_EMAIL", "ATTR_NAME"] }, (err, data) => { @@ -958,7 +958,7 @@ Queries contacts based on the specified phone number, application, and attribute **Example** - ``` + ```js contact.queryContactsByPhoneNumber('138xxxxxxxx', { holderId: 0 }, { @@ -997,7 +997,7 @@ Queries contacts based on the specified phone number, application, and attribute **Example** - ``` + ```js let promise = contact.queryContactsByPhoneNumber('138xxxxxxxx', { holderId: 0 }, { @@ -1029,7 +1029,7 @@ Queries contacts based on the specified email address. This API uses an asynchro **Example** - ``` + ```js contact.queryContactsByEmail('xxx@email.com', (err, data) => { if (err) { console.log(`queryContactsByEmail callback: err->${JSON.stringify(err)}`); @@ -1059,7 +1059,7 @@ Queries contacts based on the specified email address and application. This API **Example** - ``` + ```js contact.queryContactsByEmail('xxx@email.com', { holderId: 0 }, (err, data) => { @@ -1091,7 +1091,7 @@ Queries contacts based on the specified email address and attributes. This API u **Example** - ``` + ```js contact.queryContactsByEmail('xxx@email.com', { attributes: ["ATTR_EMAIL", "ATTR_NAME"] }, (err, data) => { @@ -1124,7 +1124,7 @@ Queries contacts based on the specified email address, application, and attribut **Example** - ``` + ```js contact.queryContactsByEmail('xxx@email.com', { holderId: 0 }, { @@ -1163,7 +1163,7 @@ Queries contacts based on the specified email address, application, and attribut **Example** - ``` + ```js let promise = contact.queryContactsByEmail('xxx@email.com', { holderId: 0 }, { @@ -1194,7 +1194,7 @@ Queries all groups of this contact. This API uses an asynchronous callback to re **Example** - ``` + ```js contact.queryGroups((err, data) => { if (err) { console.log(`queryGroups callback: err->${JSON.stringify(err)}`); @@ -1223,7 +1223,7 @@ Queries all groups of this contact based on the specified application. This API **Example** - ``` + ```js contact.queryGroups({ holderId: 0 }, (err, data) => { @@ -1258,7 +1258,7 @@ Queries all groups of this contact based on the specified application. This API **Example** - ``` + ```js let promise = contact.queryGroups({ holderId: 0 }); @@ -1287,7 +1287,7 @@ Queries all applications that have created contacts. This API uses an asynchrono **Example** - ``` + ```js contact.queryHolders((err, data) => { if (err) { console.log(`queryHolders callback: err->${JSON.stringify(err)}`); @@ -1315,7 +1315,7 @@ Queries all applications that have created contacts. This API uses a promise to **Example** - ``` + ```js let promise = contact.queryHolders(); promise.then((data) => { console.log(`queryHolders success: data->${JSON.stringify(data)}`); @@ -1343,7 +1343,7 @@ Queries the key of a contact based on the specified contact ID. This API uses an **Example** - ``` + ```js contact.queryKey(/*id*/1, (err, data) => { if (err) { console.log(`queryKey callback: err->${JSON.stringify(err)}`); @@ -1373,7 +1373,7 @@ Queries the key of a contact based on the specified contact ID and application. **Example** - ``` + ```js contact.queryKey(id, { holderId:1 }, (err, data) => { @@ -1409,7 +1409,7 @@ Queries the key of a contact based on the specified contact ID and application. **Example** - ``` + ```js let promise = contact.queryKey(id, { holderId: 0 }); @@ -1462,7 +1462,7 @@ Defines a contact. Create contact data in JSON format: -``` +```js let myContact = { phoneNumbers: [{ phoneNumber: "138xxxxxxxx" @@ -1480,7 +1480,7 @@ let myContact = { Or, create data by configuring a new Contact object. -``` +```js let myContact = new contact.Contact(); let name = new contact.Name(); name.fullName = "fullName"; @@ -1508,7 +1508,7 @@ If **null** is passed, all attributes are queried by default. Create contact data in JSON format: -``` +```js let contactAttributes = { attributes: [ contact.Attribute.ATTR_EMAIL, @@ -1521,7 +1521,7 @@ let contactAttributes = { Or, create data by configuring a **ContactAttributes** object. -``` +```js let contactAttributes = new contact.ContactAttributes(); contactAttributes.attributes = ["ATTR_EMAIL"]; ``` @@ -1555,7 +1555,7 @@ Enumerates contact attributes. Create contact data in JSON format: -``` +```js let attributes = [contact.Attribute.ATTR_EMAIL, contact.Attribute.ATTR_NAME, contact.Attribute.ATTR_PHONE]; ``` @@ -1591,7 +1591,7 @@ Defines a contact's email. Create contact data in JSON format: -``` +```js let email = { email: "xxx@email.com", displayName: "displayName" @@ -1601,7 +1601,7 @@ let email = { Or, create data by configuring an **Email** object. -``` +```js let email = new contact.Email(); email.email = "xxx@email.com"; ``` @@ -1624,7 +1624,7 @@ Defines an application that creates the contact. Create contact data in JSON format: -``` +```js let holder = { holderId: 0 }; @@ -1632,7 +1632,7 @@ let holder = { Or, create data by configuring a **Holder** object. -``` +```js let holder = new contact.Holder(); holder.holderId = 0; ``` @@ -1668,7 +1668,7 @@ Defines a contact's event. Create contact data in JSON format: -``` +```js let event = { eventDate: "xxxxxx" }; @@ -1676,7 +1676,7 @@ let event = { Or, create data by configuring an **Event** object. -``` +```js let event = new contact.Event(); event.eventDate = "xxxxxx"; ``` @@ -1698,7 +1698,7 @@ Defines a contact group. Create contact data in JSON format: -``` +```js let group = { groupId: 1, title: "title" @@ -1707,7 +1707,7 @@ let group = { Or, create data by configuring a **Group** object. -``` +```js let group = new contact.Group(); group.title = "title"; ``` @@ -1747,7 +1747,7 @@ Enumerates IM addresses. Create contact data in JSON format: -``` +```js let imAddress = { imAddress: "imAddress", labelName: "labelName" @@ -1757,7 +1757,7 @@ let imAddress = { Or, create data by configuring an **ImAddress** object. -``` +```js let imAddress = new contact.ImAddress(); imAddress.imAddress = "imAddress"; ``` @@ -1786,7 +1786,7 @@ Defines a contact's name. Create contact data in JSON format: -``` +```js let name = { familyName: "familyName", fullName: "fullName" @@ -1795,7 +1795,7 @@ let name = { Or, create data by configuring a **Name** object. -``` +```js let name = new contact.Name(); name.familyName = "familyName"; name.fullName = "fullName"; @@ -1817,7 +1817,7 @@ Defines a contact's nickname. Create contact data in JSON format: -``` +```js let nickName = { nickName: "nickName" }; @@ -1825,7 +1825,7 @@ let nickName = { Or, create data by configuring a **NickName** object. -``` +```js let nickName = new contact.NickName(); nickName.nickName = "nickName"; ``` @@ -1846,7 +1846,7 @@ Defines a contact's note. Create contact data in JSON format: -``` +```js let note = { noteContent: "noteContent" }; @@ -1854,7 +1854,7 @@ let note = { Or, create data by configuring a **Note** object. -``` +```js let note = new contact.Note(); note.noteContent = "noteContent"; ``` @@ -1876,7 +1876,7 @@ Defines a contact's organization. Create contact data in JSON format: -``` +```js let organization = { name: "name", title: "title" @@ -1885,7 +1885,7 @@ let organization = { Or, create data by configuring an **Organization** object. -``` +```js let organization = new contact.Organization(); organization.name = "name"; organization.title = "title"; @@ -1939,7 +1939,7 @@ Defines a contact's phone number. Create contact data in JSON format: -``` +```js let phoneNumber = { phoneNumber: "138xxxxxxxx", labelId: contact.PhoneNumber.NUM_HOME @@ -1948,7 +1948,7 @@ let phoneNumber = { Or, create data by configuring a new **PhoneNumber** object. -``` +```js let phoneNumber = new contact.PhoneNumber(); phoneNumber.phoneNumber = "138xxxxxxxx"; ``` @@ -1969,7 +1969,7 @@ Defines a contact's portrait. Create contact data in JSON format: -``` +```js let portrait = { uri: "uri" }; @@ -1977,7 +1977,7 @@ let portrait = { Or, create data by configuring a new **Portrait** object. -``` +```js let portrait = new contact.Portrait(); portrait.uri = "uri"; ``` @@ -2020,7 +2020,7 @@ Defines a contact's postal address. Create contact data in JSON format: -``` +```js let postalAddress = { city: "city" }; @@ -2028,7 +2028,7 @@ let postalAddress = { Or, create data by configuring a new **PostalAddress** object. -``` +```js let postalAddress = new contact.PostalAddress(); postalAddress.city = "city"; ``` @@ -2075,7 +2075,7 @@ Defines a contact's relationship. Create contact data in JSON format: -``` +```js let relation = { relationName: "relationName", labelId: contact.Relation.RELATION_ASSISTANT @@ -2084,7 +2084,7 @@ let relation = { Or, create data by configuring a new **Relation** object. -``` +```js let relation = new contact.Relation(); relation.relationName = "relationName"; relation.labelId = contact.Relation.RELATION_ASSISTANT; @@ -2121,7 +2121,7 @@ Defines a contact's SIP address. Create contact data in JSON format: -``` +```js var sipAddress = { sipAddress: "sipAddress" }; @@ -2129,7 +2129,7 @@ var sipAddress = { Or, create data by configuring a new **SipAddress** object. -``` +```js let sipAddress = new contact.SipAddress(); sipAddress.sipAddress = "sipAddress"; ``` @@ -2150,7 +2150,7 @@ Defines a contact's website. Create contact data in JSON format: -``` +```js let website = { website: "website" }; @@ -2158,7 +2158,7 @@ let website = { Or, create data by configuring a new **Website** object. -``` +```js let website = new contact.Website(); website.website = "website"; ``` diff --git a/en/application-dev/reference/apis/js-apis-convertxml.md b/en/application-dev/reference/apis/js-apis-convertxml.md index 7bf2fc1da2..1b41a320c3 100644 --- a/en/application-dev/reference/apis/js-apis-convertxml.md +++ b/en/application-dev/reference/apis/js-apis-convertxml.md @@ -1,19 +1,15 @@ # XML-to-JavaScript Conversion -> **NOTE** +> **NOTE**
> The initial APIs of this module are supported since API version 8. Newly added APIs will be marked with a superscript to indicate their earliest API version. ## Modules to Import -``` +```js import convertxml from '@ohos.convertxml'; ``` -## System Capabilities - -SystemCapability.Utils.Lang - ## ConvertXML @@ -23,61 +19,66 @@ convert(xml: string, options?: ConvertOptions) : Object Converts an XML text into a JavaScript object. +**System capability**: SystemCapability.Utils.Lang -- Parameters - | Name| Type| Mandatory| Description| - | ------- | --------------------------------- | ---- | ------------------ | - | xml | string | Yes| XML text to convert.| - | options | [ConvertOptions](#convertoptions) | No| Settings of the convert operation.| +**Parameters** -- Return value +| Name | Type | Mandatory| Description | +| ------- | --------------------------------- | ---- | --------------- | +| xml | string | Yes | XML text to convert.| +| options | [ConvertOptions](#convertoptions) | No | Options for coversion. | - | Type| Description| - | ------ | ---------------------------- | - | Object | JavaScript object.| +**Return value** -- Example +| Type | Description | +| ------ | ---------------------------- | +| Object | JavaScript object.| - ```js - let xml = - '' + - '' + - ' Happy' + - ' Work' + - ' Play' + - ''; - let conv = new convertxml.ConvertXML(); - let options = {trim : false, declarationKey:"_declaration", - instructionKey : "_instruction", attributesKey : "_attributes", - textKey : "_text", cdataKey:"_cdata", doctypeKey : "_doctype", - commentKey : "_comment", parentKey : "_parent", typeKey : "_type", - nameKey : "_name", elementsKey : "_elements"} - let result = JSON.stringify(conv.convert(xml, options)); - console.log(result) - ``` +**Example** +```js +let xml = + '' + + '' + + ' Happy' + + ' Work' + + ' Play' + + ''; +let conv = new convertxml.ConvertXML(); +let options = {trim : false, declarationKey:"_declaration", + instructionKey : "_instruction", attributesKey : "_attributes", + textKey : "_text", cdataKey:"_cdata", doctypeKey : "_doctype", + commentKey : "_comment", parentKey : "_parent", typeKey : "_type", + nameKey : "_name", elementsKey : "_elements"} +let result = JSON.stringify(conv.convert(xml, options)); +console.log(result) +``` ## ConvertOptions -| Name| Type| Mandatory| Description| +Options for coversion. + +**System capability**: SystemCapability.Utils.Lang + +| Name | Type| Mandatory| Description | | ----------------- | -------- | ---- | ----------------------------------------------------------- | -| trim | boolean | Yes| Whether to trim the whitespace characters before and after the text. The default value is **false**.| -| ignoreDeclaration | boolean | No| Whether to ignore the XML declaration. The default value is **false**.| -| ignoreInstruction | boolean | No| Whether to ignore the XML processing instruction. The default value is **false**.| -| ignoreAttributes | boolean | No| Whether to print attributes across multiple lines and indent attributes. The default value is **false**.| -| ignoreComment | boolean | No| Whether to ignore element comments. The default value is **false**.| -| ignoreCDATA | boolean | No| Whether to ignore the element's CDATA information. The default value is **false**.| -| ignoreDoctype | boolean | No| Whether to ignore the element's Doctype information. The default value is **false**.| -| ignoreText | boolean | No| Whether to ignore the element's text information. The default value is **false**.| -| declarationKey | string | Yes| Name of the attribute key for **declaration** in the output object. The default value is **_declaration**.| -| instructionKey | string | Yes| Name of the attribute key for **instruction** in the output object. The default value is **_instruction**.| -| attributesKey | string | Yes| Name of the attribute key for **attributes** in the output object. The default value is **_attributes**.| -| textKey | string | Yes| Name of the attribute key for **text** in the output object. The default value is **_text**.| -| cdataKey | string | Yes| Name of the attribute key for **CDATA** in the output object. The default value is **_cdata**.| -| doctypeKey | string | Yes| Name of the attribute key for **Doctype** in the output object. The default value is **_doctype**.| -| commentKey | string | Yes| Name of the attribute key for **comment** in the output object. The default value is **_comment**.| -| parentKey | string | Yes| Name of the attribute key for **parent** in the output object. The default value is **_parent**.| -| typeKey | string | Yes| Name of the attribute key for **type** in the output object. The default value is **_type**.| -| nameKey | string | Yes| Name of the attribute key for **name** in the output object. The default value is **_name**.| -| elementsKey | string | Yes| Name of the attribute key for **elements** in the output object. The default value is **_elements**.| +| trim | boolean | Yes | Whether to trim the whitespace characters before and after the text. The default value is **false**. | +| ignoreDeclaration | boolean | No | Whether to ignore the XML declaration. The default value is **false**. | +| ignoreInstruction | boolean | No | Whether to ignore the XML processing instruction. The default value is **false**. | +| ignoreAttributes | boolean | No | Whether to print attributes across multiple lines and indent attributes. The default value is **false**. | +| ignoreComment | boolean | No | Whether to ignore element comments. The default value is **false**. | +| ignoreCDATA | boolean | No | Whether to ignore the element's CDATA information. The default value is **false**. | +| ignoreDoctype | boolean | No | Whether to ignore the element's Doctype information. The default value is **false**. | +| ignoreText | boolean | No | Whether to ignore the element's text information. The default value is **false**. | +| declarationKey | string | Yes | Name of the attribute key for **declaration** in the output object. The default value is **_declaration**.| +| instructionKey | string | Yes | Name of the attribute key for **instruction** in the output object. The default value is **_instruction**.| +| attributesKey | string | Yes | Name of the attribute key for **attributes** in the output object. The default value is **_attributes**. | +| textKey | string | Yes | Name of the attribute key for **text** in the output object. The default value is **_text**. | +| cdataKey | string | Yes | Name of the attribute key for **CDATA** in the output object. The default value is **_cdata**. | +| doctypeKey | string | Yes | Name of the attribute key for **Doctype** in the output object. The default value is **_doctype**. | +| commentKey | string | Yes | Name of the attribute key for **comment** in the output object. The default value is **_comment**. | +| parentKey | string | Yes | Name of the attribute key for **parent** in the output object. The default value is **_parent**. | +| typeKey | string | Yes | Name of the attribute key for **type** in the output object. The default value is **_type**. | +| nameKey | string | Yes | Name of the attribute key for **name** in the output object. The default value is **_name**. | +| elementsKey | string | Yes | Name of the attribute key for **elements** in the output object. The default value is **_elements**. | diff --git a/en/application-dev/reference/apis/js-apis-display.md b/en/application-dev/reference/apis/js-apis-display.md index 1c65dc5b71..72dfe4beb9 100644 --- a/en/application-dev/reference/apis/js-apis-display.md +++ b/en/application-dev/reference/apis/js-apis-display.md @@ -1,6 +1,6 @@ # Display -> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The initial APIs of this module are supported since API version 7. Newly added APIs will be marked with a superscript to indicate their earliest API version. ## Modules to Import @@ -58,13 +58,12 @@ Obtains the default display object. **System capabilities**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | callback | AsyncCallback<[Display](#display)> | Yes| Callback used to return the default display object.| -- Example - +**Example** ```js var displayClass = null; display.getDefaultDisplay((err, data) => { @@ -85,13 +84,13 @@ Obtains the default display object. **System capabilities**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | ---------------------------------- | ---------------------------------------------- | | Promise<[Display](#display)> | Promise used to return the default display object.| -- Example +**Example** ```js let promise = display.getDefaultDisplay(); @@ -110,13 +109,13 @@ Obtains all the display objects. **System capabilities**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ---------------------------------------------------- | ---- | ------------------------------- | | callback | AsyncCallback<Array<[Display](#display)>> | Yes | Callback used to return all the display objects.| -- Example +**Example** ```js display.getAllDisplay((err, data) => { @@ -136,13 +135,13 @@ Obtains all the display objects. **System capabilities**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | ----------------------------------------------- | ------------------------------------------------------- | | Promise<Array<[Display](#display)>> | Promise used to return an array containing all the display objects.| -- Example +**Example** ```js let promise = display.getAllDisplay(); @@ -161,14 +160,13 @@ Enables listening. **System capabilities**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | type | string | Yes| Listening type. The available values are as follows:
- **add**: listening for whether a display is added
- **remove**: listening for whether a display is removed
- **change**: listening for whether a display is changed| | callback | Callback<number> | Yes| Callback used to return the ID of the display.| -- Example - +**Example** ```js var type = "add"; var callback = (data) => { @@ -186,14 +184,13 @@ Disables listening. **System capabilities**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | type | string | Yes| Listening type. The available values are as follows:
- **add**: listening for whether a display is added
- **remove**: listening for whether a display is removed
- **change**: listening for whether a display is changed| | callback | Callback<number> | No| Callback used to return the ID of the display.| -- Example - +**Example** ```js var type = "remove"; display.off(type); diff --git a/en/application-dev/reference/apis/js-apis-faultLogger.md b/en/application-dev/reference/apis/js-apis-faultLogger.md index 1233939892..79748782fc 100644 --- a/en/application-dev/reference/apis/js-apis-faultLogger.md +++ b/en/application-dev/reference/apis/js-apis-faultLogger.md @@ -1,10 +1,10 @@ # Fault Logger -> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The initial APIs of this module are supported since API version 8. Newly added APIs will be marked with a superscript to indicate their earliest API version. ## Modules to Import -``` +```js import faultLogger from '@ohos.faultLogger' ``` @@ -56,7 +56,7 @@ Obtains the fault information about the current process. This API uses a callbac **Example** -``` +```js function queryFaultLogCallback(error, value) { if (error) { console.info('error is ' + error); @@ -101,7 +101,7 @@ Obtains the fault information about the current process. This API uses a promise **Example** -``` +```js async function getLog() { let value = await faultLogger.querySelfFaultLog(faultLogger.FaultType.JS_CRASH); if (value) { diff --git a/en/application-dev/reference/apis/js-apis-hidebug.md b/en/application-dev/reference/apis/js-apis-hidebug.md index 8aa9c1e22f..0c64cfbb3d 100644 --- a/en/application-dev/reference/apis/js-apis-hidebug.md +++ b/en/application-dev/reference/apis/js-apis-hidebug.md @@ -1,6 +1,6 @@ # HiDebug -> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The initial APIs of this module are supported since API version 8. Newly added APIs will be marked with a superscript to indicate their earliest API version. You can run the hidebug command to obtain the memory usage of an application, including the static heap memory (native heap) and proportional set size (PSS) occupied by the application process. You can also export VM memory slices and collect VM CPU profiling data. @@ -20,7 +20,7 @@ Obtains the total size of the native heap memory. **System capability**: SystemCapability.HiviewDFX.HiProfiler.HiDebug -**Return Value** +**Return value** | Type | Description | | ------ | --------------------------- | @@ -42,7 +42,7 @@ Obtains the size of the allocated native heap memory. **System capability**: SystemCapability.HiviewDFX.HiProfiler.HiDebug -**Return Value** +**Return value** | Type | Description | | ------ | --------------------------------- | | bigint | Size of the allocated native heap memory.| @@ -63,7 +63,7 @@ Obtains the size of the free native heap memory. **System capability**: SystemCapability.HiviewDFX.HiProfiler.HiDebug -**Return Value** +**Return value** | Type | Description | | ------ | ------------------------------- | | bigint | Size of the free native heap memory.| @@ -84,7 +84,7 @@ Obtains the PSS of this process. **System capability**: SystemCapability.HiviewDFX.HiProfiler.HiDebug -**Return Value** +**Return value** | Type | Description | | ------ | ------------------------- | | bigint | PSS of the process.| @@ -105,7 +105,7 @@ Obtains the size of the shared dirty memory of this process. **System capability**: SystemCapability.HiviewDFX.HiProfiler.HiDebug -**Return Value** +**Return value** | Type | Description | | ------ | -------------------------- | | bigint | Size of the shared dirty memory of the process.| @@ -116,6 +116,47 @@ Obtains the size of the shared dirty memory of this process. let sharedDirty = hidebug.getSharedDirty(); ``` +## hidebug.getPrivateDirty9+ + +getPrivateDirty(): bigint + +Obtains the size of the private dirty memory of this process. + +**System capability**: SystemCapability.HiviewDFX.HiProfiler.HiDebug + + +**Return value** +| Type | Description | +| ------ | -------------------------- | +| bigint | Size of the private dirty memory of the process.| + + +**Example** + ```js + let privateDirty = hidebug.getPrivateDirty(); + ``` + +## hidebug.getCpuUsage9+ + +getCpuUsage(): number + +Obtains the CPU usage of this process. + +For example, if the CPU usage is **50%**, **0.5** is returned. + +**System capability**: SystemCapability.HiviewDFX.HiProfiler.HiDebug + + +**Return value** +| Type | Description | +| ------ | -------------------------- | +| number | CPU usage of the process.| + + +**Example** + ```js + let cpuUsage = hidebug.getCpuUsage(); + ``` ## hidebug.startProfiling @@ -135,9 +176,9 @@ Starts the profiling method. `startProfiling()` and `stopProfiling()` are called ```js hidebug.startProfiling("cpuprofiler-20220216"); -// Code block +// code block // ... -// Code block +// code block hidebug.stopProfiling(); ``` @@ -147,7 +188,7 @@ hidebug.stopProfiling(); stopProfiling() : void -Stops the profiling method. `stopProfiling()` and `startProfiling()` are called in pairs. `stopProfiling()` always occurs after `startProfiling()`; that is, calling the functions in the following sequences is prohibited: `start->start->stop`, `start->stop->stop`, and `start->start->stop->stop`. +Stops the profiling method. `startProfiling()` and `stopProfiling()` are called in pairs. `startProfiling()` always occurs before `stopProfiling()`; that is, calling the functions in the following sequences is prohibited: `start->start->stop`, `start->stop->stop`, and `start->start->stop->stop`. **System capability**: SystemCapability.HiviewDFX.HiProfiler.HiDebug @@ -155,9 +196,9 @@ Stops the profiling method. `stopProfiling()` and `startProfiling()` are called ```js hidebug.startProfiling("cpuprofiler-20220216"); -// Code block +// code block // ... -// Code block +// code block hidebug.stopProfiling(); ``` @@ -165,13 +206,13 @@ hidebug.stopProfiling(); dumpHeapData(filename : string) : void -Exports the heap data. +Exports data from the specified heap file. **System capability**: SystemCapability.HiviewDFX.HiProfiler.HiDebug **Parameters** -| Name | Type | Mandatory| Description | +| Name | Type | Mandatory | Description | | -------- | ------ | ---- | ------------------------------------------------------------ | | filename | string | Yes | User-defined heap file name. The `filename.heapsnapshot` file is generated in the `files` directory of the app based on the specified `filename`.| @@ -180,3 +221,31 @@ Exports the heap data. ```js hidebug.dumpHeapData("heap-20220216"); ``` + +## hidebug.getServiceDump9+ + +getServiceDump(serviceid : number) : string + +Obtains information on the specified system service. + +This is a system API and cannot be called by third-party applications. + +**System capability**: SystemCapability.HiviewDFX.HiProfiler.HiDebug + +**Parameters** + +| Name | Type | Mandatory| Description | +| -------- | ------ | ---- | ------------------------------------------------------------ | +| serviceid | number | Yes | ID of the system service. | + +**Return value** +| Type | Description | +| ------ | -------------------------- | +| string | Absolute path of the file that contains the service information to dump. | + +**Example** + +```js +let serviceId = 10; +let pathName = hidebug.getServiceDump(serviceId); +``` diff --git a/en/application-dev/reference/apis/js-apis-http.md b/en/application-dev/reference/apis/js-apis-http.md index c4c8d11faf..f1ef654168 100644 --- a/en/application-dev/reference/apis/js-apis-http.md +++ b/en/application-dev/reference/apis/js-apis-http.md @@ -7,13 +7,13 @@ ## Modules to Import -``` +```js import http from '@ohos.net.http'; ``` ## Example -``` +```js import http from '@ohos.net.http'; // Each HttpRequest corresponds to an HttpRequestTask object and cannot be reused. @@ -71,7 +71,7 @@ Creates an HTTP request. You can use this API to initiate or destroy an HTTP req **Example** -``` +```js import http from '@ohos.net.http'; let httpRequest = http.createHttp(); ``` @@ -100,7 +100,7 @@ Initiates an HTTP request to a given URL. This API uses an asynchronous callback **Example** -``` +```js httpRequest.request("EXAMPLE_URL", (err, data) => { if (!err) { console.info('Result:' + data.result); @@ -133,7 +133,7 @@ Initiates an HTTP request containing specified options to a given URL. This API **Example** -``` +```js httpRequest.request("EXAMPLE_URL", { method: http.RequestMethod.GET, @@ -183,7 +183,7 @@ Initiates an HTTP request to a given URL. This API uses a promise to return the **Example** -``` +```js let promise = httpRequest.request("EXAMPLE_URL", { method: http.RequestMethod.GET, connectTimeout: 60000, @@ -214,7 +214,7 @@ Destroys an HTTP request. **Example** -``` +```js httpRequest.destroy(); ``` @@ -239,7 +239,7 @@ Registers an observer for HTTP Response Header events. **Example** -``` +```js httpRequest.on('headerReceive', (err, data) => { if (!err) { console.info('header: ' + JSON.stringify(data)); @@ -273,7 +273,7 @@ Unregisters the observer for HTTP Response Header events. **Example** -``` +```js httpRequest.off('headerReceive'); ``` @@ -294,7 +294,7 @@ Registers an observer for HTTP Response Header events. **Example** -``` +```js httpRequest.on('headersReceive', (header) => { console.info('header: ' + JSON.stringify(header)); }); @@ -322,7 +322,7 @@ Unregisters the observer for HTTP Response Header events. **Example** -``` +```js httpRequest.off('headersReceive'); ``` @@ -343,7 +343,7 @@ Registers a one-time observer for HTTP Response Header events. Once triggered, t **Example** -``` +```js httpRequest.once('headersReceive', (header) => { console.info('header: ' + JSON.stringify(header)); }); diff --git a/en/application-dev/reference/apis/js-apis-net-connection.md b/en/application-dev/reference/apis/js-apis-net-connection.md index bd4404ebc0..6e1eab82db 100644 --- a/en/application-dev/reference/apis/js-apis-net-connection.md +++ b/en/application-dev/reference/apis/js-apis-net-connection.md @@ -7,7 +7,7 @@ ## Modules to Import -```javascript +```js import connection from '@ohos.net.connection' ``` @@ -29,7 +29,7 @@ Obtains the default active data network. This API uses an asynchronous callback **Example** -```javascript +```js connection.getDefaultNet(function (error, netHandle) { console.log(JSON.stringify(error)) console.log(JSON.stringify(netHandle)) @@ -54,7 +54,7 @@ Obtains the default active data network. This API uses a promise to return the r **Example** -```javascript +```js connection.getDefaultNet().then(function (netHandle) { console.log(JSON.stringify(netHandle)) }) @@ -76,7 +76,7 @@ Checks whether the default data network is activated. This API uses an asynchron **Example** -```javascript +```js connection.hasDefaultNet(function (error, has) { console.log(JSON.stringify(error)) console.log(has) @@ -99,7 +99,7 @@ Checks whether the default data network is activated. This API uses a promise to **Example** -```javascript +```js connection.hasDefaultNet().then(function (has) { console.log(has) }) @@ -122,7 +122,7 @@ Obtains the list of all active data networks. This API uses an asynchronous call **Example** -``` +```js connection.getAllNets(function (error, nets) { console.log(JSON.stringify(error)) console.log(JSON.stringify(nets)) @@ -147,7 +147,7 @@ Obtains the list of all active data networks. This API uses a promise to return **Example** -``` +```js connection.getAllNets().then(function (nets) { console.log(JSON.stringify(nets)) }); @@ -172,7 +172,7 @@ Obtains connection properties of the network corresponding to given network hand **Example** -```javascript +```js connection.getDefaultNet().then(function (netHandle) { connection.getConnectionProperties(netHandle, function (error, info) { console.log(JSON.stringify(error)) @@ -205,7 +205,7 @@ Obtains connection properties of the network corresponding to **netHandle**. Thi **Example** -```javascript +```js connection.getDefaultNet().then(function (netHandle) { connection.getConnectionProperties(netHandle).then(function (info) { console.log(JSON.stringify(info)) @@ -232,7 +232,7 @@ Obtains capability information of the network corresponding to **netHandle**. Th **Example** -```javascript +```js connection.getDefaultNet().then(function (netHandle) { connection.getNetCapabilities(netHandle, function (error, info) { console.log(JSON.stringify(error)) @@ -265,7 +265,7 @@ Obtains capability information of the network corresponding to **netHandle**. Th **Example** -```javascript +```js connection.getDefaultNet().then(function (netHandle) { connection.getNetCapabilities(netHandle).then(function (info) { console.log(JSON.stringify(info)) @@ -291,7 +291,7 @@ Reports connection of the data network. This API uses an asynchronous callback t **Example** -``` +```js connection.getDefaultNet().then(function (netHandle) { connection.reportNetConnected(netHandle, function (error) { console.log(JSON.stringify(error)) @@ -322,7 +322,7 @@ Reports connection of the data network. This API uses a promise to return the re **Example** -``` +```js connection.getDefaultNet().then(function (netHandle) { connection.reportNetConnected(netHandle).then(function () { console.log(`report success`) @@ -349,7 +349,7 @@ Reports disconnection of the data network. This API uses an asynchronous callbac **Example** -``` +```js connection.getDefaultNet().then(function (netHandle) { connection.reportNetDisconnected(netHandle, function (error) { console.log(JSON.stringify(error)) @@ -380,7 +380,7 @@ Reports disconnection of the data network. This API uses a promise to return the **Example** -``` +```js connection.getDefaultNet().then(function (netHandle) { connection.reportNetDisconnected(netHandle).then(function () { console.log(`report success`) @@ -407,7 +407,7 @@ Resolves the host name by using the default network to obtain all IP addresses. **Example** -``` +```js let host = "xxxx"; connection.getAddressesByName(host, function (error, addresses) { console.log(JSON.stringify(error)) @@ -439,7 +439,7 @@ Resolves the host name by using the default network to obtain all IP addresses. **Example** -``` +```js let host = "xxxx"; connection.getAddressesByName(host).then(function (addresses) { console.log(JSON.stringify(addresses)) @@ -469,7 +469,7 @@ Obtains the handle of the network specified by **netSpecifier**. **Example** -```javascript +```js // Default network let netConnection = connection.createNetConnection() @@ -502,7 +502,7 @@ Registers a listener for **netAvailable** events. **Example** -```javascript +```js netConnection.on('netAvailable', function (data) { console.log(JSON.stringify(data)) }) @@ -525,7 +525,7 @@ Registers a listener for **netCapabilitiesChange** events. **Example** -```javascript +```js netConnection.on('netCapabilitiesChange', function (data) { console.log(JSON.stringify(data)) }) @@ -548,7 +548,7 @@ Registers a listener for **netConnectionPropertiesChange** events. **Example** -```javascript +```js netConnection.on('netConnectionPropertiesChange', function (data) { console.log(JSON.stringify(data)) }) @@ -571,7 +571,7 @@ Registers a listener for **netBlockStatusChange** events. **Example** -```javascript +```js netConnection.on('netBlockStatusChange', function (data) { console.log(JSON.stringify(data)) }) @@ -594,7 +594,7 @@ Registers a listener for **netLost** events. **Example** -```javascript +```js let netConnection1 = connection.createNetConnection() netConnection1.on('netLost', function (data) { console.log(JSON.stringify(data)) @@ -618,7 +618,7 @@ Registers a listener for **netUnavailable** events. **Example** -```javascript +```js netConnection.on('netUnavailable', function (data) { console.log(JSON.stringify(data)) }) @@ -642,7 +642,7 @@ Registers a listener for network status changes. **Example** -```javascript +```js netConnection.register(function (error) { console.log(JSON.stringify(error)) }) @@ -664,7 +664,7 @@ Unregisters the listener for network status changes. **Example** -```javascript +```js netConnection.unregister(function (error) { console.log(JSON.stringify(error)) }) @@ -703,7 +703,7 @@ Resolves the host name by using the corresponding network to obtain all IP addre **Example** -```javascript +```js connection.getDefaultNet().then(function (netHandle) { let host = "xxxx"; netHandle.getAddressesByName(host, function (error, addresses) { @@ -737,7 +737,7 @@ Resolves the host name by using the corresponding network to obtain all IP addre **Example** -```javascript +```js connection.getDefaultNet().then(function (netHandle) { let host = "xxxx"; netHandle.getAddressesByName(host).then(function (addresses) { @@ -765,7 +765,7 @@ Resolves the host name by using the corresponding network to obtain the first IP **Example** -```javascript +```js connection.getDefaultNet().then(function (netHandle) { let host = "xxxx"; netHandle.getAddressByName(host, function (error, address) { @@ -799,7 +799,7 @@ Resolves the host name by using the corresponding network to obtain the first IP **Example** -```javascript +```js connection.getDefaultNet().then(function (netHandle) { let host = "xxxx"; netHandle.getAddressByName(host).then(function (address) { diff --git a/en/application-dev/reference/apis/js-apis-observer.md b/en/application-dev/reference/apis/js-apis-observer.md index 29d9e85a23..b68d1dc35b 100644 --- a/en/application-dev/reference/apis/js-apis-observer.md +++ b/en/application-dev/reference/apis/js-apis-observer.md @@ -7,7 +7,7 @@ ## Modules to Import -``` +```js import observer from '@ohos.telephony.observer' ``` @@ -30,7 +30,7 @@ Registers an observer for network status change events. This API uses an asynchr **Example** -``` +```js observer.on('networkStateChange', data =>{ console.log("on networkStateChange, data:" + JSON.stringify(data)); }); @@ -57,7 +57,7 @@ Registers an observer for network status change events of the SIM card in the sp **Example** -``` +```js observer.on('networkStateChange', {slotId: 0}, data =>{ console.log("on networkStateChange, data:" + JSON.stringify(data)); }); @@ -87,7 +87,7 @@ Unregisters the observer for network status change events. This API uses an asyn **Example** -``` +```js let callback = data => { console.log("on networkStateChange, data:" + JSON.stringify(data)); } @@ -114,7 +114,7 @@ Registers an observer for signal status change events. This API uses an asynchro **Example** -``` +```js observer.on('signalInfoChange', data =>{ console.log("on signalInfoChange, data:" + JSON.stringify(data)); }); @@ -139,7 +139,7 @@ Registers an observer for signal status change events of the SIM card in the spe **Example** -``` +```js observer.on('signalInfoChange', {slotId: 0}, data =>{ console.log("on signalInfoChange, data:" + JSON.stringify(data)); }); @@ -167,7 +167,7 @@ Unregisters the observer for signal status change events. This API uses an async **Example** -``` +```js let callback = data => { console.log("on signalInfoChange, data:" + JSON.stringify(data)); } @@ -197,7 +197,7 @@ Registers an observer for call status change events. This API uses an asynchrono **Example** -``` +```js observer.on('callStateChange', value =>{ console.log("on callStateChange, state:" + value.state + ", number:" + value.number); }); @@ -224,7 +224,7 @@ Registers an observer for call status change events. This API uses an asynchrono **Example** -``` +```js observer.on('callStateChange', {slotId: 0}, value =>{ console.log("on callStateChange, state:" + value.state + ", number:" + value.number); }); @@ -254,7 +254,7 @@ Unregisters the observer for call status change events. This API uses an asynchr **Example** -``` +```js let callback = value => { console.log("on callStateChange, state:" + value.state + ", number:" + value.number); } @@ -282,7 +282,7 @@ Registers an observer for connection status change events of the cellular data l **Example** -``` +```js observer.on('cellularDataConnectionStateChange', value =>{ console.log("on cellularDataConnectionStateChange, state:" + value.state + ", network:" + value.network); }); @@ -307,7 +307,7 @@ Registers an observer for connection status change events of the cellular data l **Example** -``` +```js observer.on('cellularDataConnectionStateChange', {slotId: 0}, value =>{ console.log("on cellularDataConnectionStateChange, state:" + value.state + ", network:" + value.network); }); @@ -335,7 +335,7 @@ Unregisters the observer for connection status change events of the cellular dat **Example** -``` +```js let callback = value => { console.log("on cellularDataConnectionStateChange, state:" + value.state + ", network:" + value.network); } @@ -363,7 +363,7 @@ Registers an observer for the uplink and downlink data flow status change events **Example** -``` +```js observer.on('cellularDataFlowChange', data =>{ console.log("on networkStateChange, data:" + JSON.stringify(data)); }); @@ -388,7 +388,7 @@ Registers an observer for the uplink and downlink data flow status change events **Example** -``` +```js observer.on('cellularDataFlowChange', {slotId: 0}, data =>{ console.log("on cellularDataFlowChange, data:" + JSON.stringify(data)); }); @@ -416,7 +416,7 @@ Unregisters the observer for the uplink and downlink data flow status change eve **Example** -``` +```js let callback = data => { console.log("on cellularDataFlowChange, data:" + JSON.stringify(data)); } @@ -444,7 +444,7 @@ Registers an observer for SIM card status change events. This API uses an asynch **Example** -``` +```js observer.on('simStateChange', data =>{ console.log("on simStateChange, data:" + JSON.stringify(data)); }); @@ -469,7 +469,7 @@ Registers an observer for status change events of the SIM card in the specified **Example** -``` +```js observer.on('simStateChange', {slotId: 0}, data =>{ console.log("on simStateChange, data:" + JSON.stringify(data)); }); @@ -497,7 +497,7 @@ Unregisters the observer for SIM card status change events. This API uses an asy **Example** -``` +```js let callback = data => { console.log("on simStateChange, data:" + JSON.stringify(data)); } diff --git a/en/application-dev/reference/apis/js-apis-process.md b/en/application-dev/reference/apis/js-apis-process.md index dec8f8b8f4..e8f5549c0e 100755 --- a/en/application-dev/reference/apis/js-apis-process.md +++ b/en/application-dev/reference/apis/js-apis-process.md @@ -17,13 +17,13 @@ import process from '@ohos.process'; | Name| Type| Readable| Writable| Description| | -------- | -------- | -------- | -------- | -------- | -| egid | number | Yes| No| Effective group identifier (EGID) of a process.| -| euid | number | Yes| No| Effective user identifier (EUID) of a process.| -| gid | number | Yes| No| Group identifier (GID) of a process.| +| egid | number | Yes| No| Effective group identifier (EGID) of a process. This is a system API and cannot be called by third-party applications.| +| euid | number | Yes| No| Effective user identifier (EUID) of a process. This is a system API and cannot be called by third-party applications.| +| gid | number | Yes| No| Group identifier (GID) of a process. This is a system API and cannot be called by third-party applications.| | uid | number | Yes| No| User identifier (UID) of a process.| -| groups | number[] | Yes| No| Array with supplementary group IDs.| +| groups | number[] | Yes| No| Array with supplementary group IDs. This is a system API and cannot be called by third-party applications.| | pid | number | Yes| No| Process ID (PID) of a process.| -| ppid | number | Yes| No| Parent process ID (PPID) of a process.| +| ppid | number | Yes| No| Parent process ID (PPID) of a process. This is a system API and cannot be called by third-party applications.| | tid8+ | number | Yes| No| Thread ID (TID) of a process.| @@ -38,10 +38,10 @@ Allows a process to obtain the standard input and output of its child processes, | Name| Type| Readable| Writable| Description| | -------- | -------- | -------- | -------- | -------- | -| pid | number | Yes| No| PID of the child process.| -| ppid | number | Yes| No| PPID of the child process.| -| exitCode | number | Yes| No| Exit code of the child process.| -| killed | boolean | Yes| No| Whether the parent process successfully sends a signal to the child process to terminate it.| +| pid | number | Yes| No| PID of the child process. This is a system API and cannot be called by third-party applications.| +| ppid | number | Yes| No| PPID of the child process. This is a system API and cannot be called by third-party applications.| +| exitCode | number | Yes| No| Exit code of the child process. This is a system API and cannot be called by third-party applications.| +| killed | boolean | Yes| No| Whether the parent process successfully sends a signal to the child process to terminate it. This is a system API and cannot be called by third-party applications.| ### wait @@ -50,6 +50,8 @@ wait(): Promise<number> Waits until the child process ends. This method uses a promise to return the exit code of the child process. +This is a system API and cannot be called by third-party applications. + **System capability**: SystemCapability.Utils.Lang **Return value** @@ -75,6 +77,8 @@ getOutput(): Promise<Uint8Array> Obtains the standard output of the child process. +This is a system API and cannot be called by third-party applications. + **System capability**: SystemCapability.Utils.Lang **Return value** @@ -100,6 +104,8 @@ getErrorOutput(): Promise<Uint8Array> Obtains the standard error output of the child process. +This is a system API and cannot be called by third-party applications. + **System capability**: SystemCapability.Utils.Lang **Return value** @@ -125,6 +131,8 @@ close(): void Closes the child process in running. +This is a system API and cannot be called by third-party applications. + **System capability**: SystemCapability.Utils.Lang **Example** @@ -141,6 +149,8 @@ kill(signal: number | string): void Sends a signal to the specified child process to terminate it. +This is a system API and cannot be called by third-party applications. + **System capability**: SystemCapability.Utils.Lang **Parameters** @@ -383,6 +393,8 @@ runCmd(command: string, options?: { timeout : number, killSignal : number | stri Forks a new process to run a shell command and returns the **ChildProcess** object. +This is a system API and cannot be called by third-party applications. + **System capability**: SystemCapability.Utils.Lang **Parameters** @@ -438,6 +450,8 @@ on(type: string, listener: EventListener): void Stores the events triggered by the user. +This is a system API and cannot be called by third-party applications. + **System capability**: SystemCapability.Utils.Lang **Parameters** @@ -468,6 +482,8 @@ off(type: string): boolean Deletes the event stored by the user. +This is a system API and cannot be called by third-party applications. + **System capability**: SystemCapability.Utils.Lang **Parameters** @@ -521,6 +537,8 @@ cwd(): string Obtains the working directory of this process. +This is a system API and cannot be called by third-party applications. + **System capability**: SystemCapability.Utils.Lang **Example** @@ -536,6 +554,8 @@ chdir(dir: string): void Changes the working directory of this process. +This is a system API and cannot be called by third-party applications. + **System capability**: SystemCapability.Utils.Lang **Parameters** @@ -594,6 +614,7 @@ Sends a signal to the specified process to terminate it. | boolean | Returns **true** if the signal is sent successfully; returns **false** otherwise.| **Example** + ```js var pres = process.pid var result = that.kill(28, pres) diff --git a/en/application-dev/reference/apis/js-apis-radio.md b/en/application-dev/reference/apis/js-apis-radio.md index 468091db60..4df1f4e33d 100644 --- a/en/application-dev/reference/apis/js-apis-radio.md +++ b/en/application-dev/reference/apis/js-apis-radio.md @@ -7,7 +7,7 @@ ## Modules to Import -``` +```js import radio from '@ohos.telephony.radio' ``` @@ -30,7 +30,7 @@ Obtains the radio access technology (RAT) used by the CS and PS domains. This AP **Example** -``` +```js let slotId = 0; radio.getRadioTech(slotId, (err, data) =>{ console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); @@ -62,7 +62,7 @@ Obtains the RAT used by the CS and PS domains. This API uses a promise to return **Example** -``` +```js let slotId = 0; let promise = radio.getRadioTech(slotId); promise.then(data => { @@ -91,7 +91,7 @@ Obtains the network status. This API uses an asynchronous callback to return the **Example** -``` +```js radio.getNetworkState((err, data) =>{ console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -117,7 +117,7 @@ Obtains the network status. This API uses an asynchronous callback to return the **Example** -``` +```js let slotId = 0; radio.getNetworkState(slotId, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); @@ -149,7 +149,7 @@ Obtains the network status of the SIM card in the specified slot. This API uses **Example** -``` +```js let slotId = 0; let promise = radio.getNetworkState(slotId); promise.then(data => { @@ -177,7 +177,7 @@ Obtains the network selection mode of the SIM card in the specified slot. This A **Example** -``` +```js let slotId = 0; radio.getNetworkSelectionMode(slotId, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); @@ -207,7 +207,7 @@ Obtains the network selection mode of the SIM card in the specified slot. This A **Example** -``` +```js let slotId = 0; let promise = radio.getNetworkSelectionMode(slotId); promise.then(data => { @@ -235,7 +235,7 @@ Obtains the ISO country code of the network with which the SIM card in the speci **Example** -``` +```js let slotId = 0; radio.getISOCountryCodeForNetwork(slotId, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); @@ -265,7 +265,7 @@ Obtains the ISO country code of the network with which the SIM card in the speci **Example** -``` +```js let slotId = 0; let promise = radio.getISOCountryCodeForNetwork(slotId); promise.then(data => { @@ -292,7 +292,7 @@ Obtains the ID of the slot in which the primary card is located. This API uses a **Example** -``` +```js radio.getPrimarySlotId((err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -315,7 +315,7 @@ Obtains the ID of the slot in which the primary card is located. This API uses a **Example** -``` +```js let promise = radio.getPrimarySlotId(); promise.then(data => { console.log(`getPrimarySlotId success, promise: data->${JSON.stringify(data)}`); @@ -342,7 +342,7 @@ Obtains a list of signal strengths of the network with which the SIM card in the **Example** -``` +```js let slotId = 0; radio.getSignalInformation(slotId, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); @@ -372,7 +372,7 @@ Obtains a list of signal strengths of the network with which the SIM card in the **Example** -``` +```js let slotId = 0; let promise = radio.getSignalInformation(slotId); promise.then(data => { @@ -405,7 +405,7 @@ Checks whether the current device supports 5G \(NR\). **Example** -``` +```js let slotId = 0; let result = radio.isNrSupported(slotId); console.log(result); @@ -430,7 +430,7 @@ Checks whether the radio service is enabled on the primary SIM card. This API us **Example** -``` +```js radio.isRadioOn((err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -456,7 +456,7 @@ Checks whether the radio service is enabled on the SIM card in the specified slo **Example** -``` +```js let slotId = 0; radio.isRadioOn(slotId, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); @@ -488,7 +488,7 @@ Checks whether the radio service is enabled. This API uses a promise to return t **Example** -``` +```js let slotId = 0; let promise = radio.isRadioOn(slotId); promise.then(data => { @@ -516,7 +516,7 @@ Obtains the carrier name. This API uses an asynchronous callback to return the r **Example** -``` +```js let slotId = 0; radio.getOperatorName(slotId, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); @@ -546,7 +546,7 @@ Obtains the carrier name. This API uses a promise to return the result. **Example** -``` +```js let slotId = 0; let promise = radio.getOperatorName(slotId); promise.then(data => { diff --git a/en/application-dev/reference/apis/js-apis-resource-manager.md b/en/application-dev/reference/apis/js-apis-resource-manager.md index 19572a3c96..2effb8b20a 100644 --- a/en/application-dev/reference/apis/js-apis-resource-manager.md +++ b/en/application-dev/reference/apis/js-apis-resource-manager.md @@ -1,6 +1,8 @@ # Resource Management -> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
+The resource management module provides APIs to obtain information about the current device configuration (including the language, region, screen direction, and MCC/MNC) and device capability (including the device type and resolution). + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The initial APIs of this module are supported since API version 6. Newly added APIs will be marked with a superscript to indicate their earliest API version. @@ -14,14 +16,14 @@ import resourceManager from '@ohos.resourceManager'; getResourceManager(callback: AsyncCallback<ResourceManager>): void -Obtains the **ResourceManager** object of this application. This method uses a callback to return the result. +Obtains the **ResourceManager** object of this application. This API uses a callback to return the result. **System capability**: SystemCapability.Global.ResourceManager **Parameters** | Name | Type | Mandatory | Description | | -------- | ---------------------------------------- | ---- | ----------------------------- | -| callback | AsyncCallback<[ResourceManager](#resourcemanager)> | Yes | Callback used to return the **ResourceManager** object obtained.| +| callback | AsyncCallback<[ResourceManager](#resourcemanager)> | Yes | Asynchronous callback used to return the **ResourceManager** object obtained.| **Example** ``` @@ -45,7 +47,7 @@ Obtains the **ResourceManager** object of this application. This method uses a c getResourceManager(bundleName: string, callback: AsyncCallback<ResourceManager>): void -Obtains the **ResourceManager** object of an application. This method uses an asynchronous callback to return the result. +Obtains the **ResourceManager** object of an application. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -53,7 +55,7 @@ Obtains the **ResourceManager** object of an application. This method uses an as | Name | Type | Mandatory | Description | | ---------- | ---------------------------------------- | ---- | ----------------------------- | | bundleName | string | Yes | Bundle name of the target application. | -| callback | AsyncCallback<[ResourceManager](#resourcemanager)> | Yes | Callback used to return the **ResourceManager** object obtained.| +| callback | AsyncCallback<[ResourceManager](#resourcemanager)> | Yes | Asynchronous callback used to return the **ResourceManager** object obtained.| **Example** ``` @@ -66,7 +68,7 @@ Obtains the **ResourceManager** object of an application. This method uses an as getResourceManager(): Promise<ResourceManager> -Obtains the **ResourceManager** object of this application. This method uses a promise to return the result. +Obtains the **ResourceManager** object of this application. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -95,7 +97,7 @@ Obtains the **ResourceManager** object of this application. This method uses a p getResourceManager(bundleName: string): Promise<ResourceManager> -Obtains the **ResourceManager** object of an application. This method uses a promise to return the result. +Obtains the **ResourceManager** object of an application. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -139,12 +141,12 @@ Enumerates the device types. | Name | Default Value | Description | | -------------------- | ---- | ---- | -| DEVICE_TYPE_PHONE | 0x00 | Mobile phone. | -| DEVICE_TYPE_TABLET | 0x01 | Tablet. | -| DEVICE_TYPE_CAR | 0x02 | Automobile. | -| DEVICE_TYPE_PC | 0x03 | Computer. | -| DEVICE_TYPE_TV | 0x04 | TV. | -| DEVICE_TYPE_WEARABLE | 0x06 | Wearable. | +| DEVICE_TYPE_PHONE | 0x00 | Phone | +| DEVICE_TYPE_TABLET | 0x01 | Tablet | +| DEVICE_TYPE_CAR | 0x02 | Head unit | +| DEVICE_TYPE_PC | 0x03 | PC | +| DEVICE_TYPE_TV | 0x04 | TV | +| DEVICE_TYPE_WEARABLE | 0x06 | Wearable | ## ScreenDensity @@ -175,6 +177,16 @@ Defines the device configuration. | direction | [Direction](#direction) | Yes | No | Screen direction of the device.| | locale | string | Yes | No | Current system language. | +**Example** + + ``` +resourceManager.getResourceManager((error, mgr) => { + mgr.getConfiguration((error, value) => { + console.log(value.direction); + console.log(value.locale); + }); + }); + ``` ## DeviceCapability @@ -188,6 +200,16 @@ Defines the device capability. | screenDensity | [ScreenDensity](#screendensity) | Yes | No | Screen density of the device.| | deviceType | [DeviceType](#devicetype) | Yes | No | Type of the device. | +**Example** + + ``` +resourceManager.getResourceManager((error, mgr) => { + mgr.getDeviceCapability((error, value) => { + console.log(value.screenDensity); + console.log(value.deviceType); + }); + }); + ``` ## RawFileDescriptor8+ @@ -205,7 +227,7 @@ Defines the descriptor information of the raw file.
Defines the capability of accessing application resources. -> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
+> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> - The methods involved in **ResourceManager** are applicable only to the TypeScript-based declarative development paradigm. > > - Resource files are defined in the **resources** directory of the project. You can obtain the resource ID using **$r(resource address).id**, for example, **$r('app.string.test').id**. @@ -215,7 +237,7 @@ Defines the capability of accessing application resources. getString(resId: number, callback: AsyncCallback<string>): void -Obtains the string corresponding to the specified resource ID. This method uses an asynchronous callback to return the result. +Obtains the string corresponding to the specified resource ID. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -223,7 +245,7 @@ Obtains the string corresponding to the specified resource ID. This method uses | Name | Type | Mandatory | Description | | -------- | --------------------------- | ---- | --------------- | | resId | number | Yes | Resource ID. | -| callback | AsyncCallback<string> | Yes | Callback used to return the string obtained.| +| callback | AsyncCallback<string> | Yes | Asynchronous callback used to return the obtained string.| **Example** ``` @@ -243,7 +265,7 @@ Obtains the string corresponding to the specified resource ID. This method uses getString(resId: number): Promise<string> -Obtains the string corresponding to the specified resource ID. This method uses a promise to return the result. +Obtains the string corresponding to the specified resource ID. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -273,7 +295,7 @@ Obtains the string corresponding to the specified resource ID. This method uses getStringArray(resId: number, callback: AsyncCallback<Array<string>>): void -Obtains the array of strings corresponding to the specified resource ID. This method uses an asynchronous callback to return the result. +Obtains the array of strings corresponding to the specified resource ID. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -281,7 +303,7 @@ Obtains the array of strings corresponding to the specified resource ID. This me | Name | Type | Mandatory | Description | | -------- | ---------------------------------------- | ---- | ----------------- | | resId | number | Yes | Resource ID. | -| callback | AsyncCallback<Array<string>> | Yes | Callback used to return the obtained array of strings.| +| callback | AsyncCallback<Array<string>> | Yes | Asynchronous callback used to return the obtained array of strings.| **Example** ``` @@ -301,7 +323,7 @@ Obtains the array of strings corresponding to the specified resource ID. This me getStringArray(resId: number): Promise<Array<string>> -Obtains the array of strings corresponding to the specified resource ID. This method uses a promise to return the result. +Obtains the array of strings corresponding to the specified resource ID. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -331,7 +353,7 @@ Obtains the array of strings corresponding to the specified resource ID. This me getMedia(resId: number, callback: AsyncCallback<Uint8Array>): void -Obtains the content of the media file corresponding to the specified resource ID. This method uses an asynchronous callback to return the result. +Obtains the content of the media file corresponding to the specified resource ID. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -339,7 +361,7 @@ Obtains the content of the media file corresponding to the specified resource ID | Name | Type | Mandatory | Description | | -------- | ------------------------------- | ---- | ------------------ | | resId | number | Yes | Resource ID. | -| callback | AsyncCallback<Uint8Array> | Yes | Callback used to return the content of the media file obtained.| +| callback | AsyncCallback<Uint8Array> | Yes | Asynchronous callback used to return the content of the media file obtained.| **Example** ``` @@ -359,7 +381,7 @@ Obtains the content of the media file corresponding to the specified resource ID getMedia(resId: number): Promise<Uint8Array> -Obtains the content of the media file corresponding to the specified resource ID. This method uses a promise to return the result. +Obtains the content of the media file corresponding to the specified resource ID. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -389,7 +411,7 @@ Obtains the content of the media file corresponding to the specified resource ID getMediaBase64(resId: number, callback: AsyncCallback<string>): void -Obtains the Base64 code of the image corresponding to the specified resource ID. This method uses an asynchronous callback to return the result. +Obtains the Base64 code of the image corresponding to the specified resource ID. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -397,7 +419,7 @@ Obtains the Base64 code of the image corresponding to the specified resource ID. | Name | Type | Mandatory | Description | | -------- | --------------------------- | ---- | ------------------------ | | resId | number | Yes | Resource ID. | -| callback | AsyncCallback<string> | Yes | Callback used to return the Base64 code of the image obtained.| +| callback | AsyncCallback<string> | Yes | Asynchronous callback used to return the Base64 code of the image obtained.| **Example** ``` @@ -417,7 +439,7 @@ Obtains the Base64 code of the image corresponding to the specified resource ID. getMediaBase64(resId: number): Promise<string> -Obtains the Base64 code of the image corresponding to the specified resource ID. This method uses a promise to return the result. +Obtains the Base64 code of the image corresponding to the specified resource ID. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -447,14 +469,14 @@ Obtains the Base64 code of the image corresponding to the specified resource ID. getConfiguration(callback: AsyncCallback<Configuration>): void -Obtains the device configuration. This method uses an asynchronous callback to return the result. +Obtains the device configuration. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager **Parameters** | Name | Type | Mandatory | Description | | -------- | ---------------------------------------- | ---- | ------------------------- | -| callback | AsyncCallback<[Configuration](#configuration)> | Yes | Callback used to return the obtained device configuration.| +| callback | AsyncCallback<[Configuration](#configuration)> | Yes | Asynchronous callback used to return the obtained device configuration.| **Example** ``` @@ -474,7 +496,7 @@ Obtains the device configuration. This method uses an asynchronous callback to r getConfiguration(): Promise<Configuration> -Obtains the device configuration. This method uses a promise to return the result. +Obtains the device configuration. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -499,14 +521,14 @@ Obtains the device configuration. This method uses a promise to return the resul getDeviceCapability(callback: AsyncCallback<DeviceCapability>): void -Obtains the device capability. This method uses an asynchronous callback to return the result. +Obtains the device capability. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager **Parameters** | Name | Type | Mandatory | Description | | -------- | ---------------------------------------- | ---- | ---------------------------- | -| callback | AsyncCallback<[DeviceCapability](#devicecapability)> | Yes | Callback used to return the obtained device capability.| +| callback | AsyncCallback<[DeviceCapability](#devicecapability)> | Yes | Asynchronous callback used to return the obtained device capability.| **Example** ``` @@ -526,7 +548,7 @@ Obtains the device capability. This method uses an asynchronous callback to retu getDeviceCapability(): Promise<DeviceCapability> -Obtains the device capability. This method uses a promise to return the result. +Obtains the device capability. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -551,7 +573,7 @@ Obtains the device capability. This method uses a promise to return the result. getPluralString(resId: number, num: number, callback: AsyncCallback<string>): void -Obtains the specified number of singular-plural strings corresponding to the specified resource ID. This method uses an asynchronous callback to return the result. +Obtains the specified number of singular-plural strings corresponding to the specified resource ID. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -560,7 +582,7 @@ Obtains the specified number of singular-plural strings corresponding to the spe | -------- | --------------------------- | ---- | ------------------------------- | | resId | number | Yes | Resource ID. | | num | number | Yes | Number that determines the plural or singular form. | -| callback | AsyncCallback<string> | Yes | Callback used to return the singular-plural string obtained.| +| callback | AsyncCallback<string> | Yes | Asynchronous callback used to return the singular-plural string obtained.| **Example** ``` @@ -580,7 +602,7 @@ Obtains the specified number of singular-plural strings corresponding to the spe getPluralString(resId: number, num: number): Promise<string> -Obtains the specified number of singular-plural strings corresponding to the specified resource ID. This method uses a promise to return the result. +Obtains the specified number of singular-plural strings corresponding to the specified resource ID. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -610,7 +632,7 @@ Obtains the specified number of singular-plural strings corresponding to the spe getRawFile(path: string, callback: AsyncCallback<Uint8Array>): void -Obtains the content of the raw file in the specified path. This method uses an asynchronous callback to return the result. +Obtains the content of rawfile in the specified path. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -618,7 +640,7 @@ Obtains the content of the raw file in the specified path. This method uses an a | Name | Type | Mandatory | Description | | -------- | ------------------------------- | ---- | ----------------------- | | path | string | Yes | Path of the raw file. | -| callback | AsyncCallback<Uint8Array> | Yes | Callback used to return the raw file content, in byte arrays.| +| callback | AsyncCallback<Uint8Array> | Yes | Asynchronous callback used to return the raw file content, in byte arrays.| **Example** ``` @@ -637,7 +659,7 @@ Obtains the content of the raw file in the specified path. This method uses an a getRawFile(path: string): Promise<Uint8Array> -Obtains the content of the raw file in the specified path. This method uses a promise to return the result. +Obtains the content of the raw file in the specified path. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -666,7 +688,7 @@ Obtains the content of the raw file in the specified path. This method uses a pr getRawFileDescriptor(path: string, callback: AsyncCallback<RawFileDescriptor>): void -Obtains the descriptor of the raw file in the specified path. This method uses an asynchronous callback to return the result. +Obtains the descriptor of the raw file in the specified path. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -674,7 +696,7 @@ Obtains the descriptor of the raw file in the specified path. This method uses a | Name | Type | Mandatory | Description | | -------- | ---------------------------------------- | ---- | -------------------------------- | | path | string | Yes | Path of the raw file. | -| callback | AsyncCallback<[RawFileDescriptor](#rawfiledescriptor8)> | Yes | Callback used to return the raw file descriptor.| +| callback | AsyncCallback<[RawFileDescriptor](#rawfiledescriptor8)> | Yes | Asynchronous callback used to return the raw file descriptor.| **Example** ``` @@ -695,7 +717,7 @@ Obtains the descriptor of the raw file in the specified path. This method uses a getRawFileDescriptor(path: string): Promise<RawFileDescriptor> -Obtains the descriptor of the raw file in the specified path. This method uses a promise to return the result. +Obtains the descriptor of the raw file in the specified path. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -726,7 +748,7 @@ Obtains the descriptor of the raw file in the specified path. This method uses a closeRawFileDescriptor(path: string, callback: AsyncCallback<void>): void -Closes the descriptor of the raw file in the specified path. This method uses an asynchronous callback to return the result. +Closes the descriptor of the raw file in the specified path. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.Global.ResourceManager @@ -734,7 +756,7 @@ Closes the descriptor of the raw file in the specified path. This method uses an | Name | Type | Mandatory | Description | | -------- | ------------------------- | ---- | ----------- | | path | string | Yes | Path of the raw file.| -| callback | AsyncCallback<void> | Yes | Callback used to return the result. | +| callback | AsyncCallback<void> | Yes | Asynchronous callback used to return the result. | **Example** ``` @@ -751,7 +773,7 @@ Closes the descriptor of the raw file in the specified path. This method uses an closeRawFileDescriptor(path: string): Promise<void> -Closes the descriptor of the raw file in the specified path. This method uses a promise to return the result. +Closes the descriptor of the raw file in the specified path. This API uses a promise to return the result. **System capability**: SystemCapability.Global.ResourceManager diff --git a/en/application-dev/reference/apis/js-apis-screenshot.md b/en/application-dev/reference/apis/js-apis-screenshot.md index 59e34a4d8e..cd33c37764 100644 --- a/en/application-dev/reference/apis/js-apis-screenshot.md +++ b/en/application-dev/reference/apis/js-apis-screenshot.md @@ -1,6 +1,6 @@ # Screenshot -> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The initial APIs of this module are supported since API version 7. Newly added APIs will be marked with a superscript to indicate their earliest API version. ## Modules to Import @@ -58,14 +58,14 @@ Takes a screenshot and saves it as a **PixelMap** object. This method uses a cal **Required permissions**: ohos.permission.CAPTURE_SCREEN -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | --------------------------------------- | ---- | ------------------------------------------------------------ | | options | [ScreenshotOptions](#screenshotoptions) | No | Screenshot options, which consist of **screenRect**, **imageSize**, and **rotation**. You need to set these parameters.| | callback | AsyncCallback<image.PixelMap> | Yes | Callback used to return a **PixelMap** object. | -- Example +**Example** ```js var ScreenshotOptions = { @@ -98,19 +98,19 @@ Takes a screenshot and saves it as a **PixelMap** object. This method uses a pro **Required permissions**: ohos.permission.CAPTURE_SCREEN -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ------- | --------------------------------------- | ---- | ------------------------------------------------------------ | | options | [ScreenshotOptions](#screenshotoptions) | No | Screenshot options, which consist of **screenRect**, **imageSize**, and **rotation**. You need to set these parameters.| -- Return value +**Return value** | Type | Description | | ----------------------------- | ----------------------------------------------- | | Promise<image.PixelMap> | Promise used to return an **image.PixelMap** object.| -- Example +**Example** ```js var ScreenshotOptions = { diff --git a/en/application-dev/reference/apis/js-apis-sim.md b/en/application-dev/reference/apis/js-apis-sim.md index 85e895952f..f1f20e8d81 100644 --- a/en/application-dev/reference/apis/js-apis-sim.md +++ b/en/application-dev/reference/apis/js-apis-sim.md @@ -7,7 +7,7 @@ ## Modules to Import -``` +```js import sim from '@ohos.telephony.sim'; ``` @@ -28,7 +28,7 @@ Checks whether the SIM card in the specified slot is activated. This API uses an **Example** -``` +```js sim.isSimActive(0, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -57,7 +57,7 @@ Checks whether the SIM card in the specified slot is activated. This API uses a **Example** -``` +```js let promise = sim.isSimActive(0); promise.then(data => { console.log(`isSimActive success, promise: data->${JSON.stringify(data)}`); @@ -83,7 +83,7 @@ Obtains the default slot ID of the SIM card that provides voice services. This A **Example** -``` +```js sim.getDefaultVoiceSlotId((err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -106,7 +106,7 @@ Obtains the default slot ID of the SIM card that provides voice services. This A **Example** -``` +```js let promise = sim.getDefaultVoiceSlotId(); promise.then(data => { console.log(`getDefaultVoiceSlotId success, promise: data->${JSON.stringify(data)}`); @@ -132,7 +132,7 @@ Checks whether the application (caller) has been granted the operator permission **Example** -``` +```js sim.hasOperatorPrivileges(0, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -160,7 +160,7 @@ Checks whether the application (caller) has been granted the operator permission **Example** -``` +```js let promise = sim.hasOperatorPrivileges(0); promise.then(data => { console.log(`hasOperatorPrivileges success, promise: data->${JSON.stringify(data)}`); @@ -186,7 +186,7 @@ Obtains the ISO country code of the SIM card in the specified slot. This API use **Example** -``` +```js sim.getISOCountryCodeForSim(0, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -215,7 +215,7 @@ Obtains the ISO country code of the SIM card in the specified slot. This API use **Example** -``` +```js let promise = sim.getISOCountryCodeForSim(0); promise.then(data => { console.log(`getISOCountryCodeForSim success, promise: data->${JSON.stringify(data)}`); @@ -242,7 +242,7 @@ Obtains the public land mobile network (PLMN) ID of the SIM card in the specifie **Example** -``` +```js sim.getSimOperatorNumeric(0, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -271,7 +271,7 @@ Obtains the PLMN ID of the SIM card in the specified slot. This API uses a promi **Example** -``` +```js let promise = sim.getSimOperatorNumeric(0); promise.then(data => { console.log(`getSimOperatorNumeric success, promise: data->${JSON.stringify(data)}`); @@ -298,7 +298,7 @@ Obtains the service provider name (SPN) of the SIM card in the specified slot. T **Example** -``` +```js sim.getSimSpn(0, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -327,7 +327,7 @@ Obtains the SPN of the SIM card in the specified slot. This API uses a promise t **Example** -``` +```js let promise = sim.getSimSpn(0); promise.then(data => { console.log(`getSimSpn success, promise: data->${JSON.stringify(data)}`); @@ -354,7 +354,7 @@ Obtains the status of the SIM card in the specified slot. This API uses an async **Example** -``` +```js sim.getSimState(0, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -383,7 +383,7 @@ Obtains the status of the SIM card in the specified slot. This API uses a promis **Example** -``` +```js let promise = sim.getSimState(0); promise.then(data => { console.log(`getSimState success, promise: data->${JSON.stringify(data)}`); @@ -409,7 +409,7 @@ Obtains the type of the SIM card in the specified slot. This API uses an asynchr **Example** -``` +```js sim.getCardType(0, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -438,7 +438,7 @@ Obtains the type of the SIM card in the specified slot. This API uses a promise **Example** -``` +```js let promise = sim.getCardType(0); promise.then(data => { console.log(`getCardType success, promise: data->${JSON.stringify(data)}`); @@ -465,7 +465,7 @@ Checks whether the SIM card in the specified slot is installed. This API uses an **Example** -``` +```js sim.hasSimCard(0, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -494,7 +494,7 @@ Checks whether the SIM card in the specified slot is installed. This API uses a **Example** -``` +```js let promise = sim.hasSimCard(0); promise.then(data => { console.log(`hasSimCard success, promise: data->${JSON.stringify(data)}`); @@ -520,7 +520,7 @@ Obtains the number of card slots. **Example** -``` +```js console.log(sim.getMaxSimCount()) ``` diff --git a/en/application-dev/reference/apis/js-apis-sms.md b/en/application-dev/reference/apis/js-apis-sms.md index e874588b5e..85e8f3f411 100644 --- a/en/application-dev/reference/apis/js-apis-sms.md +++ b/en/application-dev/reference/apis/js-apis-sms.md @@ -6,7 +6,7 @@ ## Modules to Import -``` +```js import sms from '@ohos.telephony.sms'; ``` @@ -28,7 +28,7 @@ Creates an SMS message instance based on the protocol data unit (PDU) and the sp **Example** -``` +```js const specification = '3gpp'; // Display PDUs using numbers in an array, for example, [0x08, 0x91, ...]. const pdu = [0x08, 0x91]; @@ -61,7 +61,7 @@ Creates an SMS message instance based on the PDU and the specified SMS protocol. **Example** -``` +```js const specification = '3gpp'; // Display PDUs using numbers in an array, for example, [0x08, 0x91, ...]. const pdu = [0x08, 0x91]; @@ -91,7 +91,7 @@ Sends an SMS message. **Example** -``` +```js let sendCallback = function (err, data) { console.log(`sendCallback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); } @@ -124,7 +124,7 @@ Obtains the default slot of the SIM card used to send SMS messages. This API use **Example** -``` +```js sms.getDefaultSmsSlotId((err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); }); @@ -147,7 +147,7 @@ Obtains the default slot of the SIM card used to send SMS messages. This API use **Example** -``` +```js let promise = sms.getDefaultSmsSlotId(); promise.then(data => { console.log(`getDefaultSmsSlotId success, promise: data->${JSON.stringify(data)}`); @@ -179,7 +179,7 @@ This is a system API and cannot be called by third-party applications. **Example** -``` +```js let slotId = 0; let smscAddr = '+861xxxxxxxxxx'; sms.setSmscAddr(slotId, smscAddr, (err,data) => { @@ -215,7 +215,7 @@ This is a system API and cannot be called by third-party applications. **Example** -``` +```js let slotId = 0; let smscAddr = '+861xxxxxxxxxx'; let promise = sms.setSmscAddr(slotId, smscAddr); @@ -248,7 +248,7 @@ This is a system API and cannot be called by third-party applications. **Example** -``` +```js let slotId = 0; sms.getSmscAddr(slotId, (err, data) => { console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); @@ -282,7 +282,7 @@ This is a system API and cannot be called by third-party applications. **Example** -``` +```js let slotId = 0; let promise = sms.getSmscAddr(slotId); promise.then(data => { @@ -306,7 +306,7 @@ Checks whether the current device can send and receive SMS messages. This API wo | ------- | ------------------------------------------------------------ | | boolean | - **true**: The device can send and receive SMS messages.
- **false**: The device cannot send or receive SMS messages.| -``` +```js let result = sms.hasSmsCapability(); console.log(`hasSmsCapability: ${JSON.stringify(result)}`); ``` diff --git a/en/application-dev/reference/apis/js-apis-socket.md b/en/application-dev/reference/apis/js-apis-socket.md index dcaf0416c8..2c83bd2e48 100644 --- a/en/application-dev/reference/apis/js-apis-socket.md +++ b/en/application-dev/reference/apis/js-apis-socket.md @@ -7,7 +7,7 @@ ## Modules to Import -``` +```js import socket from '@ohos.net.socket'; ``` @@ -28,7 +28,7 @@ Creates a **UDPSocket** object. **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); ``` @@ -56,7 +56,7 @@ Binds the IP address and port number. The port number can be specified or random **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); udp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { if (err) { @@ -93,7 +93,7 @@ Binds the IP address and port number. The port number can be specified or random **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); let promise = udp.bind({address: '192.168.xx.xxx', port: 8080, family: 1}); promise .then(() => { @@ -123,7 +123,7 @@ Sends data over a UDPSocket connection. This API uses an asynchronous callback t **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); udp.send({ data:'Hello, server!', @@ -166,7 +166,7 @@ Sends data over a UDPSocket connection. This API uses a promise to return the re **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); let promise = udp.send({ data:'Hello, server!', @@ -202,7 +202,7 @@ Closes a UDPSocket connection. This API uses an asynchronous callback to return **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); udp.close(err => { if (err) { @@ -232,7 +232,7 @@ Closes a UDPSocket connection. This API uses a promise to return the result. **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); let promise = udp.close(); promise.then(() => { @@ -264,7 +264,7 @@ Obtains the status of the UDPSocket connection. This API uses an asynchronous ca **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); udp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { if (err) { @@ -304,7 +304,7 @@ Obtains the status of the UDPSocket connection. This API uses a promise to retur **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); udp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { if (err) { @@ -345,7 +345,7 @@ Sets other properties of the UDPSocket connection. This API uses an asynchronous **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); udp.bind({address:'192.168.xx.xxx', port:xxxx, family:1}, err=> { if (err) { @@ -397,7 +397,7 @@ Sets other properties of the UDPSocket connection. This API uses a promise to re **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); let promise = udp.bind({address:'192.168.xx.xxx', port:xxxx, family:1}); promise.then(() => { @@ -437,7 +437,7 @@ Enables listening for message receiving events of the UDPSocket connection. This **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); udp.on('message', value => { console.log("on message, message:" + value.message + ", remoteInfo:" + value.remoteInfo); @@ -465,7 +465,7 @@ Disables listening for message receiving events of the UDPSocket connection. Thi **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); let callback = value =>{ console.log("on message, message:" + value.message + ", remoteInfo:" + value.remoteInfo); @@ -494,7 +494,7 @@ Enables listening for data packet message events or close events of the UDPSocke **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); udp.on('listening', () => { console.log("on listening success"); @@ -525,7 +525,7 @@ Disables listening for data packet message events or close events of the UDPSock **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); let callback1 = () =>{ console.log("on listening, success"); @@ -562,7 +562,7 @@ Enables listening for error events of the UDPSocket connection. This API uses an **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); udp.on('error', err => { console.log("on error, err:" + JSON.stringify(err)) @@ -590,7 +590,7 @@ Disables listening for error events of the UDPSocket connection. This API uses a **Example** -``` +```js let udp = socket.constructUDPSocketInstance(); let callback = err =>{ console.log("on error, err:" + JSON.stringify(err)); @@ -680,7 +680,7 @@ Creates a **TCPSocket** object. **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); ``` @@ -709,7 +709,7 @@ Binds the IP address and port number. The port number can be specified or random **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); tcp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { if (err) { @@ -745,7 +745,7 @@ Binds the IP address and port number. The port number can be specified or random **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise = tcp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}); promise.then(() => { @@ -775,7 +775,7 @@ Sets up a connection to the specified IP address and port number. This API uses **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}, err => { if (err) { @@ -811,7 +811,7 @@ Sets up a connection to the specified IP address and port number. This API uses **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise = tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}); promise.then(() => { @@ -844,7 +844,7 @@ Sends data over a TCPSocket connection. This API uses an asynchronous callback t **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise = tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}); promise.then(() => { @@ -891,7 +891,7 @@ Sends data over a TCPSocket connection. This API uses a promise to return the re **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise1 = tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}); promise1.then(() => { @@ -929,7 +929,7 @@ Closes a TCPSocket connection. This API uses an asynchronous callback to return **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); tcp.close(err => { if (err) { @@ -959,7 +959,7 @@ Closes a TCPSocket connection. This API uses a promise to return the result. **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise = tcp.close(); promise.then(() => { @@ -991,7 +991,7 @@ Obtains the remote address of a TCPSocket connection. This API uses an asynchron **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise = tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}); promise.then(() => { @@ -1030,7 +1030,7 @@ Obtains the remote address of a TCPSocket connection. This API uses a promise to **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise1 = tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}); promise1.then(() => { @@ -1069,7 +1069,7 @@ Obtains the status of the TCPSocket connection. This API uses an asynchronous ca **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise = tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}); promise.then(() => { @@ -1109,7 +1109,7 @@ Obtains the status of the TCPSocket connection. This API uses a promise to retur **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise = tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}); promise.then(() => { @@ -1148,7 +1148,7 @@ Sets other properties of the TCPSocket connection. This API uses an asynchronous **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise = tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}); promise.then(() => { @@ -1203,7 +1203,7 @@ Sets other properties of the TCPSocket connection. This API uses a promise to re **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let promise = tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}); promise.then(() => { @@ -1246,7 +1246,7 @@ Enables listening for message receiving events of the TCPSocket connection. This **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); tcp.on('message', value => { console.log("on message, message:" + value.message + ", remoteInfo:" + value.remoteInfo) @@ -1274,7 +1274,7 @@ Disables listening for message receiving events of the TCPSocket connection. Thi **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let callback = value =>{ console.log("on message, message:" + value.message + ", remoteInfo:" + value.remoteInfo); @@ -1304,7 +1304,7 @@ Enables listening for connection or close events of the TCPSocket connection. Th **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); tcp.on('connect', () => { console.log("on connect success") @@ -1335,7 +1335,7 @@ Disables listening for connection or close events of the TCPSocket connection. T **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let callback1 = () =>{ console.log("on connect success"); @@ -1371,7 +1371,7 @@ Enables listening for error events of the TCPSocket connection. This API uses an **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); tcp.on('error', err => { console.log("on error, err:" + JSON.stringify(err)) @@ -1399,7 +1399,7 @@ Disables listening for error events of the TCPSocket connection. This API uses a **Example** -``` +```js let tcp = socket.constructTCPSocketInstance(); let callback = err =>{ console.log("on error, err:" + JSON.stringify(err)); diff --git a/en/application-dev/reference/apis/js-apis-usb.md b/en/application-dev/reference/apis/js-apis-usb.md index 7ff865803c..ece95a1e8e 100644 --- a/en/application-dev/reference/apis/js-apis-usb.md +++ b/en/application-dev/reference/apis/js-apis-usb.md @@ -5,7 +5,7 @@ ## Modules to Import -``` +```js import usb from "@ohos.usb"; ``` @@ -17,13 +17,13 @@ Obtains the USB device list. **System capability**: SystemCapability.USB.USBManager -- Return value +- **Return value** | Type| Description| | -------- | -------- | | Array<Readonly<[USBDevice](#usbdevice)>> | Device information list.| -- Example - ``` +- **Example** + ```js let devicesList = usb.getDevices(); console.log(`devicesList = ${JSON.stringify(devicesList)}`); // devicesList is a list of USB devices. @@ -89,18 +89,18 @@ Before you do this, call [usb.getDevices](#usbgetdevices) to obtain the USB devi **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | device | [USBDevice](#usbdevice) | Yes| USB device information.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | Readonly<[USBDevicePipe](#usbdevicepipe)> | USB device pipe for data transfer.| -- Example - ``` +- **Example** + ```js let devicepipe= usb.connectDevice(device); console.log(`devicepipe = ${JSON.stringify(devicepipe)}`); ``` @@ -114,18 +114,18 @@ Checks whether the application has the permission to access the device. **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | deviceName | string | Yes| Device name.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | boolean | Returns **true** if the application has the permission to access the device; returns **false** otherwise.| -- Example - ``` +- **Example** + ```js let divicesName="1-1"; let bool = usb.hasRight(divicesName); console.log(bool); @@ -140,18 +140,18 @@ Requests the temporary permission for the application to access the USB device. **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | deviceName | string | Yes| Device name.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | Promise<boolean> | Returns **true** if the temporary device access permissions are granted; returns **false** otherwise.| -- Example - ``` +- **Example** + ```js let divicesName="1-1"; usb.requestRight(divicesName).then((ret) => { console.log(`requestRight = ${JSON.stringify(ret)}`); @@ -169,20 +169,20 @@ Before you do this, call [usb.getDevices](#usbgetdevices) to obtain the USB devi **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | pipe | [USBDevicePipe](#usbdevicepipe) | Yes| Device pipe, which is used to determine the bus number and device address.| | iface | [USBInterface](#usbinterface) | Yes| USB interface, which is used to determine the index of the interface to claim.| | force | boolean | No| Whether to forcibly claim the USB interface. The default value is **false**, indicating not to forcibly claim the USB interface.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | number | Returns **0** if the USB interface is successfully claimed; returns an error code otherwise.| -- Example - ``` +- **Example** + ```js let ret = usb.claimInterface(devicepipe, interfaces); console.log(`claimInterface = ${ret}`); ``` @@ -198,19 +198,19 @@ Before you do this, ensure that you have claimed the interface by calling [usb.c **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | pipe | [USBDevicePipe](#usbdevicepipe) | Yes| Device pipe, which is used to determine the bus number and device address.| | iface | [USBInterface](#usbinterface) | Yes| USB interface, which is used to determine the index of the interface to release.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | number | Returns **0** if the USB interface is successfully released; returns an error code otherwise.| -- Example - ``` +- **Example** + ```js let ret = usb.releaseInterface(devicepipe, interfaces); console.log(`releaseInterface = ${ret}`); ``` @@ -226,19 +226,19 @@ Before you do this, call [usb.getDevices](#usbgetdevices) to obtain the USB devi **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | pipe | [USBDevicePipe](#usbdevicepipe) | Yes| Device pipe, which is used to determine the bus number and device address.| | config | [USBConfig](#usbconfig) | Yes| USB configuration to set.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | number | Returns **0** if the USB configuration is successfully set; returns an error code otherwise.| -- Example - ``` +- **Example** + ```js let ret = usb.setConfiguration(devicepipe, config); console.log(`setConfiguration = ${ret}`); ``` @@ -254,19 +254,19 @@ Before you do this, call [usb.getDevices](#usbgetdevices) to obtain the USB devi **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | pipe | [USBDevicePipe](#usbdevicepipe) | Yes| Device pipe, which is used to determine the bus number and device address.| | iface | [USBInterface](#usbinterface) | Yes| USB interface to set.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | number | Returns **0** if the USB interface is successfully set; returns an error code otherwise.| -- Example - ``` +- **Example** + ```js let ret = usb.setInterface(devicepipe, interfaces); console.log(`setInterface = ${ret}`); ``` @@ -282,18 +282,18 @@ Before you do this, call [usb.getDevices](#usbgetdevices) to obtain the USB devi **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | pipe | [USBDevicePipe](#usbdevicepipe) | Yes| Device pipe, which is used to determine the bus number and device address.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | Uint8Array | Raw descriptor data.| -- Example - ``` +- **Example** + ```js let ret = usb.getRawDescriptor(devicepipe); ``` @@ -308,18 +308,18 @@ Before you do this, call [usb.getDevices](#usbgetdevices) to obtain the USB devi **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | pipe | [USBDevicePipe](#usbdevicepipe) | Yes| Device pipe, which is used to determine the bus number and device address.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | number | File descriptor of the USB device.| -- Example - ``` +- **Example** + ```js let ret = usb.getFileDescriptor(devicepipe); ``` @@ -334,20 +334,20 @@ Before you do this, call [usb.getDevices](#usbgetdevices) to obtain the USB devi **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | pipe | [USBDevicePipe](#usbdevicepipe) | Yes| USB device pipe, which is used to determine the USB device.| | contrlparam | [USBControlParams](#usbcontrolparams) | Yes| Control transfer parameters.| | timeout | number | No| Timeout duration. The default value is **0**, indicating no timeout.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | Promise<number> | Returns the size of the transmitted or received data block if the control transfer is successful; returns **-1** if an exception occurs.| -- Example - ``` +- **Example** + ```js usb.controlTransfer(devicepipe, USBControlParams).then((ret) => { console.log(`controlTransfer = ${JSON.stringify(ret)}`); }) @@ -364,7 +364,7 @@ Before you do this, call [usb.getDevices](#usbgetdevices) to obtain the USB devi **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | pipe | [USBDevicePipe](#usbdevicepipe) | Yes| USB device pipe, which is used to determine the USB device.| @@ -372,13 +372,13 @@ Before you do this, call [usb.getDevices](#usbgetdevices) to obtain the USB devi | buffer | Uint8Array | Yes| Buffer for writing or reading data.| | timeout | number | No| Timeout duration. The default value is **0**, indicating no timeout.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | Promise<number> | Returns the size of the transmitted or received data block if the control transfer is successful; returns **-1** if an exception occurs.| -- Example - ``` +- **Example** + ```js // Call usb.getDevices to obtain a data set. Then, obtain a USB device and its access permission. // Pass the obtained USB device as a parameter to usb.connectDevice. Then, call usb.connectDevice to connect the USB device. // Call usb.claimInterface to claim the USB interface. After that, call usb.bulkTransfer to start bulk transfer. @@ -398,18 +398,18 @@ Before you do this, call [usb.getDevices](#usbgetdevices) to obtain the USB devi **System capability**: SystemCapability.USB.USBManager -- Parameters +- **Parameters** | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | pipe | [USBDevicePipe](#usbdevicepipe) | Yes| USB device pipe.| -- Return value +- **Return value** | Type| Description| | -------- | -------- | | number | Returns **0** if the USB device pipe is closed successfully; returns an error code otherwise.| -- Example - ``` +- **Example** + ```js let ret = usb.closePipe(devicepipe); console.log(`closePipe = ${ret}`); ``` diff --git a/en/application-dev/reference/apis/js-apis-webSocket.md b/en/application-dev/reference/apis/js-apis-webSocket.md index 1796e369ab..a1a24975f9 100644 --- a/en/application-dev/reference/apis/js-apis-webSocket.md +++ b/en/application-dev/reference/apis/js-apis-webSocket.md @@ -12,13 +12,13 @@ If an error occurs in any of the preceding processes, the client will receive a ## Modules to Import -``` +```js import webSocket from '@ohos.net.webSocket'; ``` ## Complete Example -``` +```js import webSocket from '@ohos.net.webSocket'; var defaultIpAddress = "ws://"; @@ -78,7 +78,7 @@ Creates a WebSocket connection. You can use this API to create or close a WebSoc **Example** -``` +```js let ws = webSocket.createWebSocket(); ``` @@ -107,7 +107,7 @@ Initiates a WebSocket request to establish a WebSocket connection to a given URL **Example** -``` +```js let ws = webSocket.createWebSocket(); let url = "ws://" ws.connect(url, (err, value) => { @@ -141,7 +141,7 @@ Initiates a WebSocket request carrying specified options to establish a WebSocke **Example** -``` +```js let ws = webSocket.createWebSocket(); let url = "ws://" ws.connect(url, { @@ -184,7 +184,7 @@ Initiates a WebSocket request carrying specified options to establish a WebSocke **Example** -``` +```js let ws = webSocket.createWebSocket(); let url = "ws://" let promise = ws.connect(url); @@ -215,7 +215,7 @@ Sends data through a WebSocket connection. This API uses an asynchronous callbac **Example** -``` +```js let ws = webSocket.createWebSocket(); let url = "ws://" ws.connect(url, (err, value) => { @@ -254,7 +254,7 @@ Sends data through a WebSocket connection. This API uses a promise to return the **Example** -``` +```js let ws = webSocket.createWebSocket(); let url = "ws://" ws.connect(url, (err, value) => { @@ -286,7 +286,7 @@ Closes a WebSocket connection. This API uses an asynchronous callback to return **Example** -``` +```js let ws = webSocket.createWebSocket(); let url = "ws://" ws.close((err, value) => { @@ -318,7 +318,7 @@ Closes a WebSocket connection carrying specified options such as **code** and ** **Example** -``` +```js let ws = webSocket.createWebSocket(); let url = "ws://" ws.close({ @@ -358,7 +358,7 @@ Closes a WebSocket connection carrying specified options such as **code** and ** **Example** -``` +```js let ws = webSocket.createWebSocket(); let url = "ws://" let promise = ws.close({ @@ -391,7 +391,7 @@ Enables listening for the **open** events of a WebSocket connection. This API us **Example** -``` +```js let ws = webSocket.createWebSocket(); ws.on('open', (err, value) => { console.log("on open, status:" + value.status + ", message:" + value.message); @@ -419,7 +419,7 @@ Disables listening for the **open** events of a WebSocket connection. This API u **Example** -``` +```js let ws = webSocket.createWebSocket(); let callback1 = (err, value) => { console.log("on open, status:" + value.status + ", message:" + value.message); @@ -451,7 +451,7 @@ Enables listening for the **message** events of a WebSocket connection. This API **Example** -``` +```js let ws = webSocket.createWebSocket(); ws.on('message', (err, value) => { console.log("on message, message:" + value); @@ -480,7 +480,7 @@ Disables listening for the **message** events of a WebSocket connection. This AP **Example** -``` +```js let ws = webSocket.createWebSocket(); ws.off('message'); ``` @@ -503,7 +503,7 @@ Enables listening for the **close** events of a WebSocket connection. This API u **Example** -``` +```js let ws = webSocket.createWebSocket(); ws.on('close', (err, value) => { console.log("on close, code is " + value.code + ", reason is " + value.reason); @@ -532,7 +532,7 @@ Disables listening for the **close** events of a WebSocket connection. This API **Example** -``` +```js let ws = webSocket.createWebSocket(); ws.off('close'); ``` @@ -556,7 +556,7 @@ Enables listening for the **error** events of a WebSocket connection. This API u **Example** -``` +```js let ws = webSocket.createWebSocket(); ws.on('error', (err) => { console.log("on error, error:" + JSON.stringify(err)) @@ -584,7 +584,7 @@ Disables listening for the **error** events of a WebSocket connection. This API **Example** -``` +```js let ws = webSocket.createWebSocket(); ws.off('error'); ``` diff --git a/en/application-dev/reference/apis/js-apis-webgl.md b/en/application-dev/reference/apis/js-apis-webgl.md index 677ae513e3..93a0097271 100644 --- a/en/application-dev/reference/apis/js-apis-webgl.md +++ b/en/application-dev/reference/apis/js-apis-webgl.md @@ -1,6 +1,6 @@ # webgl -> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The initial APIs of this module are supported since API version 7. Newly added APIs will be marked with a superscript to indicate their earliest API version. @@ -11,18 +11,18 @@ This module provides WebGL APIs that correspond to the OpenGL ES 2.0 feature set Create a **** component in the HML file. The following is an example: - + ``` -
- + + -
+ ``` Obtain the **** component instance in the JS file. The following is an example: - -``` + +```js // Obtain the component instance. const el = this.$refs.canvas1; // Obtain the WebGL context from the component instance. diff --git a/en/application-dev/reference/apis/js-apis-webgl2.md b/en/application-dev/reference/apis/js-apis-webgl2.md index 330516d325..3f96a4e9ad 100644 --- a/en/application-dev/reference/apis/js-apis-webgl2.md +++ b/en/application-dev/reference/apis/js-apis-webgl2.md @@ -1,6 +1,6 @@ # webgl2 -> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The initial APIs of this module are supported since API version 7. Newly added APIs will be marked with a superscript to indicate their earliest API version. @@ -11,18 +11,18 @@ This module provides WebGL APIs that correspond to the OpenGL ES 3.0 feature set Create a **** component in the HML file. The following is an example: - + ``` -
- + + -
+ ``` Obtain the **** component instance in the JS file. The following is an example: - -``` + +```js // Obtain the component instance. const el = this.$refs.canvas1; // Obtain the WebGL context from the component instance. diff --git a/en/application-dev/reference/apis/js-apis-window.md b/en/application-dev/reference/apis/js-apis-window.md index e5ea12a05b..d2dfe5b33e 100644 --- a/en/application-dev/reference/apis/js-apis-window.md +++ b/en/application-dev/reference/apis/js-apis-window.md @@ -1,5 +1,7 @@ # Window +The **Window** module provides basic capabilities for managing windows, including creating and destroying windows and setting serial port attributes. + > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The initial APIs of this module are supported since API version 6. Newly added APIs will be marked with a superscript to indicate their earliest API version. > @@ -10,7 +12,7 @@ import window from '@ohos.window'; ``` -## WindowType7+ +## WindowType7+ Enumerates the window types. @@ -21,7 +23,7 @@ Enumerates the window types. | TYPE_APP | 0 | Application subwindow. | | TYPE_SYSTEM_ALERT | 1 | System alert window.| -## AvoidAreaType7+ +## AvoidAreaType7+ Enumerates the types of the area where the window cannot be displayed. @@ -32,7 +34,7 @@ Enumerates the types of the area where the window cannot be displayed. | TYPE_SYSTEM | 0 | Default area of the system.| | TYPE_CUTOUT | 1 | Notch. | -## WindowMode7+ +## WindowMode7+ Enumerates the window modes of an application. @@ -48,7 +50,7 @@ This is a system API and cannot be called by third-party applications. | SECONDARY | 4 | The application is displayed in the secondary window in split-screen mode. | | FLOATING | 5 | The application is displayed in a floating window.| -## SystemBarProperties +## SystemBarProperties Describes the properties of the status bar and navigation bar. @@ -63,7 +65,7 @@ Describes the properties of the status bar and navigation bar. | isNavigationBarLightIcon7+ | boolean | No | No | Whether any icon on the navigation bar is highlighted. | | navigationBarContentColor8+ | string | No | Yes | Color of the text on the navigation bar. | -## SystemBarRegionTint8+ +## SystemBarRegionTint8+ Describes the callback for a single system bar. @@ -73,13 +75,13 @@ This is a system API and cannot be called by third-party applications. | Name | Type | Readable| Writable| Description | | --------------- | ------------------------- | ---- | ---- | ------------------------------------------------------------ | -| type | [WindowType](#windowtype) | Yes | Yes | Type of the system bar whose properties are changed. Only the navigation bar and status bar are supported.| +| type | [WindowType](#windowtype) | Yes | Yes | Type of the system bar whose properties are changed. Only the status bar and navigation bar are supported.| | isEnable | boolean | Yes | Yes | Whether the system bar is displayed. | | region | [Rect](#rect) | Yes | Yes | Current position and size of the system bar. | | backgroundColor | string | Yes | Yes | Background color of the system bar. The value is a hexadecimal RGB or aRGB color value, for example, **\#00FF00** or **\#FF00FF00**.| | contentColor | string | Yes | Yes | Color of the text on the system bar. | -## SystemBarTintState8+ +## SystemBarTintState8+ Describes the callback for the current system bar. @@ -87,12 +89,12 @@ This is a system API and cannot be called by third-party applications. **System capability**: SystemCapability.WindowManager.WindowManager.Core -| Name | Type | Readable| Writable| Description | -| ---------- | -------------------------------------------------- | ---- | ---- | -------------------------- | -| displayId | number | Yes | No | ID of the current physical screen. | -| regionTint | Array<[SystemBarRegionTint](#systembartegiontint)> | Yes | Yes | All system bar information changed.| +| Name | Type | Readable| Writable| Description | +| ---------- | --------------------------------------------------- | ---- | ---- | -------------------------- | +| displayId | number | Yes | No | ID of the current physical screen. | +| regionTint | Array<[SystemBarRegionTint](#systembarregiontint8)> | Yes | Yes | All system bar information changed.| -## Rect7+ +## Rect7+ Describes a rectangle. @@ -105,7 +107,7 @@ Describes a rectangle. | width | number | Yes | Yes | Width of the rectangle. | | height | number | Yes | Yes | Height of the rectangle. | -## AvoidArea7+ +## AvoidArea7+ Describes the area where the window cannot be displayed. @@ -118,7 +120,7 @@ Describes the area where the window cannot be displayed. | rightRect | [Rect](#rect) | Yes | Yes | Rectangle on the right of the screen.| | bottomRect | [Rect](#rect) | Yes | Yes | Rectangle at the bottom of the screen.| -## Size7+ +## Size7+ Describes the window size. @@ -129,7 +131,7 @@ Describes the window size. | width | number | Yes | Yes | Window width.| | height | number | Yes | Yes | Window height.| -## WindowProperties +## WindowProperties Describes the window properties. @@ -147,10 +149,10 @@ Describes the window properties. | dimBehindValue7+ | number | Yes | Yes | Dimness of the window that is not on top. The value ranges from 0 to 1. The value **1** indicates the maximum dimness.
This API is defined but not implemented in OpenHarmony 3.1 Release. It will be available for use in OpenHarmony 3.1 MR.| | isKeepScreenOn | boolean | Yes | Yes | Whether the screen is always on. The default value is **false**.
This API is defined but not implemented in OpenHarmony 3.1 Release. It will be available for use in OpenHarmony 3.1 MR.| | isPrivacyMode7+ | boolean | Yes | Yes | Whether the window is in privacy mode. The default value is **false**.
This API is defined but not implemented in OpenHarmony 3.1 Release. It will be available for use in OpenHarmony 3.1 MR.| -| isRoundCorner7+ | boolean | Yes | Yes | Whether the window has rounded corners.
This API is defined but not implemented in OpenHarmony 3.1 Release. It will be available for use in OpenHarmony 3.1 MR.| +| isRoundCorner7+ | boolean | Yes | Yes | Whether the window has rounded corners. The default value is **false**.
This API is defined but not implemented in OpenHarmony 3.1 Release. It will be available for use in OpenHarmony 3.1 MR.| | isTransparent7+ | boolean | Yes | Yes | Whether the window is transparent. The default value is **false**.
This API is defined but not implemented in OpenHarmony 3.1 Release. It will be available for use in OpenHarmony 3.1 MR.| -## ColorSpace8+ +## ColorSpace8+ Describes the color gamut mode. @@ -171,7 +173,7 @@ This API is discarded since API version 8. You are advised to use [window.create **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | -------------------------------------- | ---- | -------------------------- | @@ -179,7 +181,7 @@ This API is discarded since API version 8. You are advised to use [window.create | type | [WindowType](#windowtype) | Yes | Window type. | | callback | AsyncCallback<[Window](#window)> | Yes | Callback used to return the subwindow created.| -- Example +**Example** ```js var windowClass = null; @@ -204,20 +206,20 @@ This API is discarded since API version 8. You are advised to use [window.create **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------------------------- | ---- | ---------- | | id | string | Yes | Window ID. | | type | [WindowType](#windowtype) | Yes | Window type.| -- Return value +**Return value** | Type | Description | | -------------------------------- | ------------------------------------------------- | | Promise<[Window](#window)> | Promise used to return the subwindow created.| -- Example +**Example** ```js var windowClass = null; @@ -240,7 +242,7 @@ Creates a system window when the context is [ServiceExtensionContext](js-apis-se **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | -------------------------------------- | ---- | ------------------------------------------------------------ | @@ -249,7 +251,7 @@ Creates a system window when the context is [ServiceExtensionContext](js-apis-se | type | [WindowType](#windowtype) | Yes | Window type. | | callback | AsyncCallback<[Window](#window)> | Yes | Callback used to return the window created. | -- Example +**Example** ```js var windowClass = null; @@ -274,7 +276,7 @@ Creates a system window when the context is [ServiceExtensionContext](js-apis-se **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------------------------- | ---- | ------------------------------------------------------------ | @@ -282,13 +284,13 @@ Creates a system window when the context is [ServiceExtensionContext](js-apis-se | id | string | Yes | Window ID. | | type | [WindowType](#windowtype) | Yes | Window type. | -- Return value +**Return value** | Type | Description | | -------------------------------- | ----------------------------------------------- | | Promise<[Window](#window)> | Promise used to return the window created.| -- Example +**Example** ```js var windowClass = null; @@ -309,14 +311,14 @@ Finds a window based on the ID. This API uses an asynchronous callback to return **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | -------------------------------------- | ---- | ---------------------------- | | id | string | Yes | Window ID. | | callback | AsyncCallback<[Window](#window)> | Yes | Callback used to return the window found.| -- Example +**Example** ```js var windowClass = null; @@ -338,19 +340,19 @@ Finds a window based on the ID. This API uses a promise to return the result. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------ | ---- | -------- | | id | string | Yes | Window ID.| -- Return value +**Return value** | Type | Description | | -------------------------------- | ----------------------------------------------- | | Promise<[Window](#window)> | Promise used to return the window found.| -- Example +**Example** ```js var windowClass = null; @@ -371,13 +373,13 @@ Obtains the top window of the current application. This API uses an asynchronous **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | -------------------------------------- | ---- | -------------------------------------- | | callback | AsyncCallback<[Window](#window)> | Yes | Callback used to return the top window obtained.| -- Example +**Example** ```js var windowClass = null; @@ -399,13 +401,13 @@ Obtains the top window of the current application. This API uses a promise to re **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | -------------------------------- | --------------------------------------------------------- | | Promise<[Window](#window)> | Promise used to return the top window obtained.| -- Example +**Example** ```js var windowClass = null; @@ -426,14 +428,14 @@ Obtains the top window of the current application. This API uses an asynchronous **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | -------------------------------------- | ---- | ------------------------------------------------------------ | | ctx | Context | Yes | Current application context.
For the definition of **Context** of API version 8, see [Context](js-apis-Context.md).
For the definition of **Context** of API version 9, see [Context](js-apis-ability-context.md).| | callback | AsyncCallback<[Window](#window)> | Yes | Callback used to return the top window obtained. | -- Example +**Example** ```js var windowClass = null; @@ -455,19 +457,19 @@ Obtains the top window of the current application. This API uses a promise to re **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------- | ---- | ------------------------------------------------------------ | | ctx | Context | Yes | Current application context.
For the definition of **Context** of API version 8, see [Context](js-apis-Context.md).
For the definition of **Context** of API version 9, see [Context](js-apis-ability-context.md).| -- Return value +**Return value** | Type | Description | | -------------------------------- | --------------------------------------------------------- | | Promise<[Window](#window)> | Promise used to return the top window obtained.| -- Example +**Example** ```js var windowClass = null; @@ -490,14 +492,14 @@ This is a system API and cannot be called by third-party applications. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | --------------------------------------------------------- | ---- | ------------------------------------------------------------ | - | type | string | Yes | Listening type.
Set it to **systemBarTintChange**, which indicates listening for properties changes of the status bar and navigation bar.| + | type | string | Yes | Type of event to listen for. The value is fixed at **systemBarTintChange**, indicating the property change event of the status bar and navigation bar.| | callback | Callback<[SystemBarTintState](#systembartintstate)> | Yes | Callback used to return the information. | -- Example +**Example** ```js var type = 'systemBarTintChange'; @@ -510,20 +512,20 @@ This is a system API and cannot be called by third-party applications. off(type: 'systemBarTintChange', callback?: Callback<SystemBarTintState >): void -Disables listening for the properties changes of the status bar and navigation bar. +Disables listening for properties changes of the status bar and navigation bar. This is a system API and cannot be called by third-party applications. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | --------------------------------------------------------- | ---- | ------------------------------------------------------------ | - | type | string | Yes | Listening type.
Set it to **systemBarTintChange**, which indicates listening for properties changes of the status bar and navigation bar.| + | type | string | Yes | Type of event to listen for. The value is fixed at **systemBarTintChange**, indicating the property change event of the status bar and navigation bar.| | callback | Callback<[SystemBarTintState](#systembartintstate)> | No | Callback used to return the information. | -- Example +**Example** ```js var type = 'systemBarTintChange'; @@ -544,13 +546,13 @@ This is a system API and cannot be called by third-party applications. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------- | ---- | ---------- | | callback | AsyncCallback<void> | Yes | Callback used to return the execution result.| -- Example +**Example** ```js windowClass.hide((err, data) => { @@ -572,13 +574,13 @@ This is a system API and cannot be called by third-party applications. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js let promise = windowClass.hide(); @@ -597,13 +599,13 @@ Shows this window. This API uses an asynchronous callback to return the result. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------- | ---- | ---------- | | callback | AsyncCallback<void> | Yes | Callback used to return the execution result.| -- Example +**Example** ```js windowClass.show((err, data) => { @@ -623,13 +625,13 @@ Shows this window. This API uses a promise to return the result. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js let promise = windowClass.show(); @@ -648,13 +650,13 @@ Destroys this window. This API uses an asynchronous callback to return the resul **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------- | ---- | ---------- | | callback | AsyncCallback<void> | Yes | Callback used to return the execution result.| -- Example +**Example** ```js windowClass.destroy((err, data) => { @@ -674,13 +676,13 @@ Destroys this window. This API uses a promise to return the result. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js let promise = windowClass.destroy(); @@ -699,7 +701,7 @@ Moves the position of this window. This API uses an asynchronous callback to ret **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------- | ---- | --------------------------------------- | @@ -707,7 +709,7 @@ Moves the position of this window. This API uses an asynchronous callback to ret | y | number | Yes | Distance that the window moves along the y-axis. A positive value indicates that the window moves downwards.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js windowClass.moveTo(300, 300, (err, data)=>{ @@ -728,20 +730,20 @@ Moves the position of this window. This API uses a promise to return the result. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------ | ---- | --------------------------------------- | | x | number | Yes | Distance that the window moves along the x-axis. A positive value indicates that the window moves to the right.| | y | number | Yes | Distance that the window moves along the y-axis. A positive value indicates that the window moves downwards.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js let promise = windowClass.moveTo(300, 300); @@ -760,7 +762,7 @@ Changes the size of this window. This API uses an asynchronous callback to retur **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------- | ---- | ---------------- | @@ -768,7 +770,7 @@ Changes the size of this window. This API uses an asynchronous callback to retur | height | number | Yes | New height of the window.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js windowClass.resetSize(500, 1000, (err, data) => { @@ -788,20 +790,20 @@ Changes the size of this window. This API uses a promise to return the result. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------ | ---- | ---------------- | | width | number | Yes | New width of the window.| | height | number | Yes | New height of the window.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js let promise = windowClass.resetSize(500, 1000); @@ -822,14 +824,14 @@ This is a system API and cannot be called by third-party applications. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------- | ---- | ---------- | | type | [WindowType](#windowtype) | Yes | Window type.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result.| -- Example +**Example** ```js var type = window.TYPE_APP; @@ -852,19 +854,19 @@ This is a system API and cannot be called by third-party applications. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------------------------- | ---- | ---------- | | type | [WindowType](#windowtype) | Yes | Window type.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var type = window.TYPE_APP; @@ -884,13 +886,13 @@ Obtains the properties of this window. This API uses an asynchronous callback to **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ---------------------------------------------------------- | ---- | ------------------ | | callback | AsyncCallback<[WindowProperties](#windowproperties)> | Yes | Callback used to return the window properties.| -- Example +**Example** ```js windowClass.getProperties((err, data) => { @@ -910,13 +912,13 @@ Obtains the properties of this window. This API uses a promise to return the res **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | ---------------------------------------------------- | ------------------------------------- | | Promise<[WindowProperties](#windowproperties)> | Promise used to return the window properties.| -- Example +**Example** ```js let promise = windowClass.getProperties(); @@ -935,14 +937,14 @@ Obtains the area where this window cannot be displayed, for example, the system **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | -------------------------------------------- | ---- | ------------------------------------------------------------ | | type | [AvoidAreaType](#avoidareatype) | Yes | Type of the area. **TYPE_SYSTEM** indicates the default area of the system. **TYPE_CUTOUT** indicates the notch.| | callback | AsyncCallback<[AvoidArea](#avoidarea)> | Yes | Callback used to return the area. | -- Example +**Example** ```js var type = window.AvoidAreaType.TYPE_SYSTEM; @@ -963,19 +965,19 @@ Obtains the area where this window cannot be displayed, for example, the system **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------------------------------- | ---- | ------------------------------------------------------------ | | type | [AvoidAreaType](#avoidareatype) | Yes | Type of the area. **TYPE_SYSTEM** indicates the default area of the system. **TYPE_CUTOUT** indicates the notch.| -- Return value +**Return value** | Type | Description | | -------------------------------------- | --------------------------------------------- | | Promise<[AvoidArea](#avoidarea)> | Promise used to return the area.| -- Example +**Example** ```js let promise = windowClass.getAvoidArea(); @@ -994,14 +996,14 @@ Sets whether to enable the full-screen mode for this window. This API uses an as **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ------------ | ------------------------- | ---- | ---------------------------------------------- | | isFullScreen | boolean | Yes | Whether to enable the full-screen mode, in which the status bar and navigation bar are hidden.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js var isFullScreen = true; @@ -1022,19 +1024,19 @@ Sets whether to enable the full-screen mode for this window. This API uses a pro **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ------------ | ------- | ---- | ---------------------------------------------- | | isFullScreen | boolean | Yes | Whether to enable the full-screen mode, in which the status bar and navigation bar are hidden.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var isFullScreen = true; @@ -1054,14 +1056,14 @@ Sets whether the window layout is in full-screen mode. This API uses an asynchro **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ------------------ | ------------------------- | ---- | ------------------------------------------------------------ | | isLayoutFullScreen | boolean | Yes | Whether the window layout is in full-screen mode, in which the status bar and navigation bar are displayed.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js var isLayoutFullScreen= true; @@ -1082,19 +1084,19 @@ Sets whether the window layout is in full-screen mode. This API uses a promise t **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ------------------ | ------- | ---- | ------------------------------------------------------------ | | isLayoutFullScreen | boolean | Yes | Whether the window layout is in full-screen mode, in which the status bar and navigation bar are displayed.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var isLayoutFullScreen = true; @@ -1114,14 +1116,14 @@ Sets whether to display the status bar and navigation bar in this window. This A **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------- | ---- | ------------------------------------------------------------ | | names | Array | Yes | Whether to display the status bar and navigation bar. For example, to display the status bar and navigation bar, set this parameter to **["status", "navigation"]**. By default, they are not displayed.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js var names = ["status", "navigation"]; @@ -1142,19 +1144,19 @@ Sets whether to display the status bar and navigation bar in this window. This A **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ----- | ---- | ------------------------------------------------------------ | | names | Array | Yes | Whether to display the status bar and navigation bar. For example, to display the status bar and navigation bar, set this parameter to **["status", "navigation"]**. By default, they are not displayed.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var names = ["status", "navigation"]; @@ -1174,14 +1176,14 @@ Sets the properties of the status bar and navigation bar in this window. This AP **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ------------------- | ------------------------------------------- | ---- | -------------------- | | SystemBarProperties | [SystemBarProperties](#systembarproperties) | Yes | Properties of the status bar and navigation bar.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js var SystemBarProperties={ @@ -1211,19 +1213,19 @@ Sets the properties of the status bar and navigation bar in this window. This AP **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ------------------- | ------------------------------------------- | ---- | -------------------- | | SystemBarProperties | [SystemBarProperties](#systembarproperties) | Yes | Properties of the status bar and navigation bar.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var SystemBarProperties={ @@ -1252,14 +1254,14 @@ Loads content to this window. This API uses an asynchronous callback to return t **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------- | ---- | -------------------- | | path | string | Yes | Path of the page from which the content will be loaded.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js windowClass.loadContent("pages/page2/page2", (err, data) => { @@ -1279,19 +1281,19 @@ Loads content to this window. This API uses a promise to return the result. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------ | ---- | -------------------- | | path | string | Yes | Path of the page from which the content will be loaded.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js let promise = windowClass.loadContent("pages/page2/page2"); @@ -1310,13 +1312,13 @@ Checks whether this window is displayed. This API uses an asynchronous callback **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ---------------------------- | ---- | -------------------------------- | | callback | AsyncCallback<boolean> | Yes | Callback used to return whether the window is displayed.| -- Example +**Example** ```js windowClass.isShowing((err, data) => { @@ -1336,13 +1338,13 @@ Checks whether this window is displayed. This API uses a promise to return the r **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | ---------------------- | ----------------------------------------------------- | | Promise<boolean> | Promise used to return whether the window is displayed.| -- Example +**Example** ```js let promise = windowClass.isShowing(); @@ -1361,14 +1363,14 @@ Enables listening for window size changes. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** - | Name | Type | Mandatory| Description | - | -------- | ----------------------------- | ---- | ------------------------------------------------------------ | - | type | string | Yes | Listening type.
Set it to **windowSizeChange**, which indicates listening for window size changes.| - | callback | Callback<[Size](#size)> | Yes | Callback used to return the information. | + | Name | Type | Mandatory| Description | + | -------- | ----------------------------- | ---- | -------------------------------------------------------- | + | type | string | Yes | Type of event to listen for. The value is fixed at **windowSizeChange**, indicating the window size change event.| + | callback | Callback<[Size](#size)> | Yes | Callback used to return the information. | -- Example +**Example** ```js var type = 'windowSizeChange'; @@ -1385,16 +1387,16 @@ Disables listening for window size changes. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** - | Name | Type | Mandatory| Description | - | -------- | ----------------------------- | ---- | ------------------------------------------------------------ | - | type | string | Yes | Listening type.
Set it to **windowSizeChange7+**, which indicates listening for window size changes.| - | callback | Callback<[Size](#size)> | No | Callback used to return the information. | + | Name | Type | Mandatory| Description | + | -------- | ----------------------------- | ---- | -------------------------------------------------------- | + | type | string | Yes | Type of event to listen for. The value is fixed at **windowSizeChange**, indicating the window size change event.| + | callback | Callback<[Size](#size)> | No | Callback used to return the information. | -- Example +**Example** - ``` + ```js var type = 'windowSizeChange'; windowClass.off(type); ``` @@ -1407,14 +1409,14 @@ Enables listening for changes to the area where the window cannot be displayed. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | --------------------------------------- | ---- | ------------------------------------------------------------ | - | type | string | Yes | Listening type.
Set it to **systemAvoidAreaChange**, which indicates listening for changes to the area where the window cannot be displayed.| + | type | string | Yes | Type of event to listen for. The value is fixed at **systemAvoidAreaChange**, indicating the event of changes to the area where the window cannot be displayed.| | callback | Callback<[AvoidArea](#avoidarea)> | Yes | Callback used to return the information. | -- Example +**Example** ```js var type = 'systemAvoidAreaChange'; @@ -1431,16 +1433,16 @@ Disables listening for changes to the area where the window cannot be displayed. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | --------------------------------------- | ---- | ------------------------------------------------------------ | - | type | string | Yes | Listening type.
Set it to **systemAvoidAreaChange**, which indicates listening for changes to the area where the window cannot be displayed.| + | type | string | Yes | Type of event to listen for. The value is fixed at **systemAvoidAreaChange**, indicating the event of changes to the area where the window cannot be displayed.| | callback | Callback<[AvoidArea](#avoidarea)> | No | Callback used to return the information. | -- Example +**Example** - ``` + ```js var type = 'systemAvoidAreaChange'; windowClass.off(type); ``` @@ -1455,14 +1457,14 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------ | ---- | ------------------------------------------------------------ | - | type | string | Yes | Listening type.
Set it to **keyboardHeightChange**, which indicates listening for keyboard height changes.| + | type | string | Yes | Type of event to listen for. The value is fixed at **keyboardHeightChange**, indicating the keyboard height change event.| | callback | Callbacknumber> | Yes | Callback used to return the information. | -- Example +**Example** ```js var type = 'keyboardHeightChange'; @@ -1481,16 +1483,16 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ---------------------- | ---- | ------------------------------------------------------------ | - | type | string | Yes | Listening type.
Set it to **keyboardHeightChange**, which indicates listening for keyboard height changes.| + | type | string | Yes | Type of event to listen for. The value is fixed at **keyboardHeightChange**, indicating the keyboard height change event.| | callback | Callback<number> | No | Callback used to return the information. | -- Example +**Example** - ``` + ```js var type = 'keyboardHeightChange'; windowClass.off(type); ``` @@ -1503,13 +1505,13 @@ Checks whether this window supports the wide color gamut mode. This API uses an **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ---------------------------- | ---- | -------------------------------- | | callback | AsyncCallback<boolean> | Yes | Callback used to return whether the wide color gamut mode is supported.| -- Example +**Example** ```js windowClass.isSupportWideGamut((err, data) => { @@ -1529,15 +1531,15 @@ Checks whether this window supports the wide color gamut mode. This API uses a p **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | ---------------------- | ------------------------------------------------------------ | | Promise<boolean> | Promise used to return whether the wide color gamut mode is supported.| -- Example +**Example** - ``` + ```js let promise = windowClass.isSupportWideGamut(); promise.then((data)=> { console.info('Succeeded in checking whether the window support WideGamut. Data: ' + JSON.stringify(data)) @@ -1554,14 +1556,14 @@ Sets this window to the wide or default color gamut mode. This API uses an async **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ---------- | ------------------------- | ---- | ------------ | | colorSpace | [ColorSpace](#colorspace) | Yes | Color gamut mode.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js windowClass.setColorSpace(window.ColorSpace.WIDE_GAMUT, (err, data) => { @@ -1581,19 +1583,19 @@ Sets this window to the wide or default color gamut mode. This API uses a promis **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ---------- | ------------------------- | ---- | ------------ | | colorSpace | [ColorSpace](#colorspace) | Yes | Color gamut mode.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js let promise = windowClass.isSupportWideGamut(window.ColorSpace.WIDE_GAMUT); @@ -1612,13 +1614,13 @@ Obtains the color gamut mode of this window. This API uses an asynchronous callb **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ---------------------------------------------- | ---- | -------------------------- | | callback | AsyncCallback<[ColorSpace](#colorspace)> | Yes | Callback used to return the color gamut mode obtained.| -- Example +**Example** ```js windowClass.getColorSpace((err, data) => { @@ -1638,13 +1640,13 @@ Obtains the color gamut mode of this window. This API uses a promise to return t **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | ---------------------------------------- | ----------------------------------------- | | Promise<[ColorSpace](#colorspace)> | Promise used to return the color gamut mode obtained.| -- Example +**Example** ```js let promise = windowClass.getColorSpace(); @@ -1665,14 +1667,14 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------- | ---- | ------------------------------------------------------------ | | color | string | Yes | Background color to set. The color is a hexadecimal value, for example, #00FF00 or #FF00FF00.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js var color = '#00ff33'; @@ -1695,19 +1697,19 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------ | ---- | ------------------------------------------------------------ | | color | string | Yes | Background color to set. The color is a hexadecimal value, for example, #00FF00 or #FF00FF00.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var color = '#00ff33'; @@ -1729,14 +1731,14 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ---------- | ------------------------- | ---- | ------------------------------------ | | brightness | number | Yes | Brightness to set, which ranges from 0 to 1. The value **1** indicates the brightest.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js var brightness = 1; @@ -1759,19 +1761,19 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ---------- | ------ | ---- | ------------------------------------ | | brightness | number | Yes | Brightness to set, which ranges from 0 to 1. The value **1** indicates the brightest.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var brightness = 1; @@ -1793,14 +1795,14 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------------- | ------------------------- | ---- | -------------------------------------------------- | | dimBehindValue | number | Yes | Dimness of the window to set. The value ranges from 0 to 1. The value **1** indicates the dimmest.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js windowClass.setDimBehind(0.5, (err, data) => { @@ -1822,19 +1824,19 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------------- | ------ | ---- | -------------------------------------------------- | | dimBehindValue | number | Yes | Dimness of the window to set. The value ranges from 0 to 1. The value **1** indicates the dimmest.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js let promise = windowClass.setDimBehind(0.5); @@ -1855,14 +1857,14 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ----------- | ------------------------- | ---- | ---------------------------- | | isFocusable | boolean | Yes | Whether the window can gain focus.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js var isFocusable= true; @@ -1885,19 +1887,19 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ----------- | ------- | ---- | ---------------------------- | | isFocusable | boolean | Yes | Whether the window can gain focus.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var isFocusable= true; @@ -1919,14 +1921,14 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------------- | ------------------------- | ---- | ------------------------ | | isKeepScreenOn | boolean | Yes | Whether to keep the screen always on.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js var isKeepScreenOn = true; @@ -1949,19 +1951,19 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------------- | ------- | ---- | ------------------------ | | isKeepScreenOn | boolean | Yes | Whether to keep the screen always on.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var isKeepScreenOn= true; @@ -1983,14 +1985,14 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | --------- | ------------------------- | ---- | ---------------- | | touchable | boolean | Yes | Whether the area outside the subwindow is touchable. The value **true** means that such an area is touchable, and **false** means the opposite.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js windowClass.setOutsideTouchable(true, (err, data) => { @@ -2012,19 +2014,19 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | --------- | ------- | ---- | ---------------- | | touchable | boolean | Yes | Whether the area outside the subwindow is touchable. The value **true** means that such an area is touchable, and **false** means the opposite.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js let promise = windowClass.setOutsideTouchable(true); @@ -2045,14 +2047,14 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ------------- | ------------------------- | ---- | -------------------- | | isPrivacyMode | boolean | Yes | Whether the window is in privacy mode.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js var isPrivacyMode = true; @@ -2076,19 +2078,19 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ------------- | ------- | ---- | -------------------- | | isPrivacyMode | boolean | Yes | Whether the window is in privacy mode.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var isPrivacyMode = true; @@ -2110,14 +2112,14 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ----------- | ------------------------- | ---- | -------------------- | | isTouchable | boolean | Yes | Whether the window is touchable.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```js var isTouchable = true; @@ -2141,19 +2143,19 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | ----------- | ------- | ---- | -------------------- | | isTouchable | boolean | Yes | Whether the window is touchable.| -- Return value +**Return value** | Type | Description | | ------------------- | ----------------------------------------------- | | Promise<void> | Promise used to return the execution result.| -- Example +**Example** ```js var isTouchable = true; @@ -2165,7 +2167,7 @@ This API is defined but not implemented in OpenHarmony 3.1 Release. It will be a }); ``` -## WindowStageEventType9+ +## WindowStageEventType9+ Describes the lifecycle of a window stage. @@ -2190,13 +2192,13 @@ Obtains the main window of this window stage. This API uses a promise to return **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | -------------------------------- | ---------------------------------------------------------- | | Promise<[Window](#window)> | Promise used to return the main window.| -- Example +**Example** ```ts class myAbility extends Ability { @@ -2222,13 +2224,13 @@ Obtains the main window of this window stage. This API uses an asynchronous call **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | -------------------------------------- | ---- | --------------------------------------- | | callback | AsyncCallback<[Window](#window)> | Yes | Callback used to return the main window.| -- Example +**Example** ```ts class myAbility extends Ability { @@ -2255,19 +2257,19 @@ Creates a subwindow for this window stage. This API uses a promise to return the **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name| Type | Mandatory| Description | | ------ | ------ | ---- | -------------- | | name | String | Yes | Name of the subwindow.| -- Return value +**Return value** | Type | Description | | -------------------------------- | ------------------------------------------------- | | Promise<[Window](#window)> | Promise used to return the subwindow created.| -- Example +**Example** ```ts class myAbility extends Ability { @@ -2293,14 +2295,14 @@ Creates a subwindow for this window stage. This API uses an asynchronous callbac **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | -------------------------------------- | ---- | ------------------------------ | | name | String | Yes | Name of the subwindow. | | callback | AsyncCallback<[Window](#window)> | Yes | Callback used to return the subwindow created.| -- Example +**Example** ```ts class myAbility extends Ability { @@ -2328,13 +2330,13 @@ Obtains all the subwindows of this window stage. This API uses a promise to retu **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Return value +**Return value** | Type | Description | | --------------------------------------------- | ------------------------------------------------------------ | | Promise<Array<[Window](#window)>> | Promise used to return all the subwindows.| -- Example +**Example** ```ts class myAbility extends Ability { @@ -2360,13 +2362,13 @@ Obtains all the subwindows of this window stage. This API uses an asynchronous c **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | --------------------------------------------------- | ---- | ------------------------------------------- | | callback | AsyncCallback<Array<[Window](#window)>> | Yes | Callback used to return all the subwindows.| -- Example +**Example** ```ts class myAbility extends Ability { @@ -2393,14 +2395,14 @@ Loads content to this window stage. This API uses an asynchronous callback to re **System capability**: SystemCapability.WindowManager.WindowManager.Coretype with the value 'windowSizeChange' -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------- | ---- | -------------------- | | path | string | Yes | Path of the page from which the content will be loaded.| | callback | AsyncCallback<void> | Yes | Callback used to return the execution result. | -- Example +**Example** ```ts class myAbility extends Ability { @@ -2425,14 +2427,14 @@ Enables listening for window stage lifecycle changes. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | - | type | string | Yes | Listening type.
Set it to **windowStageEvent**, which indicates listening for window stage lifecycle changes.| + | type | string | Yes | Type of event to listen for. The value is fixed at **windowStageEvent**, indicating the window stage lifecycle change event.| | callback | Callback<[WindowStageEventType](#windowstageeventtype9)> | Yes | Callback used to return the information. | -- Example +**Example** ```ts class myAbility extends Ability { @@ -2454,14 +2456,14 @@ Disables listening for window stage lifecycle changes. **System capability**: SystemCapability.WindowManager.WindowManager.Core -- Parameters +**Parameters** | Name | Type | Mandatory| Description | | -------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | - | type | string | Yes | Listening type.
Set it to **windowStageEvent**, which indicates listening for window stage lifecycle changes.| + | type | string | Yes | Type of event to listen for. The value is fixed at **windowStageEvent**, indicating the window stage lifecycle change event.| | callback | Callback<[WindowStageEventType](#windowstageeventtype9)> | No | Callback used to return the information. | -- Example +**Example** ```ts class myAbility extends Ability { diff --git a/en/contribute/OpenHarmony-c-coding-style-guide.md b/en/contribute/OpenHarmony-c-coding-style-guide.md index 1c59cf3ba1..47fd708789 100755 --- a/en/contribute/OpenHarmony-c-coding-style-guide.md +++ b/en/contribute/OpenHarmony-c-coding-style-guide.md @@ -240,8 +240,8 @@ typedef struct { // Good: The anonymous struct is used because self-nesting i int a; int b; } MyType; // The struct alias uses the UpperCamelCase style. - -​```c +``` +```c typedef struct tagNode { // Good: Add the 'tag' prefix or use 'Node_'. struct tagNode *prev; struct tagNode *next; diff --git a/en/device-dev/driver/driver-hdf-development.md b/en/device-dev/driver/driver-hdf-development.md index b6ffbe9f43..055ac4778e 100644 --- a/en/device-dev/driver/driver-hdf-development.md +++ b/en/device-dev/driver/driver-hdf-development.md @@ -70,9 +70,9 @@ The HDF-based driver development involves driver implementation and configuratio 2. Build the driver.
- LiteOS
- Modify **makefile** and **BUILD.gn**. + Modify the **Makefile** and **BUILD.gn** files. - - **makefile**:
+ - **Makefile**:
Use the **makefile** template provided by the HDF to compile the driver code. @@ -90,7 +90,7 @@ The HDF-based driver development involves driver implementation and configuratio ``` LITEOS_BASELIB += -lxxx # Static library generated by the link. - LIB_SUBDIRS += # Directory in which the driver code makefile is located. + LIB_SUBDIRS += # Directory in which Makefile is located. ``` - **BUILD.gn**:
@@ -141,7 +141,7 @@ The HDF-based driver development involves driver implementation and configuratio obj-$(CONFIG_DRIVERS_HDF) += xxx/ ``` - Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the **Makefile** file. + Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the file. ``` diff --git a/en/device-dev/driver/driver-peripherals-external-des.md b/en/device-dev/driver/driver-peripherals-external-des.md index f375802a58..996ad28052 100644 --- a/en/device-dev/driver/driver-peripherals-external-des.md +++ b/en/device-dev/driver/driver-peripherals-external-des.md @@ -4,7 +4,7 @@ The WLAN module is developed based on the Hardware Driver Foundation \(HDF\). It supports cross-OS migration, component adaptation, and modular assembly and compilation. Based on the unified APIs provided by the WLAN module, driver developers of WLAN vendors can adapt their driver code and are capable of creating, disabling, scanning, and connecting to WLAN hotspots. The WLAN driver provides the Hardware Device Interface \(HDI\) layer with the capabilities of setting and obtaining the device MAC address and setting the transmit power. The following figure shows the framework of the WLAN module: -**Figure 1** WLAN framework +**Figure 1** WLAN framework ![](figures/wlan-framework.png "wlan-framework") ### WLAN Driver API Architecture @@ -17,14 +17,14 @@ The WLAN module provides the following three types of APIs: 3. Capability APIs for vendors -**Figure 2** Available APIs of the WLAN module +**Figure 2** Available APIs of the WLAN module ![](figures/available-apis-of-the-wlan-module.png "available-apis-of-the-wlan-module") ## Available APIs -The WLAN driver module provides APIs that can be directly called by driver developers, such as creating/releasing a **WifiModule**, connecting to/disconnecting from a WLAN hotspot, applying for/releasing a **NetBuf**, and converting between the **pbuf** structure of Lightweight IP \(lwIP\) and a **NetBuf**. [Table 1](#table1521573319472) describes some APIs. +The WLAN driver module provides APIs that can be directly called by driver developers, such as creating/releasing a **WifiModule**, connecting to/disconnecting from a WLAN hotspot, applying for/releasing a **NetBuf**, and converting between the **pbuf** structure of Lightweight IP \(lwIP\) and a **NetBuf**. [Table 1](#table1521573319472) describes some APIs. -**Table 1** APIs that can be directly called by driver developers +**Table 1** APIs that can be directly called by driver developers

File

@@ -110,9 +110,9 @@ The WLAN driver module provides APIs that can be directly called by driver devel
-The WLAN driver module provides APIs for driver developers, such as initializing/deregistering, opening/stopping a **NetDevice**, and obtaining the state of a **NetDevice**. [Table 2](#table74613501475) describes some APIs. +The WLAN driver module provides APIs for driver developers, such as initializing/deregistering, opening/stopping a **NetDevice**, and obtaining the state of a **NetDevice**. [Table 2](#table74613501475) describes some APIs. -**Table 2** APIs for driver developers of WLAN vendors to implement +**Table 2** APIs for driver developers of WLAN vendors to implement

File

@@ -158,9 +158,9 @@ The WLAN driver module provides APIs for driver developers, such as initializing
-The WLAN driver provides the HDI layer with the APIs for creating and destroying an **IWiFi** object and setting the MAC address. [Table 3](#table141076311618) describes some APIs. +The WLAN driver provides the HDI layer with the APIs for creating and destroying an **IWiFi** object and setting the MAC address. [Table 3](#table141076311618) describes some APIs. -**Table 3** APIs provided by the WLAN HAL module +**Table 3** APIs provided by the WLAN HAL module

Header File

@@ -223,14 +223,14 @@ The WLAN driver provides the HDI layer with the APIs for creating and destroying The WLAN driver is developed based on the HDF and PLATFORM. It provides a unified driver model for WLAN modules of different vendors regardless of the operating system \(OS\) and system on a chip \(SoC\). -1. Set hardware parameters such as **module** \(different features\) and **chip** in the **wifi\_config.hcs** file. -2. Parse the **wifi\_config.hcs** file and generate a structure with the configured parameters. +1. Set hardware parameters such as **module** \(different features\) and **chip** in the **wifi\_config.hcs** file. +2. Parse the **wifi\_config.hcs** file and generate a structure with the configured parameters. 3. Initialize and create a module. 4. Mount and initialize the chip. 5. Initialize the bus. 6. Mount the upper-layer WPA service. ->![](../public_sys-resources/icon-note.gif) **NOTE:** +>![](../public_sys-resources/icon-note.gif) **NOTE:**
>Some of the above adaptation steps have been provided. For details, see [Development Example](#section1395253612512). The steps waiting to be performed by developers include setting configuration parameters based on hardware attributes, adapting and mounting a chip, and performing tests and verification. ## Development Example @@ -289,7 +289,7 @@ root { } ``` -2. Mount the **init** and **deinit** functions of the WLAN chip and WLAN chip driver. +2. Mount the **init** and **deinit** functions of the WLAN chip and WLAN chip driver. ``` /* WLAN module initialization and mount process */ @@ -504,7 +504,7 @@ int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevi } ``` -3. During the chip initialization, call the **NetDeviceInit\(\)** function to initialize a network device, call the **NetDeviceAdd\(\)** function to add the network device to a protocol stack, and implement some function pointers of **netdev**. +3. During the chip initialization, call the **NetDeviceInit\(\)** function to initialize a network device, call the **NetDeviceAdd\(\)** function to add the network device to a protocol stack, and implement some function pointers of **netdev**. ``` hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi_char* ifname, hi_u32* len) @@ -553,7 +553,7 @@ hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, co } ``` -4. Implement functions of **WifiMac80211Ops**. +4. Implement functions of **WifiMac80211Ops**. ``` /* Mount some function pointers of mac80211. */ @@ -603,5 +603,4 @@ hi_void HiMac80211Init(struct HdfChipDriver *chipDriver) chipDriver->staOps = &g_staOps; chipDriver->apOps = &g_apOps; } -``` - +``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-peripherals-sensor-des.md b/en/device-dev/driver/driver-peripherals-sensor-des.md index d06029a210..358a521220 100644 --- a/en/device-dev/driver/driver-peripherals-sensor-des.md +++ b/en/device-dev/driver/driver-peripherals-sensor-des.md @@ -112,8 +112,6 @@ The sensor driver model also provides certain driver development APIs that need | void ReadSensorData(void) | Reads sensor data.| -For details about the interface implementation, see "How to Develop" below. - ### How to Develop 1. Develop the acceleration sensor abstract driver. Specifically, implement the **Bind**, **Init**, **Release**, and **Dispatch** functions. diff --git a/en/device-dev/driver/driver-peripherals-touch-des.md b/en/device-dev/driver/driver-peripherals-touch-des.md index 461af2c0e7..4f2a3428a6 100644 --- a/en/device-dev/driver/driver-peripherals-touch-des.md +++ b/en/device-dev/driver/driver-peripherals-touch-des.md @@ -50,17 +50,17 @@ Based on the attributes of the pins, interfaces on the touchscreens can be class The interfaces shown in the figure are described as follows: -1. **Power interfaces** +- **Power interfaces** - LDO\_1P8: 1.8 V digital circuits - LDO\_3P3: 3.3 V analog circuits Generally, the touchscreen driver IC is separated from the LCD driver IC. In this case, the touchscreen driver IC requires both 1.8 V and 3.3 V power supplies. Nowadays, the touchscreen driver IC and LCD driver IC can be integrated. Therefore, the touchscreen, requires only the 1.8 V power supply, and the 3.3 V power required internally is supplied by the LCD VSP power \(typical value: 5.5 V\) in the driver IC. -2. **I/O control interfaces** +- **I/O control interfaces** - RESET: reset pin, which is used to reset the driver IC on the host when suspending or resuming the system. - INT: interrupt pin, which needs to be set to the input direction and pull-up status during driver initialization. After detecting an external touch signal, the driver triggers the interrupt by operating the interrupt pin. The driver reads the touch reporting data in the ISR function. -3. **Communications interfaces** +- **Communications interfaces** - I2C: Since only a small amount of touch data is reported by the touchscreen, I2C is used to transmit the reported data. For details about the I2C protocol and interfaces, see [I2C](driver-platform-i2c-des.md#section5361140416). - SPI: In addition to touch reporting data coordinates, some vendors need to obtain basic capacitance data. Therefore, Serial Peripheral Interface \(SPI\) is used to transmit such huge amount of data. For details about the SPI protocol and interfaces, see [SPI](driver-platform-spi-des.md#section193356154511). diff --git a/en/device-dev/driver/driver-platform-adc-des.md b/en/device-dev/driver/driver-platform-adc-des.md index 63da8cd7e0..96f5fd9458 100644 --- a/en/device-dev/driver/driver-platform-adc-des.md +++ b/en/device-dev/driver/driver-platform-adc-des.md @@ -2,11 +2,11 @@ ## Overview -- An analog-to-digital converter (ADC) is a device that converts analog signals into digital signals. +An analog-to-digital converter (ADC) is a device that converts analog signals into digital signals. -- The ADC APIs provide a set of common functions for ADC data transfer, including: - - Opening or closing an ADC device - - Obtaining the analog-to-digital (AD) conversion result +The ADC APIs provide a set of common functions for ADC data transfer, including: +- Opening or closing an ADC device +- Obtaining the analog-to-digital (AD) conversion result **Figure 1** ADC physical connection diff --git a/en/device-dev/driver/driver-platform-adc-develop.md b/en/device-dev/driver/driver-platform-adc-develop.md index fd48b7f8b7..4ff5e1eadd 100644 --- a/en/device-dev/driver/driver-platform-adc-develop.md +++ b/en/device-dev/driver/driver-platform-adc-develop.md @@ -4,7 +4,7 @@ The analog-to-digital converter \(ADC\) is a device that converts analog signals into digital signals. In the Hardware Driver Foundation \(HDF\), the ADC module uses the unified service mode for API adaptation. In this mode, a device service is used as the ADC manager to handle external access requests in a unified manner, which is reflected in the configuration file. The unified service mode applies to the scenario where there are many device objects of the same type, for example, when the ADC has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and memory resources will be consumed by services. -**Figure 1** Unified service mode +**Figure 1** Unified service mode ![](figures/unified-service-mode.png "ADC-unified-service-mode") ## Available APIs @@ -19,7 +19,7 @@ struct AdcMethod { }; ``` -**Table 1** Callbacks for the members in the AdcMethod structure +**Table 1** Callbacks for the members in the AdcMethod structure

Callback

@@ -76,39 +76,36 @@ struct AdcMethod { The ADC module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **adc\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **adc\_config.hcs** file. 3. Instantiate the ADC controller object. - - Initialize **AdcDevice**. - - Instantiate **AdcMethod** in the **AdcDevice** object. + - Initialize **AdcDevice**. + - Instantiate **AdcMethod** in the **AdcDevice** object. - >![](../public_sys-resources/icon-note.gif) **NOTE** + For details, see [Available APIs](#available-apis). - >For details, see [Available APIs](#available-apis). - - -4. Debug the driver. - - \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether the signal collection is successful. +4. \(Optional\) Debug the driver. + For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether the signal collection is successful. ## Development Example -The following uses **adc\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **adc\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits. + Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits. - ADC driver entry reference Many devices may connect to the ADC. In the HDF, a manager object needs to be created for the ADC. When a device needs to be started, the manager object locates the device based on the specified parameters. - The driver of the ADC manager is implemented by the core layer. Vendors do not need to pay attention to the implementation of this part. However, when they implement the **Init** function, the **AdcDeviceAdd** function of the core layer must be called to implement the corresponding features. + The driver of the ADC manager is implemented by the core layer. Vendors do not need to pay attention to the implementation of this part. However, when they implement the **Init** function, the **AdcDeviceAdd** function of the core layer must be called to implement the corresponding features. ``` static struct HdfDriverEntry g_hi35xxAdcDriverEntry = { @@ -129,9 +126,9 @@ The following uses **adc\_hi35xx.c** as an example to present the contents tha HDF_INIT(g_adcManagerEntry); ``` -2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **adc\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the driver implementation and the default values or value ranges of the **AdcDevice** members at the core layer. +2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **adc\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the driver implementation and the default values or value ranges of the **AdcDevice** members at the core layer. - In the unified service mode, the first device node in the **device\_info** file must be the ADC manager, and the parameters must be set as follows: + In the unified service mode, the first device node in the **device\_info** file must be the ADC manager, and the parameters must be set as follows:

Member

@@ -163,9 +160,9 @@ The following uses **adc\_hi35xx.c** as an example to present the contents tha
- Configure ADC controller information from the second node. This node specifies a type of ADC controllers rather than an ADC controller. In this example, there is only one ADC device. If there are multiple ADC devices, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **adc\_config** file. + Configure ADC controller information from the second node. This node specifies a type of ADC controllers rather than an ADC controller. In this example, there is only one ADC device. If there are multiple ADC devices, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **adc\_config** file. - - **device\_info.hcs** configuration reference + - **device\_info.hcs** configuration reference ``` root { @@ -221,10 +218,10 @@ The following uses **adc\_hi35xx.c** as an example to present the contents tha } ``` -3. Initialize the **AdcDevice** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **AdcMethod** \(used to call underlying functions of the driver\) in **AdcDevice**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **AdcDevice** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **AdcMethod** \(used to call underlying functions of the driver\) in **AdcDevice**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference - To the driver, the custom structure carries parameters and data. The values in the **adc\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number and bus number, are also passed to the **AdcDevice** object at the core layer. + To the driver, the custom structure carries parameters and data. The values in the **adc\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number and bus number, are also passed to the **AdcDevice** object at the core layer. ``` struct Hi35xxAdcDevice { @@ -254,7 +251,7 @@ The following uses **adc\_hi35xx.c** as an example to present the contents tha }; ``` - - Instantiate the callback function structure **AdcMethod** in **AdcDevice**. The **AdcLockMethod** callback function structure is not implemented in this example. To instantiate the structure, refer to the I2C driver development. Other members are initialized in the **Init** function. + - Instantiate the callback function structure **AdcMethod** in **AdcDevice**. The **AdcLockMethod** callback function structure is not implemented in this example. To instantiate the structure, refer to the I2C driver development. Other members are initialized in the **Init** function. ``` static const struct AdcMethod g_method = { @@ -268,11 +265,11 @@ The following uses **adc\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\)

Status (Value)

@@ -316,7 +313,7 @@ The following uses **adc\_hi35xx.c** as an example to present the contents tha Function description: - Initializes the custom structure object and **AdcDevice**, and calls the **AdcDeviceAdd** function at the core layer. + Initializes the custom structure object and **AdcDevice**, and calls the **AdcDeviceAdd** function at the core layer. ``` static int32_t Hi35xxAdcInit(struct HdfDeviceObject *device) @@ -371,7 +368,7 @@ The following uses **adc\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -379,7 +376,7 @@ The following uses **adc\_hi35xx.c** as an example to present the contents tha Function description: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. ``` static void Hi35xxAdcRelease(struct HdfDeviceObject *device) @@ -414,7 +411,4 @@ The following uses **adc\_hi35xx.c** as an example to present the contents tha OsalMemFree(hi35xx); } return - ``` - - - + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-dac-des.md b/en/device-dev/driver/driver-platform-dac-des.md index 9088d3b689..8d55f1da22 100644 --- a/en/device-dev/driver/driver-platform-dac-des.md +++ b/en/device-dev/driver/driver-platform-dac-des.md @@ -42,7 +42,8 @@ The DAC module is divided into the following layers: - The core layer provides the capabilities of binding, initializing, and releasing devices. - The adaptation layer implements other functions. -![](../public_sys-resources/icon-note.gif)NOTE
The core layer can call the functions of the interface layer and uses the hook to call functions of the adaptation layer. In this way, the adaptation layer can indirectly call the functions of the interface layer, but the interface layer cannot call the functions of the adaptation layer. +>![](../public_sys-resources/icon-note.gif) **NOTE**
+>The core layer can call the functions of the interface layer and uses the hook to call functions of the adaptation layer. In this way, the adaptation layer can indirectly call the functions of the interface layer, but the interface layer cannot call the functions of the adaptation layer. **Figure 1** Unified service mode @@ -88,10 +89,10 @@ DevHandle DacOpen(uint32_t number); **Table 2** Description of DacOpen -| **Parameter** | Description | +| **Parameter** | Description | | ---------- | ----------------- | | number | DAC device number. | -| **Return Value**| **Description** | +| **Return Value**| **Description** | | NULL | Failed to open the DAC device. | | Device handle | Handle of the DAC device opened.| @@ -119,7 +120,7 @@ int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val); **Table 3** Description of DacWrite -| **Parameter** | Description | +| **Parameter** | Description | | ---------- | -------------- | | handle | DAC device handle. | | channel | DAC channel number. | @@ -148,7 +149,7 @@ void DacClose(DevHandle handle); **Table 4** Description of DacClose -| **Parameter** | Description | +| **Parameter** | Description | | ---------- | -------------- | | handle | DAC device handle. | | **Return Value**| **Description**| @@ -208,4 +209,4 @@ static int32_t TestCaseDac(void) return 0; } -``` +``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-dac-develop.md b/en/device-dev/driver/driver-platform-dac-develop.md index 902035e732..50b0bc60da 100644 --- a/en/device-dev/driver/driver-platform-dac-develop.md +++ b/en/device-dev/driver/driver-platform-dac-develop.md @@ -36,7 +36,8 @@ The DAC module is divided into the following layers: - The core layer provides the capabilities of binding, initializing, and releasing devices. - The adaptation layer implements other functions. -![](../public_sys-resources/icon-note.gif)NOTE
The core layer can call the functions of the interface layer and uses the hook to call functions of the adaptation layer. In this way, the adaptation layer can indirectly call the functions of the interface layer, but the interface layer cannot call the functions of the adaptation layer. +>![](../public_sys-resources/icon-note.gif) **NOTE**
+>The core layer can call the functions of the interface layer and uses the hook to call functions of the adaptation layer. In this way, the adaptation layer can indirectly call the functions of the interface layer, but the interface layer cannot call the functions of the adaptation layer. **Figure 1** Unified service mode @@ -129,7 +130,7 @@ The DAC module adaptation procedure is as follows: Configure DAC controller information from the second node. This node specifies a type of DAC controllers rather than a specific DAC controller. In this example, there is only one DAC device. If there are multiple DAC devices, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **dac_config** file. - **device_info.hcs** configuration reference + **device_info.hcs** configuration reference ``` root { @@ -283,15 +284,15 @@ The DAC module adaptation procedure is as follows: }; ``` - ![](../public_sys-resources/icon-note.gif) **NOTE**
- For details about **DacMethod**, see [Available APIs](#available-apis). + >![](../public_sys-resources/icon-note.gif) **NOTE**
+ >For details about **DacMethod**, see [Available APIs](#available-apis). - **Init** function Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return value: @@ -388,11 +389,11 @@ The DAC module adaptation procedure is as follows: } ``` - - **Release** function + - **Release** function Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return value @@ -465,6 +466,4 @@ The DAC module adaptation procedure is as follows: 4. Debug the driver. - (Optional) Verify the basic functions of the new driver, for example, whether the test cases are successful after the driver is loaded. - - + (Optional) Verify the basic functions of the new driver, for example, whether the test cases are successful after the driver is loaded. \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-gpio-des.md b/en/device-dev/driver/driver-platform-gpio-des.md index 356c30a307..78928d8de1 100644 --- a/en/device-dev/driver/driver-platform-gpio-des.md +++ b/en/device-dev/driver/driver-platform-gpio-des.md @@ -15,7 +15,7 @@ The GPIO APIs define a set of standard functions for performing operations on GP ## Available APIs -**Table 1** APIs available for the GPIO driver +**Table 1** APIs available for the GPIO driver

Capability

@@ -75,16 +75,16 @@ The GPIO APIs define a set of standard functions for performing operations on GP
->![](../public_sys-resources/icon-note.gif) **NOTE:** +>![](../public_sys-resources/icon-note.gif) **NOTE**
>All functions provided in this document can be called only in kernel mode. ## Usage Guidelines ### How to Use -The GPIO APIs use the GPIO pin number to specify a pin. [Figure 1](#fig16151101653713) shows the general process of using a GPIO. +The GPIO APIs use the GPIO pin number to specify a pin. [Figure 1](#fig16151101653713) shows the general process of using a GPIO. -**Figure 1** Process of using a GPIO +**Figure 1** Process of using a GPIO ![](figures/process-of-using-a-gpio.png "process-of-using-a-gpio") ### Determining a GPIO Pin Number @@ -116,7 +116,7 @@ The method for converting GPIO pin numbers varies according to the GPIO controll int32\_t GpioSetDir\(uint16\_t gpio, uint16\_t dir\); - **Table 2** Description of GpioSetDir + **Table 2** Description of GpioSetDir

Parameter

@@ -159,7 +159,7 @@ The method for converting GPIO pin numbers varies according to the GPIO controll int32\_t GpioRead\(uint16\_t gpio, uint16\_t \*val\); - **Table 3** Description of GpioRead + **Table 3** Description of GpioRead

Parameter

@@ -199,7 +199,7 @@ The method for converting GPIO pin numbers varies according to the GPIO controll int32\_t GpioWrite\(uint16\_t gpio, uint16\_t val\); - **Table 4** Description of GpioWrite + **Table 4** Description of GpioWrite

Parameter

@@ -269,7 +269,7 @@ The method for converting GPIO pin numbers varies according to the GPIO controll int32\_t GpioSetIrq\(uint16\_t gpio, uint16\_t mode, GpioIrqFunc func, void \*arg\); - **Table 5** Description of GpioSetIrq + **Table 5** Description of GpioSetIrq

Parameter

@@ -316,13 +316,13 @@ The method for converting GPIO pin numbers varies according to the GPIO controll
>![](../public_sys-resources/icon-caution.gif) **CAUTION:** - >Only one ISR function can be set for a GPIO pin at a time. If **GpioSetIrq** is called repeatedly, the previous IRS function will be replaced. + >Only one ISR function can be set for a GPIO pin at a time. If **GpioSetIrq** is called repeatedly, the previous IRS function will be replaced. If the ISR function is no longer required, call the following function to cancel the setting: int32\_t GpioUnSetIrq\(uint16\_t gpio\); - **Table 6** Description of GpioUnSetIrq + **Table 6** Description of GpioUnSetIrq

Parameter

@@ -357,7 +357,7 @@ The method for converting GPIO pin numbers varies according to the GPIO controll int32\_t GpioEnableIrq\(uint16\_t gpio\); - **Table 7** Description of GpioEnableIrq + **Table 7** Description of GpioEnableIrq

Parameter

@@ -395,7 +395,7 @@ The method for converting GPIO pin numbers varies according to the GPIO controll int32\_t GpioDisableIrq\(uint16\_t gpio\); - **Table 8** Description of GpioDisableIrq + **Table 8** Description of GpioDisableIrq

Parameter

@@ -545,5 +545,4 @@ static int32_t TestCaseGpioIrqEdge(void) (void)GpioUnSetIrq(gpio); return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE; } -``` - +``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-gpio-develop.md b/en/device-dev/driver/driver-platform-gpio-develop.md index 2851ea6e4d..7b14fa0201 100644 --- a/en/device-dev/driver/driver-platform-gpio-develop.md +++ b/en/device-dev/driver/driver-platform-gpio-develop.md @@ -2,9 +2,9 @@ ## Overview -In the Hardware Driver Foundation \(HDF\) framework, the general-purpose input/output \(GPIO\) module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS system that does not distinguish the user mode and the kernel mode. In the service-free mode, **DevHandle** \(a void pointer\) directly points to the kernel-mode address of the device object. +In the Hardware Driver Foundation \(HDF\) framework, the general-purpose input/output \(GPIO\) module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS system that does not distinguish the user mode and the kernel mode. In the service-free mode, **DevHandle** \(a void pointer\) directly points to the kernel-mode address of the device object. -**Figure 1** Service-free mode +**Figure 1** Service-free mode ![](figures/service-free-mode.png "service-free-mode") ## Available APIs @@ -26,7 +26,7 @@ struct GpioMethod { int32_t (*disableIrq)(struct GpioCntlr *cntlr, uint16_t local); } ``` -**Table 1** Callbacks for the members in the GpioMethod structure +**Table 1** Callbacks for the members in the GpioMethod structure

Callback

@@ -152,32 +152,30 @@ The GPIO controller manages all pins by group. The related parameters are descri The GPIO module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF framework. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF framework. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **gpio\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **gpio\_config.hcs** file. 3. Instantiate the GPIO controller object. - - Initialize **GpioCntlr**. - - Instantiate **GpioMethod** in the **GpioCntlr** object. + - Initialize **GpioCntlr**. + - Instantiate **GpioMethod** in the **GpioCntlr** object. - >![](../public_sys-resources/icon-note.gif) **NOTE:** - >For details, see [Available APIs](#section752964871810). - + For details, see [Available APIs](#section752964871810). -4. Debug the driver. - - \(Optional\) For new drivers, verify the basic functions, such as the GPIO control status and response to interrupts. +4. \(Optional\) Debug the driver. + For new drivers, verify the basic functions, such as the GPIO control status and response to interrupts. ## Development Example -The following uses **gpio\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **gpio\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits. + Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits. - GPIO driver entry reference @@ -193,11 +191,11 @@ The following uses **gpio\_hi35xx.c** as an example to present the contents th HDF_INIT(g_gpioDriverEntry); ``` -2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **gpio\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **GpioCntlr** members at the core layer. +2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **gpio\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **GpioCntlr** members at the core layer. - In this example, there is only one GPIO controller. If there are multiple GPIO controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **gpio\_config** file. + In this example, there is only one GPIO controller. If there are multiple GPIO controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **gpio\_config** file. - - **device\_info.hcs** configuration reference + - **device\_info.hcs** configuration reference ``` root { @@ -220,7 +218,7 @@ The following uses **gpio\_hi35xx.c** as an example to present the contents th } ``` - - **gpio\_config.hcs** configuration reference + - **gpio\_config.hcs** configuration reference ``` root { @@ -240,10 +238,10 @@ The following uses **gpio\_hi35xx.c** as an example to present the contents th } ``` -3. Initialize the **GpioCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **GpioMethod** \(used to call underlying functions of the driver\) in **GpioCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **GpioCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **GpioMethod** \(used to call underlying functions of the driver\) in **GpioCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference - To the driver, the custom structure carries parameters and data. The values in the **gpio\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the index and the number of pins, are also passed to the **GpioCntlr** object at the core layer. + To the driver, the custom structure carries parameters and data. The values in the **gpio\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the index and the number of pins, are also passed to the **GpioCntlr** object at the core layer. ``` struct Pl061GpioCntlr { @@ -279,7 +277,7 @@ The following uses **gpio\_hi35xx.c** as an example to present the contents th }; ``` - - Instantiate the callback function structure **GpioMethod** in **GpioCntlr**. Other members are initialized by using the **Init** function. + - Instantiate the callback function structure **GpioMethod** in **GpioCntlr**. Other members are initialized by using the **Init** function. ``` // The members of the GpioMethod structure are all callbacks. Vendors need to implement the corresponding functions according to [Table 1](#table151341544111). @@ -304,13 +302,13 @@ The following uses **gpio\_hi35xx.c** as an example to present the contents th Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) - **Table 2** Init function description + **Table 2** Init function description

Status (Value)

@@ -354,7 +352,7 @@ The following uses **gpio\_hi35xx.c** as an example to present the contents th Function description: - Initializes the custom structure object and **GpioCntlr**, calls the **GpioCntlrAdd** function at the core layer, and connects to the VFS \(optional\). + Initializes the custom structure object and **GpioCntlr**, calls the **GpioCntlrAdd** function at the core layer, and connects to the VFS \(optional\). ``` static int32_t Pl061GpioInit(struct HdfDeviceObject *device) @@ -392,7 +390,7 @@ The following uses **gpio\_hi35xx.c** as an example to present the contents th Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -400,7 +398,7 @@ The following uses **gpio\_hi35xx.c** as an example to present the contents th Function description: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. ``` @@ -421,8 +419,4 @@ The following uses **gpio\_hi35xx.c** as an example to present the contents th OsalIoUnmap((void *)pl061->regBase);// (Mandatory) Remove the address mapping. pl061->regBase = NULL; } - ``` - - - - + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-hdmi-des.md b/en/device-dev/driver/driver-platform-hdmi-des.md index aed0b92647..16927b0fff 100644 --- a/en/device-dev/driver/driver-platform-hdmi-des.md +++ b/en/device-dev/driver/driver-platform-hdmi-des.md @@ -5,15 +5,15 @@ ### HDMI -- High-definition multimedia interface (HDMI) is an interface for transmitting audio and video data from a source device, such as a DVD player or set-top box (STB), to a sink device, such as a TV or display. -- HDMI works in master/slave mode and usually has a source and a sink. -- The HDMI APIs provide a set of common functions for HDMI transmission, including: +High-definition multimedia interface (HDMI) is an interface for transmitting audio and video data from a source device, such as a DVD player or set-top box (STB), to a sink device, such as a TV or display. +HDMI works in primary/secondary mode and usually has a source and a sink. +The HDMI APIs provide a set of common functions for HDMI transmission, including: - - Opening and closing an HDMI controller - - Starting and stopping HDMI transmission - - Setting audio, video, and High Dynamic Range (HDR) attributes, color depth, and AV mute - - Reading the raw Extended Display Identification Data (EDID) from a sink - - Registering and unregistering a callback for HDMI hot plug detect (HPD). +- Opening and closing an HDMI controller +- Starting and stopping HDMI transmission +- Setting audio, video, and High Dynamic Range (HDR) attributes, color depth, and AV mute +- Reading the raw Extended Display Identification Data (EDID) from a sink +- Registering and unregistering a callback for HDMI hot plug detect (HPD). ### Basic Concepts @@ -88,7 +88,7 @@ DevHandle HdmiOpen(int16_t number); | Parameter | Description | | ---------- | -------------------- | | number | HDMI controller ID. | -| **Return Value**| **Description** | +| **Return Value**| **Description** | | NULL | Failed to open the HDMI controller. | | Controller handle| Handle of the opened HDMI controller.| @@ -117,7 +117,7 @@ int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo | ---------- | ------------------ | | handle | HDMI controller handle. | | callback | Pointer to the callback to be invoked to return the HPD result.| -| **Return Value**| **Description** | +| **Return Value**| **Description** | | 0 | The operation is successful. | | Negative value | The operation failed. | @@ -165,7 +165,7 @@ int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len); | handle | HDMI controller handle. | | buffer | Pointer to the data buffer. | | len | Data length. | -| **Return Value**| **Description** | +| **Return Value**| **Description** | | Positive integer | Raw EDID read.| | Negative number or 0 | Failed to read the EDID. | @@ -194,7 +194,7 @@ int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr); | ------ | -------------- | | handle | HDMI controller handle.| | attr | Pointer to the audio attributes. | -| **Return Value**| **Description** | +| **Return Value**| **Description** | | 0 | The operation is successful. | | Negative value | The operation failed. | @@ -295,7 +295,7 @@ int32_t HdmiAvmuteSet(DevHandle handle, bool enable); | ---------- | ----------------- | | handle | HDMI controller handle. | | enable | Whether to enable the AV mute feature.| -| **Return Value**| **Description** | +| **Return Value**| **Description** | | 0 | The operation is successful. | | Negative value | The operation failed. | @@ -615,4 +615,4 @@ static int32_t TestCaseHdmi(void) return 0; } -``` +``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-hdmi-develop.md b/en/device-dev/driver/driver-platform-hdmi-develop.md index 56e47fa0bf..81597bf7b6 100644 --- a/en/device-dev/driver/driver-platform-hdmi-develop.md +++ b/en/device-dev/driver/driver-platform-hdmi-develop.md @@ -40,7 +40,7 @@ Currently, the HDMI module supports only the kernels (LiteOS) of mini and small HDMI features high transmission rate, wide transmission bandwidth, high compatibility, and can transmit uncompressed audio and video signals. Compared with the traditional full analog interface, HDMI simplifies connection between devices and provides HDMI-specific intelligent features, which are ideal for high-quality audio and video transmission of small-sized devices. ### Available APIs - **HdmiCntlrOps**: + **HdmiCntlrOps**: ```c struct HdmiCntlrOps { @@ -149,7 +149,7 @@ The HDMI module adaptation involves the following steps: .Bind = HdmiAdapterBind, .Init = HdmiAdapterInit, .Release = HdmiAdapterRelease, - .moduleName = "adapter_hdmi_driver",// (mandatory) The value must be the same as that in the .hcs file. + .moduleName = "adapter_hdmi_driver",// (Mandatory) The value must be the same as that in the .hcs file. }; HDF_INIT(g_hdmiDriverEntry); // Call HDF_INIT to register the driver entry with the HDF. ``` @@ -315,11 +315,11 @@ The HDMI module adaptation involves the following steps: - **Bind()** function - **Input parameter**: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. + **Input parameter**: + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. - **Return value**: - **HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** definition in the **/drivers/framework/include/utils/hdf\_base.h file**.) + **Return value**: + **HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** definition in the **/drivers/framework/include/utils/hdf\_base.h file**.) | State | Description | |:-|:-| @@ -330,7 +330,7 @@ The HDMI module adaptation involves the following steps: |HDF_SUCCESS |Transmission successful.| |HDF_FAILURE |Transmission failed.| - **Function description**: + **Function description**: Initializes the custom structure object **HdmiAdapterHost** and **HdmiCntlr**, and calls the **HdmiCntlrAdd** function to add the HDMI controller to the core layer. The **HdmiCntlr**, **HdmiAdapterHost**, and **HdfDeviceObject** assign values with each other so that other functions can be converted successfully. @@ -374,13 +374,13 @@ The HDMI module adaptation involves the following steps: - **Init()** function - **Input parameter**: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. + **Input parameter**: + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. - **Return value**: + **Return value**: HDF_STATUS - **Function description**: + **Function description**: Implements the **HdmiAdapterInit** function. @@ -393,13 +393,13 @@ The HDMI module adaptation involves the following steps: - **Release()** function - **Input parameter**: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. + **Input parameter**: + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. - **Return value**: + **Return value**: – - **Function description**: + **Function description**: Releases the memory and deletes the controller. This function assigns a value to the **Release()** API in the driver entry structure. If the HDF fails to call the **Init()** function to initialize the driver, the **Release()** function can be called to release driver resources. ```c diff --git a/en/device-dev/driver/driver-platform-i2c-develop.md b/en/device-dev/driver/driver-platform-i2c-develop.md index c5dddbd42f..95242cdf55 100644 --- a/en/device-dev/driver/driver-platform-i2c-develop.md +++ b/en/device-dev/driver/driver-platform-i2c-develop.md @@ -6,7 +6,7 @@ The Inter-Integrated Circuit \(I2C\) bus is a simple and bidirectional two-wire synchronous serial bus developed by Philips. In the Hardware Driver Foundation (HDF) framework, the I2C module uses the unified service mode for API adaptation. In this mode, a device service is used as the I2C manager to handle external access requests in a unified manner, which is reflected in the configuration file. The unified service mode applies to the scenario where there are many device objects of the same type, for example, when the I2C module has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and memory resources will be consumed by services. -**Figure 1** Unified service mode +**Figure 1** Unified service mode ![](figures/unified-service-mode.png "unified-service-mode-8") ## Available APIs @@ -23,7 +23,7 @@ struct I2cLockMethod {// Lock mechanism operation structure }; ``` -**Table 1** Callbacks for the members in the I2cMethod structure +**Table 1** Callbacks for the members in the I2cMethod structure

Callback

@@ -57,41 +57,39 @@ struct I2cLockMethod {// Lock mechanism operation structure The I2C module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF framework. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF framework. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **i2c\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **i2c\_config.hcs** file. 3. Instantiate the I2C controller object. - - Initialize **I2cCntlr**. - - Instantiate **I2cMethod** and **I2cLockMethod** in **I2cCntlr**. + - Initialize **I2cCntlr**. + - Instantiate **I2cMethod** and **I2cLockMethod** in **I2cCntlr**. - >![](../public_sys-resources/icon-note.gif) **NOTE** + For details, see [Available APIs](#available-apis). + +4. \(Optional\) Debug the driver. - >For details, see [Available APIs](#available-apis). - - -4. Debug the driver. - - \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether data is successfully transmitted. + For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether data is successfully transmitted. ## Development Example -The following uses **i2c\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **i2c\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. + Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. - I2C driver entry reference Many devices may be connected to the I2C module. Therefore, in the HDF framework, a manager object is created for the I2C, and a manager service is launched to handle external access requests in a unified manner. When a user wants to open a device, the user obtains the manager service first. Then, the manager service locates the target device based on the parameters specified by the user. - The driver of the I2C manager is implemented by the core layer. Vendors do not need to pay attention to the implementation of this part. However, when they implement the **Init** function, the **I2cCntlrAdd** function of the core layer must be called to implement the corresponding features. + The driver of the I2C manager is implemented by the core layer. Vendors do not need to pay attention to the implementation of this part. However, when they implement the **Init** function, the **I2cCntlrAdd** function of the core layer must be called to implement the corresponding features. ``` struct HdfDriverEntry g_i2cDriverEntry = { @@ -113,11 +111,11 @@ The following uses **i2c\_hi35xx.c** as an example to present the contents tha HDF_INIT(g_i2cManagerEntry); ``` -2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **i2c\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the driver implementation and the default values or value ranges of the **I2cCntlr** members at the core layer. +2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **i2c\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the driver implementation and the default values or value ranges of the **I2cCntlr** members at the core layer. - In the unified service mode, the first device node in the **device\_info** file must be the I2C manager. [Table 2](#table96651915911) lists settings of its parameters. + In the unified service mode, the first device node in the **device\_info** file must be the I2C manager. [Table 2](#table96651915911) lists settings of its parameters. - **Table 2** Settings of the I2C manager + **Table 2** Settings of the I2C manager

Member

@@ -149,9 +147,9 @@ The following uses **i2c\_hi35xx.c** as an example to present the contents tha
- Configure I2C controller information from the second node. This node specifies a type of I2C controllers rather than an I2C controller. The **busID** and **reg\_pbase** parameters distinguish controllers, which can be seen in the **i2c\_config** file. + Configure I2C controller information from the second node. This node specifies a type of I2C controllers rather than an I2C controller. The **busID** and **reg\_pbase** parameters distinguish controllers, which can be seen in the **i2c\_config** file. - - **device\_info.hcs** configuration reference + - **device\_info.hcs** configuration reference ``` root { @@ -180,7 +178,7 @@ The following uses **i2c\_hi35xx.c** as an example to present the contents tha } ``` - - **i2c\_config.hcs** configuration reference + - **i2c\_config.hcs** configuration reference ``` root { @@ -208,10 +206,10 @@ The following uses **i2c\_hi35xx.c** as an example to present the contents tha } ``` -3. Initialize the **I2cCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **I2cMethod** \(used to call underlying functions of the driver\) in **I2cCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **I2cCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **I2cMethod** \(used to call underlying functions of the driver\) in **I2cCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference - To the driver, the custom structure carries parameters and data. The values in the **i2c\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number and bus number, are also passed to the **I2cCntlr** object at the core layer. + To the driver, the custom structure carries parameters and data. The values in the **i2c\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number and bus number, are also passed to the **I2cCntlr** object at the core layer. ``` // Vendor custom function structure @@ -238,7 +236,7 @@ The following uses **i2c\_hi35xx.c** as an example to present the contents tha }; ``` - - Instantiate the member callback function structure **I2cMethod** in **I2cCntlr** and the lock callback function structure **I2cLockMethod**. Other members are initialized by using the **Init** function. + - Instantiate the member callback function structure **I2cMethod** in **I2cCntlr** and the lock callback function structure **I2cLockMethod**. Other members are initialized by using the **Init** function. ``` // Example in i2c_hi35xx.c @@ -256,13 +254,13 @@ The following uses **i2c\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) - **Table 3** Input parameters and return values of the Init function + **Table 3** Input parameters and return values of the Init function

Status (Value)

@@ -306,7 +304,7 @@ The following uses **i2c\_hi35xx.c** as an example to present the contents tha Function description: - Initializes the custom structure object and **I2cCntlr**, calls the **I2cCntlrAdd** function at the core layer, and connects to the VFS \(optional\). + Initializes the custom structure object and **I2cCntlr**, calls the **I2cCntlrAdd** function at the core layer, and connects to the VFS \(optional\). ``` static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device) @@ -358,7 +356,7 @@ The following uses **i2c\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -366,7 +364,7 @@ The following uses **i2c\_hi35xx.c** as an example to present the contents tha Function description: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. ``` static void Hi35xxI2cRelease(struct HdfDeviceObject *device) @@ -394,7 +392,4 @@ The following uses **i2c\_hi35xx.c** as an example to present the contents tha } return; } - ``` - - - + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-i3c-develop.md b/en/device-dev/driver/driver-platform-i3c-develop.md index e5b08e2067..d67a87a160 100644 --- a/en/device-dev/driver/driver-platform-i3c-develop.md +++ b/en/device-dev/driver/driver-platform-i3c-develop.md @@ -24,7 +24,7 @@ The Improved Inter-Integrated Circuit (I3C) is a simple and cost-efficient bidir }; ``` - **Table 1** APIs for the members in the I3cMethod structure + **Table 1** APIs for the members in the I3cMethod structure |Method|Input Parameter|Output Parameter|Return Value|Description| |-|-|-|-|-| @@ -52,7 +52,9 @@ The I3C module adaptation involves the following steps: 3. Instantiate the I3C controller object. - Initialize **I3cCntlr**. - - Instantiate **I3cMethod** in **I3cCntlr**. For details, see [Available APIs](#available-apis). + - Instantiate **I3cMethod** in **I3cCntlr**. + + For details, see [Available APIs](#available-apis). 4. Register an interrupt handler. Register an interrupt handler for the controller to implement the device hot-join and in-band interrupt (IBI) features. @@ -197,7 +199,7 @@ The I3C module adaptation involves the following steps: - **Init** function > Input parameter: - > **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. + > **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. > > Return value: > **HDF_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** definition in the **/drivers/framework/include/utils/hdf\_base.h file**.) @@ -410,4 +412,4 @@ The I3C module adaptation involves the following steps: return HDF_SUCCESS; } - ``` + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-mipicsi-develop.md b/en/device-dev/driver/driver-platform-mipicsi-develop.md index 4c84061f5c..cacae8bec9 100644 --- a/en/device-dev/driver/driver-platform-mipicsi-develop.md +++ b/en/device-dev/driver/driver-platform-mipicsi-develop.md @@ -1,15 +1,10 @@ # MIPI CSI -- [Overview](#section72226945170128) -- [Available APIs](#section735525713405) -- [How to Develop](#section378858277170128) -- [Development Example](#section2049027816170128) - ## Overview Defined by the Mobile Industry Processor Interface \(MIPI\) Alliance, the Camera Serial Interface \(CSI\) is a specification that allows data to be transmitted from the camera to the host processor on mobile platforms. In the Hardware Driver Foundation \(HDF\), the MIPI CSI module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS that does not distinguish the user mode and the kernel mode. In the service-free mode, DevHandle \(a void pointer\) directly points to the kernel-mode address of the device object. -**Figure 1** Service-free mode +**Figure 1** Service-free mode ![](figures/service-free-mode.png "Service-free mode") @@ -34,7 +29,7 @@ struct MipiCsiCntlrMethod { }; ``` -**Table 1** Callbacks for the members in the MipiCsiCntlrMethod structure +**Table 1** Callbacks for the members in the MipiCsiCntlrMethod structure

Callback

@@ -202,35 +197,33 @@ struct MipiCsiCntlrMethod { The MIPI CSI module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **mipicsi\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **mipicsi\_config.hcs** file. 3. Instantiate the MIPI CSI controller object. - - Initialize **MipiCsiCntlr**. - - Instantiate **MipiCsiCntlrMethod** in the **MipiCsiCntlr** object. - - >![](../public_sys-resources/icon-note.gif) **NOTE:** - >For details, see [Available APIs](#available-apis). + - Initialize **MipiCsiCntlr**. + - Instantiate **MipiCsiCntlrMethod** in the **MipiCsiCntlr** object. - -4. Debug the driver. - - \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether data is successfully transmitted. + For details, see [Available APIs](#available-apis). + +4. \(Optional\) Debug the driver. + For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether data is successfully transmitted. ## Development Example -The following uses **mipi\_rx\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **mipi\_rx\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Generally, you need to configure the device attributes in **busxx\_config.hcs** and add the **deviceNode** information to the **device\_info.hcs** file. The device attribute values are closely related to the default values or value range of the **MipiCsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration. +1. Generally, you need to configure the device attributes in **busxx\_config.hcs** and add the **deviceNode** information to the **device\_info.hcs** file. The device attribute values are closely related to the default values or value range of the **MipiCsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration. >![](../public_sys-resources/icon-note.gif) **NOTE:** - >In this example, the MIPI controller attributes are defined in the source file. If required, add the **deviceMatchAttr** information to **deviceNode** in the **device\_info** file and add the** mipicsi\_config.hcs** file. + >In this example, the MIPI controller attributes are defined in the source file. If required, add the **deviceMatchAttr** information to **deviceNode** in the **device\_info** file and add the** mipicsi\_config.hcs** file. - **device\_info.hcs** configuration reference: + **device\_info.hcs** configuration reference: ``` root { @@ -253,9 +246,9 @@ The following uses **mipi\_rx\_hi35xx.c** as an example to present the content } ``` -2. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. The function pointer members of the **HdfDriverEntry** structure are filled by the vendors' operation functions. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +2. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. The function pointer members of the **HdfDriverEntry** structure are filled by the vendors' operation functions. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit. + Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit. MIPI CSI driver entry reference: @@ -269,11 +262,11 @@ The following uses **mipi\_rx\_hi35xx.c** as an example to present the content HDF_INIT(g_mipiCsiDriverEntry); // Call HDF_INIT to register the driver entry with the HDF. ``` -3. Initialize the **MipiCsiCntlr** object at the core layer, including initializing the vendor custom structure \(passing parameters and data\), instantiating **MipiCsiCntlrMethod** \(used to call underlying functions of the driver\) in **MipiCsiCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **MipiCsiCntlr** object at the core layer, including initializing the vendor custom structure \(passing parameters and data\), instantiating **MipiCsiCntlrMethod** \(used to call underlying functions of the driver\) in **MipiCsiCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference: >![](../public_sys-resources/icon-note.gif) **NOTE:** - >To the driver, the custom structure carries parameters and data. The values in the **config** file are used to initialize the structure members. In this example, the MIPI CSI attributes are defined in the source file. Therefore, the basic member structure is similar to that of **MipiCsiCntlr**. + >To the driver, the custom structure carries parameters and data. The values in the **config** file are used to initialize the structure members. In this example, the MIPI CSI attributes are defined in the source file. Therefore, the basic member structure is similar to that of **MipiCsiCntlr**. ``` typedef struct { @@ -328,7 +321,7 @@ The following uses **mipi\_rx\_hi35xx.c** as an example to present the content }; ``` - - **\(Important\)** Instantiate the callback function structure **MipiCsiCntlrMethod** in **MipiCsiCntlr**. Other members are initialized by using the **Init** function. + - **\(Important\)** Instantiate the callback function structure **MipiCsiCntlrMethod** in **MipiCsiCntlr**. Other members are initialized by using the **Init** function. ``` static struct MipiCsiCntlrMethod g_method = { @@ -351,11 +344,11 @@ The following uses **mipi\_rx\_hi35xx.c** as an example to present the content Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **/drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **/drivers/framework/include/utils/hdf\_base.h** file.\)

Status (Value)

@@ -399,7 +392,7 @@ The following uses **mipi\_rx\_hi35xx.c** as an example to present the content Function description: - Connects to the **MipiCsiCntlrMethod** instance, calls **MipiCsiRegisterCntlr**, and performs other vendor-defined initialization operations. + Connects to the **MipiCsiCntlrMethod** instance, calls **MipiCsiRegisterCntlr**, and performs other vendor-defined initialization operations. ``` static int32_t Hi35xxMipiCsiInit(struct HdfDeviceObject *device) @@ -408,9 +401,9 @@ The following uses **mipi\_rx\_hi35xx.c** as an example to present the content HDF_LOGI("%s: enter!", __func__); g_mipiCsi.priv = NULL; // g_mipiTx is a global variable defined. - //static struct MipiCsiCntlr g_mipiCsi = { - //.devNo = 0 - //}; + // static struct MipiCsiCntlr g_mipiCsi = { + // .devNo = 0 + // }; g_mipiCsi.ops = &g_method; // Connect to the MipiCsiCntlrMethod instance. #ifdef CONFIG_HI_PROC_SHOW_SUPPORT g_mipiCsi.debugs = &g_debugMethod; @@ -468,7 +461,7 @@ The following uses **mipi\_rx\_hi35xx.c** as an example to present the content Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -476,7 +469,7 @@ The following uses **mipi\_rx\_hi35xx.c** as an example to present the content Function description: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. ``` static void Hi35xxMipiCsiRelease(struct HdfDeviceObject *device) @@ -484,7 +477,7 @@ The following uses **mipi\_rx\_hi35xx.c** as an example to present the content struct MipiCsiCntlr *cntlr = NULL; ... cntlr = MipiCsiCntlrFromDevice(device); // A forced conversion from HdfDeviceObject to MipiCsiCntlr is involved. - //return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service; + // return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service; ... OsalSpinDestroy(&cntlr->ctxLock); @@ -497,7 +490,4 @@ The following uses **mipi\_rx\_hi35xx.c** as an example to present the content HDF_LOGI("%s: unload mipi csi driver success!", __func__); } - ``` - - - + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-mipidsi-des.md b/en/device-dev/driver/driver-platform-mipidsi-des.md index c7cecdc8e1..3845f8078c 100644 --- a/en/device-dev/driver/driver-platform-mipidsi-des.md +++ b/en/device-dev/driver/driver-platform-mipidsi-des.md @@ -2,18 +2,18 @@ ## Overview -- The Display Serial Interface \(DSI\) is a specification stipulated by the Mobile Industry Processor Interface \(MIPI\) Alliance, aiming to reduce the cost of display controllers in a mobile device. It defines a serial bus and communication protocol among the host, the source of image data, and the target device. In this way, the DSI can send pixel data or commands to peripherals \(usually LCDs or similar display devices\) in serial mode, or reads information such as status and pixel from the peripherals. +The Display Serial Interface \(DSI\) is a specification stipulated by the Mobile Industry Processor Interface \(MIPI\) Alliance, aiming to reduce the cost of display controllers in a mobile device. It defines a serial bus and communication protocol among the host, the source of image data, and the target device. In this way, the DSI can send pixel data or commands to peripherals \(usually LCDs or similar display devices\) in serial mode, or reads information such as status and pixel from the peripherals. -- MIPI DSI is capable of working in both high speed \(HS\) mode and low power \(LP\) mode. All data lanes can only travel from the DSI host to a peripheral in HS mode, except the first data lane, which can also receive data such as status information and pixels from the peripheral in LP mode. The clock lane is dedicated to transmitting synchronization clock signals in HS mode. -- [Figure 1](#fig1122611461203) shows a simplified DSI interface. Conceptually, a DSI-compliant interface has the same features as interfaces complying with DBI-2 and DPI-2 standards. It sends pixels or commands to a peripheral and can read status or pixel information from the peripheral. The main difference is that the DSI serializes all pixel data, commands, and events that, in traditional interfaces, are conveyed to and from the peripheral on a parallel data bus with additional control signals. +MIPI DSI is capable of working in both high speed \(HS\) mode and low power \(LP\) mode. All data lanes can only travel from the DSI host to a peripheral in HS mode, except the first data lane, which can also receive data such as status information and pixels from the peripheral in LP mode. The clock lane is dedicated to transmitting synchronization clock signals in HS mode. +[Figure 1](#fig1122611461203) shows a simplified DSI interface. Conceptually, a DSI-compliant interface has the same features as interfaces complying with DBI-2 and DPI-2 standards. It sends pixels or commands to a peripheral and can read status or pixel information from the peripheral. The main difference is that the DSI serializes all pixel data, commands, and events that, in traditional interfaces, are conveyed to and from the peripheral on a parallel data bus with additional control signals. - **Figure 1** DSI transmitting and receiving interface + **Figure 1** DSI transmitting and receiving interface ![](figures/dsi-transmitting-and-receiving-interface.png "dsi-transmitting-and-receiving-interface") ## Available APIs -**Table 1** APIs for MIPI DSI +**Table 1** APIs for MIPI DSI

Capability

@@ -75,25 +75,25 @@
->![](../public_sys-resources/icon-note.gif) **NOTE:** +>![](../public_sys-resources/icon-note.gif) **NOTE**
>All functions described in this document can be called only in kernel space. ## Usage Guidelines ### How to Use -[Figure 2](#fig129103491241) shows the process of using a MIPI DSI device. +[Figure 2](#fig129103491241) shows the process of using a MIPI DSI device. -**Figure 2** Process of using a MIPI DSI device +**Figure 2** Process of using a MIPI DSI device ![](figures/process-of-using-a-mipi-dsi-device.png) ### Obtaining a MIPI DSI Device Handle -Before performing MIPI DSI communication, obtain a MIPI DSI device handle by calling **MipiDsiOpen**. This function returns a MIPI DSI device handle with a specified channel ID. +Before performing MIPI DSI communication, obtain a MIPI DSI device handle by calling **MipiDsiOpen**. This function returns a MIPI DSI device handle with a specified channel ID. DevHandle MipiDsiOpen\(uint8\_t id\); -**Table 2** Description of **MipiDsiOpen** +**Table 2** Description of **MipiDsiOpen**

Parameter

@@ -125,7 +125,7 @@ DevHandle MipiDsiOpen\(uint8\_t id\);
-The following example shows how to obtain a MIPI DSI device handle with the channel ID **0**: +The following example shows how to obtain a MIPI DSI device handle with the channel ID **0**: ``` DevHandle mipiDsiHandle = NULL; /* Device handle */ @@ -145,7 +145,7 @@ if (mipiDsiHandle == NULL) { int32\_t MipiDsiSetCfg\(DevHandle handle, struct MipiCfg \*cfg\); -**Table 3** Description of **MipiDsiSetCfg** +**Table 3** Description of **MipiDsiSetCfg**

Parameter

@@ -213,7 +213,7 @@ if (ret != 0) { int32\_t MipiDsiGetCfg\(DevHandle handle, struct MipiCfg \*cfg\); -**Table 4** Description of **MipiDsiGetCfg** +**Table 4** Description of **MipiDsiGetCfg**

Parameter

@@ -267,7 +267,7 @@ if (ret != HDF_SUCCESS) { int32\_t MipiDsiTx\(PalHandle handle, struct DsiCmdDesc \*cmd\); -**Table 5** Description of **MipiDsiTx** +**Table 5** Description of **MipiDsiTx**

Parameter

@@ -335,7 +335,7 @@ HdfFree(cmd); int32\_t MipiDsiRx\(DevHandle handle, struct DsiCmdDesc \*cmd, uint32\_t readLen, uint8\_t \*out\); -**Table 6** Description of **MipiDsiRx** +**Table 6** Description of **MipiDsiRx**

Parameter

@@ -417,9 +417,9 @@ After the MIPI DSI communication, release the MIPI DSI device handle by calling void MipiDsiClose\(DevHandle handle\); -This function releases the resources requested by **MipiDsiOpen**. +This function releases the resources requested by **MipiDsiOpen**. -**Table 7** Description of **MipiDsiClose** +**Table 7** Description of **MipiDsiClose**

Parameter

@@ -536,5 +536,4 @@ void PalMipiDsiTestSample(void) /* Release the MIPI DSI device handle. */ MipiDsiClose(handle); } -``` - +``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-mipidsi-develop.md b/en/device-dev/driver/driver-platform-mipidsi-develop.md index ceb69f730c..d45115a8d7 100644 --- a/en/device-dev/driver/driver-platform-mipidsi-develop.md +++ b/en/device-dev/driver/driver-platform-mipidsi-develop.md @@ -3,9 +3,9 @@ ## Overview -The Display Serial Interface \(DSI\) is a specification developed by the Mobile Industry Processor Interface \(MIPI\) Alliance to reduce the cost of display controllers in mobile devices. In the Hardware Driver Foundation (HDF) framework, the MIPI DSI module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS system that does not distinguish the user mode and the kernel mode. In the service-free mode, **DevHandle** \(a void pointer\) directly points to the kernel-mode address of the device object. +The Display Serial Interface \(DSI\) is a specification developed by the Mobile Industry Processor Interface \(MIPI\) Alliance to reduce the cost of display controllers in mobile devices. In the Hardware Driver Foundation (HDF) framework, the MIPI DSI module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS system that does not distinguish the user mode and the kernel mode. In the service-free mode, **DevHandle** \(a void pointer\) directly points to the kernel-mode address of the device object. -**Figure 1** Service-free mode +**Figure 1** Service-free mode ![](figures/service-free-mode.png "service-free-mode") ## Available APIs @@ -26,7 +26,7 @@ struct MipiDsiCntlrMethod {// Member functions of the core layer structure }; ``` -**Table 1** Callbacks for the members in the MipiDsiCntlrMethod structure +**Table 1** Callbacks for the members in the MipiDsiCntlrMethod structure

Callback

@@ -105,36 +105,33 @@ struct MipiDsiCntlrMethod {// Member functions of the core layer structure The MIPI DSI module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF framework. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF framework. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **mipidsi\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **mipidsi\_config.hcs** file. 3. Instantiate the MIPI DSI controller object. - - Initialize **MipiDsiCntlr**. - - Instantiate **MipiDsiCntlrMethod** in the **MipiDsiCntlr** object. + - Initialize **MipiDsiCntlr**. + - Instantiate **MipiDsiCntlrMethod** in the **MipiDsiCntlr** object. - >![](../public_sys-resources/icon-note.gif) **NOTE** - - >For details, see [Available APIs](#available-apis). + For details, see [Available APIs](#available-apis). - -4. Debug the driver. - - \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether data is successfully transmitted. +4. \(Optional\) Debug the driver. + For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether data is successfully transmitted. ## Development Example -The following uses **mipi\_tx\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **mipi\_tx\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Generally, you need to configure the device attributes in **xx\_config.hcs** and add the **deviceNode** information to the **device\_info.hcs** file. The device attribute values are closely related to the default values or value range of the **MipiDsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration. +1. Generally, you need to configure the device attributes in **xx\_config.hcs** and add the **deviceNode** information to the **device\_info.hcs** file. The device attribute values are closely related to the default values or value range of the **MipiDsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration. - In this example, no additional attribute needs to be configured for the MIPI DSI controller. If required, you need to add the **deviceMatchAttr** information to **deviceNode** in the **device\_info** file and add the **mipidsi\_config** file. + In this example, no additional attribute needs to be configured for the MIPI DSI controller. If required, you need to add the **deviceMatchAttr** information to **deviceNode** in the **device\_info** file and add the **mipidsi\_config** file. - - **device\_info.hcs** configuration reference + - **device\_info.hcs** configuration reference ``` root { @@ -157,9 +154,9 @@ The following uses **mipi\_tx\_hi35xx.c** as an example to present the content } ``` -2. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. The function pointer members of the **HdfDriverEntry** structure are filled by the vendors' operation functions. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +2. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. The function pointer members of the **HdfDriverEntry** structure are filled by the vendors' operation functions. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits. + Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits. - MIPI DSI driver entry reference @@ -173,10 +170,10 @@ The following uses **mipi\_tx\_hi35xx.c** as an example to present the content HDF_INIT(g_mipiTxDriverEntry); // Call HDF_INIT to register the driver entry with the HDF framework. ``` -3. Initialize the **MipiDsiCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **MipiDsiCntlrMethod** \(used to call underlying functions of the driver\) in **MipiDsiCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **MipiDsiCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **MipiDsiCntlrMethod** \(used to call underlying functions of the driver\) in **MipiDsiCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference - To the driver, the custom structure carries parameters and data. The values in the **config** file are used to initialize the structure members. In this example, the MIPI DSI has no device attribute file. Therefore, the basic member structure is similar to that of **MipiDsiCntlr**. + To the driver, the custom structure carries parameters and data. The values in the **config** file are used to initialize the structure members. In this example, the MIPI DSI has no device attribute file. Therefore, the basic member structure is similar to that of **MipiDsiCntlr**. ``` typedef struct { @@ -202,7 +199,7 @@ The following uses **mipi\_tx\_hi35xx.c** as an example to present the content }; ``` - - Instantiate the callback function structure **MipiDsiCntlrMethod** in **MipiDsiCntlr**. Other members are initialized by using the Init function. + - Instantiate the callback function structure **MipiDsiCntlrMethod** in **MipiDsiCntlr**. Other members are initialized by using the Init function. ``` static struct MipiDsiCntlrMethod g_method = { @@ -218,11 +215,11 @@ The following uses **mipi\_tx\_hi35xx.c** as an example to present the content Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\)

Status (Value)

@@ -266,16 +263,16 @@ The following uses **mipi\_tx\_hi35xx.c** as an example to present the content Function description: - Connects to the **MipiDsiCntlrMethod** instance, calls **MipiDsiRegisterCntlr**, and performs other vendor-defined initialization operations. + Connects to the **MipiDsiCntlrMethod** instance, calls **MipiDsiRegisterCntlr**, and performs other vendor-defined initialization operations. ``` static int32_t Hi35xxMipiTxInit(struct HdfDeviceObject *device) { int32_t ret; g_mipiTx.priv = NULL; // g_mipiTx is a global variable. - //static struct MipiDsiCntlr g_mipiTx { + // static struct MipiDsiCntlr g_mipiTx { // .devNo=0 - //}; + // }; g_mipiTx.ops = &g_method;// Connect to the MipiDsiCntlrMethod instance. ret = MipiDsiRegisterCntlr(&g_mipiTx, device);// (Mandatory) Call the function at the core layer and g_mipiTx to initialize global variables at the core layer. ... @@ -308,7 +305,7 @@ The following uses **mipi\_tx\_hi35xx.c** as an example to present the content Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -316,7 +313,7 @@ The following uses **mipi\_tx\_hi35xx.c** as an example to present the content Function description: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. ``` static void Hi35xxMipiTxRelease(struct HdfDeviceObject *device) @@ -331,7 +328,4 @@ The following uses **mipi\_tx\_hi35xx.c** as an example to present the content g_mipiTx.priv = NULL; HDF_LOGI("%s: unload mipi_tx driver 1212!", __func__); } - ``` - - - + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-mmc-develop.md b/en/device-dev/driver/driver-platform-mmc-develop.md index 7becfa6f23..ea96f25d14 100644 --- a/en/device-dev/driver/driver-platform-mmc-develop.md +++ b/en/device-dev/driver/driver-platform-mmc-develop.md @@ -4,7 +4,7 @@ In the Hardware Driver Foundation \(HDF\) framework, the MultiMedia Card \(MMC\) uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to handle external access requests. After receiving an access request from an API, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDFDeviceManager can be directly used. However, you need to configure a device node for each device, which increases the memory usage. -**Figure 1** Independent service mode +**Figure 1** Independent service mode ![](figures/independent-service-mode.png "independent-service-mode") ## Available APIs @@ -31,7 +31,7 @@ struct MmcCntlrOps { }; ``` -**Table 1** Callbacks for the members in the MmcCntlrOps structure +**Table 1** Callbacks for the members in the MmcCntlrOps structure

Callback

@@ -196,33 +196,30 @@ struct MmcCntlrOps { The MMC module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF framework. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF framework. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **mmc\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **mmc\_config.hcs** file. 3. Instantiate the MMC controller object. - - Initialize **MmcCntlr**. - - Instantiate **MmcCntlrOps** in the **MmcCntlr** object. + - Initialize **MmcCntlr**. + - Instantiate **MmcCntlrOps** in the **MmcCntlr** object. - >![](../public_sys-resources/icon-note.gif) **NOTE** + For details, see [Available APIs](#available-apis). - >For details, see [Available APIs](#available-apis). - - -4. Debug the driver. - - \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the mount operation and whether the device starts successfully. +4. \(Optional\) Debug the driver. + For new drivers, verify basic functions, for example, verify the information returned after the mount operation and whether the device starts successfully. ## Development Example -The following uses **himci.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **himci.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. + Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. - MMC driver entry reference @@ -237,11 +234,11 @@ The following uses **himci.c** as an example to present the contents that need HDF_INIT(g_mmcDriverEntry); // Call HDF_INIT to register the driver entry with the HDF framework. ``` -2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **mmc\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **MmcCntlr** members at the core layer. +2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **mmc\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **MmcCntlr** members at the core layer. - If there are multiple devices, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **mmc\_config** file. + If there are multiple devices, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **mmc\_config** file. - - **device\_info.hcs** configuration reference + - **device\_info.hcs** configuration reference ``` root { @@ -281,7 +278,7 @@ The following uses **himci.c** as an example to present the contents that need } ``` - - **mmc\_config.hcs** configuration reference + - **mmc\_config.hcs** configuration reference ``` root { @@ -334,10 +331,10 @@ The following uses **himci.c** as an example to present the contents that need } ``` -3. Initialize the **MmcCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **MmcCntlrOps** \(used to call underlying functions of the driver\) in **MmcCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **MmcCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **MmcCntlrOps** \(used to call underlying functions of the driver\) in **MmcCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference - To the driver, the custom structure carries parameters and data. The values in the **mmc\_config.hcs** file are read by the HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values are also transferred to the objects at the core layer. + To the driver, the custom structure carries parameters and data. The values in the **mmc\_config.hcs** file are read by the HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values are also transferred to the objects at the core layer. ``` struct HimciHost { @@ -389,7 +386,7 @@ The following uses **himci.c** as an example to present the contents that need }; ``` - - Instantiate the callback function structure **MmcCntlrOps** in **MmcCntlr**. Other members are initialized by using the **Bind** function. + - Instantiate the callback function structure **MmcCntlrOps** in **MmcCntlr**. Other members are initialized by using the **Bind** function. ``` static struct MmcCntlrOps g_himciHostOps = { @@ -415,11 +412,11 @@ The following uses **himci.c** as an example to present the contents that need Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\)

Status (Value)

@@ -463,7 +460,7 @@ The following uses **himci.c** as an example to present the contents that need Function description: - Initializes the custom structure **HimciHost** object and **MmcCntlr**, and calls the **MmcCntlrAdd** function at the core layer. **MmcCntlr**, **HimciHost**, and **HdfDeviceObject** assign values with each other so that other functions can be converted successfully. + Initializes the custom structure **HimciHost** object and **MmcCntlr**, and calls the **MmcCntlrAdd** function at the core layer. **MmcCntlr**, **HimciHost**, and **HdfDeviceObject** assign values with each other so that other functions can be converted successfully. ``` static int32_t HimciMmcBind(struct HdfDeviceObject *obj) @@ -501,7 +498,7 @@ The following uses **himci.c** as an example to present the contents that need Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -531,7 +528,7 @@ The following uses **himci.c** as an example to present the contents that need Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -539,7 +536,7 @@ The following uses **himci.c** as an example to present the contents that need Function description: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. ``` static void HimciMmcRelease(struct HdfDeviceObject *obj) @@ -550,7 +547,4 @@ The following uses **himci.c** as an example to present the contents that need ... HimciDeleteHost((struct HimciHost *)cntlr->priv);// Memory release function customized by the vendor. A forced conversion from MmcCntlr to HimciHost is involved in the process. } - ``` - - - + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-pin-des.md b/en/device-dev/driver/driver-platform-pin-des.md index 91e05c5f19..fe73cbd7cb 100644 --- a/en/device-dev/driver/driver-platform-pin-des.md +++ b/en/device-dev/driver/driver-platform-pin-des.md @@ -5,12 +5,12 @@ ### Pin -- The pin, also called pin controller, manages pin resources of system on a chip (SoC) vendors and provides the pin multiplexing function. -- The pin module defines a set of common methods for managing pins, including: +The pin module, also called pin controller, manages pin resources of system on a chip (SoC) vendors and provides the pin multiplexing function. +The module defines a set of common methods for managing pins, including: - Obtaining or releasing the pin description handle: The kernel compares the pin name passed in with the pin names of each controller in the linked list. If a match is found, a pin description handle is obtained. After the operation on the pin is complete, the pin description handle will be released. - - Setting or obtaining the pull type of a pin: The pull type can be pull-up, pull-down, or floating. - - Setting or obtaining the pull strength of a pin: You can set the pull strength as required. - - Setting or obtaining the functions of a pin to implement pin multiplexing +- Setting or obtaining the pull type of a pin: The pull type can be pull-up, pull-down, or floating. +- Setting or obtaining the pull strength of a pin: You can set the pull strength as required. +- Setting or obtaining the functions of a pin to implement pin multiplexing ### Basic Concepts Pin, as a software concept, provides APIs for uniformly managing the pins from different SoC vendors, providing the pin multiplexing function, and configuring the electrical features of pins. @@ -52,7 +52,7 @@ The table below describes the APIs of the pin module. For more details, see API **Table 1** Pin driver APIs -| **API** | **Description** | +| **API** | **Description** | | ------------------------------------------------------------ | ---------------- | | DevHandle PinGet(const char *pinName); | Obtains the pin description handle.| | void PinPut(DevHandle handle); | Releases the pin description handle.| @@ -88,7 +88,7 @@ DevHandle PinGet(const char *pinName); | Parameter | Description | | ---------- | ----------------------- | | pinName | Pointer to the pin name. | -| **Return Value**| **Description** | +| **Return Value**| **Description** | | NULL | Failed to obtain the pin description handle.| | handle | Pin description handle obtained. | @@ -120,7 +120,7 @@ int32_t PinSetPull(DevHandle handle, enum PinPullType pullType); | ---------- | ----------------------- | | handle | Pin description handle. | | pullType | Pull type to set. | -| **Return Value**| **Description** | +| **Return Value**| **Description** | | 0 | The operation is successful.| | Negative value | The operation fails.| @@ -154,7 +154,7 @@ int32_t PinGetPull(DevHandle handle, enum PinPullType *pullType); | ---------- | ------------------------- | | handle | Pin description handle. | | pullType | Pointer to the pull type obtained.| -| **Return Value**| **Description** | +| **Return Value**| **Description** | | 0 | The operation is successful. | | Negative value | The operation fails. | @@ -187,7 +187,7 @@ int32_t PinSetStrength(DevHandle handle, uint32_t strength); | ---------- | ----------------------- | | handle | Pin description handle. | | strength | Pull strength to set. | -| **Return Value**| **Description** | +| **Return Value**| **Description** | | 0 | The operation is successful.| | Negative value | The operation fails.| @@ -221,7 +221,7 @@ int32_t PinGetStrength(DevHandle handle, uint32_t *strength); | ---------- | ------------------------- | | handle | Pin description handle. | | strength | Pointer to the pull strength obtained.| -| **Return Value**| **Description** | +| **Return Value**| **Description** | | 0 | The operation is successful. | | Negative value | The operation fails. | @@ -256,7 +256,7 @@ int32_t PinSetFunc(DevHandle handle, const char *funcName); | ---------- | ------------------- | | handle | Pin description handle. | | funcName | Pointer to the pin function to set. | -| **Return Value**| **Description** | +| **Return Value**| **Description** | | 0 | The operation is successful.| | Negative value | The operation fails.| @@ -289,7 +289,7 @@ int32_t PinGetFunc(DevHandle handle, const char **funcName); | ---------- | --------------------- | | handle | Pin description handle. | | funcName | Pointer to the function name obtained.| -| **Return Value**| **Description** | +| **Return Value**| **Description** | | 0 | The operation is successful. | | Negative value | The operation fails. | @@ -406,4 +406,4 @@ ERR: /* Release the pin description handle. */ PinPut(handle); return ret; -} +} \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-pwm-develop.md b/en/device-dev/driver/driver-platform-pwm-develop.md index 269e990a87..a208a9d5b9 100644 --- a/en/device-dev/driver/driver-platform-pwm-develop.md +++ b/en/device-dev/driver/driver-platform-pwm-develop.md @@ -19,7 +19,7 @@ struct PwmMethod { }; ``` -**Table 1** Callbacks for the members in the PwmMethod structure +**Table 1** Callbacks for the members in the PwmMethod structure

Callback

@@ -68,33 +68,30 @@ struct PwmMethod { The PWM module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **pwm\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **pwm\_config.hcs** file. 3. Instantiate the PWM controller object. - - Initialize **PwmDev**. - - Instantiate **PwmMethod** in the **PwmDev** object. + - Initialize **PwmDev**. + - Instantiate **PwmMethod** in the **PwmDev** object. - >![](../public_sys-resources/icon-note.gif) **NOTE** + For details, see [Available APIs](#available-apis). - >For details, see [Available APIs](#available-apis). - - -4. Debug the driver. - - \(Optional\) For new drivers, verify the basic functions, such as the PWM control status and response to interrupts. +4. \(Optional\) Debug the driver. + For new drivers, verify the basic functions, such as the PWM control status and response to interrupts. ## Development Example -The following uses **pwm\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **pwm\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits. + Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits. - PWM driver entry reference @@ -110,8 +107,8 @@ The following uses **pwm\_hi35xx.c** as an example to present the contents tha HDF_INIT(g_hdfPwm); ``` -2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **pwm\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **PwmDev** members at the core layer. If there are multiple devices, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **pwm\_config** file. - - **device\_info.hcs** configuration reference +2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **pwm\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **PwmDev** members at the core layer. If there are multiple devices, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **pwm\_config** file. + - **device\_info.hcs** configuration reference ``` root { @@ -143,7 +140,7 @@ The following uses **pwm\_hi35xx.c** as an example to present the contents tha } ``` - - **pwm\_config.hcs** configuration reference + - **pwm\_config.hcs** configuration reference ``` root { @@ -168,10 +165,10 @@ The following uses **pwm\_hi35xx.c** as an example to present the contents tha } ``` -3. Initialize the **PwmDev** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **PwmMethod** \(used to call underlying functions of the driver\) in **PwmDev**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **PwmDev** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **PwmMethod** \(used to call underlying functions of the driver\) in **PwmDev**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference - To the driver, the custom structure carries parameters and data. The values in the **pwm\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number, are also passed to the objects at the core layer. + To the driver, the custom structure carries parameters and data. The values in the **pwm\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number, are also passed to the objects at the core layer. ``` struct HiPwm { @@ -208,7 +205,7 @@ The following uses **pwm\_hi35xx.c** as an example to present the contents tha }; ``` - - Instantiate the callback function structure **PwmMethod** in **PwmDev**. Other members are initialized by using the **Init** function. + - Instantiate the callback function structure **PwmMethod** in **PwmDev**. Other members are initialized by using the **Init** function. ``` // Example in pwm_hi35xx.c: fill the hook function @@ -221,11 +218,11 @@ The following uses **pwm\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\)

Status (Value)

@@ -269,7 +266,7 @@ The following uses **pwm\_hi35xx.c** as an example to present the contents tha Function description: - Initializes the custom structure object and **PwmDev**, and calls the **PwmDeviceAdd** function at the core layer. + Initializes the custom structure object and **PwmDev**, and calls the **PwmDeviceAdd** function at the core layer. ``` // The bind function is empty. It can be combined with the init function or implement related operations based on the vendor's requirements. @@ -320,7 +317,7 @@ The following uses **pwm\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -328,7 +325,7 @@ The following uses **pwm\_hi35xx.c** as an example to present the contents tha Function description: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. ``` static void HdfPwmRelease(struct HdfDeviceObject *obj) @@ -340,7 +337,4 @@ The following uses **pwm\_hi35xx.c** as an example to present the contents tha PwmDeviceRemove(obj, &(hp->dev));// (Mandatory) Call the core layer functions to release PwmDev devices and services. A forced conversion from HiPwm to PwmDev is involved in the process. HiPwmRemove(hp); //Release HiPwm. } - ``` - - - + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-regulator-develop.md b/en/device-dev/driver/driver-platform-regulator-develop.md index 94fd1f76d0..960c3b88bf 100644 --- a/en/device-dev/driver/driver-platform-regulator-develop.md +++ b/en/device-dev/driver/driver-platform-regulator-develop.md @@ -266,13 +266,13 @@ The regulator module adaptation procedure is as follows: Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. Return value: - **HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.) + **HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.) - **Table 2** HDF\_STATUS + **Table 2** HDF\_STATUS | State | Description | | ---------------------- | -------------- | @@ -319,11 +319,11 @@ The regulator module adaptation procedure is as follows: } ``` - - **Release** function + - **Release** function Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. Return value: @@ -341,8 +341,6 @@ The regulator module adaptation procedure is as follows: } ``` -4. Debug the driver. +4. (Optional) Debug the driver. - (Optional) Verify the basic functions of the new driver, for example, whether the test cases are successful after the driver is loaded. - - + Verify the basic functions of the new driver, for example, whether the test cases are successful after the driver is loaded. \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-rtc-des.md b/en/device-dev/driver/driver-platform-rtc-des.md index b124a0cd79..529546787b 100644 --- a/en/device-dev/driver/driver-platform-rtc-des.md +++ b/en/device-dev/driver/driver-platform-rtc-des.md @@ -6,7 +6,7 @@ The real-time clock \(RTC\) driver provides precise real time for the operating ## Available APIs -**Table 1** APIs provided by the RTC driver +**Table 1** APIs provided by the RTC driver

Capability

@@ -95,7 +95,7 @@ The real-time clock \(RTC\) driver provides precise real time for the operating
->![](../public_sys-resources/icon-note.gif) **NOTE:** +>![](../public_sys-resources/icon-note.gif) **NOTE**
>All functions provided in this document can be called only in kernel mode. ## Usage Guidelines @@ -106,19 +106,19 @@ During the OS startup, the HDF loads the RTC driver based on the configuration f [Figure 1](#fig1610020107333) illustrates the process of using an RTC device. -**Figure 1** Process of using an RTC device +**Figure 1** Process of using an RTC device ![](figures/process-of-using-an-rtc-device.png "process-of-using-an-rtc-device") ### Creating an RTC Device Handle After the RTC driver is loaded, you can use the API provided by the HDF and call APIs of the RTC driver. ->![](../public_sys-resources/icon-note.gif) **NOTE:** +>![](../public_sys-resources/icon-note.gif) **NOTE**
>Currently, only one RTC device is supported in the OS. DevHandle RtcOpen\(void\); -**Table 2** Description of RtcOpen +**Table 2** Description of RtcOpen

Parameter

@@ -165,7 +165,7 @@ You can call the following function to release the RTC device handle, thereby re void RtcClose\(DevHandle handle\); -**Table 3** Description of RtcClose +**Table 3** Description of RtcClose

Parameter

@@ -188,11 +188,11 @@ RtcClose(handle); ### Registering RtcAlarmCallback -After the OS is started, call the following function to register **RtcAlarmCallback**, which will be invoked when an alarm is generated at the specified time: +After the OS is started, call the following function to register **RtcAlarmCallback**, which will be invoked when an alarm is generated at the specified time: int32\_t RtcRegisterAlarmCallback\(DevHandle handle, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb\); -**Table 4** Description of RtcRegisterAlarmCallback +**Table 4** Description of RtcRegisterAlarmCallback

Parameter

@@ -234,7 +234,7 @@ int32\_t RtcRegisterAlarmCallback\(DevHandle handle, enum RtcAlarmIndex alarmInd
-The following is an example of registering **RtcAlarmCallback** for processing alarm **RTC\_ALARM\_INDEX\_A**: +The following is an example of registering **RtcAlarmCallback** for processing alarm **RTC\_ALARM\_INDEX\_A**: ``` /* Register an RTC alarm callback. */ @@ -265,7 +265,7 @@ Call the following function to read time information from the RTC driver, includ int32\_t RtcReadTime\(DevHandle handle, struct RtcTime \*time\); -**Table 5** Description of RtcReadTime +**Table 5** Description of RtcReadTime

Parameter

@@ -318,7 +318,7 @@ Call the following function to set the RTC time: int32\_t RtcWriteTime\(DevHandle handle, struct RtcTime \*time\); -**Table 6** Description of RtcWriteTime +**Table 6** Description of RtcWriteTime

Parameter

@@ -354,8 +354,8 @@ int32\_t RtcWriteTime\(DevHandle handle, struct RtcTime \*time\);
->![](../public_sys-resources/icon-note.gif) **NOTE:** ->The RTC start time is 1970/01/01 Thursday 00:00:00 \(UTC\). The maximum value of **year** must be set based on the requirements specified in the product manual of the in-use component. You do not need to configure the day of the week. +>![](../public_sys-resources/icon-note.gif) **NOTE**
+>The RTC start time is 1970/01/01 Thursday 00:00:00 \(UTC\). The maximum value of **year** must be set based on the requirements specified in the product manual of the in-use component. You do not need to configure the day of the week. ``` int32_t ret; @@ -382,7 +382,7 @@ Call the following function to read the alarm time: int32\_t RtcReadAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); -**Table 7** Description of RtcReadAlarm +**Table 7** Description of RtcReadAlarm

Parameter

@@ -440,7 +440,7 @@ Call the following function to set the RTC alarm time based on the alarm index: int32\_t RtcWriteAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); -**Table 8** Description of RtcWriteAlarm +**Table 8** Description of RtcWriteAlarm

Parameter

@@ -481,8 +481,8 @@ int32\_t RtcWriteAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct
->![](../public_sys-resources/icon-note.gif) **NOTE:** ->The RTC start time is 1970/01/01 Thursday 00:00:00 \(UTC\). The maximum value of **year** must be set based on the requirements specified in the product manual of the in-use component. You do not need to configure the day of the week. +>![](../public_sys-resources/icon-note.gif) **NOTE**
+>The RTC start time is 1970/01/01 Thursday 00:00:00 \(UTC\). The maximum value of **year** must be set based on the requirements specified in the product manual of the in-use component. You do not need to configure the day of the week. ``` int32_t ret; @@ -505,11 +505,11 @@ if (ret != 0) { - Enabling or disabling alarm interrupts -Before performing alarm operations, use the following function to enable alarm interrupts, so that **RtcAlarmCallback** will be called when the alarm is not generated upon a timeout: +Before performing alarm operations, use the following function to enable alarm interrupts, so that **RtcAlarmCallback** will be called when the alarm is not generated upon a timeout: int32\_t RtcAlarmInterruptEnable\(DevHandle handle, enum RtcAlarmIndex alarmIndex, uint8\_t enable\); -**Table 9** Description of RtcAlarmInterruptEnable +**Table 9** Description of RtcAlarmInterruptEnable

Parameter

@@ -566,7 +566,7 @@ Call the following function to read the frequency of the external crystal oscill int32\_t RtcGetFreq\(DevHandle handle, uint32\_t \*freq\); -**Table 10** Description of RtcGetFreq +**Table 10** Description of RtcGetFreq

Parameter

@@ -619,7 +619,7 @@ Call the following function to set the frequency of the external crystal oscilla int32\_t RtcSetFreq\(DevHandle handle, uint32\_t freq\); -**Table 11** Description of RtcSetFreq +**Table 11** Description of RtcSetFreq

Parameter

@@ -672,7 +672,7 @@ Call the following function to perform a reset on the RTC driver \(after the res int32\_t RtcReset\(DevHandle handle\); -**Table 12** Description of RtcReset +**Table 12** Description of RtcReset

Parameter

@@ -719,7 +719,7 @@ Call the following function to read the configuration of a custom RTC register b int32\_t RtcReadReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t \*value\); -**Table 13** Description of RtcReadReg +**Table 13** Description of RtcReadReg

Parameter

@@ -778,7 +778,7 @@ Call the following function to configure a register based on the specified regis int32\_t RtcWriteReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t value\); -**Table 14** Description of RtcWriteReg +**Table 14** Description of RtcWriteReg

Parameter

@@ -838,7 +838,7 @@ This section describes the process of using RTC APIs: 1. During the OS startup, the HDF identifies the RTC component in the system. 2. The HDF initializes and creates the RTC device. 3. You can perform operations on the RTC device by calling different APIs. -4. Call the **RtcClose** function to release the device handle and device resources. +4. Call the **RtcClose** function to release the device handle and device resources. Example: @@ -926,5 +926,4 @@ void RtcTestSample(void) /* Release the RTC device handle. */ RtcClose(handle); } -``` - +``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-rtc-develop.md b/en/device-dev/driver/driver-platform-rtc-develop.md index 20639f951a..3b718858e3 100644 --- a/en/device-dev/driver/driver-platform-rtc-develop.md +++ b/en/device-dev/driver/driver-platform-rtc-develop.md @@ -4,7 +4,7 @@ In the Hardware Driver Foundation \(HDF\) framework, the real-time clock \(RTC\) uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to handle external access requests. After receiving an access request from an API, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDFDeviceManager can be directly used. However, you need to configure a device node for each device, which increases the memory usage. -**Figure 1** Independent service mode +**Figure 1** Independent service mode ![](figures/independent-service-mode.png "independent-service-mode-11") ## Available APIs @@ -27,7 +27,7 @@ struct RtcMethod { }; ``` -**Table 1** Callbacks for the members in the RtcMethod structure +**Table 1** Callbacks for the members in the RtcMethod structure

Callback

@@ -183,33 +183,31 @@ struct RtcMethod { The RTC module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **rtc\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **rtc\_config.hcs** file. 3. Instantiate the RTC controller object. - - Initialize **RtcHost**. - - Instantiate **RtcMethod** in the **RtcHost** object. - - >![](../public_sys-resources/icon-note.gif) **NOTE** - - >For details, see [Available APIs](#available-apis). + - Initialize **RtcHost**. + - Instantiate **RtcMethod** in the **RtcHost** object. + For details, see [Available APIs](#available-apis). + +4. \(Optional\) Debug the driver. -4. Debug the driver. - - \(Optional\) For new drivers, verify the basic functions, such as the RTC control status and response to interrupts. + For new drivers, verify the basic functions, such as the RTC control status and response to interrupts. ## Development Example -The following uses **rtc\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **rtc\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. + Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. - RTC driver entry reference @@ -225,11 +223,11 @@ The following uses **rtc\_hi35xx.c** as an example to present the contents tha HDF_INIT(g_rtcDriverEntry); ``` -2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **rtc\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **RtcHost** members at the core layer. +2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **rtc\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **RtcHost** members at the core layer. - In this example, there is only one RTC controller. If there are multiple RTC controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **rtc\_config** file. + In this example, there is only one RTC controller. If there are multiple RTC controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **rtc\_config** file. - - **device\_info.hcs** configuration reference + - **device\_info.hcs** configuration reference ``` root { @@ -250,7 +248,7 @@ The following uses **rtc\_hi35xx.c** as an example to present the contents tha } ``` - - **rtc\_config.hcs** configuration reference + - **rtc\_config.hcs** configuration reference ``` root { @@ -274,10 +272,10 @@ The following uses **rtc\_hi35xx.c** as an example to present the contents tha } ``` -3. Initialize the **RtcHost** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **RtcMethod** \(used to call underlying functions of the driver\) in **RtcHost**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **RtcHost** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **RtcMethod** \(used to call underlying functions of the driver\) in **RtcHost**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference - To the driver, the custom structure carries parameters and data. The values in the **rtc\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. + To the driver, the custom structure carries parameters and data. The values in the **rtc\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. ``` struct RtcConfigInfo { @@ -303,7 +301,7 @@ The following uses **rtc\_hi35xx.c** as an example to present the contents tha }; ``` - - Instantiate the callback function structure **RtcMethod** in **RtcHost**. Other members are initialized by using the **Init** function. + - Instantiate the callback function structure **RtcMethod** in **RtcHost**. Other members are initialized by using the **Init** function. ``` // Example in rtc_hi35xx.c: instantiate the hook. @@ -326,13 +324,13 @@ The following uses **rtc\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) - **Table 2** Input parameters and return values of the Bind function + **Table 2** Input parameters and return values of the Bind function

Status (Value)

@@ -376,7 +374,7 @@ The following uses **rtc\_hi35xx.c** as an example to present the contents tha Function description: - Associates the **HdfDeviceObject** object and **RtcHost**. + Associates the **HdfDeviceObject** object and **RtcHost**. ``` static int32_t HiRtcBind(struct HdfDeviceObject *device) @@ -395,7 +393,7 @@ The following uses **rtc\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -403,7 +401,7 @@ The following uses **rtc\_hi35xx.c** as an example to present the contents tha Function description: - Initializes the custom structure object and **RtcHost**. + Initializes the custom structure object and **RtcHost**. ``` static int32_t HiRtcInit(struct HdfDeviceObject *device) @@ -437,15 +435,15 @@ The following uses **rtc\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: – - **Function description**: + **Function description**: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** or **Bind** function has the corresponding value assignment operations. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** or **Bind** function has the corresponding value assignment operations. ``` static void HiRtcRelease(struct HdfDeviceObject *device) @@ -462,7 +460,4 @@ The following uses **rtc\_hi35xx.c** as an example to present the contents tha } RtcHostDestroy(host); // Release RtcHost. } - ``` - - - + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-spi-des.md b/en/device-dev/driver/driver-platform-spi-des.md index 4388fdd99b..a8b35d2682 100644 --- a/en/device-dev/driver/driver-platform-spi-des.md +++ b/en/device-dev/driver/driver-platform-spi-des.md @@ -2,46 +2,46 @@ ## Overview -- Serial Peripheral Interface \(SPI\) is a serial bus specification used for high-speed, full-duplex, and synchronous communication. -- SPI is developed by Motorola. It is commonly used for communication with flash memory, real-time clocks, sensors, and analog-to-digital \(A/D\) converters. -- SPI works in controller/device mode. Generally, there is one SPI controller that controls one or more SPI devices. They are connected via four wires: - - SCLK: clock signals output from the SPI controller - - MOSI: data output from the SPI controller and input into an SPI device - - MISO: data output from an SPI device and input into the SPI controller - - CS: signals enabled by an SPI device and controlled by the SPI controller +Serial Peripheral Interface \(SPI\) is a serial bus specification used for high-speed, full-duplex, and synchronous communication. +SPI is developed by Motorola. It is commonly used for communication with flash memory, real-time clocks, sensors, and analog-to-digital \(A/D\) converters. +SPI works in controller/device mode. Generally, there is one SPI controller that controls one or more SPI devices. They are connected via four wires: +- SCLK: clock signals output from the SPI controller +- MOSI: data output from the SPI controller and input into an SPI device +- MISO: data output from an SPI device and input into the SPI controller +- CS: signals enabled by an SPI device and controlled by the SPI controller -- [Figure 1](#fig89085710359) shows the connection between one SPI controller and two SPI devices \(device A and device B\). In this figure, device A and device B share three pins \(SCLK, MISO, and MOSI\) of the controller. CS0 of device A and CS1 of device B are connected to CS0 and CS1 of the controller, respectively. +[Figure 1](#fig89085710359) shows the connection between one SPI controller and two SPI devices \(device A and device B\). In this figure, device A and device B share three pins \(SCLK, MISO, and MOSI\) of the controller. CS0 of device A and CS1 of device B are connected to CS0 and CS1 of the controller, respectively. -**Figure 1** SPI controller/device connection +**Figure 1** SPI controller/device connection ![](figures/spi-controller-device-connection.png "spi-controller-device-connection") -- SPI communication is usually initiated by the SPI controller and is operated as follows: +SPI communication is usually initiated by the SPI controller and is operated as follows: 1. A single SPI device is selected at a time via the CS to communicate with the SPI controller. 2. Clock signals are provided for the selected SPI device via the SCLK. 3. The SPI controller sends data to SPI devices via the MOSI, and receives data from SPI devices via the MISO. - SPI can work in one of the following four modes, equivalent to one of the four possible states for Clock Polarity \(CPOL\) and Clock Phase \(CPHA\): - - If both CPOL and CPHA are **0**, the clock signal level is low in the idle state and data is sampled on the first clock edge. - - If CPOL is **0** and CPHA is **1**, the clock signal level is low in the idle state and data is sampled on the second clock edge. - - If CPOL is **1** and CPHA is **0**, the clock signal level is high in the idle state and data is sampled on the first clock edge. - - If both CPOL and CPHA are **1**, the clock signal level is high in the idle state and data is sampled on the second clock edge. + - If both CPOL and CPHA are **0**, the clock signal level is low in the idle state and data is sampled on the first clock edge. + - If CPOL is **0** and CPHA is **1**, the clock signal level is low in the idle state and data is sampled on the second clock edge. + - If CPOL is **1** and CPHA is **0**, the clock signal level is high in the idle state and data is sampled on the first clock edge. + - If both CPOL and CPHA are **1**, the clock signal level is high in the idle state and data is sampled on the second clock edge. - SPI defines a set of common functions for operating an SPI device, including those for: - Obtaining and releasing the handle of an SPI device. - Reading or writing data of a specified length from or into an SPI device. - - Customizing data reading or writing via **SpiMsg**. + - Customizing data reading or writing via **SpiMsg**. - Obtaining and setting SPI device configuration parameters. ->![](../public_sys-resources/icon-note.gif) **NOTE:** +>![](../public_sys-resources/icon-note.gif) **NOTE**
>Currently, these functions are only applicable in the communication initiated by the SPI controller. ## Available APIs -**Table 1** APIs for the SPI driver +**Table 1** APIs for the SPI driver

Capability

@@ -106,16 +106,16 @@ [Figure 2](#fig1586912310348) shows the process of using an SPI device. -**Figure 2** Process of using an SPI device +**Figure 2** Process of using an SPI device ![](figures/process-of-using-an-spi-device.png "process-of-using-an-spi-device") ### Obtaining an SPI Device Handle -Before performing SPI communication, obtain an SPI device handle by calling **SpiOpen**. This function returns an SPI device handle with a specified bus number and CS number. +Before performing SPI communication, obtain an SPI device handle by calling **SpiOpen**. This function returns an SPI device handle with a specified bus number and CS number. DevHandle SpiOpen\(const struct SpiDevInfo \*info\); -**Table 2** Description of SpiOpen +**Table 2** Description of SpiOpen

Parameter

@@ -146,7 +146,7 @@ DevHandle SpiOpen\(const struct SpiDevInfo \*info\);
-The following example shows how to obtain an SPI device handle based on the assumption that both the bus number and CS number of the SPI device are **0**. +The following example shows how to obtain an SPI device handle based on the assumption that both the bus number and CS number of the SPI device are **0**. ``` struct SpiDevInfo spiDevinfo; /* SPI device descriptor */ @@ -168,7 +168,7 @@ After obtaining the SPI device handle, obtain the SPI device configuration param int32\_t SpiGetCfg\(DevHandle handle, struct SpiCfg \*cfg\); -**Table 3** Description of SpiGetCfg +**Table 3** Description of SpiGetCfg

Parameter

@@ -219,7 +219,7 @@ After obtaining the SPI device handle, set SPI device configuration parameters b int32\_t SpiSetCfg\(DevHandle handle, struct SpiCfg \*cfg\); -**Table 4** Description of SpiSetCfg +**Table 4** Description of SpiSetCfg

Parameter

@@ -276,7 +276,7 @@ To write data into an SPI device only once, call the following function: int32\_t SpiWrite\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); -**Table 5** Description of SpiWrite +**Table 5** Description of SpiWrite

Parameter

@@ -333,7 +333,7 @@ To read data from an SPI device only once, call the following function: int32\_t SpiRead\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); -**Table 6** Description of SpiRead +**Table 6** Description of SpiRead

Parameter

@@ -390,7 +390,7 @@ To launch a custom transfer, call the following function: int32\_t SpiTransfer\(DevHandle handle, struct SpiMsg \*msgs, uint32\_t count\); -**Table 7** Description of SpiTransfer +**Table 7** Description of SpiTransfer

Parameter

@@ -457,7 +457,7 @@ void SpiClose\(DevHandle handle\); This function will release the resources previously obtained. -**Table 8** Description of SpiClose +**Table 8** Description of SpiClose

Parameter

@@ -545,5 +545,4 @@ err: /* Destroy the SPI device handle. */ SpiClose(spiHandle); } -``` - +``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-spi-develop.md b/en/device-dev/driver/driver-platform-spi-develop.md index ca8873bd9c..40ed76d024 100644 --- a/en/device-dev/driver/driver-platform-spi-develop.md +++ b/en/device-dev/driver/driver-platform-spi-develop.md @@ -5,7 +5,7 @@ In the Hardware Driver Foundation \(HDF\), the Serial Peripheral Interface \(SPI\) uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to handle external access requests. After receiving an access request from an API, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDFDeviceManager can be directly used. However, you need to configure a device node for each device, which increases the memory usage. -**Figure 1** Independent service mode +**Figure 1** Independent service mode ![](figures/independent-service-mode.png "SPI-independent-service-mode") ## Available APIs @@ -21,7 +21,7 @@ struct SpiCntlrMethod { int32_t (*Close)(struct SpiCntlr *cntlr); }; ``` -**Table 1** Callbacks for the members in the SpiCntlrMethod structure +**Table 1** Callbacks for the members in the SpiCntlrMethod structure

Callback

@@ -91,32 +91,30 @@ struct SpiCntlrMethod { The SPI module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **spi\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **spi\_config.hcs** file. 3. Instantiate the SPI controller object. - - Initialize **SpiCntlr**. - - Instantiate **SpiCntlrMethod** in the **SpiCntlr** object. + - Initialize **SpiCntlr**. + - Instantiate **SpiCntlrMethod** in the **SpiCntlr** object. - >![](../public_sys-resources/icon-note.gif) **NOTE** + For details, see [Available APIs](#section752964871810). - >For details, see [Available APIs](#section752964871810). - -4. Debug the driver. - - \(Optional\) For new drivers, verify the basic functions, such as the SPI control status and response to interrupts. + 4. \(Optional\) Debug the driver. + For new drivers, verify the basic functions, such as the SPI control status and response to interrupts. ## Development Example -The following uses **spi\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **spi\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. + Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. - SPI driver entry reference @@ -132,11 +130,11 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha HDF_INIT(g_hdfSpiDevice); ``` -2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **spi\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **SpiCntlr** members at the core layer. +2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **spi\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **SpiCntlr** members at the core layer. - In this example, there is only one SPI controller. If there are multiple SPI controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **spi\_config** file. + In this example, there is only one SPI controller. If there are multiple SPI controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **spi\_config** file. - - **device\_info.hcs** configuration reference + - **device\_info.hcs** configuration reference ``` root { @@ -169,7 +167,7 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha } ``` - - **spi\_config.hcs** configuration reference + - **spi\_config.hcs** configuration reference ``` root { @@ -218,10 +216,10 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha } ``` -3. Initialize the **SpiCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **SpiCntlrMethod** \(used to call underlying functions of the driver\) in **SpiCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **SpiCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **SpiCntlrMethod** \(used to call underlying functions of the driver\) in **SpiCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference - To the driver, the custom structure carries parameters and data. The values in the **spi\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number and bus number, are also passed to the object at the core layer. + To the driver, the custom structure carries parameters and data. The values in the **spi\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number and bus number, are also passed to the object at the core layer. ``` struct Pl022 {// Corresponds to parameters in .hcs. @@ -264,7 +262,7 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha }; ``` - - Instantiate the callback function structure **SpiCntlrMethod** in **SpiCntlr**. Other members are initialized by using the **Init** function. + - Instantiate the callback function structure **SpiCntlrMethod** in **SpiCntlr**. Other members are initialized by using the **Init** function. ``` // Example in spi_hi35xx.c: instantiate the hook. @@ -281,7 +279,7 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -289,7 +287,7 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha Function description: - Associates the **SpiCntlr** object with **HdfDeviceObject**. + Associates the **SpiCntlr** object with **HdfDeviceObject**. ``` static int32_t HdfSpiDeviceBind(struct HdfDeviceObject *device) @@ -317,13 +315,13 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **/drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **/drivers/framework/include/utils/hdf\_base.h** file.\) - **Table 2** Input parameters and return values of the init function + **Table 2** Input parameters and return values of the init function

Status (Value)

@@ -367,7 +365,7 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha Function description: - Initializes the custom structure object and **SpiCntlr**. + Initializes the custom structure object and **SpiCntlr**. ``` static int32_t HdfSpiDeviceInit(struct HdfDeviceObject *device) @@ -418,7 +416,7 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -426,7 +424,7 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha Function description: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. ``` static void HdfSpiDeviceRelease(struct HdfDeviceObject *device) @@ -441,8 +439,4 @@ The following uses **spi\_hi35xx.c** as an example to present the contents tha } SpiCntlrDestroy(cntlr); // Release the Pl022 object. } - ``` - - - - + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-uart-des.md b/en/device-dev/driver/driver-platform-uart-des.md index 0d8809f05b..37d4c34d6d 100644 --- a/en/device-dev/driver/driver-platform-uart-des.md +++ b/en/device-dev/driver/driver-platform-uart-des.md @@ -2,27 +2,29 @@ ## Overview -- The Universal Asynchronous Receiver/Transmitter \(UART\) is a universal serial data bus used for asynchronous communication. It enables bi-directional communication between devices in full-duplex mode. -- UART is widely used to print information for debugging or to connect to various external modules such as GPS and Bluetooth. -- A UART is connected to other modules through two wires \(as shown in [Figure 1](#fig68294715408)\) or four wires \(as shown in [Figure 2](#fig179241542163112)\). - - TX: TX pin of the transmitting UART. It is connected to the RX pin of the peer UART. - - RX: RX pin of the receiving UART. It is connected to the TX pin of the peer UART. - - RTS: Request to Send signal pin. It is connected to the CTS pin of the peer UART and is used to indicate whether the local UART is ready to receive data. - - CTS: Clear to Send signal pin. It is connected to the RTS pin of the peer UART and is used to indicate whether the local UART is allowed to send data to the peer end. - - **Figure 1** 2-wire UART communication +The Universal Asynchronous Receiver/Transmitter \(UART\) is a universal serial data bus used for asynchronous communication. It enables bi-directional communication between devices in full-duplex mode. +UART is widely used to print information for debugging or to connect to various external modules such as GPS and Bluetooth. +A UART is connected to other modules through two wires \(as shown in [Figure 1](#fig68294715408)\) or four wires \(as shown in [Figure 2](#fig179241542163112)\). +- TX: TX pin of the transmitting UART. It is connected to the RX pin of the peer UART. +- RX: RX pin of the receiving UART. It is connected to the TX pin of the peer UART. +- RTS: Request to Send signal pin. It is connected to the CTS pin of the peer UART and is used to indicate whether the local UART is ready to receive data. +- CTS: Clear to Send signal pin. It is connected to the RTS pin of the peer UART and is used to indicate whether the local UART is allowed to send data to the peer end. + + **Figure 1** 2-wire UART communication ![](figures/2-wire-uart-communication.png "2-wire-uart-communication") - **Figure 2** 4-wire UART communication + **Figure 2** 4-wire UART communication ![](figures/4-wire-uart-communication.png "4-wire-uart-communication") -- The transmitting and receiving UARTs must ensure that they have the same settings on particular attributes such as the baud rate and data format \(start bit, data bit, parity bit, and stop bit\) before they start to communicate. During data transmission, a UART sends data to the peer end over the TX pin and receives data from the peer end over the RX pin. When the size of the buffer used by a UART for storing received data reaches the preset threshold, the RTS signal of the UART changes to **1** \(data cannot be received\), and the peer UART stops sending data to it because its CTS signal does not allow it to send data. -- The UART interface defines a set of common functions for operating a UART port, including obtaining and releasing device handles, reading and writing data of a specified length, and obtaining and setting the baud rate, as well as the device attributes. +The transmitting and receiving UARTs must ensure that they have the same settings on particular attributes such as the baud rate and data format \(start bit, data bit, parity bit, and stop bit\) before they start to communicate. During data transmission, a UART sends data to the peer end over the TX pin and receives data from the peer end over the RX pin. When the size of the buffer used by a UART for storing received data reaches the preset threshold, the RTS signal of the UART changes to **1** \(data cannot be received\), and the peer UART stops sending data to it because its CTS signal does not allow it to send data. + ## Available APIs -**Table 1** APIs for the UART driver +The UART interface defines a set of common functions for operating a UART port, including obtaining and releasing device handles, reading and writing data of a specified length, and obtaining and setting the baud rate, as well as the device attributes. + +**Table 1** APIs for the UART driver

Capability

@@ -94,7 +96,7 @@
->![](../public_sys-resources/icon-note.gif) **NOTE:** +>![](../public_sys-resources/icon-note.gif) **NOTE**
>All functions provided in this document can be called only in kernel space. ## Usage Guidelines @@ -103,16 +105,16 @@ [Figure 3](#fig99673244388) shows the process of using a UART device. -**Figure 3** Process of using a UART device +**Figure 3** Process of using a UART device ![](figures/process-of-using-a-uart-device.png "process-of-using-a-uart-device") ### Obtaining a UART Device Handle -Before performing UART communication, call **UartOpen** to obtain a UART device handle. This function returns the pointer to the UART device handle with a specified port number. +Before performing UART communication, call **UartOpen** to obtain a UART device handle. This function returns the pointer to the UART device handle with a specified port number. DevHandle UartOpen\(uint32\_t port\); -**Table 2** Description of UartOpen +**Table 2** Description of UartOpen

Parameter

@@ -144,7 +146,7 @@ DevHandle UartOpen\(uint32\_t port\);
-The following example shows how to obtain a UART device handle based on the assumption that the UART port number is **3**: +The following example shows how to obtain a UART device handle based on the assumption that the UART port number is **3**: ``` DevHandle handle = NULL; /* The UART device handle */ @@ -162,7 +164,7 @@ After obtaining the UART device handle, set the UART baud rate by calling the fo int32\_t UartSetBaud\(DevHandle handle, uint32\_t baudRate\); -**Table 3** Description of UartSetBaud +**Table 3** Description of UartSetBaud

Parameter

@@ -199,7 +201,7 @@ int32\_t UartSetBaud\(DevHandle handle, uint32\_t baudRate\);
-The following example shows how to set the UART baud rate to **9600**: +The following example shows how to set the UART baud rate to **9600**: ``` int32_t ret; @@ -216,7 +218,7 @@ After setting the UART baud rate, obtain the current baud rate by calling the fo int32\_t UartGetBaud\(DevHandle handle, uint32\_t \*baudRate\); -**Table 4** Description of UartGetBaud +**Table 4** Description of UartGetBaud

Parameter

@@ -271,7 +273,7 @@ Before performing UART communication, set the UART device attributes by calling int32\_t UartSetAttribute\(DevHandle handle, struct UartAttribute \*attribute\); -**Table 5** Description of UartSetAttribute +**Table 5** Description of UartSetAttribute

Parameter

@@ -333,7 +335,7 @@ After setting the UART device attributes, obtain the current device attributes b int32\_t UartGetAttribute\(DevHandle handle, struct UartAttribute \*attribute\); -**Table 6** Description of UartGetAttribute +**Table 6** Description of UartGetAttribute

Parameter

@@ -388,7 +390,7 @@ Before performing UART communication, set the UART transmission mode by calling int32\_t UartSetTransMode\(DevHandle handle, enum UartTransMode mode\); -**Table 7** Description of UartSetTransMode +**Table 7** Description of UartSetTransMode

Parameter

@@ -425,7 +427,7 @@ int32\_t UartSetTransMode\(DevHandle handle, enum UartTransMode mode\);
-The following example shows how to set the transmission mode to **UART\_MODE\_RD\_BLOCK**: +The following example shows how to set the transmission mode to **UART\_MODE\_RD\_BLOCK**: ``` int32_t ret; @@ -442,7 +444,7 @@ To write data into a UART device, call the following function: int32\_t UartWrite\(DevHandle handle, uint8\_t \*data, uint32\_t size\); -**Table 8** Description of UartWrite +**Table 8** Description of UartWrite

Parameter

@@ -502,7 +504,7 @@ To write data into a UART device, call the following function: int32\_t UartRead\(DevHandle handle, uint8\_t \*data, uint32\_t size\); -**Table 9** Description of UartRead +**Table 9** Description of UartRead

Parameter

@@ -557,7 +559,7 @@ if (ret < 0) { ``` >![](../public_sys-resources/icon-caution.gif) **CAUTION:** ->Data is successfully read from the UART device if a non-negative value is returned. If the return value is **0**, no valid data can be read from the UART device. If the return value is greater than **0**, the return value is the length of the data actually read from the UART device. The length is less than or equal to the value of **size** and does not exceed the maximum length of data to read at a time specified by the UART controller in use. +>Data is successfully read from the UART device if a non-negative value is returned. If the return value is **0**, no valid data can be read from the UART device. If the return value is greater than **0**, the return value is the length of the data actually read from the UART device. The length is less than or equal to the value of **size** and does not exceed the maximum length of data to read at a time specified by the UART controller in use. ### Destroying the UART Device Handle @@ -567,7 +569,7 @@ void UartClose\(DevHandle handle\); This function will release the resources previously obtained. -**Table 10** Description of UartClose +**Table 10** Description of UartClose

Parameter

@@ -655,5 +657,4 @@ _ERR: /* Destroy the UART device handle. */ UartClose(handle); } -``` - +``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-uart-develop.md b/en/device-dev/driver/driver-platform-uart-develop.md index bc6d827363..72437ef747 100644 --- a/en/device-dev/driver/driver-platform-uart-develop.md +++ b/en/device-dev/driver/driver-platform-uart-develop.md @@ -4,7 +4,7 @@ In the Hardware Driver Foundation \(HDF\), the Universal Asynchronous Receiver/Transmitter \(UART\) uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to handle external access requests. After receiving an access request from an API, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDF Device Manager can be directly used. However, you need to configure a device node for each device, which increases the memory usage. -**Figure 1** Independent service mode +**Figure 1** Independent service mode ![](figures/independent-service-mode.png "independent-service-mode-14") ## Available APIs @@ -26,7 +26,7 @@ struct UartHostMethod { }; ``` -**Table 1** Callbacks for the members in the UartHostMethod structure +**Table 1** Callbacks for the members in the UartHostMethod structure

Callback

@@ -167,33 +167,31 @@ struct UartHostMethod { The UART module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **uart\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **uart\_config.hcs** file. 3. Instantiate the UART controller object. - - Initialize **UartHost**. - - Instantiate **UartHostMethod** in the **UartHost** object. + - Initialize **UartHost**. + - Instantiate **UartHostMethod** in the **UartHost** object. - >![](../public_sys-resources/icon-note.gif) **NOTE** - - >For details, see [Available APIs](#available-apis). - - -4. Debug the driver. - - \(Optional\) For new drivers, verify the basic functions, such as the UART control status and response to interrupts. + For details, see [Available APIs](#available-apis). + +4. \(Optional\) Debug the driver. + + For new drivers, verify the basic functions, such as the UART control status and response to interrupts. ## Development Example -The following uses **uart\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **uart\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. + Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. - UART driver entry reference @@ -209,11 +207,11 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th HDF_INIT(g_hdfUartDevice); ``` -2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **uart\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **UartHost** members at the core layer. +2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **uart\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **UartHost** members at the core layer. - In this example, there is only one UART controller. If there are multiple UART controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **uart\_config** file. + In this example, there is only one UART controller. If there are multiple UART controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **uart\_config** file. - - **device\_info.hcs** configuration reference + - **device\_info.hcs** configuration reference ``` root { @@ -246,7 +244,7 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th } ``` - - **uart\_config.hcs** configuration reference + - **uart\_config.hcs** configuration reference ``` root { @@ -278,10 +276,10 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th } ``` -3. Initialize the **UartHost** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **UartHostMethod** \(used to call underlying functions of the driver\) in **UartHost**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **UartHost** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **UartHostMethod** \(used to call underlying functions of the driver\) in **UartHost**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference - To the driver, the custom structure carries parameters and data. The values in the **uart\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number, are also passed to the objects at the core layer. + To the driver, the custom structure carries parameters and data. The values in the **uart\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number, are also passed to the objects at the core layer. ``` struct UartPl011Port {// Structure related to the API @@ -314,7 +312,7 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th #define UART_FLG_RD_BLOCK (1 << 2) RecvNotify recv; // Pointer to the function that receives serial port data struct UartOps *ops; // Custom function pointer structure. For details, see device/hisilicon/drivers/uart/uart_pl011.c. - void *private; // It stores the pointer to the start address of UartPl011Port for easy invocation. + void *private; // Pointer to the start address of UartPl011Port for easy invocation }; // UartHost is the controller structure at the core layer. Its members are assigned with values by using the Init function. @@ -328,7 +326,7 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th }; ``` - - Instantiate the callback function structure **UartHostMethod** in **UartHost**. Other members are initialized by using the **Bind** function. + - Instantiate the callback function structure **UartHostMethod** in **UartHost**. Other members are initialized by using the **Bind** function. ``` // Example in pwm_hi35xx.c: instantiate the hook. @@ -350,13 +348,13 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) - **Table 2** Input parameters and return values of the Bind function + **Table 2** Input parameters and return values of the Bind function

Status (Value)

@@ -400,7 +398,7 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th Function description: - Initializes the custom structure object and **UartHost**. + Initializes the custom structure object and **UartHost**. ``` //uart_hi35xx.c @@ -430,7 +428,7 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -438,7 +436,7 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th Function description: - Initializes the custom structure object and **UartHost**, calls the **artAddDev** function at the core layer, and connects to VFS. + Initializes the custom structure object and **UartHost**, calls the **artAddDev** function at the core layer, and connects to VFS. ``` int32_t HdfUartDeviceInit(struct HdfDeviceObject *device) @@ -502,7 +500,7 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th Input parameters: - **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. + **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. Return values: @@ -510,7 +508,7 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th Function description: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. ``` void HdfUartDeviceRelease(struct HdfDeviceObject *device) @@ -544,7 +542,4 @@ The following uses **uart\_hi35xx.c** as an example to present the contents th (void)OsalMemFree(udd);// Release UartDriverData. host->priv = NULL; } - ``` - - - + ``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-watchdog-des.md b/en/device-dev/driver/driver-platform-watchdog-des.md index e571e6fc34..2a9b44765c 100644 --- a/en/device-dev/driver/driver-platform-watchdog-des.md +++ b/en/device-dev/driver/driver-platform-watchdog-des.md @@ -6,7 +6,7 @@ A watchdog, also called a watchdog timer, is a hardware timing device. If an err ## Available APIs -**Table 1** Watchdog APIs +**Table 1** Watchdog APIs

Capability

@@ -70,7 +70,7 @@ A watchdog, also called a watchdog timer, is a hardware timing device. If an err
->![](../public_sys-resources/icon-note.gif) **NOTE:** +>![](../public_sys-resources/icon-note.gif) **NOTE**
>All watchdog functions provided in this document can be called only in kernel mode. ## Usage Guidelines @@ -79,16 +79,16 @@ A watchdog, also called a watchdog timer, is a hardware timing device. If an err [Figure 1](#fig430533913392) illustrates the process of using a watchdog. -**Figure 1** Process of using a watchdog +**Figure 1** Process of using a watchdog ![](figures/process-of-using-a-watchdog.png "process-of-using-a-watchdog") ### Opening a Watchdog -Use **WatchdogOpen** to open a watchdog. A system may have multiple watchdogs. You can open the specified watchdog by using the ID. +Use **WatchdogOpen** to open a watchdog. A system may have multiple watchdogs. You can open the specified watchdog by using the ID. int32\_t WatchdogOpen\(int16\_t wdtId\); -**Table 2** Description of WatchdogOpen +**Table 2** Description of WatchdogOpen

Parameter

@@ -133,7 +133,7 @@ if (handle == NULL) { int32\_t WatchdogGetStatus\(DevHandle handle, int32\_t \*status\); -**Table 3** Description of WatchdogGetStatus +**Table 3** Description of WatchdogGetStatus

Parameter

@@ -185,7 +185,7 @@ if (ret != 0) { int32\_t WatchdogSetTimeout\(PalHandle \*handle, uint32\_t seconds\); -**Table 4** Description of WatchdogSetTimeout +**Table 4** Description of WatchdogSetTimeout

Parameter

@@ -237,7 +237,7 @@ if (ret != 0) { int32\_t WatchdogGetTimeout\(PalHandle \*handle, uint32\_t \*seconds\); -**Table 5** Description of WatchdogGetTimeout +**Table 5** Description of WatchdogGetTimeout

Parameter

@@ -289,7 +289,7 @@ if (ret != 0) { int32\_t WatchdogStart\(DevHandle handle\); -**Table 6** Description of WatchdogStart +**Table 6** Description of WatchdogStart

Parameter

@@ -335,7 +335,7 @@ if (ret != 0) { int32\_t WatchdogFeed\(DevHandle handle\); -**Table 7** Description of WatchdogFeed +**Table 7** Description of WatchdogFeed

Parameter

@@ -381,7 +381,7 @@ if (ret != 0) { int32\_t WatchdogStop\(DevHandle handle\); -**Table 8** Description of WatchdogStop +**Table 8** Description of WatchdogStop

Parameter

@@ -425,11 +425,11 @@ if (ret != 0) { ### Closing a Watchdog -If the watchdog is no longer required, call **WatchdogClose** to close the watchdog handle. +If the watchdog is no longer required, call **WatchdogClose** to close the watchdog handle. void WatchdogClose\(DevHandle handle\); -**Table 9** Description of WatchdogClose +**Table 9** Description of WatchdogClose

Parameter

@@ -535,5 +535,4 @@ static int32_t TestCaseWatchdog(void) WatchdogClose(handle); return -1; } -``` - +``` \ No newline at end of file diff --git a/en/device-dev/driver/driver-platform-watchdog-develop.md b/en/device-dev/driver/driver-platform-watchdog-develop.md index 367b2531c4..13898cfeaa 100644 --- a/en/device-dev/driver/driver-platform-watchdog-develop.md +++ b/en/device-dev/driver/driver-platform-watchdog-develop.md @@ -5,7 +5,7 @@ In the Hardware Driver Foundation \(HDF\), the Watchdog \(also called Watchdog timer\) module uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to handle external access requests. After receiving an access request from an API, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDF Device Manager can be directly used. However, you need to configure a device node for each device, which increases the memory usage. -**Figure 1** Independent service mode +**Figure 1** Independent service mode ![](figures/independent-service-mode.png "independent-service-mode-15") ## Available APIs @@ -25,7 +25,7 @@ struct WatchdogMethod { }; ``` -**Table 1** Callbacks for the members in the WatchdogMethod structure +**Table 1** Callbacks for the members in the WatchdogMethod structure

Callback

@@ -116,33 +116,31 @@ struct WatchdogMethod { The Watchdog module adaptation involves the following steps: 1. Instantiate the driver entry. - - Instantiate the **HdfDriverEntry** structure. - - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. + - Instantiate the **HdfDriverEntry** structure. + - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. 2. Configure attribute files. - - Add the **deviceNode** information to the **device\_info.hcs** file. - - \(Optional\) Add the **watchdog\_config.hcs** file. + - Add the **deviceNode** information to the **device\_info.hcs** file. + - \(Optional\) Add the **watchdog\_config.hcs** file. 3. Instantiate the Watchdog controller object. - - Initialize **WatchdogCntlr**. - - Instantiate **WatchdogMethod** in the **WatchdogCntlr** object. + - Initialize **WatchdogCntlr**. + - Instantiate **WatchdogMethod** in the **WatchdogCntlr** object. - >![](../public_sys-resources/icon-note.gif) **NOTE** + For details, see [Available APIs](#available-apis). - >For details, see [Available APIs](#available-apis). +4. \(Optional\) Debug the driver. - -4. Debug the driver. - - \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether the watchdog timer is successfully set. + For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether the watchdog timer is successfully set. ## Development Example -The following uses **watchdog\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. +The following uses **watchdog\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. -1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. +1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. - Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. + Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit. - Watchdog driver entry reference @@ -157,11 +155,11 @@ The following uses **watchdog\_hi35xx.c** as an example to present the content HDF_INIT(g_watchdogDriverEntry);// Call HDF_INIT to register the driver entry with the HDF. ``` -2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the component attributes in the **watchdog\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **WatchdogCntlr** members at the core layer. +2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the component attributes in the **watchdog\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **WatchdogCntlr** members at the core layer. - In this example, there is only one Watchdog controller. If there are multiple Watchdog controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **watchdog\_config** file. + In this example, there is only one Watchdog controller. If there are multiple Watchdog controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **watchdog\_config** file. - - **device\_info.hcs** configuration reference + - **device\_info.hcs** configuration reference ``` root { @@ -184,7 +182,7 @@ The following uses **watchdog\_hi35xx.c** as an example to present the content } ``` - - **watchdog\_config.hcs** configuration reference + - **watchdog\_config.hcs** configuration reference ``` root { @@ -204,10 +202,10 @@ The following uses **watchdog\_hi35xx.c** as an example to present the content } ``` -3. Initialize the **WatchdogCntlr** object at the core layer, including initializing the vendor custom structure \(passing parameters and data\), instantiating **WatchdogMethod** \(used to call underlying functions of the driver\) in **WatchdogCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). +3. Initialize the **WatchdogCntlr** object at the core layer, including initializing the vendor custom structure \(passing parameters and data\), instantiating **WatchdogMethod** \(used to call underlying functions of the driver\) in **WatchdogCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). - Custom structure reference - To the driver, the custom structure carries parameters and data. The values in the **watchdog\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the index and the number of pins, are also passed to the **WatchdogCntlr** object at the core layer. + To the driver, the custom structure carries parameters and data. The values in the **watchdog\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the index and the number of pins, are also passed to the **WatchdogCntlr** object at the core layer. ``` struct Hi35xxWatchdog { @@ -228,7 +226,7 @@ The following uses **watchdog\_hi35xx.c** as an example to present the content }; ``` - - Instantiate the callback function structure **WatchdogMethod** in **WatchdogCntlr**. Other members are initialized by using the **Init** and **Bind** functions. + - Instantiate the callback function structure **WatchdogMethod** in **WatchdogCntlr**. Other members are initialized by using the **Init** and **Bind** functions. ``` static struct WatchdogMethod g_method = { @@ -245,13 +243,13 @@ The following uses **watchdog\_hi35xx.c** as an example to present the content Input parameters: - **HdfDeviceObject**: device object created by the HDF for each driver. It stores device-related private data and service APIs. + **HdfDeviceObject**: device object created by the HDF for each driver. It stores device-related private data and service APIs. Return values: - HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) + HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) - **Table 2** Input parameters and return values of the Init and Bind functions + **Table 2** Input parameters and return values of the Init and Bind functions

Status (Value)

@@ -290,7 +288,7 @@ The following uses **watchdog\_hi35xx.c** as an example to present the content Function description: - Initializes the custom structure object and **WatchdogCntlr**, and calls the **WatchdogCntlrAdd** function at the core layer. + Initializes the custom structure object and **WatchdogCntlr**, and calls the **WatchdogCntlrAdd** function at the core layer. ``` // Generally, the Init function initializes the members of the Hi35xxWatchdog structure based on the attribute values of the input parameter (HdfDeviceObject). @@ -328,7 +326,7 @@ The following uses **watchdog\_hi35xx.c** as an example to present the content Input parameters: - **HdfDeviceObject**: device object created by the HDF for each driver. It stores device-related private data and service APIs. + **HdfDeviceObject**: device object created by the HDF for each driver. It stores device-related private data and service APIs. Return values: @@ -336,7 +334,7 @@ The following uses **watchdog\_hi35xx.c** as an example to present the content Function description: - Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. + Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. ``` static void Hi35xxWatchdogRelease(struct HdfDeviceObject *device) @@ -357,7 +355,4 @@ The following uses **watchdog\_hi35xx.c** as an example to present the content } OsalMemFree(hwdt); // Release the memory occupied by the vendor-defined objects. } - ``` - - - + ``` \ No newline at end of file diff --git a/en/readme/update.md b/en/readme/update.md index 062f0dbbd9..58abb6e73e 100755 --- a/en/readme/update.md +++ b/en/readme/update.md @@ -67,11 +67,11 @@ base/update # Update subsystem repository **Update subsystem** -update\_app +[update\_app](https://gitee.com/openharmony/update_app) -update\_updateservice +[update\_updateservice](https://gitee.com/openharmony/update_updateservice) -update\_updater +[update\_updater](https://gitee.com/openharmony/update_updater) -update\_packaging\_tools +[update\_packaging\_tools](https://gitee.com/openharmony/update_packaging_tools) diff --git a/zh-cn/application-dev/ability/context-userguide.md b/zh-cn/application-dev/ability/context-userguide.md index f5472f3e54..791e7014ad 100644 --- a/zh-cn/application-dev/ability/context-userguide.md +++ b/zh-cn/application-dev/ability/context-userguide.md @@ -11,7 +11,7 @@ ​ **FA模型** 只有app/Context中的方法属于FA模型对应的Context。该模式下,应用级别的Context和Ability级别的Context都是该类型的实例,如果在应用级别的Context里面调用了Ability级别的方法,会产生错误。所以开发者需要注意context实例所代表的实际含义。 -​ **Stage模型** 除了app/Context之外的Context都属于Stage模型,分别有application/Context、application/AbilityStageContext、application/ExtensionContext、application/AbilityContext、application/FormExtensionContext和application/ServiceExtensionContext六种Context。这些Context的介绍及使用方式将会在[Stage模型和Context详细介绍](#stage模型和context详细介绍)种进行说明。 +​ **Stage模型** 除了app/Context之外的Context都属于Stage模型,分别有application/Context、application/ApplicationContext、application/AbilityStageContext、application/ExtensionContext、application/AbilityContext、application/FormExtensionContext和application/ServiceExtensionContext七种Context。这些Context的介绍及使用方式将会在[Stage模型和Context详细介绍](#stage模型和context详细介绍)种进行说明。 ![contextIntroduction](figures/contextIntroduction.png) @@ -55,13 +55,13 @@ export default { ## Stage模型和Context详细介绍 -​ Stage模型有6大Context: +​ Stage模型有7大Context: ### application/Context **概述** -​ application/Context类型的Context是基类Context,里面提供了应用的一些基础信息:resourceManager、applicationInfo、cacheDir等,还有应用的一些基本方法:createBundleContext、switchArea等。应用级别的Context也是application/Context这种类型。 +​ application/Context类型的Context是基类Context,里面提供了应用的一些基础信息:resourceManager、applicationInfo、cacheDir、area等,还有应用的一些基本方法:createBundleContext等。 **获取方法** @@ -89,15 +89,77 @@ export default class MainAbility extends Ability { ​ https://gitee.com/openharmony/interface_sdk-js/blob/master/api/application/Context.d.ts +### application/ApplicationContext + + **概述** + +​ application/ApplicationContext是应用级别的Context。和基类Context相比,应用级别的Context中提供了监听进程内组件的生命周期的能力,包括registerAbilityLifecycleCallback和unregisterAbilityLifecycleCallback两种方法。 + +**获取方法** + +​ 在Ability中通过context.getApplicationContext()方法获取。 + +**示例** + +```javascript +import AbilityStage from "@ohos.application.AbilityStage"; + +var lifecycleid; + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log("MyAbilityStage onCreate") + let AbilityLifecycleCallback = { + onAbilityCreate(ability){ + console.log("AbilityLifecycleCallback onAbilityCreate ability:" + JSON.stringify(ability)); + }, + onAbilityWindowStageCreate(ability){ + console.log("AbilityLifecycleCallback onAbilityWindowStageCreate ability:" + JSON.stringify(ability)); + }, + onAbilityWindowStageDestroy(ability){ + console.log("AbilityLifecycleCallback onAbilityWindowStageDestroy ability:" + JSON.stringify(ability)); + }, + onAbilityDestroy(ability){ + console.log("AbilityLifecycleCallback onAbilityDestroy ability:" + JSON.stringify(ability)); + }, + onAbilityForeground(ability){ + console.log("AbilityLifecycleCallback onAbilityForeground ability:" + JSON.stringify(ability)); + }, + onAbilityBackground(ability){ + console.log("AbilityLifecycleCallback onAbilityBackground ability:" + JSON.stringify(ability)); + }, + onAbilityContinue(ability){ + console.log("AbilityLifecycleCallback onAbilityContinue ability:" + JSON.stringify(ability)); + } + } + // 1.通过context属性获取applicationContext + let applicationContext = this.context.getApplicationContext(); + // 2.通过applicationContext注册监听应用内生命周期 + lifecycleid = applicationContext.registerAbilityLifecycleCallback(AbilityLifecycleCallback); + console.log("registerAbilityLifecycleCallback number: " + JSON.stringify(lifecycleid)); + } + onDestroy() { + let applicationContext = this.context.getApplicationContext(); + applicationContext.unregisterAbilityLifecycleCallback(lifecycleid, (error, data) => { + console.log("unregisterAbilityLifecycleCallback success, err: " + JSON.stringify(error)); + }); + } +} +``` + +**d.ts声明** + +​ https://gitee.com/openharmony/interface_sdk-js/blob/master/api/application/ApplicationContext.d.ts + ### application/AbilityStageContext -​ **概述** + **概述** ​ application/AbilityStageContext是Hap包级别的Context。和基类Context相比,Hap包级别的Context中多了HapModuleInfo和Configuration两个信息。 **获取方法** -​ 可以直接在AbilityStage中通过context属性拿到。 +​ 可以直接在AbilityStage中通过context属性获取。 **示例** @@ -116,7 +178,7 @@ export default class MyAbilityStage extends AbilityStage { ### application/AbilityContext -​ **概述** + **概述** ​ Stage模型下,每个Ability中都包含了一个Context属性。 @@ -124,7 +186,7 @@ export default class MyAbilityStage extends AbilityStage { **获取方法** -​ 在Ability中通过context属性拿到。 +​ 在Ability中通过context属性获取。 **示例** @@ -158,7 +220,7 @@ export default class MainAbility extends Ability { ### application/ExtensionContext -​ **概述** + **概述** ​ 和FA模型不同的是,Stage模型把Service从Ability中剥离出来,单独定义了一组通用扩展类Extension用来处理等同的功能。Extension是一个基类,不承担具体业务功能。业务方根据自己的需要去扩展对应的Extension,例如:ServiceAbility扩展为了ServiceExtensionAbility,卡片扩展为了FormExtension。 @@ -174,7 +236,7 @@ export default class MainAbility extends Ability { ### application/ServiceExtensionContext -​ **概述** + **概述** ​ ServiceExtensionAbility类似于FA模型的ServiceAbility,里面只有生命周期回调相关的处理。 @@ -213,18 +275,11 @@ export default class ServiceExtAbility extends ServiceExtensionAbility { ``` -**d.ts声明** - -​ https://gitee.com/openharmony/interface_sdk-js/blob/master/api/application/ServiceExtensionContext.d.ts ### application/FormExtensionContext ​ [FormExtensionContext](/zh-cn/application-dev/reference/apis/js-apis-formextensioncontext.md) -**d.ts声明** - -​ https://gitee.com/openharmony/interface_sdk-js/blob/master/api/application/FormExtensionContext.d.ts - ## 常见问题 **通过globalThis去获取Context** diff --git a/zh-cn/application-dev/ability/fa-formability.md b/zh-cn/application-dev/ability/fa-formability.md index 41ed0fec0e..014a8361f8 100644 --- a/zh-cn/application-dev/ability/fa-formability.md +++ b/zh-cn/application-dev/ability/fa-formability.md @@ -210,6 +210,7 @@ Form需要在应用配置文件config.json中进行配置。 let formName = want.parameters["ohos.extra.param.key.form_name"]; let tempFlag = want.parameters["ohos.extra.param.key.form_temporary"]; // 由开发人员自行实现,将创建的卡片信息持久化,以便在下次获取/更新该卡片实例时进行使用 + // storeFormInfo 接口未在此处实现,具体实现请参考:相关实例 章节中的 FormAbility FA模型卡片 实例 storeFormInfo(formId, formName, tempFlag, want); let obj = { @@ -225,9 +226,11 @@ Form需要在应用配置文件config.json中进行配置。 ```javascript onDestroy(formId) { - // 删除卡片实例数据 - deleteFormInfo(formId); console.log('FormAbility onDestroy'); + + // 由开发人员自行实现,删除之前持久化的卡片实例数据 + // deleteFormInfo 接口未在此处实现,具体实现请参考:相关实例 章节中的 FormAbility FA模型卡片 实例 + deleteFormInfo(formId); } ``` diff --git a/zh-cn/application-dev/ability/figures/contextIntroduction.png b/zh-cn/application-dev/ability/figures/contextIntroduction.png index a0f1f79d715377e990c4d3c3ea48bdd62aa139bb..2ab1528f753dad2fdf8e52ae992471773f56e7f4 100644 GIT binary patch literal 52284 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 literal 56717 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�N|#b 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 diff --git a/zh-cn/application-dev/ability/stage-formextension.md b/zh-cn/application-dev/ability/stage-formextension.md index d6977be8d4..ae28124cd8 100644 --- a/zh-cn/application-dev/ability/stage-formextension.md +++ b/zh-cn/application-dev/ability/stage-formextension.md @@ -223,6 +223,7 @@ Form需要在应用配置文件module.json中进行配置。 let formName = want.parameters["ohos.extra.param.key.form_name"]; let tempFlag = want.parameters["ohos.extra.param.key.form_temporary"]; // 由开发人员自行实现,将创建的卡片信息持久化,以便在下次获取/更新该卡片实例时进行使用 + // storeFormInfo 接口未在此处实现,具体实现请参考:相关实例 章节中的 FormExtAbility Stage模型卡片 实例 storeFormInfo(formId, formName, tempFlag, want); let obj = { @@ -238,9 +239,11 @@ Form需要在应用配置文件module.json中进行配置。 ```javascript onDestroy(formId) { - // 删除卡片实例数据 - deleteFormInfo(formId); console.log('FormAbility onDestroy'); + + // 由开发人员自行实现,删除之前持久化的卡片实例数据 + // deleteFormInfo 接口未在此处实现,具体实现请参考:相关实例 章节中的 FormExtAbility Stage模型卡片 实例 + deleteFormInfo(formId); } ``` diff --git a/zh-cn/application-dev/media/audio-capturer.md b/zh-cn/application-dev/media/audio-capturer.md index 40dfa18e4d..50ca00d493 100644 --- a/zh-cn/application-dev/media/audio-capturer.md +++ b/zh-cn/application-dev/media/audio-capturer.md @@ -10,6 +10,10 @@ AudioCapturer提供了用于获取原始音频文件的方法。开发者可以 详细API含义可参考:[音频管理API文档AudioCapturer](../reference/apis/js-apis-audio.md) +**图1** 音频采集状态机 + +![](figures/audio-capturer-state.png) + ## 开发步骤 1. 使用createAudioCapturer()创建一个AudioCapturer实例。 diff --git a/zh-cn/application-dev/media/audio-renderer.md b/zh-cn/application-dev/media/audio-renderer.md index e1c2509561..0699103caa 100644 --- a/zh-cn/application-dev/media/audio-renderer.md +++ b/zh-cn/application-dev/media/audio-renderer.md @@ -14,10 +14,16 @@ AudioRenderer提供了渲染音频文件和控制播放的接口,开发者可 在进行应用开发的过程中,建议开发者通过on('stateChange')方法订阅AudioRenderer的状态变更。因为针对AudioRenderer的某些操作,仅在音频播放器在固定状态时才能执行。如果应用在音频播放器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。 +**图1** 音频渲染状态机 + +![](figures/audio-renderer-state.png) + ### 异步操作 为保证UI线程不被阻塞,大部分AudioRenderer调用都是异步的。对于每个API均提供了callback函数和Promise函数,以下示例均采用Promise函数,更多方式可参考[音频管理API文档AudioRenderer](../reference/apis/js-apis-audio.md#audiorenderer8)。 + + ## 开发步骤 1. 使用createAudioRenderer()创建一个AudioRenderer实例。 diff --git a/zh-cn/application-dev/media/figures/audio-capturer-state.png b/zh-cn/application-dev/media/figures/audio-capturer-state.png new file mode 100644 index 0000000000000000000000000000000000000000..52b5556260dbf78c5e816b37013248a07e8dbbc6 GIT binary patch literal 29079 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 1)字符串以字母、数字、下划线和符号”.”组成;
2)以字母开头;
3)最小长度7个字节,最大长度127个字节。
推荐采用反域名形式命名(如 :com.example.xxx,建议第一级为域名后缀com,第二级为厂商/个人名,第三级为应用名,也可以多级)。
其中,随系统源码编译的应用需命名为”com.ohos.xxx”形式, ohos标识OpenHarmony系统应用。 | 字符串 | 否 | +| debug | 该标签标识应用是否可调试。 | 布尔值 | 该标签可以缺省,缺省为false。 | +| icon | 该标签标识应用的图标,标签值为资源文件的索引。 | 字符串 | 该标签不可缺省。 | +| label | 该标签标识应用的的名称,标签值为资源文件的索引,以支持多语言。 | 字符串 | 该标签不可缺省。 | +| description | 该标签标识App的描述信息,标签值是是字符串类型或对描述内容的资源索引,以支持多语言。 | 字符串 | 该标签可缺省,缺省值为空。 | +| vendor | 该标签是对应用开发厂商的描述。该标签的值是字符串类型(最大255个字节)。 | 字符串 | 该标签可以缺省,缺省为空。 | +| versionCode | 该标签标识应用的版本号,该标签值为32位非负整数。此数字仅用于确定某个版本是否比另一个版本更新,数值越大表示版本越高。开发者可以将该值设置为任何正整数,但是必须确保应用的新版本都使用比旧版本更大的值。该标签不可缺省,versionCode 值应小于2的31方。 | 数值 | 该标签不可缺省 | +| versionName | 该标签标识版本号的文字描述,用于向用户展示。
该标签仅由数字和点构成,推荐采用“A.B.C.D”四段式的形式。四段式推荐的含义如下所示。
第一段 :主版本号/Major,范围0-99,重大修改的版本,如实现新的大功能或重大变化。
第二段 :次版本号/Minor,范围0-99,表示实现较突出的特点,如新功能添加和大问题修复。
第三段 :特性版本号/Feature,范围0-99,标识规划的新版本特性。
第四段 :修订版本号/Patch,范围0-999,表示维护版本,修复bug。 | 字符串 | 该标签不可缺省 | +| minCompatibleVersionCode | 该标签标识该app pack能够兼容的最低历史版本号。 | 数值 | 该标签可缺省。缺省值等于versionCode标签值。 | +| minAPIVersion | 该标签标识应用运行需要的API最小版本。 | 数值 | 该标签不可缺省。 | +| targetAPIVersion | 该标签标识应用运行需要的API目标版本。 | 整形 | 该标签不可缺省。 | +| apiReleaseType | 该标签标识应用运行需要的API目标版本的类型,采用字符串类型表示。取值为“CanaryN”、“BetaN”或者“Release”,其中,N代表大于零的整数。
Canary :受限发布的版本。
Beta :公开发布的Beta版本。
Release :公开发布的正式版本。 | 字符串 | 该标签可缺省,缺省为“Release”。 | +| distributedNotificationEnabled | 该标签标记该应用是否开启分布式通知。 | 布尔值 | 该标签可缺省,缺省值为true。 | +| entityType | 该标签标记该应用的类别,具体有 :游戏类(game),影音类(media)、社交通信类(communication)、新闻类(news)、出行类(travel)、工具类(utility)、购物类(shopping)、教育类(education)、少儿类(kids)、商务类(business)、拍摄类(photography)。 | 字符串 | 该标签可以缺省,缺省为unspecified。 | + +### module对象内部结构 + +module.json示例: + +```json +{ "module": { "name": "myHapName", "type": "entry|feature|har", @@ -163,31 +195,6 @@ module.json示例: } ``` -### app对象内部结构 - -该标签为整个应用的属性,影响应用中所有hap及组件。该标签的内部结构参见表2。 - -表2 app对象的内部结构说明 - -| 属性名称 | 含义 | 数据类型 | 是否可缺省 | -| ------------------------------ | ------------------------------------------------------------ | -------- | ------------------------------------------- | -| bundleName | 该标签表示应用的包名,用于标识应用的唯一性。该标签不可缺省。标签的值命名规则 :
1)字符串以字母、数字、下划线和符号”.”组成;
2)以字母开头;
3)最小长度7个字节,最大长度127个字节。
推荐采用反域名形式命名(如 :com.example.xxx,建议第一级为域名后缀com,第二级为厂商/个人名,第三级为应用名,也可以多级)。
其中,随系统源码编译的应用需命名为”com.ohos.xxx”形式, ohos标识OpenHarmony系统应用。 | 字符串 | 否 | -| debug | 该标签标识应用是否可调试。 | 布尔值 | 该标签可以缺省,缺省为false。 | -| icon | 该标签标识应用的图标,标签值为资源文件的索引。 | 字符串 | 该标签不可缺省。 | -| label | 该标签标识应用的的名称,标签值为资源文件的索引,以支持多语言。 | 字符串 | 该标签不可缺省。 | -| description | 该标签标识App的描述信息,标签值是是字符串类型或对描述内容的资源索引,以支持多语言。 | 字符串 | 该标签可缺省,缺省值为空。 | -| vendor | 该标签是对应用开发厂商的描述。该标签的值是字符串类型(最大255个字节)。 | 字符串 | 该标签可以缺省,缺省为空。 | -| versionCode | 该标签标识应用的版本号,该标签值为32位非负整数。此数字仅用于确定某个版本是否比另一个版本更新,数值越大表示版本越高。开发者可以将该值设置为任何正整数,但是必须确保应用的新版本都使用比旧版本更大的值。该标签不可缺省,versionCode 值应小于2的31方。 | 数值 | 该标签不可缺省 | -| versionName | 该标签标识版本号的文字描述,用于向用户展示。
该标签仅由数字和点构成,推荐采用“A.B.C.D”四段式的形式。四段式推荐的含义如下所示。
第一段 :主版本号/Major,范围0-99,重大修改的版本,如实现新的大功能或重大变化。
第二段 :次版本号/Minor,范围0-99,表示实现较突出的特点,如新功能添加和大问题修复。
第三段 :特性版本号/Feature,范围0-99,标识规划的新版本特性。
第四段 :修订版本号/Patch,范围0-999,表示维护版本,修复bug。 | 字符串 | 该标签不可缺省 | -| minCompatibleVersionCode | 该标签标识该app pack能够兼容的最低历史版本号。 | 数值 | 该标签可缺省。缺省值等于versionCode标签值。 | -| minAPIVersion | 该标签标识应用运行需要的API最小版本。 | 数值 | 该标签不可缺省。 | -| targetAPIVersion | 该标签标识应用运行需要的API目标版本。 | 整形 | 该标签不可缺省。 | -| apiReleaseType | 该标签标识应用运行需要的API目标版本的类型,采用字符串类型表示。取值为“CanaryN”、“BetaN”或者“Release”,其中,N代表大于零的整数。
Canary :受限发布的版本。
Beta :公开发布的Beta版本。
Release :公开发布的正式版本。 | 字符串 | 该标签可缺省,缺省为“Release”。 | -| distributedNotificationEnabled | 该标签标记该应用是否开启分布式通知。 | 布尔值 | 该标签可缺省,缺省值为true。 | -| entityType | 该标签标记该应用的类别,具体有 :游戏类(game),影音类(media)、社交通信类(communication)、新闻类(news)、出行类(travel)、工具类(utility)、购物类(shopping)、教育类(education)、少儿类(kids)、商务类(business)、拍摄类(photography)。 | 字符串 | 该标签可以缺省,缺省为unspecified。 | - -### module对象内部结构 - hap包的配置信息,该标签下的配置只对当前hap包生效。 表3 module对象内部结构 diff --git a/zh-cn/application-dev/quick-start/start-overview.md b/zh-cn/application-dev/quick-start/start-overview.md index 77592bd907..e26343b371 100644 --- a/zh-cn/application-dev/quick-start/start-overview.md +++ b/zh-cn/application-dev/quick-start/start-overview.md @@ -23,11 +23,12 @@ OpenHarmony提供了一套UI开发框架,即方舟开发框架(ArkUI框架 | 类Web开发范式 | JS语言 | 数据驱动更新 | 界面较为简单的程序应用和卡片 | Web前端开发人员 | | 声明式开发范式 | 扩展的TS语言(eTS) | 数据驱动更新 | 复杂度较大、团队合作度较高的程序 | 移动系统应用开发人员、系统应用开发人员 | -对于DevEco Studio V2.2 Beta1及更高版本,在使用JS语言开发时,除传统代码方式外,还支持使用低代码方式。 +对于JS语言开发时,低代码方式在DevEco Studio V2.2 Beta1及更高版本中支持。 -对于eTS语言开发,除传统代码方式外,低代码方式则在DevEco Studio V3.0 Beta3及更高版本中支持。 +对于eTS语言开发,低代码方式在DevEco Studio V3.0 Beta3及更高版本中支持。 OpenHarmony低代码开发方式具有丰富的UI界面编辑功能,遵循JS开发规范,通过可视化界面开发方式快速构建布局,可有效降低开发者的上手成本并提升开发者构建UI界面的效率。 +更多UI框架的开发内容及指导,请参见[UI开发](../ui/arkui-overview.md)。 ### Ability diff --git a/zh-cn/application-dev/quick-start/start-with-ets-low-code.md b/zh-cn/application-dev/quick-start/start-with-ets-low-code.md index 848c052531..2be296de7c 100644 --- a/zh-cn/application-dev/quick-start/start-with-ets-low-code.md +++ b/zh-cn/application-dev/quick-start/start-with-ets-low-code.md @@ -50,43 +50,43 @@ OpenHarmony低代码开发方式具有丰富的UI界面编辑功能,通过可 第一个页面内有一个容器、文本和一个按钮,通过Column、Text和Button组件来实现。其中,Column为沿垂直方向布局的容器组件,具体使用请见[Column](../reference/arkui-ts/ts-container-column.md)。 -1. **删除画布原有模板组件。**
+1. 删除画布原有模板组件。 打开index.visual文件,选中画布中的组件,单击鼠标右键,选择Delete删除画布原有模板组件。操作如下所示: ![zh-cn_image_0000001233208980](figures/zh-cn_image_0000001233208980.gif) -2. **添加容器,设置Column容器的样式和属性。** +2. 添加容器,设置Column容器的样式和属性。 选中UI Control中的Column组件,将其拖至画布。点击右侧属性样式栏中的图标![zh-cn_image_0000001233048996](figures/zh-cn_image_0000001233048996.png)(General),设置Column组件的高度Height为100%,使其占满屏幕;点击右侧属性样式栏中的图标![zh-cn_image_0000001233368860](figures/zh-cn_image_0000001233368860.png)(Feature),设置Column组件的AlignItems样式为center,使得其子组件在水平轴上居中显示。操作如下所示: ![zh-cn_image_0000001277488977](figures/zh-cn_image_0000001277488977.gif) -3. **添加文本。** +3. 添加文本。 选中UI Control中的Text组件,将其拖至画布,再拖至Column组件的中央区域。点击右侧属性样式栏中的图标![zh-cn_image_0000001277608813](figures/zh-cn_image_0000001277608813.png)(Feature),设置Text组件的Content属性为“this.message”(即“Hello World”);设置组件的FontSize样式为30fp,使得其文字放大;设置组件的TextAlign样式为center,使得组件文字居中显示。再选中画布上的Text组件,拖动放大。操作如下所示: ![zh-cn_image_0000001235731706](figures/zh-cn_image_0000001233528156.gif) -4. **添加按钮。** +4. 添加按钮。 选中UI Control中的Button组件,将其拖至画布,再拖至Text组件下面。点击右侧属性样式栏中的图标![zh-cn_image_0000001277728577](figures/zh-cn_image_0000001277728577.png)(General),设置Button组件的Height为40vp;点击右侧属性样式栏中的图标![zh-cn_image_0000001277809337](figures/zh-cn_image_0000001277809337.png)(Feature),设置Button组件的Label属性为“Next”;设置Button组件的FontSize样式为25fp,使得其文字放大。操作如下所示: ![zh-cn_image_0000001235732402](figures/zh-cn_image_0000001233208988.gif) -5. **在编辑窗口右上角的侧边工具栏,点击Previewer,打开预览器。** 第一个页面效果如下图所示: +5. 在编辑窗口右上角的侧边工具栏,点击Previewer,打开预览器。第一个页面效果如下图所示: ![zh-cn_image_0000001235892798](figures/zh-cn_image_0000001233049004.png) ## 构建第二个页面 -1. **创建第二个页面。** +1. 创建第二个页面。 在“**Project**”窗口,打开“**entry > src > main > ets > MainAbility**”,右键点击“**pages**”文件夹,选择“**New > Visual**”,命名为“**second**”,单击“**Finish**”,即完成第二个页面的创建。可以看到文件目录结构如下: ![zh-cn_image_0000001233368868](figures/zh-cn_image_0000001233368868.png) -2. **[删除画布原有模板组件。](#delete_origin_content)** +2. [删除画布原有模板组件。](#delete_origin_content) -3. **[添加容器,设置Column容器的样式和属性。](#add_container)** +3. [添加容器,设置Column容器的样式和属性。](#add_container) -4. **添加文本。** +4. 添加文本。 - 在second.ets文件中,将本页面的message文本内容设置为“Hi there”,示例如下: @@ -109,7 +109,7 @@ OpenHarmony低代码开发方式具有丰富的UI界面编辑功能,通过可 ![zh-cn_image_0000001280255513](figures/zh-cn_image_0000001277608817.gif) -5. **添加按钮。** +5. 添加按钮。 选中UI Control中的Button组件,将其拖至画布,再拖至Text组件下面。点击右侧属性样式栏中的图标![zh-cn_image_0000001233528160](figures/zh-cn_image_0000001233528160.png)(General),设置Button组件的Height为40vp;点击右侧属性样式栏中的图标![zh-cn_image_0000001277728597](figures/zh-cn_image_0000001277728597.png)(Feature),设置Button组件的Value属性为“Back”;设置组件的FontSize样式为25fp,使得其文字放大。操作如下所示: ![zh-cn_image_0000001280383937](figures/zh-cn_image_0000001277809361.gif) @@ -119,7 +119,7 @@ OpenHarmony低代码开发方式具有丰富的UI界面编辑功能,通过可 页面间的导航可以通过页面路由router来实现。页面路由router根据页面uri找到目标页面,从而实现跳转。使用页面路由请导入router模块。 -1. **第一个页面跳转到第二个页面。** +1. 第一个页面跳转到第二个页面。 在第一个页面中,跳转按钮绑定onclick方法,点击按钮时跳转到第二页。需同时处理ets文件及visual文件。 - “**index.ets**”示例如下: @@ -150,7 +150,7 @@ OpenHarmony低代码开发方式具有丰富的UI界面编辑功能,通过可 ![zh-cn_image_0000001235745716](figures/zh-cn_image_0000001233049040.png) -2. **第二个页面返回到第一个页面。** +2. 第二个页面返回到第一个页面。 在第二个页面中,返回按钮绑定back方法,点击按钮时返回到第一页。需同时处理ets文件及visual文件。 - “**second.ets**”示例如下: @@ -180,7 +180,7 @@ OpenHarmony低代码开发方式具有丰富的UI界面编辑功能,通过可 ![zh-cn_image_0000001280385809](figures/zh-cn_image_0000001277489017.png) -3. **打开index.visual或index.ets文件,点击预览器中的** ![zh-cn_image_0000001277608849](figures/zh-cn_image_0000001277608849.png) **按钮进行刷新。** 效果如下图所示: +3. 打开index.visual或index.ets文件,点击预览器中的 ![zh-cn_image_0000001277608849](figures/zh-cn_image_0000001277608849.png) 按钮进行刷新。效果如下图所示: ![zh-cn_image_0000001233528192](figures/zh-cn_image_0000001233528192.png) diff --git a/zh-cn/application-dev/quick-start/start-with-ets.md b/zh-cn/application-dev/quick-start/start-with-ets.md index 5feed1264b..0b84c9b3f6 100644 --- a/zh-cn/application-dev/quick-start/start-with-ets.md +++ b/zh-cn/application-dev/quick-start/start-with-ets.md @@ -25,9 +25,10 @@ - **src > main > ets** :用于存放ets源码。 - **src > main > ets > MainAbility** :应用/服务的入口。 - **src > main > ets > MainAbility > pages** :MainAbility包含的页面。 + - **src > main > ets > MainAbility > pages > index.ets** :pages列表中的第一个页面,即应用的首页入口。 - **src > main > ets > MainAbility > app.ets** :承载Ability生命周期。 - **src > main > resources** :用于存放应用/服务所用到的资源文件,如图形、多媒体、字符串、布局文件等。 - - **src > main > config.json** :模块配置文件。主要包含HAP包的配置信息、应用/服务在具体设备上的配置信息以及应用/服务的全局配置信息。 + - **src > main > config.json** :模块配置文件。主要包含HAP包的配置信息、应用/服务在具体设备上的配置信息以及应用/服务的全局配置信息。具体的配置文件说明,详见[应用包结构配置文件的说明](package-structure.md)。 - **build-profile.json5** :当前的模块信息 、编译信息配置项,包括 buildOption target配置等。 - **hvigorfile.js** :模块级编译构建任务脚本,开发者可以自定义相关任务和代码实现。 @@ -38,8 +39,8 @@ ## 构建第一个页面 -1. **使用文本组件。** - 工程同步完成后,在“**Project**”窗口,点击“**entry > src > main > ets > MainAbility > pages**”,打开“**index.ets**”文件,可以看到页面由Text组件组成。“**index.ets**”文件的示例如下: +1. 使用文本组件。 +工程同步完成后,在“**Project**”窗口,点击“**entry > src > main > ets > MainAbility > pages**”,打开“**index.ets**”文件,可以看到页面由Text组件组成。“**index.ets**”文件的示例如下: ``` @@ -62,7 +63,7 @@ } ``` -2. **添加按钮。** +2. 添加按钮。 在默认页面基础上,我们添加一个Button组件,作为按钮接收用户点击的动作,从而实现跳转到另一个页面。“**index.ets**”文件的示例如下: @@ -99,19 +100,19 @@ } ``` -3. **在编辑窗口右上角的侧边工具栏,点击Previewer,打开预览器。** 第一个页面效果如下图所示: +3. 在编辑窗口右上角的侧边工具栏,点击Previewer,打开预览器。第一个页面效果如下图所示: ![zh-cn_image_0000001216239356](figures/zh-cn_image_0000001216239356.png) ## 构建第二个页面 -1. **创建第二个页面。** +1. 创建第二个页面。 在“**Project**”窗口,打开“**entry > src > main > ets > MainAbility**”,右键点击“**pages**”文件夹,选择“**New > Page**”,命名为“**second**”,点击“**Finish**”,即完成第二个页面的创建。可以看到文件目录结构如下: ![zh-cn_image_0000001223397122](figures/zh-cn_image_0000001223397122.png) -2. **添加文本及按钮。** +2. 添加文本及按钮。 参照第一个页面,在第二个页面添加Text组件、Button组件等,并设置其样式。“**second.ets**”文件的示例如下: @@ -152,7 +153,7 @@ 页面间的导航可以通过页面路由router来实现。页面路由router根据页面uri找到目标页面,从而实现跳转。使用页面路由请导入router模块。 -1. **第一个页面跳转到第二个页面。** +1. 第一个页面跳转到第二个页面。 在第一个页面中,跳转按钮绑定onClick事件,点击按钮时跳转到第二页。“**index.ets**”文件的示例如下: @@ -195,7 +196,7 @@ } ``` -2. **第二个页面返回到第一个页面。** +2. 第二个页面返回到第一个页面。 在第二个页面中,返回按钮绑定onClick事件,点击按钮时返回到第一页。“**second.ets**”文件的示例如下: @@ -237,7 +238,7 @@ } ``` -3. **打开index.ets文件,点击预览器中的** ![zh-cn_image_0000001262219043](figures/zh-cn_image_0000001262219043.png) **按钮进行刷新。** 效果如下图所示: +3. 打开index.ets文件,点击预览器中的 ![zh-cn_image_0000001262219043](figures/zh-cn_image_0000001262219043.png) 按钮进行刷新。 效果如下图所示: ![zh-cn_image_0000001260684127](figures/zh-cn_image_0000001260684127.png) diff --git a/zh-cn/application-dev/quick-start/start-with-js-low-code.md b/zh-cn/application-dev/quick-start/start-with-js-low-code.md index f7f7a6898e..f8b9a22bda 100644 --- a/zh-cn/application-dev/quick-start/start-with-js-low-code.md +++ b/zh-cn/application-dev/quick-start/start-with-js-low-code.md @@ -54,48 +54,48 @@ OpenHarmony低代码开发方式具有丰富的UI界面编辑功能,通过可 第一个页面内有一个容器、文本和一个按钮,通过Div、Text和Button组件来实现。 -1. **删除画布原有模板组件。** +1. 删除画布原有模板组件。 打开index.visual文件,选中画布中的组件,单击鼠标右键,选择Delete删除画布原有模板组件。操作如下所示: ![zh-cn_image_0000001216600980](figures/zh-cn_image_0000001216600980.gif) -2. **添加容器,设置Div容器的样式和属性。** +2. 添加容器,设置Div容器的样式和属性。 选中UI Control中的Div组件,将其拖至画布。点击右侧属性样式栏中的样式图标![zh-cn_image_0000001260226691](figures/zh-cn_image_0000001260226691.png)(General),设置Div组件的高度Height为100%,使其占满屏幕;点击右侧属性样式栏中的样式图标![zh-cn_image_0000001215226858](figures/zh-cn_image_0000001215226858.png)(Flex),设置Div组件的FlexDirection样式为column,使Div的主轴垂直;设置Div组件的JustifyContent样式为center,使得其子组件在主轴上居中显示;设置Div组件的AlignItems样式为center,使得其子组件在交叉轴上居中显示。操作如下所示: ![zh-cn_image_0000001216448880](figures/zh-cn_image_0000001216448880.gif) -3. **添加文本。** +3. 添加文本。 选中UI Control中的Text组件,将其拖至Div组件的中央区域。点击右侧属性样式栏中的属性图标![zh-cn_image_0000001215066868](figures/zh-cn_image_0000001215066868.png)(Properties),设置Text组件的Content属性为“Hello World”;点击右侧属性样式栏中的样式图标![zh-cn_image_0000001215386842](figures/zh-cn_image_0000001215386842.png)(Feature),设置组件的FontSize样式为60px,使得其文字放大;设置组件的TextAlign样式为center,使得组件文字居中显示。再选中画布上的Text组件,拖动放大。操作如下所示: ![zh-cn_image_0000001216446670](figures/zh-cn_image_0000001216446670.gif) -4. **添加按钮。** +4. 添加按钮。 选中UI Control中的Button组件,将其拖至Text组件下面。点击右侧属性样式栏中的属性图标![zh-cn_image_0000001260106745](figures/zh-cn_image_0000001260106745.png)(Properties),设置Button组件的Value属性为“Next”,点击右侧属性样式栏中的样式图标![zh-cn_image_0000001259866741](figures/zh-cn_image_0000001259866741.png)(Feature),设置组件的FontSize样式为40px,使得其文字放大;再选中画布上的Button组件,拖动放大。操作如下所示: ![zh-cn_image_0000001260928361](figures/zh-cn_image_0000001260928361.gif) -5. **在编辑窗口右上角的侧边工具栏,点击Previewer,打开预览器。** 第一个页面效果如下图所示: +5. 在编辑窗口右上角的侧边工具栏,点击Previewer,打开预览器。第一个页面效果如下图所示: ![zh-cn_image_0000001216288558](figures/zh-cn_image_0000001216288558.png) ## 构建第二个页面 -1. **创建第二个页面。** +1. 创建第二个页面。 在“**Project**”窗口,打开“**entry > src > main > js > MainAbility**”,右键点击“**pages**”文件夹,选择“**New > Visual**”,命名为“**second**”,单击“**Finish**”,即完成第二个页面的创建。可以看到文件目录结构如下: ![zh-cn_image_0000001223882030](figures/zh-cn_image_0000001223882030.png) -2. **[删除画布原有模板组件。](#delete_origin_content)** +2. [删除画布原有模板组件。](#delete_origin_content) -3. **[添加容器,设置Div容器的样式和属性。](#add_container)** +3. [添加容器,设置Div容器的样式和属性。](#add_container) -4. **添加文本。** +4. 添加文本。 选中Text组件,拖至Div组件的中央区域。点击右侧属性样式栏中的属性图标![zh-cn_image_0000001260227453](figures/zh-cn_image_0000001260227453.png)(Properties),设置Text组件的Content属性为“Hi there”;点击右侧属性样式栏中的样式图标![zh-cn_image_0000001260107497](figures/zh-cn_image_0000001260107497.png)(Feature),设置组件的FontSize样式为60px;设置组件的TextAlign样式为center。再选中画布上的Text组件,拖动放大。操作如下所示: ![zh-cn_image_0000001216614132](figures/zh-cn_image_0000001216614132.gif) -5. **添加按钮。** +5. 添加按钮。 选中UI Control中的Button组件,将其拖至Text组件下面。点击右侧属性样式栏中的属性图标![zh-cn_image_0000001215227618](figures/zh-cn_image_0000001215227618.png)(Properties),设置Button组件的Value属性为“Back”,点击右侧属性样式栏中的样式图标![zh-cn_image_0000001259987441](figures/zh-cn_image_0000001259987441.png)(Feature),设置组件的FontSize样式为40px,使得其文字放大;再选中画布上的Button组件,拖动放大。操作如下所示: ![zh-cn_image_0000001261017331](figures/zh-cn_image_0000001261017331.gif) @@ -105,7 +105,7 @@ OpenHarmony低代码开发方式具有丰富的UI界面编辑功能,通过可 页面间的导航可以通过[页面路由router](../ui/ui-js-building-ui-routes.md)来实现。页面路由router根据页面uri找到目标页面,从而实现跳转。使用页面路由请导入router模块。 -1. **第一个页面跳转到第二个页面。** +1. 第一个页面跳转到第二个页面。 在第一个页面中,跳转按钮绑定onclick方法,点击按钮时跳转到第二页。需同时处理js文件及visual文件。 - “**index.js**”示例如下: @@ -125,7 +125,7 @@ OpenHarmony低代码开发方式具有丰富的UI界面编辑功能,通过可 ![zh-cn_image_0000001223722586](figures/zh-cn_image_0000001223722586.png) -2. **第二个页面返回到第一个页面。** +2. 第二个页面返回到第一个页面。 在第二个页面中,返回按钮绑定back方法,点击按钮时返回到第一页。 需同时处理js文件及visual文件。 @@ -145,7 +145,7 @@ OpenHarmony低代码开发方式具有丰富的UI界面编辑功能,通过可 ![zh-cn_image_0000001268082945](figures/zh-cn_image_0000001268082945.png) -3. **打开index.visual或index.js文件,点击预览器中的** ![zh-cn_image_0000001261979271](figures/zh-cn_image_0000001261979271.png) **按钮进行刷新。** 效果如下图所示: +3. 打开index.visual或index.js文件,点击预览器中的 ![zh-cn_image_0000001261979271](figures/zh-cn_image_0000001261979271.png) 按钮进行刷新。效果如下图所示: ![zh-cn_image_0000001261142799](figures/zh-cn_image_0000001261142799.png) diff --git a/zh-cn/application-dev/quick-start/start-with-js.md b/zh-cn/application-dev/quick-start/start-with-js.md index 112eacc069..e3861a65ad 100644 --- a/zh-cn/application-dev/quick-start/start-with-js.md +++ b/zh-cn/application-dev/quick-start/start-with-js.md @@ -28,7 +28,7 @@ - **src > main > js > MainAbility > app.js** :承载Ability生命周期。 - **src > main > resources** :用于存放应用/服务所用到的资源文件,如图形、多媒体、字符串、布局文件等。 - - **src > main > config.json** :模块配置文件。主要包含HAP包的配置信息、应用/服务在具体设备上的配置信息以及应用/服务的全局配置信息。 + - **src > main > config.json** :模块配置文件。主要包含HAP包的配置信息、应用/服务在具体设备上的配置信息以及应用/服务的全局配置信息。具体的配置文件说明,详见[应用包结构配置文件的说明](package-structure.md)。 - **build-profile.json5** :当前的模块信息 、编译信息配置项,包括 buildOption target配置等。 - **hvigorfile.js** :模块级编译构建任务脚本,开发者可以自定义相关任务和代码实现。 @@ -39,7 +39,7 @@ ## 构建第一个页面 -1. **使用文本组件。** +1. 使用文本组件。 工程同步完成后,在“**Project**”窗口,点击“**entry > src > main > js > MainAbility > pages> index**”,打开“**index.hml**”文件,设置Text组件内容。“**index.hml**”文件的示例如下: @@ -51,7 +51,7 @@ ``` -2. **添加按钮,并绑定onclick方法。** +2. 添加按钮,并绑定onclick方法。 在默认页面基础上,我们添加一个button类型的input组件,作为按钮接收用户点击的动作,从而实现跳转到另一个页面。“**index.hml**”文件的示例代码如下: @@ -66,7 +66,7 @@ ``` -3. **设置页面样式。** +3. 设置页面样式。 在“**Project**”窗口,点击“**entry > src > main > js > MainAbility > pages> index**”,打开“**index.css**”文件,可以对页面中文本、按钮设置宽高、字体大小、间距等样式。“**index.css**”文件的示例如下: @@ -100,7 +100,7 @@ } ``` -4. **在编辑窗口右上角的侧边工具栏,点击Previewer,打开预览器。** 第一个页面效果如下图所示: +4. 在编辑窗口右上角的侧边工具栏,点击Previewer,打开预览器。第一个页面效果如下图所示: ![zh-cn_image_0000001216084724](figures/zh-cn_image_0000001216084724.png) @@ -108,12 +108,12 @@ ## 构建第二个页面 -1. **创建第二个页面。** +1. 创建第二个页面。 在“**Project**”窗口,打开“**entry > src > main > js > MainAbility**”,右键点击“**pages**”文件夹,选择“**New > Page**”,命名为“**second**”,点击“**Finish**”,即完成第二个页面的创建。可以看到文件目录结构如下: ![zh-cn_image_0000001223877210](figures/zh-cn_image_0000001223877210.png) -2. **添加文本及按钮。** +2. 添加文本及按钮。 参照第一个页面,在第二个页面添加文本、按钮及点击按钮绑定页面返回等。“**second.hml**”文件的示例如下: @@ -128,7 +128,7 @@ ``` -3. **设置页面样式**。“**second.css**”文件的示例如下: +3. 设置页面样式。“**second.css**”文件的示例如下: ``` .container { @@ -165,7 +165,7 @@ 页面间的导航可以通过[页面路由router](../ui/ui-js-building-ui-routes.md)来实现。页面路由router根据页面uri找到目标页面,从而实现跳转。使用页面路由请导入router模块。 -1. **第一个页面跳转到第二个页面。** +1. 第一个页面跳转到第二个页面。 在第一个页面中,跳转按钮绑定onclick方法,点击按钮时跳转到第二页。“**index.js**”示例如下: @@ -181,7 +181,7 @@ } ``` -2. **第二个页面返回到第一个页面。** +2. 第二个页面返回到第一个页面。 在第二个页面中,返回按钮绑定back方法,点击按钮时返回到第一页。“**second.js**”示例如下: @@ -195,7 +195,7 @@ } ``` -3. **打开index文件夹下的任意一个文件,点击预览器中的** ![zh-cn_image_0000001262339067](figures/zh-cn_image_0000001262339067.png) **按钮进行刷新。** 效果如下图所示: +3. 打开index文件夹下的任意一个文件,点击预览器中的 ![zh-cn_image_0000001262339067](figures/zh-cn_image_0000001262339067.png) 按钮进行刷新。效果如下图所示: ![zh-cn_image_0000001216269940](figures/zh-cn_image_0000001216269940.png) diff --git a/zh-cn/application-dev/reference/apis/js-apis-application-ability.md b/zh-cn/application-dev/reference/apis/js-apis-application-ability.md index 3432776f68..306be5858b 100644 --- a/zh-cn/application-dev/reference/apis/js-apis-application-ability.md +++ b/zh-cn/application-dev/reference/apis/js-apis-application-ability.md @@ -143,7 +143,7 @@ Ability生命周期回调,在销毁时回调,执行资源清理等操作。 onForeground(): void; -Ability生命周期回调,当应用处于前台时触发。 +Ability生命周期回调,当应用从后台转到前台时触发。 **系统能力**:SystemCapability.Ability.AbilityRuntime.AbilityCore @@ -162,7 +162,7 @@ Ability生命周期回调,当应用处于前台时触发。 onBackground(): void; -Ability生命周期回调,当应用处于后台时触发。 +Ability生命周期回调,当应用从前台转到后台时触发。 **系统能力**:SystemCapability.Ability.AbilityRuntime.AbilityCore diff --git a/zh-cn/application-dev/reference/apis/js-apis-application-abilityLifecycleCallback.md b/zh-cn/application-dev/reference/apis/js-apis-application-abilityLifecycleCallback.md new file mode 100644 index 0000000000..bd4ad4df68 --- /dev/null +++ b/zh-cn/application-dev/reference/apis/js-apis-application-abilityLifecycleCallback.md @@ -0,0 +1,153 @@ +# AbilityLifecycleCallback + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> 本模块首批接口从API version 9 开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 + + +应用上下文ApplicationContext的生命周期监听方法的回调类,里面提供了onAbilityCreate、onAbilityWindowStageCreate、onAbilityWindowStageDestroy等方法。 + + +## AbilityLifecycleCallback.onAbilityCreate + +onAbilityCreate(ability: Ability): void; + +注册监听应用上下文的生命周期后,在ability创建时触发回调。 + +**系统能力**:SystemCapability.Ability.AbilityRuntime.AbilityCore + +**参数:** + + | 参数名 | 类型 | 必填 | 说明 | + | -------- | -------- | -------- | -------- | + | ability | [Ability](js-apis-application-ability.md#Ability) | 是 | 当前Ability对象 | + + +## AbilityLifecycleCallback.onAbilityWindowStageCreate + +onAbilityWindowStageCreate(ability: Ability): void; + +注册监听应用上下文的生命周期后,在windowStage创建时触发回调。 + +**系统能力**:SystemCapability.Ability.AbilityRuntime.AbilityCore + +**参数:** + + | 参数名 | 类型 | 必填 | 说明 | + | -------- | -------- | -------- | -------- | + | ability | [Ability](js-apis-application-ability.md#Ability) | 是 | 当前Ability对象 | + + +## AbilityLifecycleCallback.onAbilityWindowStageDestroy + +onAbilityWindowStageDestroy(ability: Ability): void; + +注册监听应用上下文的生命周期后,在windowStage销毁时触发回调。 + +**系统能力**:SystemCapability.Ability.AbilityRuntime.AbilityCore + +**参数:** + + | 参数名 | 类型 | 必填 | 说明 | + | -------- | -------- | -------- | -------- | + | ability | [Ability](js-apis-application-ability.md#Ability) | 是 | 当前Ability对象 | + + +## AbilityLifecycleCallback.onAbilityDestroy + +onAbilityDestroy(ability: Ability): void; + +注册监听应用上下文的生命周期后,在ability销毁时触发回调。 + +**系统能力**:SystemCapability.Ability.AbilityRuntime.AbilityCore + +**参数:** + + | 参数名 | 类型 | 必填 | 说明 | + | -------- | -------- | -------- | -------- | + | ability | [Ability](js-apis-application-ability.md#Ability) | 是 | 当前Ability对象 | + + +## AbilityLifecycleCallback.onAbilityForeground + +onAbilityForeground(ability: Ability): void; + +注册监听应用上下文的生命周期后,在ability的状态从后台转到前台时触发回调。 + +**系统能力**:SystemCapability.Ability.AbilityRuntime.AbilityCore + +**参数:** + + | 参数名 | 类型 | 必填 | 说明 | + | -------- | -------- | -------- | -------- | + | ability | [Ability](js-apis-application-ability.md#Ability) | 是 | 当前Ability对象 | + + +## AbilityLifecycleCallback.onAbilityBackground + +onAbilityBackground(ability: Ability): void; + +注册监听应用上下文的生命周期后,在ability的状态从前台转到后台时触发回调。 + +**系统能力**:SystemCapability.Ability.AbilityRuntime.AbilityCore + +**参数:** + + | 参数名 | 类型 | 必填 | 说明 | + | -------- | -------- | -------- | -------- | + | ability | [Ability](js-apis-application-ability.md#Ability) | 是 | 当前Ability对象 | + + +## AbilityLifecycleCallback.onAbilityContinue + +onAbilityContinue(ability: Ability): void; + +注册监听应用上下文的生命周期后,在ability迁移时触发回调。 + +**系统能力**:SystemCapability.Ability.AbilityRuntime.AbilityCore + +**参数:** + + | 参数名 | 类型 | 必填 | 说明 | + | -------- | -------- | -------- | -------- | + | ability | [Ability](js-apis-application-ability.md#Ability) | 是 | 当前Ability对象 | + +**示例:** + + + ```js + import AbilityStage from "@ohos.application.AbilityStage"; + + export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log("MyAbilityStage onCreate") + let AbilityLifecycleCallback = { + onAbilityCreate(ability){ + console.log("AbilityLifecycleCallback onAbilityCreate ability:" + JSON.stringify(ability)); + }, + onAbilityWindowStageCreate(ability){ + console.log("AbilityLifecycleCallback onAbilityWindowStageCreate ability:" + JSON.stringify(ability)); + }, + onAbilityWindowStageDestroy(ability){ + console.log("AbilityLifecycleCallback onAbilityWindowStageDestroy ability:" + JSON.stringify(ability)); + }, + onAbilityDestroy(ability){ + console.log("AbilityLifecycleCallback onAbilityDestroy ability:" + JSON.stringify(ability)); + }, + onAbilityForeground(ability){ + console.log("AbilityLifecycleCallback onAbilityForeground ability:" + JSON.stringify(ability)); + }, + onAbilityBackground(ability){ + console.log("AbilityLifecycleCallback onAbilityBackground ability:" + JSON.stringify(ability)); + }, + onAbilityContinue(ability){ + console.log("AbilityLifecycleCallback onAbilityContinue ability:" + JSON.stringify(ability)); + } + } + // 1.通过context属性获取applicationContext + let applicationContext = this.context.getApplicationContext(); + // 2.通过applicationContext注册监听应用内生命周期 + let lifecycleid = applicationContext.registerAbilityLifecycleCallback(AbilityLifecycleCallback); + console.log("registerAbilityLifecycleCallback number: " + JSON.stringify(lifecycleid)); + } + } + ``` \ No newline at end of file diff --git a/zh-cn/application-dev/reference/apis/js-apis-application-applicationContext.md b/zh-cn/application-dev/reference/apis/js-apis-application-applicationContext.md new file mode 100644 index 0000000000..aa5097904e --- /dev/null +++ b/zh-cn/application-dev/reference/apis/js-apis-application-applicationContext.md @@ -0,0 +1,71 @@ +# ApplicationContext + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> 本模块首批接口从API version 9开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 + + +提供开发者应用级别的的上下文,提供注册及取消注册应用内组件生命周期的监听接口。 + + +## 使用说明 + +在使用ApplicationContext的功能前,需要通过context的实例获取。 + +```js +let applicationContext = this.context.getApplicationContext(); +``` + + +## ApplicationContext.registerAbilityLifecycleCallback + +registerAbilityLifecycleCallback(callback: AbilityLifecycleCallback): **number**; + +注册监听应用内生命周期 + +**系统能力**:SystemCapability.Ability.AbilityRuntime.Core + +**参数:** + +| 参数名 | 类型 | 必填 | 说明 | +| ------------------------ | -------- | ---- | ------------------------------ | +| [AbilityLifecycleCallback](js-apis-application-abilityLifecycleCallback.md) | callback | 是 | 回调方法,返回注册监听事件的id | + +**返回值:** + +| 类型 | 说明 | +| ------ | ------------------------------ | +| number | 返回的此次注册监听生命周期的id(每次注册该id会自增+1,当超过监听上限数量2^63-1时,返回-1)| + +**示例:** + + ```js + let applicationContext = this.context.getApplicationContext(); + console.log("stage applicationContext: " + JSON.stringify(applicationContext)); + let lifecycleid = applicationContext.registerAbilityLifecycleCallback(AbilityLifecycleCallback); + console.log("registerAbilityLifecycleCallback number: " + JSON.stringify(lifecycleid)); + ``` + +## ApplicationContext.unregisterAbilityLifecycleCallback + +unregisterAbilityLifecycleCallback(callbackId: **number**, callback: AsyncCallback<**void**>): **void**; + +取消监听应用内生命周期 + +**系统能力**:SystemCapability.Ability.AbilityRuntime.Core + +**参数:** + +| 参数名 | 类型 | 必填 | 说明 | +| ------------- | -------- | ---- | -------------------------- | +| callbackId | number | 是 | 注册监听应用内生命周期的id | +| AsyncCallback | callback | 是 | 回调方法 | + +**示例:** + + ```js + let applicationContext = this.context.getApplicationContext(); + console.log("stage applicationContext: " + JSON.stringify(applicationContext)); + applicationContext.unregisterAbilityLifecycleCallback(lifecycleid, (error, data) => { + console.log("unregisterAbilityLifecycleCallback success, err: " + JSON.stringify(error)); + }); + ``` diff --git a/zh-cn/application-dev/reference/apis/js-apis-application-context.md b/zh-cn/application-dev/reference/apis/js-apis-application-context.md index a36f566438..5aec0d2417 100644 --- a/zh-cn/application-dev/reference/apis/js-apis-application-context.md +++ b/zh-cn/application-dev/reference/apis/js-apis-application-context.md @@ -29,6 +29,7 @@ | bundleCodeDir | string | 是 | 否 | 应用安装路径。 | | distributedFilesDir | string | 是 | 否 | 应用的分布式文件路径。 | | eventHub | [EventHub](js-apis-eventhub.md) | 是 | 否 | 事件中心信息。| +| area | [AreaMode](#areamode) | 是 | 是 | 文件分区。| ## Context.createBundleContext @@ -61,66 +62,23 @@ createBundleContext(bundleName: string): Context; ## Context.getApplicationContext -getApplicationContext(): Context; +getApplicationContext(): ApplicationContext; -获取当前context。 +获取当前applicationContext。 **系统能力**:SystemCapability.Ability.AbilityRuntime.Core **返回值:** - | 类型 | 说明 | - | -------- | -------- | - | Context | 当前Context 信息。 | +| 类型 | 说明 | +| -------- | -------- | +| ApplicationContext | 当前ApplicationContext对象信息。 | **示例:** ```js // 必选项。 - let context = this.context.getApplicationContext(); - ``` - - -## Context.switchArea - -switchArea(mode: AreaMode): void; - -切换需要访问的文件分区。 - -**系统能力**:SystemCapability.Ability.AbilityRuntime.Core - -**参数:** - - | 参数名 | 类型 | 必填 | 说明 | - | -------- | -------- | -------- | -------- | - | mode | [AreaMode](#areamode) | 是 | 文件分区。 | - -**示例:** - - ```js - var areaMode = 0; - this.context.switchArea(areaMode); - ``` - - -## Context.getArea() - -getArea(): AreaMode; - -获取文件分级信息,可以查看当前是处于哪个分区。 - -**系统能力**:SystemCapability.Ability.AbilityRuntime.Core - -**返回值:** - - | 类型 | 说明 | - | -------- | -------- | - | [AreaMode](#areamode) | 文件分区。 | - -**示例:** - - ```js - let mode = this.context.getArea(); + let applicationContext = this.context.getApplicationContext(); ``` @@ -133,4 +91,4 @@ getArea(): AreaMode; | 变量 | 值 | 描述 | | --------------- | ---- | --------------- | | EL1 | 0 | 设备级加密区。 | -| EL2 | 1 | 用户凭据加密区。默认为EL2。 | \ No newline at end of file +| EL2 | 1 | 用户凭据加密区。默认为EL2。 | diff --git a/zh-cn/application-dev/security/accesstoken-overview.md b/zh-cn/application-dev/security/accesstoken-overview.md index 47f590536a..c500915d41 100644 --- a/zh-cn/application-dev/security/accesstoken-overview.md +++ b/zh-cn/application-dev/security/accesstoken-overview.md @@ -36,7 +36,7 @@ ATM(AccessTokenManager)是OpenHarmony上基于AccessToken构建的统一的应 视频播放类应用要使用多媒体功能,应用必须对用户外部存储的媒体文件信息进行读取和写入,所以应用需要至少申请以下两个权限: - (1) ohos.permission.READ_MEDIA 允许应用读取用户外部存储中的媒体文件信息。 + (1) ohos.permission.READ_MEDIA 允许应用读取用户外部存储中的媒体文件信息。 (2) ohos.permission.WRITE_MEDIA 允许应用读写用户外部存储中的媒体文件信息。 @@ -44,7 +44,7 @@ ATM(AccessTokenManager)是OpenHarmony上基于AccessToken构建的统一的应 摄影美图类应用需要使用到相机功能,那么应用访问相机服务前,需要申请到相机权限: - (1) ohos.permission.CAMERA 允许应用使用相机拍摄照片和录制视频。 + (1) ohos.permission.CAMERA 允许应用使用相机拍摄照片和录制视频。 ### 基本原则 @@ -75,8 +75,7 @@ ATM(AccessTokenManager)是OpenHarmony上基于AccessToken构建的统一的应 | normal等级 | 普通应用。 | 默认情况下,应用的APL等级都为normal等级,如果应用需要将自身的APL等级声明为system_basic及以上的APL等级,需要进行以下步骤: -- 申请应用市场审核并通过。 -- 开发应用安装包时,需要修改应用的profile文件,在文件的"apl"字段声明应用的APL等级,并使用profile签名工具生成证书。具体签名流程可以查看页面[配置OpenHarmony应用签名信息](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-debugging-and-running-0000001263040487#section17660437768)。 +- 开发应用安装包时,需要修改应用的profile文件,在文件的"apl"字段声明应用的APL等级,并使用profile签名工具生成证书。具体签名流程可以查看页面[Hap包签名工具指导](hapsigntool-guidelines.md)。 ### 权限等级说明 @@ -118,7 +117,7 @@ ACL方式的工作流程可以参考[ACL方式使用说明](#ACL方式使用说 - **system_grant** - system_grant指的是系统授权类型,在该类型的权限许可下,应用被允许访问的数据不会涉及到用户或设备的敏感信息,应用被允许执行的操作不会对系统或者其他应用产生大的不利影响。 + system_grant指的是系统授权类型,在该类型的权限许可下,应用被允许访问的数据不会涉及到用户或设备的敏感信息,应用被允许执行的操作不会对系统或者其他应用产生大的不利影响。 如果在应用中申请了system_grant权限,那么系统会在用户安装应用时,自动把相应权限授予给应用。应用需要在应用商店的详情页面,向用户展示所申请的system_grant权限列表。 @@ -172,8 +171,7 @@ ACL方式的工作流程可以参考[ACL方式使用说明](#ACL方式使用说 **ACL申请方式须知** -* 申请应用市场审核并通过。 -* 开发应用安装包时,需要修改应用的profile文件,在文件的"acl"字段声明目标的访问控制列表,并使用profile签名工具生成证书。具体签名流程可以查看页面[配置OpenHarmony应用签名信息](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-debugging-and-running-0000001263040487#section17660437768)。 +* 开发应用安装包时,需要修改应用的profile文件,在文件的"acl"字段声明目标的访问控制列表,并使用profile签名工具生成证书。具体签名流程可以查看页面[Hap包签名工具指导](hapsigntool-guidelines.md)。 ## 权限定义列表 @@ -186,6 +184,7 @@ ACL方式的工作流程可以参考[ACL方式使用说明](#ACL方式使用说 | ohos.permission.MANAGE_BLUETOOTH | system_basic | system_grant | TRUE | 允许应用配对蓝牙设备,并对设备的电话簿或消息进行访问。 | | ohos.permission.INTERNET | normal | system_grant | TRUE | 允许使用Internet网络。 | | ohos.permission.MODIFY_AUDIO_SETTINGS | normal | system_grant | TRUE | 允许应用修改音频设置。 | +| ohos.permission.ACCESS_NOTIFICATION_POLICY | normal | system_grant | FALSE | 在本设备上允许应用访问通知策略。 | | ohos.permission.GET_TELEPHONY_STATE | system_basic | system_grant | TRUE | 允许应用读取电话信息。 | | ohos.permission.REQUIRE_FORM | system_basic | system_grant | TRUE | 允许应用获取Ability Form。 | | ohos.permission.GET_NETWORK_INFO | normal | system_grant | TRUE | 允许应用获取数据网络信息。 | @@ -221,6 +220,8 @@ ACL方式的工作流程可以参考[ACL方式使用说明](#ACL方式使用说 | ohos.permission.CLEAN_BACKGROUND_PROCESSES | normal | system_grant | TRUE | 允许应用根据包名清理相关后台进程。 | | ohos.permission.KEEP_BACKGROUND_RUNNING | normal | system_grant | TRUE | 允许Service Ability在后台持续运行。 | | ohos.permission.UPDATE_CONFIGURATION | system_basic | system_grant | TRUE | 允许更新系统配置。 | +| ohos.permission.UPDATE_SYSTEM | system_basic | system_grant | TRUE | 允许调用升级接口。 | +| ohos.permission.FACTORY_RESET | system_basic | system_grant | TRUE | 允许调用回复出厂接口。 | | ohos.permission.GRANT_SENSITIVE_PERMISSIONS | system_core | system_grant | TRUE | 允许应用为其他应用授予敏感权限。 | | ohos.permission.REVOKE_SENSITIVE_PERMISSIONS | system_core | system_grant | TRUE | 允许应用撤销给其他应用授予的敏感信息。 | | ohos.permission.GET_SENSITIVE_PERMISSIONS | system_core | system_grant | TRUE | 允许应用读取其他应用的敏感权限的状态。 | @@ -244,8 +245,36 @@ ACL方式的工作流程可以参考[ACL方式使用说明](#ACL方式使用说 | ohos.permission.CONTROL_TASK_SYNC_ANIMATOR | system_core | system_grant | TRUE | 允许应用使用同步任务动画。 | | ohos.permission.INPUT_MONITORING | system_core | system_grant | TRUE | 允许应用监听输入事件,仅系统签名应用可申请此权限。 | | ohos.permission.MANAGE_MISSIONS | system_core | system_grant | TRUE | 允许用户管理元能力任务栈。 | -| ohos.permission.NOTIFICATION_CONTROLLER | system_core | system_grant | TRUE | 允许应用管理通知和订阅通知。当前仅支持系统应用申请该权限。 | -| ohos.permission.CONNECTIVITY_INTERNAL | system_basic | system_grant | TRUE | 允许应用程序获取网络相关的信息或修改网络相关设置。当前仅支持系统应用申请该权限。 | +| ohos.permission.NOTIFICATION_CONTROLLER | system_core | system_grant | TRUE | 允许应用管理通知和订阅通知。 | +| ohos.permission.CONNECTIVITY_INTERNAL | system_basic | system_grant | TRUE | 允许应用程序获取网络相关的信息或修改网络相关设置。 | +| ohos.permission.SET_ABILITY_CONTROLLER | system_basic | system_grant | TRUE | 允许设置ability组件启动和停止控制权。 | +| ohos.permission.USE_USER_IDM | system_basic | system_grant | FALSE | 允许应用访问系统身份凭据信息。 | +| ohos.permission.MANAGE_USER_IDM | system_basic | system_grant | FALSE | 允许应用使用系统身份凭据管理能力进行口令、人脸、指纹等录入、修改、删除等操作。 | +| ohos.permission.ACCESS_BIOMETRIC | normal | system_grant | TRUE | 允许应用使用生物特征识别能力进行身份认证。 | +| ohos.permission.ACCESS_USER_AUTH_INTERNAL | system_basic | system_grant | FALSE | 允许应用使用系统身份认证能力进行用户身份认证或身份识别。 | +| ohos.permission.ACCESS_PIN_AUTH | system_basic | system_grant | FALSE | 允许应用使用口令输入接口,用于系统应用完成口令输入框绘制场景。 | +| ohos.permission.GET_RUNNING_INFO | system_basic | system_grant | TRUE | 允许应用获取运行态信息。 | +| ohos.permission.CLEAN_APPLICATION_DATA | system_basic | system_grant | TRUE | 允许应用清理应用数据。 | +| ohos.permission.RUNNING_STATE_OBSERVER | system_basic | system_grant | TRUE | 允许应用观察应用状态。 | +| ohos.permission.CAPTURE_SCREEN | system_core | system_grant | TRUE | 允许应用截取屏幕图像。 | +| ohos.permission.GET_WIFI_INFO | normal | system_grant | TRUE | 允许应用获取WLAN信息。 | +| ohos.permission.GET_WIFI_INFO_INTERNAL | system_core | system_grant | TRUE | 允许应用获取WLAN信息。 | +| ohos.permission.SET_WIFI_INFO | normal | system_grant | TRUE | 允许应用配置WLAN设备。 | +| ohos.permission.GET_WIFI_PEERS_MAC | system_core | system_grant | TRUE | 允许应用获取对端WLAN或者蓝牙设备的MAC地址。 | +| ohos.permission.GET_WIFI_LOCAL_MAC | system_basic | system_grant | TRUE | 允许应用获取本机WLAN或者蓝牙设备的MAC地址。 | +| ohos.permission.GET_WIFI_CONFIG | system_basic | system_grant | TRUE | 允许应用获取WLAN配置信息。 | +| ohos.permission.SET_WIFI_CONFIG | system_basic | system_grant | TRUE | 允许应用配置WLAN信息。 | +| ohos.permission.MANAGE_WIFI_CONNECTION | system_core | system_grant | TRUE | 允许应用管理WLAN连接。 | +| ohos.permission.MANAGE_WIFI_HOTSPOT | system_core | system_grant | TRUE | 允许应用开启或者关闭WLAN热点。 | +| ohos.permission.GET_ALL_APP_ACCOUNTS | system_core | system_grant | FALSE | 允许应用获取所有应用账户信息。 | +| ohos.permission.MANAGE_SECURE_SETTINGS | system_basic | system_grant | TRUE | 允许应用修改安全类系统设置。 | +| ohos.permission.READ_DFX_SYSEVENT | system_basic | system_grant | FALSE | 允许获取所有应用账号信息。 | +| ohos.permission.MANAGE_ADMIN | system_core | system_grant | TRUE | 允许应用激活设备管理员应用。 | +| ohos.permission.EDM_MANAGE_DATETIME | normal | system_grant | FALSE | 允许设备管理员应用设置系统时间。 | +| ohos.permission.NFC_TAG | normal | system_grant | FALSE | 允许应用读取Tag卡片。 | +| ohos.permission.NFC_CARD_EMULATION | normal | system_grant | FALSE | 允许应用实现卡模拟功能。 | +| ohos.permission.PERMISSION_USED_STATS | system_core | system_grant | TRUE | 允许系统应用访问权限使用记录。 | +| ohos.permission.NOTIFICATION_AGENT_CONTROLLER | system_core | system_grant | TRUE | 允许应用发送代理通知。 | | ohos.permission.ANSWER_CALL | system_basic | user_grant | TRUE | 允许应用接听来电。 | | ohos.permission.READ_CALENDAR | normal | user_grant | TRUE | 允许应用读取日历信息。 | | ohos.permission.READ_CALL_LOG | system_basic | user_grant | TRUE | 允许应用读取通话记录。 | diff --git a/zh-cn/device-dev/driver/driver-peripherals-audio-des.md b/zh-cn/device-dev/driver/driver-peripherals-audio-des.md index 738ae28de2..094404d5af 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-audio-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-audio-des.md @@ -5,7 +5,7 @@ 多媒体系统是物联网设备开发中不可缺少的一部分,Audio作为其中重要的一个模块,Audio驱动模型的构建显得尤为重要。 -本文主要介绍基于HDF(Hardware Driver Foundation)驱动框架开发的Audio驱动,包括Audio驱动的架构组成和功能部件。芯片厂商可以根据此驱动架构,进行各自驱动的开发及HAL层接口的调用。 +本文主要介绍基于HDF(Hardware Driver Foundation)驱动框架开发的Audio驱动,包括Audio驱动的架构组成和功能部件。芯片厂商可以根据此驱动架构,进行各自驱动的开发及HAL层接口的调用。 @@ -16,45 +16,45 @@ Audio驱动框架基于[HDF驱动框架](https://device.harmonyos.com/cn/docs/do ![](figures/Audio框架图.png) 驱动架构主要由以下几部分组成。 -- HDI adapter : 实现Audio HAL层驱动(HDI接口适配),给Audio服务(frameworks)提供所需的音频硬件驱动能力接口。包含 Audio Manager、Audio Adapter、 Audio Control、Audio Capture、Audio Render 等接口对象。 -- Audio Interface Lib : 配合内核中的Audio Driver Model使用,实现音频硬件的控制、录音数据的读取、播放数据的写入。它里面包括Stream_ctrl_common 通用层,主要是为了和上层的audio HDI adapter 层进行对接。 -- ADM(Audio Driver Model): 音频驱动框架模型,向上服务于多媒体音频子系统,便于系统开发者能够更便捷的根据场景来开发应用。向下服务于具体的设备厂商,对于Codec和DSP设备厂商来说,可根据ADM模块提供的向下统一接口适配各自的驱动代码,就可以实现快速开发和适配OpenHarmony系统。 -- Audio Control Dispatch : 接收lib层的控制指令并将控制指令分发到驱动层。 -- Audio Stream Dispatch : 接收lib层的数据并将数据分发到驱动层。 +- HDI adapter: 实现Audio HAL层驱动(HDI接口适配),给Audio服务(frameworks)提供所需的音频硬件驱动能力接口。包含 Audio Manager、Audio Adapter、Audio Control、Audio Capture、Audio Render等接口对象。 +- Audio Interface Lib:配合内核中的Audio Driver Model使用,实现音频硬件的控制、录音数据的读取、播放数据的写入。它里面包括Stream_ctrl_common 通用层,主要是为了和上层的audio HDI adapter层进行对接。 +- ADM(Audio Driver Model):音频驱动框架模型,向上服务于多媒体音频子系统,便于系统开发者能够更便捷的根据场景来开发应用。向下服务于具体的设备厂商,对于Codec和DSP设备厂商来说,可根据ADM模块提供的向下统一接口适配各自的驱动代码,就可以实现快速开发和适配OpenHarmony系统。 +- Audio Control Dispatch: 接收lib层的控制指令并将控制指令分发到驱动层。 +- Audio Stream Dispatch: 接收lib层的数据并将数据分发到驱动层。 -- Card Manager : 多声卡管理模块。每个声卡含有Dai、Platform、Codec、Accessory、Dsp、SAPM模块。 -- Platform Drivers : 驱动适配层。 -- SAPM(Smart Audio Power Manager) : 电源管理模块,对整个ADM电源进行功耗策略优化。 +- Card Manager: 多声卡管理模块。每个声卡含有Dai、Platform、Codec、Accessory、Dsp、SAPM模块。 +- Platform Drivers: 驱动适配层。 +- SAPM(Smart Audio Power Manager):电源管理模块,对整个ADM电源进行功耗策略优化。 ## Audio驱动开发 以下将基于Audio驱动框架,并以Hi3516DV300平台为例,介绍相关驱动开发的具体步骤。 ### Audio ADM模块框架介绍 -Audio驱动对HDI层提供三个服务hdf_audio_render、hdf_audio_capture、hdf_audio_control。开发板dev目录下 驱动服务节点如下: +Audio驱动对HDI层提供三个服务hdf_audio_render、hdf_audio_capture、hdf_audio_control。开发板dev目录下驱动服务节点如下: ```c # ls -l hdf_audio* -crw-rw---- 1 system system 248, 6 1970-01-01 00:00 hdf_audio_capture //音频数据录音流服务。 -crw-rw---- 1 system system 248, 4 1970-01-01 00:00 hdf_audio_codec_dev0 //音频声卡设备0名称。 -crw-rw---- 1 system system 248, 4 1970-01-01 00:00 hdf_audio_codec_dev1 //音频声卡设备1名称。 -crw-rw---- 1 system system 248, 5 1970-01-01 00:00 hdf_audio_control //音频控制流服务。 -crw-rw---- 1 system system 248, 7 1970-01-01 00:00 hdf_audio_render //音频数据播放流务。 +crw-rw---- 1 system system 248, 6 1970-01-01 00:00 hdf_audio_capture // 音频数据录音流服务。 +crw-rw---- 1 system system 248, 4 1970-01-01 00:00 hdf_audio_codec_dev0 // 音频声卡设备0名称。 +crw-rw---- 1 system system 248, 4 1970-01-01 00:00 hdf_audio_codec_dev1 // 音频声卡设备1名称。 +crw-rw---- 1 system system 248, 5 1970-01-01 00:00 hdf_audio_control // 音频控制流服务。 +crw-rw---- 1 system system 248, 7 1970-01-01 00:00 hdf_audio_render // 音频数据播放流务。 ``` 音频声卡设备包括的驱动服务: hdf_audio_codec_dev0 -- dma_service_0 : dma 服务 -- dai_service : cpu dai 服务 -- codec_service_0 : codec 服务(特指内置codec) +- dma_service_0 : dma服务 +- dai_service : cpu dai服务 +- codec_service_0 : codec服务(特指内置codec) - dsp_service_0 : dsp 服务(可选项) hdf_audio_codec_dev1 -- dma_service_0 : dma 服务 -- dai_service : cpu dai 服务 -- codec_service_1 : accessory 服务(特指smartPA) -- dsp_service_0 : dsp 服务(可选项) +- dma_service_0 : dma服务 +- dai_service : cpu dai服务 +- codec_service_1 : accessory服务(特指smartPA) +- dsp_service_0 : dsp服务(可选项) #### 启动流程 @@ -99,7 +99,7 @@ hdf_audio_codec_dev1 #### 已有平台开发 -ADM适配已有平台(Hi3516DV300)Codec或Accessory(Smart PA)的驱动开发流程: +ADM适配已有平台(Hi3516DV300)Codec或Accessory(Smart PA)的驱动开发流程: ![](figures/开发流程图1.png) @@ -166,7 +166,7 @@ struct AudioDaiOps g_codecDaiDeviceOps = { struct DaiData g_codecDaiData = { .DaiInit = CodecDaiDeviceInit, // codecdai设备初始化(适配新平台需重新实现) - .ops = &g_codecDaiDeviceOps, //codecdai操作函数 + .ops = &g_codecDaiDeviceOps, // codecdai操作函数 }; ``` @@ -178,27 +178,27 @@ CodecDeviceInit将完成AIAO的设置、寄存器默认值初始化、g_audioCon int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec) { ... - /* hi3516平台AIAO的Set和Get 注册*/ + /* hi3516平台AIAO的Set和Get注册 */ CodecSetCtlFunc(codec->devData, AudioCodecAiaoGetCtrlOps, AudioCodecAiaoSetCtrlOps) ... - /* hi3516平台codec寄存器IoRemap*/ + /* hi3516平台codec寄存器IoRemap */ CodecHalSysInit(); ... - /* hi3516平台codec寄存器默认值初始化*/ + /* hi3516平台codec寄存器默认值初始化 */ CodecRegDefaultInit(codec->devData->regCfgGroup); ... - /* hi3516平台g_audioControls 挂到Control链表上*/ + /* hi3516平台g_audioControls挂到Control链表上 */ AudioAddControls(audioCard, codec->devData->controls, codec->devData->numControls); ... - /* hi3516平台codec加载到sapm*/ + /* hi3516平台codec加载到sapm */ AudioSapmNewComponents(audioCard, codec->devData->sapmComponents, codec->devData->numSapmComponent); ... - /* hi3516平台codec加挂到通路选择链表上*/ + /* hi3516平台codec加挂到通路选择链表上 */ AudioSapmAddRoutes(audioCard, g_audioRoutes, HDF_ARRAY_SIZE(g_audioRoutes); ... AudioSapmNewControls(audioCard); ... - /* hi3516平台codec电源管理*/ + /* hi3516平台codec电源管理 */ AudioSapmSleep(audioCard); ... return HDF_SUCCESS; @@ -357,7 +357,7 @@ vendor/hisilicon/hispark_taurus/hdf_config/ permission = 0666; moduleName = "CODEC_HI3516"; // 名字会与HdfDriverEntry结构体中moduleName进行匹配 serviceName = "codec_service_0"; // 对外提供的服务名称 - deviceMatchAttr = "hdf_codec_driver"; //私有配置属性名称,通过此名称匹配对应的私有数据(包含寄存器配置) + deviceMatchAttr = "hdf_codec_driver"; // 私有配置属性名称,通过此名称匹配对应的私有数据(包含寄存器配置) } } ``` @@ -373,15 +373,15 @@ root { platform { ... controller_0x120c1001 :: card_controller { - //配置私有数据属性名称,与device_info.hcs中的deviceMatchAttr对应 + // 配置私有数据属性名称,与device_info.hcs中的deviceMatchAttr对应 match_attr = "hdf_audio_driver_1"; - serviceName = "hdf_audio_smartpa_dev0"; //对外提供的服务名称 - accessoryName = "codec_service_1"; //外置codec服务名称 - platformName = "dma_service_0"; //dma服务 - cpuDaiName = "dai_service"; //cpu dai 服务 - accessoryDaiName = "accessory_dai"; //外置dai - dspName = "dsp_service_0"; //dsp服务名称 - dspDaiName = "dsp_dai"; //dsp dai + serviceName = "hdf_audio_smartpa_dev0"; // 对外提供的服务名称 + accessoryName = "codec_service_1"; // 外置codec服务名称 + platformName = "dma_service_0"; // dma服务 + cpuDaiName = "dai_service"; // cpu dai服务 + accessoryDaiName = "accessory_dai"; // 外置dai + dspName = "dsp_service_0"; // dsp服务名称 + dspDaiName = "dsp_dai"; // dsp dai } } } @@ -405,7 +405,7 @@ root { - initSeqConfig:初始化过程寄存器配置组名称。 -- controlsConfig:控制功能配置组,其中array index(具体业务场景)和 iface(与HAL保持一致)为固定的值。 +- controlsConfig:控制功能配置组,其中array index(具体业务场景)和iface(与HAL保持一致)为固定的值。 ``` array index @@ -446,9 +446,9 @@ ctrlParamsSeqConfig:控制功能寄存器配置组,其中item与controlsConf /* 3516寄存器基地址 */ idInfo { - chipName = "hi3516"; //codec名字 - chipIdRegister = 0x113c0000; //codec 基地址 - chipIdSize = 0x1000; //codec 地址偏移 + chipName = "hi3516"; // codec名字 + chipIdRegister = 0x113c0000; // codec基地址 + chipIdSize = 0x1000; // codec地址偏移 } /* 寄存器配置,包含各种寄存器配置信息 */ @@ -494,13 +494,13 @@ ctrlParamsSeqConfig:控制功能寄存器配置组,其中item与controlsConf /* control function register config reg, rreg, shift, rshift, min, max, mask, invert, value */ ctrlParamsSeqConfig = [ - 0x3c, 0x3c, 24, 24, 0x0, 0x57, 0x7F, 1, 0, //"Main Capture Volume" - 0x38, 0x38, 31, 31, 0x0, 0x1, 0x1, 0, 0, //"Playback Mute" - 0x3c, 0x3c, 31, 31, 0x0, 0x1, 0x1, 0, 0, //"Capture Mute" - 0x20, 0x20, 16, 16, 0x0, 0xF, 0x1F, 0, 0, //"Mic Left Gain" - 0x20, 0x20, 24, 24, 0x0, 0xF, 0x1F, 0, 0, //"Mic Right Gain" - 0x2000, 0x2000, 16, 16, 0x0, 0x7, 0x7, 0, 0, //"Render Channel Mode" - 0x1000, 0x1000, 16, 16, 0x0, 0x7, 0x7, 0, 0 //"Capture Channel Mode" + 0x3c, 0x3c, 24, 24, 0x0, 0x57, 0x7F, 1, 0, // "Main Capture Volume" + 0x38, 0x38, 31, 31, 0x0, 0x1, 0x1, 0, 0, // "Playback Mute" + 0x3c, 0x3c, 31, 31, 0x0, 0x1, 0x1, 0, 0, // "Capture Mute" + 0x20, 0x20, 16, 16, 0x0, 0xF, 0x1F, 0, 0, // "Mic Left Gain" + 0x20, 0x20, 24, 24, 0x0, 0xF, 0x1F, 0, 0, // "Mic Right Gain" + 0x2000, 0x2000, 16, 16, 0x0, 0x7, 0x7, 0, 0, // "Render Channel Mode" + 0x1000, 0x1000, 16, 16, 0x0, 0x7, 0x7, 0, 0 // "Capture Channel Mode" ]; /* 上层下发参数后,写入音频相关信息的寄存器 @@ -514,10 +514,10 @@ ctrlParamsSeqConfig:控制功能寄存器配置组,其中item与controlsConf /* 电源管理功能寄存器配置 reg, rreg, shift, rshift, min, max, mask, invert, value */ ctrlSapmParamsSeqConfig = [ - 0x20, 0x20, 23, 23, 0x0, 0x1, 0x1, 0, 0, //LPGA MIC 0 -- connect MIC - 0x20, 0x20, 31, 31, 0x0, 0x1, 0x1, 0, 0, //RPGA MIC 0 -- connect MIC - 0x30, 0x30, 27, 27, 0x0, 0x1, 0x1, 0, 0, //dacl to dacr mixer - 0x30, 0x30, 26, 26, 0x0, 0x1, 0x1, 0, 0 //dacr to dacl mixer + 0x20, 0x20, 23, 23, 0x0, 0x1, 0x1, 0, 0, // LPGA MIC 0 -- connect MIC + 0x20, 0x20, 31, 31, 0x0, 0x1, 0x1, 0, 0, // RPGA MIC 0 -- connect MIC + 0x30, 0x30, 27, 27, 0x0, 0x1, 0x1, 0, 0, // dacl to dacr mixer + 0x30, 0x30, 26, 26, 0x0, 0x1, 0x1, 0, 0 // dacr to dacl mixer ]; /* @@ -526,19 +526,19 @@ ctrlParamsSeqConfig:控制功能寄存器配置组,其中item与controlsConf sapmType,compNameIndex,reg, mask,shift,invert, kcontrolNews,kcontrolsNum */ sapmComponent = [ - 10, 0, 0x20, 0x1, 15, 1, 0, 0, //ADCL - 10, 1, 0x20, 0x1, 14, 1, 0, 0, //ADCR - 11, 2, 0x14, 0x1, 11, 1, 0, 0, //DACL - 11, 3, 0x14, 0x1, 12, 1, 0, 0, //DACR - 8, 4, 0x20, 0x1, 13, 1, 1, 1, //LPGA - 8, 5, 0x20, 0x1, 12, 1, 2, 1, //RPGA - 15, 6, 0, 0x1, 0, 0, 3, 1, //SPKL - 15, 7, 0, 0x1, 0, 0, 4, 1, //SPKR - 0, 8, 0, 0x1, 0, 0, 0, 0 //MIC + 10, 0, 0x20, 0x1, 15, 1, 0, 0, // ADCL + 10, 1, 0x20, 0x1, 14, 1, 0, 0, // ADCR + 11, 2, 0x14, 0x1, 11, 1, 0, 0, // DACL + 11, 3, 0x14, 0x1, 12, 1, 0, 0, // DACR + 8, 4, 0x20, 0x1, 13, 1, 1, 1, // LPGA + 8, 5, 0x20, 0x1, 12, 1, 2, 1, // RPGA + 15, 6, 0, 0x1, 0, 0, 3, 1, // SPKL + 15, 7, 0, 0x1, 0, 0, 4, 1, // SPKR + 0, 8, 0, 0x1, 0, 0, 0, 0 // MIC ]; /* 电源管理功能配置 - array index, iface, enable + array index, iface, enable */ sapmConfig = [ 0, 5, 1, @@ -624,11 +624,11 @@ SmartPA归属于Accessory驱动的一种,开发步骤类似于codec: Accessory模块需要填充如下3个结构体: -- g_tfa9879Data :accessory设备操作函数集,其中包含HCS文件中的配置信息,且定义与映射了accessory设备的初始化、读写寄存器的方法函数。 +- g_tfa9879Data:accessory设备操作函数集,其中包含HCS文件中的配置信息,且定义与映射了accessory设备的初始化、读写寄存器的方法函数。 -- g_tfa9879DaiDeviceOps :accessory设备DAI的数据集,其中定义与映射了accessory设备DAI的操作集。 +- g_tfa9879DaiDeviceOps:accessory设备DAI的数据集,其中定义与映射了accessory设备DAI的操作集。 -- g_tfa9879DaiData :accessory设备DAI的数据集,其中定义与映射了accessory设备的数据访问接口的驱动名、初始化和操作集。 +- g_tfa9879DaiData:accessory设备DAI的数据集,其中定义与映射了accessory设备的数据访问接口的驱动名、初始化和操作集。 ```c struct AccessoryData g_tfa9879Data = { @@ -850,13 +850,13 @@ struct AudioDmaOps g_dmaDeviceOps = { .DmaPrep = Hi3516DmaPrep, // dma准备函数接口 .DmaSubmit = Hi3516DmaSubmit, // dma submit函数接口 .DmaPending = Hi3516DmaPending, // dma pending函数接口 - .DmaPause = Hi3516DmaPause, // dma 暂停、停止函数接口 - .DmaResume = Hi3516DmaResume, // dma 恢复函数接口 + .DmaPause = Hi3516DmaPause, // dma暂停、停止函数接口 + .DmaResume = Hi3516DmaResume, // dma恢复函数接口 .DmaPointer = Hi3516DmaPointer, // dma获取当前播放或录音位置函数接口 }; struct PlatformData g_platformData = { - .PlatformInit = AudioDmaDeviceInit, //dma设备初始化接口 + .PlatformInit = AudioDmaDeviceInit, // dma设备初始化接口 .ops = &g_dmaDeviceOps, }; ``` @@ -904,7 +904,7 @@ int32_t Hi3516DmaPointer(struct PlatformData *data, uint32_t *pointer); - 填充g_platformDriverEntry结构体 - moduleName与device_info.hcs中的moduleName匹配 -- 实现Bind、Init、Release函数指针。 +- 实现Bind、Init、Release函数指针 drivers/peripheral/audio/chipsets/hi3516dv300/soc/src/hi3516_dma_adapter.c @@ -961,9 +961,9 @@ Dai驱动开发主要包含如下几个重要步骤: Dai模块需要填充如下2个结构体: -- g_daiData :dai设备私有配置,其中包含dai设备的初始化、读写寄存器、操作函数。 +- g_daiData:dai设备私有配置,其中包含dai设备的初始化、读写寄存器、操作函数。 -- g_daiDeviceOps :dai设备操作函数集,包含了dai的参数设置、触发、启动。 +- g_daiDeviceOps:dai设备操作函数集,包含了dai的参数设置、触发、启动。 ```c struct AudioDaiOps g_daiDeviceOps = { @@ -1196,9 +1196,9 @@ $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_adapter.c │   │   └── hi3516_dma_ops.h │   ├── src │   │   ├── hi3516_aiao_impl.c -│   │   ├── hi3516_dai_adapter.c //dai驱动入口 +│   │   ├── hi3516_dai_adapter.c // dai驱动入口 │   │   ├── hi3516_dai_ops.c -│   │   ├── hi3516_dma_adapter.c //dma驱动入口 +│   │   ├── hi3516_dma_adapter.c // dma驱动入口 │   │   └── hi3516_dma_ops.c │   └── test │   └── unittest @@ -1265,7 +1265,7 @@ HAL(Hardware Abstraction Layer)的核心功能说明如下: 4. 调用创建好的播放类中挂载的方法调用render->control.Start()、render->RenderFrame()进行下发开始命令,音频数据循环下发。 -5. 播放过程中可调用其他控制命令对播放业务进行控制操作,例如调节音量、暂停、静音等render->control.Pause()、 render->control.Resume()、 render->volume.SetVolume()。 +5. 播放过程中可调用其他控制命令对播放业务进行控制操作,例如调节音量、暂停、静音等render->control.Pause()、render->control.Resume()、render->volume.SetVolume()。 6. 播放业务完成后,下发停止命令、销毁播放类、卸载声卡。 @@ -1284,7 +1284,7 @@ HAL(Hardware Abstraction Layer)的核心功能说明如下: #include #include "audio_manager.h" - /* so动态库引用打开 */ + /* so动态库引用打开 */ char *soPathHdi = "/system/lib/libhdi_audio.z.so"; void *g_handle = dlopen(soPathHdi , 1); @@ -1315,7 +1315,7 @@ int32_t FrameStart(void *param) static void *hal_main() { - /* 映射入口函数及调用 */ + /* 映射入口函数及调用 */ struct AudioManager *(*getAudioManager)() = (struct AudioManager *(*)())(dlsym(g_handle, "GetAudioManagerFuncs")); struct AudioManager *manager = getAudioManager(); @@ -1334,23 +1334,23 @@ static void *hal_main() /* 根据匹配到的声卡信息进行加载声卡 */ struct AudioAdapter *adapter = NULL; struct AudioAdapterDescriptor *desc = &descs[index]; // 根据匹配到的声卡信息获取对应设备 - manager->LoadAdapter(manager, desc, &adapter); //加载声卡,获取声卡方法实例 + manager->LoadAdapter(manager, desc, &adapter); // 加载声卡,获取声卡方法实例 /* 创建播放类 */ struct AudioRender *render; struct AudioDeviceDescriptor devDesc; struct AudioSampleAttributes attrs; - InitDevDesc(&devDesc, renderPort.portId); //初始化设置设备参数 + InitDevDesc(&devDesc, renderPort.portId); // 初始化设置设备参数 WavHeadAnalysis(g_file, &attrs); // 解析音频文件设置Attributes adapter->CreateRender(adapter, &devDesc, &attrs, &render); /* 下发音频数播放 */ render->control.Start((AudioHandle)render); // 下发控制命令start,准备动作 - pthread_create(&g_tids, NULL, (void *)(&FrameStart), &g_str); // 起线程进行播放 + pthread_create(&g_tids, NULL, (void *)(&FrameStart), &g_str); // 拉起线程进行播放 /* 控制命令 */ - render->control.Pause((AudioHandle)render); // 下发进行暂停操作 - render->control.Resume((AudioHandle)render); // 恢复操作 + render->control.Pause((AudioHandle)render); // 下发暂停操作 + render->control.Resume((AudioHandle)render); // 下发恢复操作 render->volume.SetVolume((AudioHandle)render, 0.5); // 设置音量 /* 停止播放,销毁播放类 */ diff --git a/zh-cn/device-dev/driver/driver-peripherals-camera-des.md b/zh-cn/device-dev/driver/driver-peripherals-camera-des.md index 4b529c1588..a531d05d65 100755 --- a/zh-cn/device-dev/driver/driver-peripherals-camera-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-camera-des.md @@ -4,7 +4,7 @@ ### 功能简介 OpenHarmony相机驱动框架模型对上实现相机HDI(Hardware Device Interface)接口,对下实现相机Pipeline模型,管理相机各个硬件设备。 -该驱动框架模型内部分为三层,依次为HDI实现层、框架层和设备适配层,各层基本概念如下: +该驱动框架模型内部分为三层,依次为HDI实现层、框架层和设备适配层。各层基本概念如下: + HDI实现层:实现OHOS(OpenHarmony Operation System)相机标准南向接口。 + 框架层:对接HDI实现层的控制、流的转发,实现数据通路的搭建,管理相机各个硬件设备等功能。 @@ -51,7 +51,7 @@ Camera模块主要用以相机预览、拍照、视频流等场景下对相机 | 功能描述 | 接口名称 | | ---------------------------- | ------------------------------------------------------------ | - | 获取流控制器 | CamRetCode GetStreamOperator(
const OHOS::sptr &callback,
OHOS::sptr &streamOperator) | + | 获取流控制器 | CamRetCode GetStreamOperator(
const OHOS::sptr &callback,
OHOS::sptr &streamOperator) | | 更新设备控制参数 | CamRetCode UpdateSettings(const std::shared_ptr &settingss) | | 设置Result回调模式和回调函数 | CamRetCode SetResultMode(const ResultCallbackMode &mode) | | 获取使能的ResultMeta | CamRetCode GetEnabledResults(std::vector &results) | @@ -73,8 +73,8 @@ Camera模块主要用以相机预览、拍照、视频流等场景下对相机 | ------------------------------ | ------------------------------------------------------------ | | 设置ICameraHost回调接口 | CamRetCode SetCallback(const OHOS::sptr &callback) | | 获取当前可用的Camera设备ID列表 | CamRetCode GetCameraIds(std::vector\ &cameraIds) | - | 获取Camera设备能力集合 | CamRetCode GetCameraAbility(const std::string &cameraId,
std::shared_ptr &ability) | - | 打开Camera设备 | CamRetCode OpenCamera(const std::string &cameraId,
const OHOS::sptr &callback,
OHOS::sptr &device) | + | 获取Camera设备能力集合 | CamRetCode GetCameraAbility(const std::string &cameraId, std::shared_ptr &ability) | + | 打开Camera设备 | CamRetCode OpenCamera(const std::string &cameraId,
const OHOS::sptr &callback,
OHOS::sptr &device) | | 打开或关闭闪光灯 | CamRetCode SetFlashlight(const std::string &cameraId, bool &isEnable) | - icamera_host_callback.h @@ -96,30 +96,30 @@ Camera模块主要用以相机预览、拍照、视频流等场景下对相机 | 功能描述 | 接口名称 | | -------------------------------- | ------------------------------------------------------------ | - | 查询是否支持添加参数对应的流 | CamRetCode IsStreamsSupported(
OperationMode mode,
const std::shared_ptr\ &modeSetting,
const std::vector<std::shared_ptr<StreamInfo>> &info,
StreamSupportType &type) | + | 查询是否支持添加参数对应的流 | CamRetCode IsStreamsSupported(
OperationMode mode,
const std::shared_ptr\ &modeSetting,
const std::vector<std::shared_ptr<StreamInfo>> &info,
StreamSupportType &type) | | 创建流 | CamRetCode CreateStreams(const std::vector> &streamInfos) | | 释放流 | CamRetCode ReleaseStreams(const std::vector &streamIds) | - | 配置流 | CamRetCode CommitStreams(OperationMode mode,
const std::shared_ptr &modeSetting) | - | 获取流的属性 | CamRetCode GetStreamAttributes(
std::vector> &attributes) | + | 配置流 | CamRetCode CommitStreams(OperationMode mode, const std::shared_ptr &modeSetting) | + | 获取流的属性 | CamRetCode GetStreamAttributes(std::vector> &attributes) | | 绑定生产者句柄和指定流 | CamRetCode AttachBufferQueue(int streamId, const OHOS::sptr\ &producer) | | 解除生产者句柄和指定流的绑定关系 | CamRetCode DetachBufferQueue(int streamId) | - | 捕获图像 | CamRetCode Capture(int captureId,
const std::shared_ptr &info, bool isStreaming) | + | 捕获图像 | CamRetCode Capture(int captureId, const std::shared_ptr &info, bool isStreaming) | | 取消捕获 | CamRetCode CancelCapture(int captureId) | - | 将指定流转换成离线流 | CamRetCode ChangeToOfflineStream(const std::vector &streamIds,
OHOS::sptr &callback,
OHOS::sptr &offlineOperator) | + | 将指定流转换成离线流 | CamRetCode ChangeToOfflineStream(const std::vector &streamIds,
OHOS::sptr &callback,
OHOS::sptr &offlineOperator) | - istream_operator_callback.h | 功能描述 | 接口名称 | | ---------------------------------------- | ------------------------------------------------------------ | | 捕获开始回调,在捕获开始时调用 | void OnCaptureStarted(int32_t captureId, const std::vector &streamIds) | - | 捕获结束回调,在捕获结束时调用 | void OnCaptureEnded(int32_t captureId,
const std::vector> &infos) | - | 捕获错误回调,在捕获过程中发生错误时调用 | void OnCaptureError(int32_t captureId,
const std::vector> &infos) | - | 帧捕获回调 | void OnFrameShutter(int32_t captureId,
const std::vector &streamIds, uint64_t timestamp) | + | 捕获结束回调,在捕获结束时调用 | void OnCaptureEnded(int32_t captureId, const std::vector> &infos) | + | 捕获错误回调,在捕获过程中发生错误时调用 | void OnCaptureError(int32_t captureId, const std::vector> &infos) | + | 帧捕获回调 | void OnFrameShutter(int32_t captureId,
const std::vector &streamIds, uint64_t timestamp) | ### 开发步骤 Camera驱动的开发过程主要包含以下步骤: -1. **注册CameraHost** +1. 注册CameraHost 定义Camera的HdfDriverEntry结构体,该结构体中定义了CameraHost初始化的方法。 ``` @@ -133,7 +133,7 @@ Camera驱动的开发过程主要包含以下步骤: HDF_INIT(g_cameraHostDriverEntry); // 将Camera的HdfDriverEntry结构体注册到HDF上 ``` -2. **初始化Host服务** +2. 初始化Host服务 步骤1中提到的HdfCameraHostDriverBind接口提供了CameraServiceDispatch和CameraHostStubInstance的注册。这两个接口一个是远端调用CameraHost的方法,如OpenCamera(),SetFlashlight()等,另外一个是Camera设备的初始化,在开机时被调用。 @@ -142,7 +142,7 @@ Camera驱动的开发过程主要包含以下步骤: { HDF_LOGI("HdfCameraHostDriverBind enter!"); if (deviceObject == nullptr) { - HDF_LOGE("HdfCameraHostDriverBind: HdfDeviceObject is NULL !"); + HDF_LOGE("HdfCameraHostDriverBind: HdfDeviceObject is NULL!"); return HDF_FAILURE; } HdfCameraService *hdfCameraService = reinterpret_cast(OsalMemAlloc(sizeof(HdfCameraService))); @@ -192,7 +192,7 @@ Camera驱动的开发过程主要包含以下步骤: CameraHostStubInstance()接口最终调用CameraHostImpl::Init()方法,该方法会获取物理Camera,并对DeviceManager和PipelineCore进行初始化。 -3. **获取Host服务** +3. 获取Host服务 调用Get()接口从远端CameraService中获取CameraHost对象。get()方法如下: @@ -218,7 +218,7 @@ Camera驱动的开发过程主要包含以下步骤: } ``` -4. **打开设备** +4. 打开设备 CameraHostProxy对象中有五个方法,分别是SetCallback、GetCameraIds、GetCameraAbility、OpenCamera和SetFlashlight。下面着重描述OpenCamera接口。 CameraHostProxy的OpenCamera()接口通过CMD_CAMERA_HOST_OPEN_CAMERA调用远端CameraHostStubOpenCamera()接口并获取ICameraDevice对象。 @@ -285,7 +285,7 @@ Camera驱动的开发过程主要包含以下步骤: } ``` -5. **获取流** +5. 获取流 CameraDeviceImpl定义了GetStreamOperator、UpdateSettings、SetResultMode和GetEnabledResult等方法,获取流操作方法如下: @@ -299,7 +299,7 @@ Camera驱动的开发过程主要包含以下步骤: } spCameraDeviceCallback_ = callback; if (spStreamOperator_ == nullptr) { - // 这里new了一个spStreamOperator对象传递给调用者,以便对stream进行各种操作。 + // 这里新建一个spStreamOperator对象传递给调用者,以便对stream进行各种操作。 spStreamOperator_ = new(std::nothrow) StreamOperatorImpl(spCameraDeviceCallback_, shared_from_this()); if (spStreamOperator_ == nullptr) { CAMERA_LOGW("create stream operator failed."); @@ -315,7 +315,7 @@ Camera驱动的开发过程主要包含以下步骤: } ``` -6. **创建流** +6. 创建流 调用CreateStreams创建流前需要填充StreamInfo结构体,具体内容如下: @@ -439,17 +439,17 @@ Camera驱动的开发过程主要包含以下步骤: } ``` -9. **取消捕获和释放离线流** +9. 取消捕获和释放离线流 StreamOperatorImpl类中的CancelCapture()接口的主要作用是根据captureId取消数据流的捕获。 ``` CamRetCode StreamOperatorImpl::CancelCapture(int captureId) { - auto itr = camerCaptureMap_.find(captureId); //根据captureId 在Map中查找对应的CameraCapture对象 - RetCode rc = itr->second->Cancel(); //调用CameraCapture中Cancel方法结束数据捕获 + auto itr = camerCaptureMap_.find(captureId); // 根据captureId 在Map中查找对应的CameraCapture对象 + RetCode rc = itr->second->Cancel(); // 调用CameraCapture中Cancel方法结束数据捕获 std::unique_lock lock(captureMutex_); - camerCaptureMap_.erase(itr); //擦除该CameraCapture对象 + camerCaptureMap_.erase(itr); // 擦除该CameraCapture对象 return NO_ERROR; } ``` @@ -459,14 +459,14 @@ Camera驱动的开发过程主要包含以下步骤: ``` CamRetCode StreamOperatorImpl::ReleaseStreams(const std::vector& streamIds) { - RetCode rc = DestroyStreamPipeline(streamIds); //销毁该streamIds 的pipeline + RetCode rc = DestroyStreamPipeline(streamIds); // 销毁该streamIds 的pipeline rc = DestroyHostStreamMgr(streamIds); - rc = DestroyStreams(streamIds); //销毁该streamIds 的 Stream + rc = DestroyStreams(streamIds); // 销毁该streamIds 的 Stream return NO_ERROR; } ``` -10. **关闭Camera设备** +10. 关闭Camera设备 调用CameraDeviceImpl中的Close()来关闭CameraDevice,该接口调用deviceManager中的PowerDown()来给设备下电。 diff --git a/zh-cn/device-dev/driver/driver-peripherals-external-des.md b/zh-cn/device-dev/driver/driver-peripherals-external-des.md index d20139cfac..24cea68de6 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-external-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-external-des.md @@ -3,25 +3,35 @@ ## 概述 -WLAN是基于HDF(Hardware Driver Foundation)驱动框架开发的模块,该模块可实现跨操作系统迁移,自适应器件差异,模块化拼装编译等功能。各WLAN厂商驱动开发人员可根据WLAN模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭WLAN热点、扫描、关联WLAN热点等;对HDI层向上提供能力如下:设置MAC地址、设置发射功率、获取设备的MAC地址等。WLAN模块框架图如下: +WLAN是基于HDF(Hardware Driver Foundation)驱动框架开发的模块,可实现跨操作系统迁移,自适应器件差异,模块化拼装编译等功能。各WLAN厂商驱动开发人员可根据WLAN模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭WLAN热点、扫描、关联WLAN热点等;对HDI层向上提供能力如下:设置MAC地址、设置发射功率、获取设备的MAC地址等。WLAN模块框架图如下: **图1** WLAN框架 ![image](figures/WLAN框架.png "WLAN框架") **图2** WLAN Driver框架 + ![zh-cn_image_0000001300092359](figures/zh-cn_image_0000001300092359.png) -1.WLAN Message:该部件为每个服务单独提供业务接口,每个服务也可依赖其他服务形成组合业务接口,此模块支持在用户态、内核态和MCU环境运行,实现组件间的充分解耦。 -2.WLAN Configuration Core:WLAN相关的配置文件进行解析。 -3.AP:AP为WLAN终端提供外部接入入口的设备。 -4.STA:STA为接入WLAN系统的终端。 -5.Mac80211:定义底层驱动相关的MAC层接口。 -6.Bus:该驱动模块向上提供统一的总线抽象接口。通过向下调用Platform层提供的SDIO接口和封装适配USB、PCIE接口,屏蔽不同内核的差异;通过对不同类型的总线操作进行统一封装,屏蔽不同芯片差异,能够对不同芯片厂商提供完备的总线驱动能力,不同厂商共用此模块接口,从而使厂商的开发更为便捷和统一。 -7.NetDevice:用于建立专属网络设备,屏蔽不同OS的差异,对WiFi驱动提供统一接口,提供统一的HDF NetDevice数据结构,及其统一管理、注册、去注册能力;对接轻设备及富设备上的Linux的网络设备层。 -8.NetBuf:该部件为WLAN驱动提供Linux或者LiteOS原生的网络数据缓冲的统一数据结构的封装以及对网络数据的操作接口的封装。 -9.FlowCtl:流控模块。 -10.HCC-CFG:WLAN相关参数配置其中包括板级配置、驱动配置、Module配置。 +1. WLAN Message:该部件为每个服务单独提供业务接口,每个服务也可依赖其他服务形成组合业务接口,此模块支持在用户态、内核态和MCU环境运行,实现组件间的充分解耦。 + +2. WLAN Configuration Core:WLAN相关的配置文件进行解析。 + +3. AP:AP为WLAN终端提供外部接入入口的设备。 + +4. STA:STA为接入WLAN系统的终端。 + +5. Mac80211:定义底层驱动相关的MAC层接口。 + +6. Bus:该驱动模块向上提供统一的总线抽象接口。通过向下调用Platform层提供的SDIO接口和封装适配USB、PCIE接口,屏蔽不同内核的差异;通过对不同类型的总线操作进行统一封装,屏蔽不同芯片差异,能够对不同芯片厂商提供完备的总线驱动能力,不同厂商共用此模块接口,从而使厂商的开发更为便捷和统一。 + +7. NetDevice:用于建立专属网络设备,屏蔽不同OS的差异,对WiFi驱动提供统一接口,提供统一的HDF NetDevice数据结构,及其统一管理、注册、去注册能力;对接轻设备及富设备上的Linux的网络设备层。 + +8. NetBuf:该部件为WLAN驱动提供Linux或者LiteOS原生的网络数据缓冲的统一数据结构的封装以及对网络数据的操作接口的封装。 + +9. FlowCtl:流控模块。 + +10. HCC-CFG:WLAN相关参数配置其中包括板级配置、驱动配置、Module配置。 ### WLAN驱动接口架构 @@ -33,7 +43,7 @@ WLAN模块有三部分对外开放的API接口,如下图所示: 3. 提供给各厂商实现的能力接口。 - **图2** WLAN模块开放能力分布图 + **图3** WLAN模块开放能力分布图 ![image](figures/WLAN模块开放能力分布图.png "WLAN模块开放能力分布图") @@ -111,9 +121,9 @@ WLAN驱动模块对HDI层提供的能力接口,主要功能有:创建/销毁 WLAN驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。 -1. 通过wifi_config.hcs文件,配置硬件参数:module(不同feature),芯片等。 +1. 通过wifi_config.hcs文件,配置硬件参数:module(不同feature)、芯片等。 -2. 解析配置文件, 生成全量配置的结构体对象。 +2. 解析配置文件,生成全量配置的结构体对象。 3. Module初始化,创建Module。 @@ -124,7 +134,7 @@ WLAN驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台, 6. 上层wpa业务挂接。 -> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 以上驱动框架适配步骤一部分已经提供(详细见开发实例),待开发人员实现的部分有:1、根据硬件,修改配置参数;2、适配挂接chip;3、测试自验证。 @@ -142,7 +152,7 @@ hisi :& deviceList { powers { power0 { powerSeqDelay = 0; /* 电源序列延时 */ - powerType = 1; /* 电源类型:0--总是打开;1--GPIO */ + powerType = 1; /* 电源类型:0--总是打开;1--GPIO */ gpioId = 1; /* GPIO管脚号 */ activeLevel=1; /* 有效电平:0--低;1--高 */ } @@ -184,7 +194,7 @@ root { } ``` - 2、适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化 + 2、适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化。 ``` /* WLAN初始化挂接流程 */ @@ -400,7 +410,7 @@ int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevi } ``` - 3、在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针 + 3、在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针。 ``` hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi_char* ifname, hi_u32* len) @@ -408,7 +418,7 @@ hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi oal_net_device_stru *netdev = HI_NULL; ...... - /* 初始化网络设备,获取对应的实例。*/ + /* 初始化网络设备,获取对应的实例 */ netdev = NetDeviceInit(ifname, *len, LITE_OS); oal_wireless_dev *wdev = (oal_wireless_dev *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, sizeof(oal_wireless_dev)); ret = wal_init_netif(type, netdev, wdev); @@ -417,7 +427,7 @@ hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi return HI_SUCCESS; } -/* 挂接netdev的一些函数指针,详细挂接函数{@link NetDeviceInterFace} */ +/* 挂接netdev的一些函数指针,详细挂接函数{@link NetDeviceInterFace} */ oal_net_device_ops_stru g_wal_net_dev_ops = { .getStats = wal_netdev_get_stats, diff --git a/zh-cn/device-dev/driver/driver-peripherals-face_auth-des.md b/zh-cn/device-dev/driver/driver-peripherals-face_auth-des.md index 09d32e8904..1517510c4d 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-face_auth-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-face_auth-des.md @@ -206,7 +206,7 @@ Face_auth驱动的主要工作是为上层用户认证框架和Face_auth服务 .Release = HdfFaceAuthInterfaceDriverRelease, }; - // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 + // 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 HDF_INIT(g_faceAuthInterfaceDriverEntry); ``` diff --git a/zh-cn/device-dev/driver/driver-peripherals-lcd-des.md b/zh-cn/device-dev/driver/driver-peripherals-lcd-des.md index 02c936b351..a033285894 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-lcd-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-lcd-des.md @@ -175,7 +175,7 @@ LCD器件驱动示例如下: #define VERTICAL_SYNC_WIDTH 2 #define FRAME_RATE 60 -/* Panel Info结构体结构体 */ +/* PanelInfo结构体结构体 */ struct PanelInfo { uint32_t width; uint32_t height; diff --git a/zh-cn/device-dev/driver/driver-peripherals-light-des.md b/zh-cn/device-dev/driver/driver-peripherals-light-des.md index 39f4114765..04b8debbdf 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-light-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-light-des.md @@ -1,11 +1,11 @@ -# LIGHT +# Light ## 概述 ### 功能简介 -​ Light驱动模型为上层Light硬件服务层提供稳定的灯控制能力接口,包括获取灯类型、配置点灯模式、配置灯闪烁效果、点灯、熄灯等。基于HDF(Hardware Driver Foundation)驱动框架开发的Light驱动模型,实现跨操作系统迁移,器件差异配置等功能。实现Light驱动“一次开发,多系统部署”的目标。Light驱动模型如图1示: +Light驱动模型为上层Light硬件服务层提供稳定的灯控制能力接口,包括获取灯类型、配置点灯模式、配置灯闪烁效果、点灯、熄灯等。基于HDF(Hardware Driver Foundation)驱动框架开发的Light驱动模型,实现跨操作系统迁移,器件差异配置等功能。实现Light驱动“一次开发,多系统部署”的目标。Light驱动模型如图1示: **图 1** Light驱动模型图 @@ -21,8 +21,8 @@ Light驱动模型以标准系统Hi3516DV300为例,介绍整个驱动加载及运行流程: -1. 从device info HCS 的Light Host里读取Light设备管理配置信息。 -2. 从light_config HCS读取Light数据配置信息。 +1. 从device_info.hcs配置文件的Light Host里读取Light设备管理配置信息。 +2. 从light_config.hcs配置文件读取Light数据配置信息。 3. 解析Light设备管理配置信息,并关联对应设备驱动。 4. 客户端下发Light Stub控制到服务端。 5. 服务端调用Light Stub控制。 @@ -36,7 +36,7 @@ Light驱动模型以标准系统Hi3516DV300为例,介绍整个驱动加载及 ### 接口说明 -Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模式和闪烁时间的能力。Light硬件服务调用GetLightInfo获取Light设备的基本信息;调用TurnOnLight接口启动配置的闪烁效果。Light驱动模型对外开放的API接口能力,参考表1。 +Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模式和闪烁时间的能力。Light Hardware服务调用GetLightInfo获取Light设备的基本信息;调用TurnOnLight接口启动配置的闪烁效果。Light驱动模型对外开放的API接口能力,参考表1。 **表1** Light驱动模型对外API接口能力介绍 @@ -47,10 +47,10 @@ Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模 | int32_t (*TurnOffLight)(uint32_t type) | 根据指定的灯类型关闭灯列表中可用的灯。 | ### 开发步骤 -1. 基于HDF驱动框架,按照驱动Driver Entry程序,完成Light抽象驱动开发(主要由Bind、Init、Release、Dispatch函数接口实现),资源配置及HCS解析。完成Light驱动的设备信息配置。 +1. 基于HDF驱动框架,按照驱动Driver Entry程序,完成Light抽象驱动开发(主要由Bind、Init、Release、Dispatch函数接口实现),资源配置及HCS配置文件解析。完成Light驱动的设备信息配置。 - 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - Light驱动模型使用HCS作为配置描述源码,HCS配置字段详细介绍请参考[配置管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/driver-hdf-manage.md)。 + Light驱动模型使用HCS配置文件作为配置描述源码。HCS配置字段详细介绍请参考[配置管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/driver-hdf-manage.md)。 其Driver Entry入口函数定义如下: ```c @@ -153,15 +153,15 @@ Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模 } ``` - - Light设备管理模块负责系统中Light器件接口发布,在系统启动过程中,HDF框架机制通过灯Host里设备HCS配置信息,加载设备管理驱动。 + - Light设备管理模块负责系统中Light器件接口发布。在系统启动过程中,HDF框架机制通过Light Host里设备HCS配置信息,加载设备管理驱动。 ``` - /* 灯设备HCS配置 */ + /* Light设备HCS配置 */ device_light :: device { device0 :: deviceNode { - policy = 2; // 驱动服务发布的策略(0:不提供服务,1:对内核态发布服务,2:对内核态和用户态都发布服务) + policy = 2; // 驱动服务发布的策略(0:不提供服务,1:对内核态发布服务;2:对内核态和用户态都发布服务) priority = 100; // Light驱动启动优先级(0-200),值越大优先级越低,建议配置为100,优先级相同则不保证device的加载顺序 - preload = 0; // 驱动按需加载字段,0表示加载,2表示不加载 + preload = 0; // 驱动按需加载字段,0:加载;2:不加载 permission = 0664; // 驱动创建设备节点权限 moduleName = "HDF_LIGHT"; // Light驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 serviceName = "hdf_light"; // Light驱动对外发布服务的名称,必须唯一 @@ -176,11 +176,11 @@ Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模 static int32_t ParseLightInfo(const struct DeviceResourceNode *node) { ..... - /* 从HCS获取支持灯的类型个数 */ + /* 从HCS配置获取支持灯的类型个数 */ drvData->lightNum = parser->GetElemNum(light, "lightType"); .... for (i = 0; i < drvData->lightNum; ++i) { - /* 获取类型 */ + /* 获取灯的类型 */ ret = parser->GetUint32ArrayElem(light, "lightType", i, &temp, 0); CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "lightType"); } @@ -210,7 +210,7 @@ Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模 static int32_t GetAllLightInfo(struct HdfSBuf *data, struct HdfSBuf *reply) { ..... - /* 获取Light类型个数 */ + /* 获取灯的类型个数 */ if (!HdfSbufWriteUint32(reply, drvData->lightNum)) { HDF_LOGE("%s: write sbuf failed", __func__); return HDF_FAILURE; @@ -253,7 +253,7 @@ Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模 /* 闪烁模式 */ if (buf->flashEffect.flashMode == LIGHT_FLASH_TIMED) { drvData->info[lightType]->lightState = LIGHT_STATE_START; - /* 用户设置的闪烁时间小于系统支持的最短时间,采用系统配置的时间(HCS配置) */ + /* 用户设置的闪烁时间小于系统支持的最短时间,采用系统配置的时间(HCS配置) */ drvData->info[lightType]->onTime = buf->flashEffect.onTime < drvData->info[lightType]->onTime ? drvData->info[lightType]->onTime : buf->flashEffect.onTime; drvData->info[lightType]->offTime = buf->flashEffect.offTime < drvData->info[lightType]->offTime ? @@ -298,7 +298,7 @@ Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模 驱动开发完成后,在灯单元测试里面开发自测试用例,验证驱动基本功能。测试环境采用开发者自测试平台。 ```c++ -/* 用例执行前,初始化灯接口实例 */ +/* 用例执行前,初始化Light接口实例 */ void HdfLightTest::SetUpTestCase() { g_lightDev = NewLightInterfaceInstance(); @@ -320,7 +320,7 @@ void HdfLightTest::TearDownTestCase() } } -/* 测试灯获取类型 */ +/* 获取测试灯类型 */ HWTEST_F(HdfLightTest, GetLightList001, TestSize.Level1) { struct LightInfo *info = nullptr; diff --git a/zh-cn/device-dev/driver/driver-peripherals-pinauth-des.md b/zh-cn/device-dev/driver/driver-peripherals-pinauth-des.md index 56a50a7878..6f3b111bce 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-pinauth-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-pinauth-des.md @@ -6,7 +6,7 @@ 口令认证是端侧设备不可或缺的一部分,为设备提供一种用户认证能力,可应用于设备解锁、支付、应用登录等身份认证场景。用户注册口令后,口令认证模块就可为设备提供密码解锁的功能,保证设备的安全使用。口令识别的整体架构如图1。 -基于HDF(Hardware Driver Foundation)驱动框架开发的pin_auth驱动,pin_auth驱动模型屏蔽硬件差异,为上层用户IAM子系统基础框架和口令认证SA提供稳定的口令认证基础能力,包括口令认证执行器列表查询、执行器信息查询、指定模板防暴信息查询、用户认证和执行器间的模板信息对账,以及口令的录入、认证、删除。 +基于HDF(Hardware Driver Foundation)驱动框架开发的Pin_auth驱动,Pin_auth驱动模型屏蔽硬件差异,为上层用户IAM子系统基础框架和口令认证SA提供稳定的口令认证基础能力,包括口令认证执行器列表查询、执行器信息查询、指定模板防暴信息查询、用户认证和执行器间的模板信息对账,以及口令的录入、认证、删除。 **图1** 口令认证架构图 @@ -27,9 +27,9 @@ - ​ 全功能执行器:执行器可独立处理一次凭据注册和身份认证请求,即可提供用户认证数据采集、处理、储存及比对能力。 - - ​ 采集器:执行器提供用户认证时的数据采集能力,需要和认证期配合完成用户认证。 + - ​ 采集器:执行器提供用户认证时的数据采集能力,需要和认证器配合完成用户认证。 - - ​ 认证器:认证器提供用户认证是时数据处理,读取存储凭据模板信息并完成比对。 + - ​ 认证器:认证器提供用户认证时的数据处理能力,读取存储的凭据模板与当前认证信息完成对比。 - 执行器类型 @@ -37,16 +37,16 @@ - 用户认证框架公钥 & 执行器公钥 - 用户身份认证处理需要保证用户数据安全以及认证结果的准确性,用户认证框架于基础认证服务间的关键交互信息需要做数据完整性保护,各基础认证服务将提供的执行器能力对接到用户认证框架时,需要交互各自的公钥,其中: + 用户身份认证处理需要保证用户数据安全以及认证结果的准确性,用户认证框架与基础认证服务间的关键交互信息需要做数据完整性保护,各基础认证服务将提供的执行器能力对接到用户认证框架时,需要交换各自的公钥,其中: - - 执行器通过用户认证框架公钥校验调度指令的准确性,如锁定一个口令模板,这种情况导致无法使用口令认证功能,属于敏感操作,需要确保指令准确,才可处理。 + - 执行器通过用户认证框架公钥校验调度指令的准确性。 - 执行器公钥可被用户认证框架用于校验认证结果的准确性,同时用于执行器交互认证时的校验交互信息的完整性。 - 口令认证凭据模板 - 认证凭据是在用户设置认证凭据时由认证服务产生并存储,每个模板有一个ID。用于索引模板信息文件,再认证时读取模板信息并用于与当次认证过程中产生的认证数据做对比,完成身份认证。 + 认证凭据是在用户设置认证凭据时由认证服务产生并存储,每个模板有一个ID,用于索引模板信息文件,再认证时读取模板信息并用于与当次认证过程中产生的认证数据做对比,完成身份认证。 - 执行器对账 @@ -76,13 +76,13 @@ Pin_auth驱动的主要工作是为上层用户认证框架和Pin_auth服务提 | GetExecutorList(std::vector>& executorList) | 获取执行器列表。 | | GetExecutorInfo(ExecutorInfo& info) | 获取执行器信息。 | | GetTemplateInfo(uint64_t templateId, TemplateInfo& info) | 获取指定templateId的模板信息。 | -| OnRegisterFinish(const std::vector& templateIdList,
const std::vector& frameworkPublicKey,
const std::vector& extraInfo) | 执行器注册成功后,获取用户认证框架的公钥信息;获取用户认证框架的template 列表用于对账。 | +| OnRegisterFinish(const std::vector& templateIdList,
const std::vector& frameworkPublicKey,
const std::vector& extraInfo) | 执行器注册成功后,获取用户认证框架的公钥信息;获取用户认证框架的template 列表用于对账。 | | OnSetData(uint64_t scheduleId, uint64_t authSubType,
const std::vector &data) | 用于回调传pin码认证的子类型和脱敏数据。 | -| Enroll(uint64_t scheduleId, const std::vector& extraInfo,
const sptr& callbackObj) | pin码录入操作。 | -| Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector& extraInfo, const sptr& callbackObj) | pin码认证操作。 | +| Enroll(uint64_t scheduleId, const std::vector& extraInfo,
const sptr& callbackObj) | 录入pin码。 | +| Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector& extraInfo, const sptr& callbackObj) | pin码认证。 | | Delete(uint64_t templateId) | 删除pin码模板。 | | Cancel(uint64_t scheduleId) | 通过scheduleId取消指定操作。 | -| SendCommand(int32_t commandId, const std::vector& extraInfo,
const sptr& callbackObj) | pin码预留接口。 | +| SendCommand(int32_t commandId, const std::vector& extraInfo,
const sptr& callbackObj) | 预留接口。 | **表2** 回调函数介绍 @@ -262,7 +262,7 @@ Pin_auth驱动的主要工作是为上层用户认证框架和Pin_auth服务提 ScheduleMap scheduleMap_; }; - // 获取执行器列表实现,创建执行器 (仅作示例) + // 获取执行器列表实现,创建执行器(仅作示例) int32_t PinAuthInterfaceService::GetExecutorList(std::vector> &executorList) { IAM_LOGI("start"); @@ -340,7 +340,7 @@ Pin_auth驱动的主要工作是为上层用户认证框架和Pin_auth服务提 return HDF_SUCCESS; } - // 实现执行器注册成功后,获取用户认证框架的公钥信息、获取用户认证框架的template 列表接口,将公钥信息保持,template 列表用于和本地的template做对账 + // 实现执行器注册成功后,获取用户认证框架的公钥信息、获取用户认证框架的template 列表接口,将公钥信息保持,template列表用于和本地的template做对账 int32_t ExecutorImpl::OnRegisterFinish(const std::vector &templateIdList, const std::vector &frameworkPublicKey, const std::vector &extraInfo) { @@ -395,7 +395,7 @@ Pin_auth驱动的主要工作是为上层用户认证框架和Pin_auth服务提 return HDF_SUCCESS; } - //实现回调数据获取的接口 + // 实现回调数据获取的接口 int32_t ExecutorImpl::OnSetData(uint64_t scheduleId, uint64_t authSubType, const std::vector &data) { IAM_LOGI("start"); diff --git a/zh-cn/device-dev/driver/driver-peripherals-sensor-des.md b/zh-cn/device-dev/driver/driver-peripherals-sensor-des.md index 98b8370080..9ad956ac1d 100755 --- a/zh-cn/device-dev/driver/driver-peripherals-sensor-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-sensor-des.md @@ -5,7 +5,7 @@ ### 功能简介 -Sensor驱动模型屏蔽硬件器件差异,为上层Sensor服务系统提供稳定的Sensor基础能力接口,包括Sensor列表查询、Sensor启停、Sensor订阅及取消订阅,Sensor参数配置等功能;Sensor设备驱动的开发是基于HDF驱动框架基础上,结合操作系统适配层(OSAL)和平台驱动接口(比如I2C/SPI/UART总线等平台资源)能力,屏蔽不同操作系统和平台总线资源差异,实现Sensor驱动“一次开发,多系统部署”的目标。Sensor驱动模型如图1所示。 +Sensor驱动模型屏蔽硬件器件差异,为上层Sensor服务系统提供稳定的Sensor基础能力接口,包括Sensor列表查询、Sensor启停、Sensor订阅及取消订阅,Sensor参数配置等功能。Sensor设备驱动的开发是基于HDF驱动框架基础上,结合操作系统适配层(OSAL)和平台驱动接口(比如I2C/SPI/UART总线等平台资源)能力,屏蔽不同操作系统和平台总线资源差异,实现Sensor驱动“一次开发,多系统部署”的目标。Sensor驱动模型如图1所示。 **图 1** Sensor驱动模型图 @@ -29,13 +29,13 @@ Sensor驱动模型屏蔽硬件器件差异,为上层Sensor服务系统提供 Sensor驱动模型以标准系统Hi3516DV300产品中的加速度传感器驱动为例,介绍整个驱动加载及运行流程: -1. 从device info HCS 的Sensor Host读取Sensor设备管理配置信息。 +1. 从device_info.hcs配置文件的Sensor Host读取Sensor设备管理配置信息。 2. HDF配置框架从HCB数据库解析Sensor设备管理配置信息,并关联对应设备驱动。 3. 加载并初始化Sensor设备管理驱动。 4. Sensor设备管理驱动向HDI发布Sensor基础能力接口。 -5. 从device info HCS 的Sensor Host读取加速度传感器驱动配置信息。 +5. 从device_info.hcs配置文件的Sensor Host读取加速度传感器驱动配置信息。 6. 加载加速度传感器抽象驱动,调用初始化接口,完成Sensor器件驱动资源分配和数据处理队列创建。 -7. 从accel_xxx_config HCS读取加速度传感器差异化驱动配置和私有化配置信息。 +7. 从accel_xxx_config.hcs配置文件读取加速度传感器差异化驱动配置和私有化配置信息。 8. 加速度传感器差异化驱动,调用通用配置解析接口,完成器件属性信息解析,器件寄存器解析。 9. 加速度传感器差异化驱动完成器件探测,并分配加速度传感器配置资源,完成加速度传感器差异化接口注册。 10. 加速度传感器探测成功之后,加速度传感器差异化驱动通知加速度传感器抽象驱动,注册加速度传感器设备到Sensor设备管理中。 @@ -54,11 +54,11 @@ Sensor驱动模型以标准系统Hi3516DV300产品中的加速度传感器驱动 Sensor驱动模型对外开放的API接口能力如下: -- 提供Sensor HDI(Hardware Device Interface)能力接口,简化服务开发。 +- 提供Sensor HDI(Hardware Device Interface)能力接口,简化服务开发。 - 提供Sensor驱动模型能力接口: - 依赖HDF驱动框架实现Sensor器件驱动的注册,加载,去注册,器件探测等能力。 - 提供同一类型Sensor器件驱动归一接口, 寄存器配置解析操作接口,总线访问抽象接口,平台抽象接口。 -- 提供开发者实现的能力接口:依赖HDF驱动框架的HCS(HDF Configuration Source)配置管理,根据同类型Sensor差异化配置,实现Sensor器件参数序列化配置和器件部分操作接口,简化Sensor器件驱动开发。 +- 提供开发者实现的能力接口:依赖HDF驱动框架的HCS(HDF Configuration Source)配置管理,根据同类型Sensor差异化配置,实现Sensor器件参数序列化配置和器件部分操作接口,简化Sensor器件驱动开发。 Sensor驱动模型对外开放的API接口能力的具体实现请参考: @@ -122,14 +122,14 @@ Sensor驱动模型要求驱动开发者实现的接口功能,请参考: ```c /* 注册加速度计传感器入口数据结构体对象 */ struct HdfDriverEntry g_sensorAccelDevEntry = { - .moduleVersion = 1, //加速度计传感器模块版本号 - .moduleName = "HDF_SENSOR_ACCEL", //加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样 + .moduleVersion = 1, // 加速度计传感器模块版本号 + .moduleName = "HDF_SENSOR_ACCEL", // 加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样 .Bind = BindAccelDriver, // 加速度计传感器绑定函数 .Init = InitAccelDriver, // 加速度计传感器初始化函数 .Release = ReleaseAccelDriver, // 加速度计传感器资源释放函数 }; - /* 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 */ + /* 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 */ HDF_INIT(g_sensorAccelDevEntry); ``` @@ -523,8 +523,8 @@ Sensor驱动模型要求驱动开发者实现的接口功能,请参考: 驱动开发完成后,在传感器单元测试里面开发自测试用例,验证驱动基本功能。测试环境采用开发者自测试平台。 ``` -static int32_t g_sensorDataFlag = 0; //标识是否上报传感器数据 -static const struct SensorInterface *g_sensorDev = nullptr; //保持获取的传感器接口实例地址 +static int32_t g_sensorDataFlag = 0; // 标识是否上报传感器数据 +static const struct SensorInterface *g_sensorDev = nullptr; // 保持获取的传感器接口实例地址 /* 订阅者注册数据上报函数 */ static int SensorTestDataCallback(struct SensorEvents *event) diff --git a/zh-cn/device-dev/driver/driver-peripherals-touch-des.md b/zh-cn/device-dev/driver/driver-peripherals-touch-des.md index 4cf0a8cecf..70a83e91e6 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-touch-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-touch-des.md @@ -34,7 +34,7 @@ ## 接口说明 -Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类: +Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类: - 电源接口 @@ -93,7 +93,7 @@ Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区 配置对应的IO管脚功能,例如对单板上为Touchscreen设计预留的I2C Pin脚,需设置对应的寄存器,使其选择I2C的通信功能。 3. 实现器件差异化适配接口 - 根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](../driver/driver-platform-gpio-des.md#概述) + 根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](../driver/driver-platform-gpio-des.md#概述)。 ## 开发实例 @@ -114,7 +114,7 @@ input :: host { device0 :: deviceNode { policy = 2; // 向外发布服务 priority = 100; // 加载优先级,在input模块内,manager模块优先级应为最高 - preload = 0; // 加载该驱动 0:加载 1:不加载 + preload = 0; // 加载该驱动,0:加载;1:不加载 permission = 0660; moduleName = "HDF_INPUT_MANAGER"; serviceName = "input_dev_manager"; diff --git a/zh-cn/device-dev/driver/driver-peripherals-usb-des.md b/zh-cn/device-dev/driver/driver-peripherals-usb-des.md index 4aa4e22adc..cfe37f3408 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-usb-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-usb-des.md @@ -89,8 +89,8 @@ USB驱动模型Device侧开放的API接口功能,参考USB Device驱动模型 | 接口名称 | 功能描述 | | -------- | -------- | | const struct UsbFnDevice \*UsbFnCreateDevice(const
char \*udcName, const struct UsbFnDescriptorData
\*descriptor); | 创建Usb设备 | -| int UsbFnRemoveDevice(struct UsbFnDevice
\*fnDevice); | 删除Usb设备 | -| const struct UsbFnDevice \*UsbFnGetDevice(const char
\*udcName); | 获取Usb设备 | +| int UsbFnRemoveDevice(struct UsbFnDevice
\*fnDevice); | 删除USB设备 | +| const struct UsbFnDevice \*UsbFnGetDevice(const char
\*udcName); | 获取USB设备 | **表4** usbfn_interface.h @@ -182,37 +182,37 @@ root { "host_acm_table" ]; host_acm_table { - //驱动模块名,该字段的值必须和驱动入口结构的moduleName一致 + // 驱动模块名,该字段的值必须和驱动入口结构的moduleName一致 moduleName = "usbhost_acm"; - //驱动对外发布服务的名称,必须唯一 + // 驱动对外发布服务的名称,必须唯一 serviceName = "usbhost_acm_pnp_service"; - //驱动私有数据匹配关键字 + // 驱动私有数据匹配关键字 deviceMatchAttr = "usbhost_acm_pnp_matchAttr"; - //从该字段开始(包含该字段)之后数据长度,以byte为单位 + // 从该字段开始(包含该字段)之后数据长度,以byte为单位 length = 21; - //USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber + // USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber matchFlag = 0x0303; - //厂商编号 + // 厂商编号 vendorId = 0x12D1; - //产品编号 + // 产品编号 productId = 0x5000; - //设备出厂编号,低16位 + // 设备出厂编号,低16位 bcdDeviceLow = 0x0000; - //设备出厂编号,高16位 + // 设备出厂编号,高16位 bcdDeviceHigh = 0x0000; - //USB分配的设备类代码 + // USB分配的设备类代码 deviceClass = 0; - //USB分配的子类代码 + // USB分配的子类代码 deviceSubClass = 0; - //USB分配的设备协议代码 + // USB分配的设备协议代码 deviceProtocol = 0; - //接口类型,根据实际需要可填写多个 + // 接口类型,根据实际需要可填写多个 interfaceClass = [0]; - //接口子类型,根据实际需要可填写多个 + // 接口子类型,根据实际需要可填写多个 interfaceSubClass = [2, 0]; - //接口所遵循的协议,根据实际需要可填写多个 + // 接口所遵循的协议,根据实际需要可填写多个 interfaceProtocol = [1, 2]; - //接口的编号,根据实际需要可填写多个 + // 接口的编号,根据实际需要可填写多个 interfaceNumber = [2, 3]; } } @@ -291,7 +291,7 @@ static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm, { struct UsbInterface *tmpIf = NULL; tmpIf = (struct UsbInterface *)UsbClaimInterface(acm->session, acm->busNum, - acm->devAddr, interfaceIndex); //获取UsbInterface接口对象 + acm->devAddr, interfaceIndex); // 获取UsbInterface接口对象 return tmpIf; } ... @@ -315,7 +315,7 @@ static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm, for (i = 0; i <= info->pipeNum; i++) { struct UsbPipeInfo p; - ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);//获取指定索引为i的pipeInfo信息 + ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);// 获取指定索引为i的pipeInfo信息 if (ret < 0) { continue; } @@ -413,7 +413,7 @@ static int AcmAllocReadRequests(struct AcmDevice *acm) int ret; struct UsbRequestParams readParams; for (int i = 0; i < ACM_NR; i++) { - acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize); //分配待发送的readReq IO Request对象 + acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize); // 分配待发送的readReq IO Request对象 if (!acm->readReq[i]) { HDF_LOGE("readReq request failed"); goto error; @@ -428,7 +428,7 @@ static int AcmAllocReadRequests(struct AcmDevice *acm) readParams.dataReq.numIsoPackets = 0; readParams.dataReq.direction = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1; readParams.dataReq.length = acm->readSize; - ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParams); //填充待发送的readReq对象 + ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParams); // 填充待发送的readReq对象 if (HDF_SUCCESS != ret) { HDF_LOGE("%s: UsbFillRequest failed, ret=%d n", __func__, ret); goto error; @@ -445,7 +445,7 @@ static int AcmAllocNotifyRequest(struct AcmDevice *acm) { int ret; struct UsbRequestParams intParams = {}; - acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize); //分配待发送的中断IO Request对象 + acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize); // 分配待发送的中断IO Request对象 if (!acm->notifyReq) { HDF_LOGE("notifyReq request failed"); return HDF_ERR_MALLOC_FAIL; @@ -460,7 +460,7 @@ static int AcmAllocNotifyRequest(struct AcmDevice *acm) intParams.dataReq.numIsoPackets = 0; intParams.dataReq.direction = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK; intParams.dataReq.length = acm->intSize; - ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParams); //填充预先分配的中断IO Request + ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParams); // 填充预先分配的中断IO Request if (HDF_SUCCESS != ret) { HDF_LOGE("%s: UsbFillRequest failed, ret=%d n", __func__, ret); goto error; @@ -489,14 +489,14 @@ static void AcmReleaseInterfaces(struct AcmDevice *acm) static int32_t AcmClaimInterfaces(struct AcmDevice *acm) { for (int i = 0; i < acm->interfaceCnt; i++) { - acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]); //获取UsbInterface接口对象 + acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]); // 获取UsbInterface接口对象 if (acm->iface[i] == NULL) { HDF_LOGE("%s: interface%d is null", __func__, acm->interfaceIndex[i]); goto error; } } - acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID); //获取控制接口对应的UsbInterface接口对象 + acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID); // 获取控制接口对应的UsbInterface接口对象 if (acm->ctrIface == NULL) { HDF_LOGE("%s: GetUsbInterfaceById null", __func__); goto error; @@ -527,7 +527,7 @@ static int32_t AcmOpenInterfaces(struct AcmDevice *acm) { for (int i = 0; i < acm->interfaceCnt; i++) { if (acm->iface[i]) { - acm->devHandle[i] = UsbOpenInterface(acm->iface[i]); //打开获取到的UsbInterface接口对象 + acm->devHandle[i] = UsbOpenInterface(acm->iface[i]); // 打开获取到的UsbInterface接口对象 if (acm->devHandle[i] == NULL) { HDF_LOGE("%s: UsbOpenInterface null", __func__); goto error; @@ -549,25 +549,25 @@ error: static int32_t AcmGetPipes(struct AcmDevice *acm) { - acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);//获取dataInPipe的pipeInfo信息 + acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);// 获取dataInPipe的pipeInfo信息 if (acm->dataInPipe == NULL) { HDF_LOGE("dataInPipe is NULL"); goto error; } - acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT);//获取dataOutPipe的pipeInfo信息 + acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT);// 获取dataOutPipe的pipeInfo信息 if (acm->dataOutPipe == NULL) { HDF_LOGE("dataOutPipe is NULL"); goto error; } - acm->ctrPipe = EnumePipe(acm, acm->ctrIface->info.interfaceIndex, USB_PIPE_TYPE_CONTROL, USB_PIPE_DIRECTION_OUT); //获取控制pipe的pipeInfo信息 + acm->ctrPipe = EnumePipe(acm, acm->ctrIface->info.interfaceIndex, USB_PIPE_TYPE_CONTROL, USB_PIPE_DIRECTION_OUT); // 获取控制pipe的pipeInfo信息 if (acm->ctrPipe == NULL) { HDF_LOGE("ctrPipe is NULL"); goto error; } - acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN);//获取中断pipe的pipeInfo信息 + acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN);// 获取中断pipe的pipeInfo信息 if (acm->intPipe == NULL) { HDF_LOGE("intPipe is NULL"); goto error; @@ -616,13 +616,13 @@ static int32_t AcmAllocRequests(struct AcmDevice *acm) } } - ret = AcmAllocNotifyRequest(acm); //分配并填充中断IO Request对象 + ret = AcmAllocNotifyRequest(acm); // 分配并填充中断IO Request对象 if (ret != HDF_SUCCESS) { HDF_LOGE("%s:%d AcmAllocNotifyRequest failed", __func__, __LINE__); goto error_alloc_int_req; } - ret = AcmAllocReadRequests(acm); //分配并填充readReq IO Request对象 + ret = AcmAllocReadRequests(acm); // 分配并填充readReq IO Request对象 if (ret) { HDF_LOGE("%s:%d AcmAllocReadRequests failed", __func__, __LINE__); goto error_alloc_read_req; @@ -649,7 +649,7 @@ static int32_t AcmInit(struct AcmDevice *acm) return HDF_SUCCESS; } - ret = UsbInitHostSdk(NULL); //初始化Host DDK + ret = UsbInitHostSdk(NULL); // 初始化Host DDK if (ret != HDF_SUCCESS) { HDF_LOGE("%s: UsbInitHostSdk failed", __func__); return HDF_ERR_IO; @@ -777,7 +777,7 @@ static void UsbSerialDriverRelease(struct HdfDeviceObject *device) struct HdfDriverEntry g_usbSerialDriverEntry = { .moduleVersion = 1, - .moduleName = "usbhost_acm", //驱动模块名称,必须与hcs文件中配置的名称一致 + .moduleName = "usbhost_acm", // 驱动模块名称,必须与hcs文件中配置的名称一致 .Bind = UsbSerialDriverBind, .Init = UsbSerialDriverInit, .Release = UsbSerialDriverRelease, @@ -799,38 +799,38 @@ root { idTableList = [ "host_acm_rawapi_table" ]; - host_acm_rawapi_table { //驱动配置匹配表信息 - //驱动模块名,该字段的值必须和驱动入口结构的moduleName一致 + host_acm_rawapi_table { // 驱动配置匹配表信息 + // 驱动模块名,该字段的值必须和驱动入口结构的moduleName一致 moduleName = "usbhost_acm_rawapi"; - //驱动对外发布服务的名称,必须唯一 + // 驱动对外发布服务的名称,必须唯一 serviceName = "usbhost_acm_rawapi_service"; - //驱动私有数据匹配关键字 + // 驱动私有数据匹配关键字 deviceMatchAttr = "usbhost_acm_rawapi_matchAttr"; - //从该字段开始(包含该字段)之后数据长度,以byte为单位 + // 从该字段开始(包含该字段)之后数据长度,以byte为单位 length = 21; - //USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber + // USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber matchFlag = 0x0303; - //厂商编号 + // 厂商编号 vendorId = 0x12D1; - //产品编号 + // 产品编号 productId = 0x5000; - //设备出厂编号,低16位 + // 设备出厂编号,低16位 bcdDeviceLow = 0x0000; - //设备出厂编号,高16位 + // 设备出厂编号,高16位 bcdDeviceHigh = 0x0000; - //USB分配的设备类代码 + // USB分配的设备类代码 deviceClass = 0; - //USB分配的子类代码 + // USB分配的子类代码 deviceSubClass = 0; - //USB分配的设备协议代码 + // USB分配的设备协议代码 deviceProtocol = 0; - //接口类型,根据实际需要可填写多个 + // 接口类型,根据实际需要可填写多个 interfaceClass = [0]; - //接口子类型,根据实际需要可填写多个 + // 接口子类型,根据实际需要可填写多个 interfaceSubClass = [2, 0]; - //接口所遵循的协议,根据实际需要可填写多个 + // 接口所遵循的协议,根据实际需要可填写多个 interfaceProtocol = [1, 2]; - //接口的编号,根据实际需要可填写多个 + // 接口的编号,根据实际需要可填写多个 interfaceNumber = [2, 3]; } } @@ -1224,7 +1224,7 @@ HDF_INIT(g_usbSerialRawDriverEntry); ### Device DDK API驱动开发 -USB ACM设备核心代码路径为drivers\peripheral\usb\gadget\function\acm\cdcacm.c,其使用示例如下所示,首先根据描述符创建设备,然后获取接口,打开接口,获取Pipe信息,接收Event事件,接着进行USB通信(读写等),设备卸载时候,关闭接口,停止Event接收,删除设备。 +USB ACM设备核心代码路径为drivers\peripheral\usb\gadget\function\acm\cdcacm.c。其使用示例如下所示,首先根据描述符创建设备,然后获取接口,打开接口,获取Pipe信息,接收Event事件,接着进行USB通信(读写等),设备卸载时候,关闭接口,停止Event接收,删除设备。 ``` diff --git a/zh-cn/device-dev/driver/driver-peripherals-vibrator-des.md b/zh-cn/device-dev/driver/driver-peripherals-vibrator-des.md index abd127096a..33daa6cfc1 100755 --- a/zh-cn/device-dev/driver/driver-peripherals-vibrator-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-vibrator-des.md @@ -5,7 +5,7 @@ ### 功能简介 -为了快速开发传感器驱动,基于HDF(Hardware Driver Foundation)驱动框架开发了马达驱动模型。马达驱动模型,屏蔽设备驱动与系统交互的实现,为硬件服务层提供统一稳定的驱动接口能力,为驱动开发者提供开放的接口和解析接口的能力。用于不同操作系统马达设备部件的部署指导和马达设备部件驱动的开发。马达驱动模型如图1所示: +为了快速开发传感器驱动,基于HDF(Hardware Driver Foundation)驱动框架开发了马达(Vibrator)驱动模型。马达驱动模型,屏蔽设备驱动与系统交互的实现,为硬件服务层提供统一稳定的驱动接口能力,为驱动开发者提供开放的接口和解析接口的能力。用于不同操作系统马达设备部件的部署指导和马达设备部件驱动的开发。马达驱动模型如图1所示: **图 1** 马达驱动模型图 @@ -21,7 +21,7 @@ - 周期振动 - 周期振动是指按照预置的效果模式控制振动。例如: 预置效果为“haptic.clock.timer” = [600, 600, 200, 600],等待600ms,振动600ms,等待200ms,振动600ms。 + 周期振动是指按照预置的效果模式控制振动。例如:预置效果为“haptic.clock.timer” = [600, 600, 200, 600],等待600ms,振动600ms,等待200ms,振动600ms。 ### 运作机制 @@ -33,9 +33,9 @@ 马达驱动模型以标准系统Hi3516DV300产品为例,介绍整个驱动加载及运行流程: -1. 从device info HCS 的Vibrator Host读取Vibrator管理配置信息。 +1. 从device_info.hcs配置文件中的Vibrator Host读取Vibrator管理配置信息。 2. 解析Vibrator管理配置信息,并关联对应马达抽象驱动。 -3. 从linear_vibrator_config HCS读取Vibrator数据配置信息。 +3. 从linear_vibrator_config.hcs配置文件中读取Vibrator数据配置信息。 4. 解析Vibrator数据配置信息,并关联对应Haptic驱动。 5. 客户端下发Vibrator Stub控制到服务端。 6. Vibrator Stub控制调用马达服务。 @@ -48,7 +48,7 @@ ### 场景介绍 -当设备需要设置不同的振动效果时,可以调用 Vibrator 模块,例如,设备的按键可以设置不同强度和时长的振动,闹钟和来电可以设置不同强度和时长的单次或周期性振动。 +当设备需要设置不同的振动效果时,可以调用Vibrator模块,例如,设备的按键可以设置不同强度和时长的振动,闹钟和来电可以设置不同强度和时长的单次或周期性振动。 ### 接口说明 @@ -64,7 +64,7 @@ ### 开发步骤 -Vibrator驱动模型为上层马达硬件服务层提供稳定的马达控制能力接口,包括马达一次振动、马达效果配置震动、马达停止。基于HDF(Hardware Driver Foundation)驱动框架开发的马达驱动模型,实现跨操作系统迁移、器件差异配置等功能。马达具体的开发步骤如下: +Vibrator驱动模型为上层马达硬件服务层提供稳定的马达控制能力接口,包括马达一次振动、马达效果配置震动、马达停止。基于HDF驱动框架开发的马达驱动模型,实现跨操作系统迁移、器件差异配置等功能。马达具体的开发步骤如下: 1. 基于HDF驱动框架,按照驱动Driver Entry程序,完成马达抽象驱动开发,主要由Bind、Init、Release、Dispatch函数接口实现,配置资源和HCS解析。 @@ -73,11 +73,11 @@ Vibrator驱动模型为上层马达硬件服务层提供稳定的马达控制能 ```c /* 注册马达抽象驱动入口数据结构体对象 */ struct HdfDriverEntry g_vibratorDriverEntry = { - .moduleVersion = 1, //马达模块版本号 - .moduleName = "HDF_VIBRATOR", //马达模块名,要与device_info.hcs文件里的马达moduleName字段值一样 - .Bind = BindVibratorDriver, //马达绑定函数 - .Init = InitVibratorDriver, //马达初始化函数 - .Release = ReleaseVibratorDriver, //马达资源释放函数 + .moduleVersion = 1, // 马达模块版本号 + .moduleName = "HDF_VIBRATOR", // 马达模块名,要与device_info.hcs文件里的马达moduleName字段值一样 + .Bind = BindVibratorDriver, // 马达绑定函数 + .Init = InitVibratorDriver, // 马达初始化函数 + .Release = ReleaseVibratorDriver, // 马达资源释放函数 }; HDF_INIT(g_vibratorDriverEntry); @@ -154,13 +154,13 @@ Vibrator驱动模型为上层马达硬件服务层提供稳定的马达控制能 hostName = "vibrator_host"; device_vibrator :: device { device0 :: deviceNode { - policy = 2; //驱动服务发布的策略 - priority = 100; //驱动启动优先级(0-200),值越大优先级越低,建议配置100,优先级相同则不保证device的加载顺序 - preload = 0; //驱动按需加载字段,0表示加载,2表示不加载 - permission = 0664; //驱动创建设备节点权限 - moduleName = "HDF_VIBRATOR"; //驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 - serviceName = "hdf_misc_vibrator"; //驱动对外发布服务的名称,必须唯一 - deviceMatchAttr = "hdf_vibrator_driver"; //驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 + policy = 2; // 驱动服务发布的策略 + priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议配置100,优先级相同则不保证device的加载顺序 + preload = 0; // 驱动按需加载字段,0表示加载,2表示不加载 + permission = 0664; // 驱动创建设备节点权限 + moduleName = "HDF_VIBRATOR"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 + serviceName = "hdf_misc_vibrator"; // 驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "hdf_vibrator_driver"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 } } ``` @@ -201,23 +201,23 @@ Vibrator驱动模型为上层马达硬件服务层提供稳定的马达控制能 } ``` - - 马达效果模型使用HCS作为配置描述源码,HCS配置字段详细介绍参考[配置管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/driver-hdf-manage.md)。 + - 马达效果模型使用HCS作为配置描述源码,hcs配置文件字段详细介绍参考[配置管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/driver-hdf-manage.md)。 ``` /* 马达数据配置模板(vibrator_config.hcs) */ root { vibratorConfig { boardConfig { - match_attr = "hdf_vibrator_driver"; //需要和马达设备配置match_attr字段保持一致 + match_attr = "hdf_vibrator_driver"; // 需要和马达设备配置match_attr字段保持一致 vibratorAttr { - /* 0:转子 1:线性 */ - deviceType = 1; //设备类型 - supportPreset = 1; //支持的预设类型 + /* 0:转子;1:线性 */ + deviceType = 1; // 设备类型 + supportPreset = 1; // 支持的预设类型 } vibratorHapticConfig { haptic_clock_timer { effectName = "haptic.clock.timer"; - type = 1; // 0 内置模式, 1 时间序列 + type = 1; // 0:内置模式;1:时间序列 seq = [600, 600, 200, 600]; // 时间序列 } haptic_default_effect { diff --git a/zh-cn/device-dev/driver/driver-peripherals.md b/zh-cn/device-dev/driver/driver-peripherals.md index c7c28e00ed..8782cdd943 100644 --- a/zh-cn/device-dev/driver/driver-peripherals.md +++ b/zh-cn/device-dev/driver/driver-peripherals.md @@ -1,13 +1,24 @@ # 外设驱动使用 +- **[Audio](driver-peripherals-audio-des.md)** + +- **[Camera](driver-peripherals-camera-des.md)** + +- **[WLAN](driver-peripherals-external-des.md)** + +- **[Face_auth](driver-peripherals-face_auth-des.md)** - **[LCD](driver-peripherals-lcd-des.md)** -- **[Touchscreen](driver-peripherals-touch-des.md)** +- **[Light](driver-peripherals-light-des.md)** -- **[SENSOR](driver-peripherals-sensor-des.md)** +- **[Pin_auth](driver-peripherals-pinauth-des.md)** -- **[WLAN](driver-peripherals-external-des.md)** +- **[Sensor](driver-peripherals-sensor-des.md)** + +- **[Touchscreen](driver-peripherals-touch-des.md)** + +- **[USB](driver-peripherals-usb-des.md)** -- **[USB](driver-peripherals-usb-des.md)** \ No newline at end of file +- **[Vibrator](driver-peripherals-vibrator-des.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-adc-des.md b/zh-cn/device-dev/driver/driver-platform-adc-des.md index ccd7fdcd5a..bb5975ce1b 100755 --- a/zh-cn/device-dev/driver/driver-platform-adc-des.md +++ b/zh-cn/device-dev/driver/driver-platform-adc-des.md @@ -1,25 +1,14 @@ # ADC -- [概述](#section1) - - [功能简介](#section2) - - [基本概念](#section3) - - [运作机制](#section4) - - [约束与限制](#section5) -- [使用指导](#section6) - - [场景介绍](#section7) - - [接口说明](#section8) - - [开发步骤](#section9) - - [使用实例](#section10) - ## 概述 ### 功能简介 -- ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备。 +ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备。 -- ADC接口定义了完成ADC传输的通用方法集合,包括: - - ADC设备管理:打开或关闭ADC设备。 - - ADC读取转换结果:读取AD转换结果。 +ADC接口定义了完成ADC传输的通用方法集合,包括: +- ADC设备管理:打开或关闭ADC设备。 +- ADC读取转换结果:读取AD转换结果。 ### 基本概念 diff --git a/zh-cn/device-dev/driver/driver-platform-adc-develop.md b/zh-cn/device-dev/driver/driver-platform-adc-develop.md index 39f71ec672..0e4c0363d1 100755 --- a/zh-cn/device-dev/driver/driver-platform-adc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-adc-develop.md @@ -3,7 +3,7 @@ ## 概述 -ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备,在HDF框架中,ADC模块接口适配模式采用统一服务模式,这需要一个设备服务来作为ADC模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如ADC可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 +ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备。在HDF框架中,ADC模块接口适配模式采用统一服务模式,这需要一个设备服务来作为ADC模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如ADC可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 **图1** ADC统一服务 @@ -27,36 +27,36 @@ struct AdcMethod { | 函数成员 | 入参 | 出参 | 返回值 | 功能 | | -------- | -------- | -------- | -------- | -------- | -| read | device: 结构体指针,核心层ADC控制器;
channel:uint32_t,传入的通道号; | val:uint32_t指针,要传出的信号数据; | HDF_STATUS相关状态 | 读取ADC采样的信号数据 | -| stop | device: 结构体指针,核心层ADC控制器; | 无 | HDF_STATUS相关状态 | 关闭ADC设备 | -| start | device: 结构体指针,核心层ADC控制器; | 无 | HDF_STATUS相关状态 | 开启ADC设备 | +| read | device:结构体指针,核心层ADC控制器
channel:uint32_t,传入的通道号 | val:uint32_t指针,要传出的信号数据 | HDF_STATUS相关状态 | 读取ADC采样的信号数据 | +| stop | device:结构体指针,核心层ADC控制器 | 无 | HDF_STATUS相关状态 | 关闭ADC设备 | +| start | device:结构体指针,核心层ADC控制器 | 无 | HDF_STATUS相关状态 | 开启ADC设备 | ## 开发步骤 ADC模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 -1. **实例化驱动入口:** +1. 实例化驱动入口: - 实例化HdfDriverEntry结构体成员。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 -2. **配置属性文件:** +2. 配置属性文件: - 在device_info.hcs文件中添加deviceNode描述。 - 【可选】添加adc_config.hcs器件属性文件。 -3. **实例化ADC控制器对象:** +3. 实例化ADC控制器对象: - 初始化AdcDevice成员。 - 实例化AdcDevice成员AdcMethod。 - > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 实例化AdcDevice成员AdcMethod,其定义和成员说明见[接口说明](#接口说明)。 -4. **驱动调试:** +4. 驱动调试: 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,信号采集的成功与否等。 ## 开发实例 - 接下来以 adc_hi35xx.c 为示例, 展示需要厂商提供哪些内容来完整实现设备功能。 + 接下来以adc_hi35xx.c为示例, 展示需要厂商提供哪些内容来完整实现设备功能。 1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 @@ -74,30 +74,30 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, .Release = Hi35xxAdcRelease, .moduleName = "hi35xx_adc_driver",//【必要且与HCS文件里面的名字匹配】 }; - HDF_INIT(g_hi35xxAdcDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_hi35xxAdcDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 - //核心层adc_core.c管理器服务的驱动入口 + // 核心层adc_core.c管理器服务的驱动入口 struct HdfDriverEntry g_adcManagerEntry = { .moduleVersion = 1, .Init = AdcManagerInit, .Release = AdcManagerRelease, - .moduleName = "HDF_PLATFORM_ADC_MANAGER",//这与device_info文件中device0对应 + .moduleName = "HDF_PLATFORM_ADC_MANAGER",// 这与device_info文件中device0对应 }; HDF_INIT(g_adcManagerEntry); ``` 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在adc_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层AdcDevice相关成员的默认值或限制范围有密切关系。 统一服务模式的特点是device_info文件中第一个设备节点必须为ADC管理器,其各项参数必须如下设置: - | 成员名 | 值 | + | 成员名 | 值 | | -------- | -------- | - | moduleName | 固定为 HDF_PLATFORM_ADC_MANAGER | + | moduleName | 固定为HDF_PLATFORM_ADC_MANAGER | | serviceName | 无 | | policy | 具体配置为0,不发布服务 | | deviceMatchAttr | 没有使用,可忽略 | 从第二个节点开始配置具体ADC控制器信息,此节点并不表示某一路ADC控制器,而是代表一个资源性质设备,用于描述一类ADC控制器的信息。本例只有一个ADC设备,如有多个设备,则需要在device_info文件增加deviceNode信息,以及在adc_config文件中增加对应的器件属性。 - - device_info.hcs 配置参考。 + - device_info.hcs配置参考 ``` @@ -125,7 +125,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, } } ``` - - adc_config.hcs 配置参考。 + - adc_config.hcs配置参考 ``` @@ -134,13 +134,13 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, adc_config_hi35xx { match_attr = "hisilicon_hi35xx_adc"; template adc_device { - regBasePhy = 0x120e0000;//寄存器物理基地址 - regSize = 0x34; //寄存器位宽 - deviceNum = 0; //设备号 - validChannel = 0x1; //有效通道 - dataWidth = 10; //信号接收的数据位宽 - scanMode = 1; //扫描模式 - delta = 0; //delta参数 + regBasePhy = 0x120e0000;// 寄存器物理基地址 + regSize = 0x34; // 寄存器位宽 + deviceNum = 0; // 设备号 + validChannel = 0x1; // 有效通道 + dataWidth = 10; // 信号接收的数据位宽 + scanMode = 1; // 扫描模式 + delta = 0; // delta参数 deglitch = 0; glitchSample = 5000; rate = 20000; @@ -177,7 +177,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, uint32_t rate; //【必要】采样率 }; - //AdcDevice是核心层控制器结构体,其中的成员在Init函数中会被赋值 + // AdcDevice是核心层控制器结构体,其中的成员在Init函数中会被赋值 struct AdcDevice { const struct AdcMethod *ops; OsalSpinlock spin; @@ -202,18 +202,18 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, 入参: - HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: - HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。 + HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS定义)。 | 状态(值) | 问题描述 | | -------- | -------- | | HDF_ERR_INVALID_OBJECT | 控制器对象非法 | | HDF_ERR_INVALID_PARAM | 参数非法 | | HDF_ERR_MALLOC_FAIL | 内存分配失败 | - | HDF_ERR_IO | I/O 错误 | + | HDF_ERR_IO | I/O错误 | | HDF_SUCCESS | 传输成功 | | HDF_FAILURE | 传输失败 | @@ -227,9 +227,9 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, int32_t ret; struct DeviceResourceNode *childNode = NULL; ... - //遍历、解析adc_config.hcs中的所有配置节点,并分别调用Hi35xxAdcParseInit函数来初始化device + // 遍历、解析adc_config.hcs中的所有配置节点,并分别调用Hi35xxAdcParseInit函数来初始化device DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - ret = Hi35xxAdcParseInit(device, childNode);//函数定义见下 + ret = Hi35xxAdcParseInit(device, childNode);// 函数定义见下 ... } return ret; @@ -258,7 +258,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, return HDF_SUCCESS; __ERR__: - if (hi35xx != NULL) { //不成功的话,需要反向执行初始化相关函数 + if (hi35xx != NULL) { // 不成功的话,需要反向执行初始化相关函数 if (hi35xx->regBase != NULL) { OsalIoUnmap((void *)hi35xx->regBase); hi35xx->regBase = NULL; @@ -269,11 +269,11 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, return ret; } ``` - - Release 函数参考 + - Release函数参考 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: @@ -281,7 +281,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, 函数说明: - 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 ``` @@ -289,9 +289,9 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, { const struct DeviceResourceNode *childNode = NULL; ... - //遍历、解析adc_config.hcs中的所有配置节点,并分别进行release操作 + // 遍历、解析adc_config.hcs中的所有配置节点,并分别进行release操作 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - Hi35xxAdcRemoveByNode(childNode);//函数定义见下 + Hi35xxAdcRemoveByNode(childNode);// 函数定义见下 } } @@ -307,7 +307,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, ... ret = drsOps->GetUint32(node, "deviceNum", (uint32_t *)&deviceNum, 0); ... - //可以调用AdcDeviceGet函数通过设备的deviceNum获取AdcDevice对象, 以及调用AdcDeviceRemove函数来释放AdcDevice对象的内容 + // 可以调用AdcDeviceGet函数通过设备的deviceNum获取AdcDevice对象,以及调用AdcDeviceRemove函数来释放AdcDevice对象的内容 device = AdcDeviceGet(deviceNum); if (device != NULL && device->priv == node) { AdcDevicePut(device); diff --git a/zh-cn/device-dev/driver/driver-platform-dac-des.md b/zh-cn/device-dev/driver/driver-platform-dac-des.md index ff4940c997..840e95dc41 100644 --- a/zh-cn/device-dev/driver/driver-platform-dac-des.md +++ b/zh-cn/device-dev/driver/driver-platform-dac-des.md @@ -5,11 +5,11 @@ ### 功能简介 -- DAC(Digital to Analog Converter)是一种通过电流、电压或电荷的形式将数字信号转换为模拟信号的设备 。 +DAC(Digital to Analog Converter)是一种通过电流、电压或电荷的形式将数字信号转换为模拟信号的设备。 -- DAC接口定义了完成DAC传输的通用方法集合,包括: - - DAC设备管理:打开或关闭DAC设备。 - - DAC设置目标值:设置DAC设备需要将数字信号转成模拟信号的目标值。 +DAC接口定义了完成DAC传输的通用方法集合,包括: +- DAC设备管理:打开或关闭DAC设备。 +- DAC设置目标值:设置DAC设备需要将数字信号转成模拟信号的目标值。 ### 基本概念 @@ -31,7 +31,7 @@ DAC模块支持数模转换的开发,它主要用于: 转换速度一般由建立时间决定。从输入由全0突变为全1时开始,到输出电压稳定在FSR±½LSB范围(或以FSR±x%FSR指明范围)内为止,这段时间称为建立时间,它是DAC的最大响应时间,所以用它衡量转换速度的快慢。 - 满量程范围FSR(Full Scale Range),是指DAC输出信号幅度的最大范围,不同的DAC有不同的满量程范围, 该范围可以用正、负电流或者正、负电压来限制 。 + 满量程范围FSR(Full Scale Range),是指DAC输出信号幅度的最大范围,不同的DAC有不同的满量程范围,该范围可以用正、负电流或者正、负电压来限制。 最低有效位LSB(Least Significant Byte),指的是一个二进制数字中的第0位(即最低位)。 @@ -41,7 +41,7 @@ DAC模块支持数模转换的开发,它主要用于: DAC模块各分层的作用为:接口层提供打开设备,写入数据,关闭设备的接口。核心层主要提供绑定设备、初始化设备以及释放设备的能力。适配层实现其他具体的功能。 -![](../public_sys-resources/icon-note.gif) 说明:核心层可以调用接口层的函数,核心层通过钩子函数调用适配层函数,从而适配层间接的可以调用接口层函数,但是不可逆转接口层调用适配层函数。 +![](../public_sys-resources/icon-note.gif) 说明:
核心层可以调用接口层的函数,核心层通过钩子函数调用适配层函数,从而适配层间接的可以调用接口层函数,但是不可逆转接口层调用适配层函数。 **图 1** DAC统一服务模式 @@ -49,7 +49,7 @@ DAC模块各分层的作用为:接口层提供打开设备,写入数据, ### 约束与限制 - DAC模块当前仅支持轻量和小型系统内核(LiteOS) 。 + DAC模块当前仅支持轻量和小型系统内核(LiteOS)。 ## 使用指导 @@ -181,7 +181,7 @@ DAC设备的具体使用方式可以参考如下示例代码,示例代码步 /* DAC例程总入口 */ static int32_t TestCaseDac(void) { - //设置要写入的val值 + // 设置要写入的val值 uint32_t val = 2; int32_t ret; DevHandle dacHandle; diff --git a/zh-cn/device-dev/driver/driver-platform-dac-develop.md b/zh-cn/device-dev/driver/driver-platform-dac-develop.md index f60d2b54ac..11a9961805 100644 --- a/zh-cn/device-dev/driver/driver-platform-dac-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-dac-develop.md @@ -4,15 +4,15 @@ ### 功能简介 -DAC(Digital to Analog Converter)是一种通过电流、电压或电荷的形式将数字信号转换为模拟信号的设备 。 - -### 基本概念 +DAC(Digital to Analog Converter)是一种通过电流、电压或电荷的形式将数字信号转换为模拟信号的设备。 DAC模块支持数模转换的开发。它主要用于: 1. 作为过程控制计算机系统的输出通道,与执行器相连,实现对生产过程的自动控制。 2. 在利用反馈技术的魔术转换器设计中,作为重要的功能模块呈现。 +### 基本概念 + - 分辨率 分辨率指的是D/A转换器能够转换的二进制位数,位数越多分辨率越高。 @@ -35,7 +35,7 @@ DAC模块支持数模转换的开发。它主要用于: DAC模块各分层的作用为:接口层提供打开设备,写入数据,关闭设备接口的能力。核心层主要提供绑定设备、初始化设备以及释放设备的能力。适配层实现其他具体的功能。 -![](../public_sys-resources/icon-note.gif) 说明:核心层可以调用接口层的函数,也可以通过钩子函数调用适配层函数,从而使得适配层间接的可以调用接口层函数,但是不可逆转接口层调用适配层函数。 +![](../public_sys-resources/icon-note.gif) 说明:
核心层可以调用接口层的函数,也可以通过钩子函数调用适配层函数,从而使得适配层间接的可以调用接口层函数,但是不可逆转接口层调用适配层函数。 **图 1** 统一服务模式 @@ -62,11 +62,11 @@ DacMethod定义: ``` struct DacMethod { - //写入数据的钩子函数 + // 写入数据的钩子函数 int32_t (*write)(struct DacDevice *device, uint32_t channel, uint32_t val); - //启动DAC设备的钩子函数 + // 启动DAC设备的钩子函数 int32_t (*start)(struct DacDevice *device); - //停止DAC设备的钩子函数 + // 停止DAC设备的钩子函数 int32_t (*stop)(struct DacDevice *device); }; ``` @@ -77,9 +77,9 @@ struct DacMethod { | 函数成员 | 入参 | 出参 | 返回值 | 功能 | | -------- | ------------------------------------------------------------ | ---- | ------------------ | -------------- | -| write | device:结构体指针,核心层DAC控制器;
channel:uint32_t,传入的通道号;
val:uint32_t,要传入的数据; | 无 | HDF_STATUS相关状态 | 写入DA的目标值 | -| start | device:结构体指针,核心层DAC控制器; | 无 | HDF_STATUS相关状态 | 开启DAC设备 | -| stop | device:结构体指针,核心层DAC控制器; | 无 | HDF_STATUS相关状态 | 关闭DAC设备 | +| write | device:结构体指针,核心层DAC控制器
channel:uint32_t,传入的通道号
val:uint32_t,要传入的数据 | 无 | HDF_STATUS相关状态 | 写入DA的目标值 | +| start | device:结构体指针,核心层DAC控制器 | 无 | HDF_STATUS相关状态 | 开启DAC设备 | +| stop | device:结构体指针,核心层DAC控制器 | 无 | HDF_STATUS相关状态 | 关闭DAC设备 | @@ -92,7 +92,7 @@ DAC模块适配包含以下四个步骤: - 实例化核心层接口函数。 - 驱动调试。 -1. **实例化驱动入口:** +1. 实例化驱动入口: 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。 HDF框架会汇总所有加载的驱动的HdfDriverEntry对象入口 ,形成一个类似数组的段地址空间,方便上层调用。 @@ -105,10 +105,10 @@ DAC模块适配包含以下四个步骤: .Release = VirtualDacRelease, .moduleName = "virtual_dac_driver", //【必要且与 HCS 里面的名字匹配】 }; - HDF_INIT(g_dacDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_dacDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 ``` -2. **配置属性文件:** +2. 配置属性文件: - 在vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件中添加deviceNode描述。 @@ -119,7 +119,7 @@ DAC模块适配包含以下四个步骤: | 成员名 | 值 | | --------------- | ------------------------------------------------------------ | | policy | 具体配置为0,不发布服务| - | priority | 驱动启动优先级(0-200),值越大优先级越低,,优先级相同则不保证device的加载顺序。| + | priority | 驱动启动优先级(0-200),值越大优先级越低,优先级相同则不保证device的加载顺序。| | permission | 驱动权限| | moduleName | 固定为HDF_PLATFORM_DAC_MANAGER| | serviceName | 固定为HDF_PLATFORM_DAC_MANAGER| @@ -127,12 +127,12 @@ DAC模块适配包含以下四个步骤: 从第二个节点开始配置具体DAC控制器信息,此节点并不表示某一路DAC控制器,而是代表一个资源性质设备,用于描述一类DAC控制器的信息。本例只有一个DAC设备,如有多个设备,则需要在device_info文件增加deviceNode信息,以及在dac_config文件中增加对应的器件属性。 - device_info.hcs 配置参考。 + device_info.hcs配置参考。 ``` root { device_dac :: device { - //device0是DAC管理器 + // device0是DAC管理器 device0 :: deviceNode { policy = 0; priority = 52; @@ -141,7 +141,7 @@ DAC模块适配包含以下四个步骤: moduleName = "HDF_PLATFORM_DAC_MANAGER"; } } - //dac_virtual是DAC控制器 + // dac_virtual是DAC控制器 dac_virtual :: deviceNode { policy = 0; priority = 56; @@ -154,7 +154,7 @@ DAC模块适配包含以下四个步骤: ``` - 添加dac_test_config.hcs器件属性文件 - 在vendor/vendor_hisilicon/hispark_taurus/hdf_config/hdf_test/xxx_test_config.hcs目录下新增文件用于驱动配置参数,(例如:vendor/vendor_hisilicon/hispark_taurus/hdf_config/hdf_test/dac_test_config.hcs)其中配置参数如下 + 在vendor/vendor_hisilicon/hispark_taurus/hdf_config/hdf_test/xxx_test_config.hcs目录下新增文件用于驱动配置参数,(例如:vendor/vendor_hisilicon/hispark_taurus/hdf_config/hdf_test/dac_test_config.hcs)其中配置参数如下: ``` root { @@ -162,79 +162,79 @@ DAC模块适配包含以下四个步骤: dac_config { match_attr = "virtual_dac"; //【必要】需要和device_info.hcs中的deviceMatchAttr值一致 template dac_device { - deviceNum = 0; //设备号 - validChannel = 0x1; //有效通道1 - rate = 20000; //速率 + deviceNum = 0; // 设备号 + validChannel = 0x1; // 有效通道1 + rate = 20000; // 速率 } device_0 :: dac_device { - deviceNum = 0; //设备号 - validChannel = 0x2; //有效通道2 + deviceNum = 0; // 设备号 + validChannel = 0x2; // 有效通道2 } } } } ``` -3. **实例化核心层接口函数:** +3. 实例化核心层接口函数: - 初始化DacDevice成员。 在VirtualDacParseAndInit函数中对DacDevice成员进行初始化操作。 ``` - //虚拟驱动自定义结构体 + // 虚拟驱动自定义结构体 struct VirtualDacDevice { - //DAC设备结构体 + // DAC设备结构体 struct DacDevice device; - //DAC设备号 + // DAC设备号 uint32_t deviceNum; - //有效通道 + // 有效通道 uint32_t validChannel; - //DAC速率 + // DAC速率 uint32_t rate; }; - //解析并且初始化核心层DacDevice对象 + // 解析并且初始化核心层DacDevice对象 static int32_t VirtualDacParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) { - //定义返回值 + // 定义返回值 int32_t ret; - //DAC设备虚拟指针 + // DAC设备虚拟指针 struct VirtualDacDevice *virtual = NULL; (void)device; - //给virtual指针开辟空间 + // 给virtual指针开辟空间 virtual = (struct VirtualDacDevice *)OsalMemCalloc(sizeof(*virtual)); if (virtual == NULL) { - //为空则返回错误参数 + // 为空则返回错误参数 HDF_LOGE("%s: Malloc virtual fail!", __func__); return HDF_ERR_MALLOC_FAIL; } - //读取属性文件配置参数 + // 读取属性文件配置参数 ret = VirtualDacReadDrs(virtual, node); if (ret != HDF_SUCCESS) { - //读取失败 + // 读取失败 HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret); - //释放virtual空间 + // 释放virtual空间 OsalMemFree(virtual); - //指针置为0 + // 指针置为0 virtual = NULL; return ret; } - //初始化虚拟指针 + // 初始化虚拟指针 VirtualDacDeviceInit(virtual); - //对DacDevice中priv对象初始化 + // 对DacDevice中priv对象初始化 virtual->device.priv = (void *)node; - //对DacDevice中devNum对象初始化 + // 对DacDevice中devNum对象初始化 virtual->device.devNum = virtual->deviceNum; - //对DacDevice中ops对象初始化 + // 对DacDevice中ops对象初始化 virtual->device.ops = &g_method; - //添加DAC设备 + // 添加DAC设备 ret = DacDeviceAdd(&virtual->device); if (ret != HDF_SUCCESS) { - //添加设备失败 + // 添加设备失败 HDF_LOGE("%s: add Dac controller failed! ret = %d", __func__, ret); - //释放virtual空间 + // 释放virtual空间 OsalMemFree(virtual); - //虚拟指针置空 + // 虚拟指针置空 virtual = NULL; return ret; } @@ -257,12 +257,12 @@ DAC模块适配包含以下四个步骤: uint32_t rate; //【必要】采样率 }; - //DacDevice是核心层控制器结构体,其中的成员在Init函数中会被赋值 + // DacDevice是核心层控制器结构体,其中的成员在Init函数中会被赋值 struct DacDevice { const struct DacMethod *ops; - OsalSpinlock spin; //自旋锁 - uint32_t devNum; //设备号 - uint32_t chanNum; //设备通道号 + OsalSpinlock spin; // 自旋锁 + uint32_t devNum; // 设备号 + uint32_t chanNum; // 设备通道号 const struct DacLockMethod *lockOps; void *priv; }; @@ -275,13 +275,13 @@ DAC模块适配包含以下四个步骤: ``` static const struct DacMethod g_method = { - .write = VirtualDacWrite, //DAC设备写入值 - .stop = VirtualDacStop, //停止DAC设备 - .start = VirtualDacStart, //开始启动DAC设备 + .write = VirtualDacWrite, // DAC设备写入值 + .stop = VirtualDacStop, // 停止DAC设备 + .start = VirtualDacStart, // 开始启动DAC设备 }; ``` - ![](../public_sys-resources/icon-note.gif) **说明:** + ![](../public_sys-resources/icon-note.gif) **说明:**
DacDevice成员DacMethod的定义和成员说明见[接口说明](#接口说明)。 @@ -289,7 +289,7 @@ DAC模块适配包含以下四个步骤: 入参: - HdfDeviceObject这个是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 + HdfDeviceObject这个是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: @@ -386,11 +386,11 @@ DAC模块适配包含以下四个步骤: } ``` - - Release 函数参考 + - Release函数参考 入参: - HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: @@ -461,7 +461,7 @@ DAC模块适配包含以下四个步骤: } ``` -4. **驱动调试:** +4. 驱动调试: 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的测试用例是否成功等。 diff --git a/zh-cn/device-dev/driver/driver-platform-gpio-des.md b/zh-cn/device-dev/driver/driver-platform-gpio-des.md index 8f3969e840..fd9632060c 100644 --- a/zh-cn/device-dev/driver/driver-platform-gpio-des.md +++ b/zh-cn/device-dev/driver/driver-platform-gpio-des.md @@ -26,7 +26,7 @@ GPIO接口定义了操作GPIO管脚的标准方法集合,包括: | GPIO配置 | - GpioSetDir:设置管脚方向
- GpioGetDir:获取管脚方向 | | GPIO中断设置 | - GpioSetIrq:设置管脚对应的中断服务函数
- GpioUnSetIrq:取消管脚对应的中断服务函数
- GpioEnableIrq:使能管脚中断
- GpioDisableIrq:禁止管脚中断 | -> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 @@ -154,7 +154,7 @@ GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流 | 0 | 设置成功 | | 负数 | 设置失败 | - > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** + > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**
> 同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。 当不再需要响应中断服务函数时,使用如下函数取消中断设置: @@ -183,7 +183,7 @@ GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流 | 0 | 使能成功 | | 负数 | 使能失败 | - > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** + > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**
> 必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。 如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断: diff --git a/zh-cn/device-dev/driver/driver-platform-gpio-develop.md b/zh-cn/device-dev/driver/driver-platform-gpio-develop.md index 30bf8d1935..2215fce1f2 100755 --- a/zh-cn/device-dev/driver/driver-platform-gpio-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-gpio-develop.md @@ -3,9 +3,7 @@ ## 概述 -GPIO(General-purpose input/output)即通用型输入输出,在HDF框架中, - -GPIO的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 +GPIO(General-purpose input/output)即通用型输入输出,在HDF框架中,GPIO的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 **图1** GPIO无服务模式结构图 @@ -37,35 +35,35 @@ struct GpioMethod { | 函数成员 | 入参 | 出参 | 返回值 | 功能 | | -------- | -------- | -------- | -------- | -------- | -| write | cntlr:结构体指针,核心层GPIO控制器;
local:uint16_t,GPIO端口标识号 ;
val:uint16_t,电平传入值; | 无 | HDF_STATUS相关状态 | GPIO引脚写入电平值 | -| read | cntlr:结构体指针,核心层GPIO控制器;
local:uint16_t,GPIO端口标识; | val:uint16_t 指针,用于传出电平值。 | HDF_STATUS相关状态 | GPIO引脚读取电平值 | -| setDir | cntlr:结构体指针,核心层GPIO控制器;
local:uint16_t,GPIO端口标识号 ;
dir:uint16_t,管脚方向传入值; | 无 | HDF_STATUS相关状态 | 设置GPIO引脚输入/输出方向 | -| getDir | cntlr:结构体指针,核心层GPIO控制器;
local:uint16_t,GPIO端口标识号; | dir:uint16_t 指针,用于传出管脚方向值。 | HDF_STATUS相关状态 | 读GPIO引脚输入/输出方向 | -| setIrq | cntlr:结构体指针,核心层GPIO控制器;
local:uint16_t,GPIO端口标识号;
mode:uint16_t,表示触发模式(边沿或电平);
func:函数指针,中断服务程序;
arg:void指针,中断服务程序入参; | 无 | HDF_STATUS相关状态 | 将GPIO引脚设置为中断模式 | -| unsetIrq | cntlr:结构体指针,核心层GPIO控制器;
local:uint16_t,GPIO端口标识号; | 无 | HDF_STATUS相关状态 | 取消GPIO中断设置 | -| enableIrq | cntlr:结构体指针,核心层GPIO控制器;
local:uint16_t,GPIO端口标识号; | 无 | HDF_STATUS相关状态 | 使能GPIO管脚中断 | -| disableIrq | cntlr:结构体指针,核心层GPIO控制器;
local:uint16_t,GPIO端口标识号; | 无 | HDF_STATUS相关状态 | 禁止GPIO管脚中断 | +| write | cntlr:结构体指针,核心层GPIO控制器
local:uint16_t,GPIO端口标识号
val:uint16_t,电平传入值 | 无 | HDF_STATUS相关状态 | GPIO引脚写入电平值 | +| read | cntlr:结构体指针,核心层GPIO控制器
local:uint16_t,GPIO端口标识 | val:uint16_t指针,用于传出电平值。 | HDF_STATUS相关状态 | GPIO引脚读取电平值 | +| setDir | cntlr:结构体指针,核心层GPIO控制器
local:uint16_t,GPIO端口标识号
dir:uint16_t,管脚方向传入值 | 无 | HDF_STATUS相关状态 | 设置GPIO引脚输入/输出方向 | +| getDir | cntlr:结构体指针,核心层GPIO控制器
local:uint16_t,GPIO端口标识号 | dir:uint16_t指针,用于传出管脚方向值 | HDF_STATUS相关状态 | 读GPIO引脚输入/输出方向 | +| setIrq | cntlr:结构体指针,核心层GPIO控制器
local:uint16_t,GPIO端口标识号
mode:uint16_t,表示触发模式(边沿或电平)
func:函数指针,中断服务程序;
arg:void指针,中断服务程序入参 | 无 | HDF_STATUS相关状态 | 将GPIO引脚设置为中断模式 | +| unsetIrq | cntlr:结构体指针,核心层GPIO控制器
local:uint16_t,GPIO端口标识号 | 无 | HDF_STATUS相关状态 | 取消GPIO中断设置 | +| enableIrq | cntlr:结构体指针,核心层GPIO控制器
local:uint16_t,GPIO端口标识号 | 无 | HDF_STATUS相关状态 | 使能GPIO管脚中断 | +| disableIrq | cntlr:结构体指针,核心层GPIO控制器
local:uint16_t,GPIO端口标识号 | 无 | HDF_STATUS相关状态 | 禁止GPIO管脚中断 | ## 开发步骤 GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。GPIO控制器分组管理所有管脚,相关参数会在属性文件中有所体现;驱动入口和接口函数的实例化环节是厂商驱动接入HDF的核心环节。 -1. **实例化驱动入口:** +1. 实例化驱动入口: - 实例化HdfDriverEntry结构体成员。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 -2. **配置属性文件:** +2. 配置属性文件: - 在device_info.hcs文件中添加deviceNode描述。 - 【可选】添加gpio_config.hcs器件属性文件。 -3. **实例化GPIO控制器对象:** +3. 实例化GPIO控制器对象: - 初始化GpioCntlr成员。 - 实例化GpioCntlr成员GpioMethod。 - > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 实例化GpioCntlr成员GpioMethod,详见[接口说明](#接口说明)。 -4. **驱动调试:** +4. 驱动调试: 【可选】针对新增驱动程序,建议验证驱动基本功能,例如GPIO控制状态,中断响应情况等。 @@ -81,19 +79,19 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ``` struct HdfDriverEntry g_gpioDriverEntry = { .moduleVersion = 1, - .Bind = Pl061GpioBind, //GPIO不需要实现Bind,本例是一个空实现,厂商可根据自身需要添加相关操作 - .Init = Pl061GpioInit, //见Init参考 - .Release = Pl061GpioRelease, //见Release参考 + .Bind = Pl061GpioBind, // GPIO不需要实现Bind,本例是一个空实现,厂商可根据自身需要添加相关操作 + .Init = Pl061GpioInit, // 见Init参考 + .Release = Pl061GpioRelease, // 见Release参考 .moduleName = "hisi_pl061_driver",//【必要且需要与HCS文件中里面的moduleName匹配】 }; - //调用HDF_INIT将驱动入口注册到HDF框架中 + // 调用HDF_INIT将驱动入口注册到HDF框架中 HDF_INIT(g_gpioDriverEntry); ``` 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 gpio_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层GpioCntlr 成员的默认值或限制范围有密切关系。 本例只有一个GPIO控制器,如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在gpio_config文件中增加对应的器件属性。 - - device_info.hcs 配置参考。 + - device_info.hcs配置参考 ``` root { @@ -108,14 +106,14 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, permission = 0644; // 驱动创建设备节点权限 moduleName = "hisi_pl061_driver"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; deviceMatchAttr = "hisilicon_hi35xx_pl061";//【必要】用于配置控制器私有数据,要与 gpio_config.hcs 中 - //对应控制器保持一致,其他控制器信息也在文件中 + // 对应控制器保持一致,其他控制器信息也在文件中 } } } } } ``` - - gpio_config.hcs 配置参考。 + - gpio_config.hcs配置参考 ``` root { @@ -123,7 +121,7 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, gpio_config { controller_0x120d0000 { match_attr = "hisilicon_hi35xx_pl061"; //【必要】必须和device_info.hcs中的deviceMatchAttr值一致 - groupNum = 12; //【必要】GPIO组索引 需要根据设备情况填写 + groupNum = 12; //【必要】GPIO组索引,需要根据设备情况填写 bitNum = 8; //【必要】每组GPIO管脚数 regBase = 0x120d0000;//【必要】物理基地址 regStep = 0x1000; //【必要】寄存器偏移步进 @@ -143,17 +141,17 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ``` struct Pl061GpioCntlr { - struct GpioCntlr cntlr;//【必要】 是核心层控制对象,其成员定义见下面 + struct GpioCntlr cntlr;//【必要】是核心层控制对象,其成员定义见下面 volatile unsigned char *regBase; //【必要】寄存器基地址 - uint32_t phyBase; //【必要】 物理基址 - uint32_t regStep; //【必要】 寄存器偏移步进 - uint32_t irqStart; //【必要】 中断开启 - uint16_t groupNum; //【必要】 用于描述厂商的GPIO端口号的参数 - uint16_t bitNum; //【必要】 用于描述厂商的GPIO端口号的参数 - uint8_t irqShare; //【必要】 共享中断 - struct Pl061GpioGroup *groups; //【可选】 根据厂商需要设置 + uint32_t phyBase; //【必要】物理基址 + uint32_t regStep; //【必要】寄存器偏移步进 + uint32_t irqStart; //【必要】中断开启 + uint16_t groupNum; //【必要】用于描述厂商的GPIO端口号的参数 + uint16_t bitNum; //【必要】用于描述厂商的GPIO端口号的参数 + uint8_t irqShare; //【必要】共享中断 + struct Pl061GpioGroup *groups; //【可选】根据厂商需要设置 }; - struct Pl061GpioGroup { //包括寄存器地址,中断号,中断函数和和锁 + struct Pl061GpioGroup { // 包括寄存器地址,中断号,中断函数和和锁 volatile unsigned char *regBase; unsigned int index; unsigned int irq; @@ -182,15 +180,15 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, static struct GpioMethod g_method = { .request = NULL, .release = NULL, - .write = Pl061GpioWrite, //写管脚 - .read = Pl061GpioRead, //读管脚 - .setDir = Pl061GpioSetDir, //设置管脚方向 - .getDir = Pl061GpioGetDir, //获取管脚方向 + .write = Pl061GpioWrite, // 写管脚 + .read = Pl061GpioRead, // 读管脚 + .setDir = Pl061GpioSetDir, // 设置管脚方向 + .getDir = Pl061GpioGetDir, // 获取管脚方向 .toIrq = NULL, - .setIrq = Pl061GpioSetIrq, //设置管脚中断,如不具备此能力可忽略 - .unsetIrq = Pl061GpioUnsetIrq, //取消管脚中断设置,如不具备此能力可忽略 - .enableIrq = Pl061GpioEnableIrq, //使能管脚中断,如不具备此能力可忽略 - .disableIrq = Pl061GpioDisableIrq,//禁止管脚中断,如不具备此能力可忽略 + .setIrq = Pl061GpioSetIrq, // 设置管脚中断,如不具备此能力可忽略 + .unsetIrq = Pl061GpioUnsetIrq, // 取消管脚中断设置,如不具备此能力可忽略 + .enableIrq = Pl061GpioEnableIrq, // 使能管脚中断,如不具备此能力可忽略 + .disableIrq = Pl061GpioDisableIrq,// 禁止管脚中断,如不具备此能力可忽略 }; ``` @@ -224,13 +222,13 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, static int32_t Pl061GpioInit(struct HdfDeviceObject *device) { ... - struct Pl061GpioCntlr *pl061 = &g_pl061;//利用静态全局变量完成初始化 - //static struct Pl061GpioCntlr g_pl061 = { + struct Pl061GpioCntlr *pl061 = &g_pl061;// 利用静态全局变量完成初始化 + // static struct Pl061GpioCntlr g_pl061 = { // .groups = NULL, // .groupNum = PL061_GROUP_MAX, // .bitNum = PL061_BIT_MAX, //}; - ret = Pl061GpioReadDrs(pl061, device->property);//利用从gpio_config.HCS文件读取的属性值来初始化自定义结构体对象成员 + ret = Pl061GpioReadDrs(pl061, device->property);// 利用从gpio_config.HCS文件读取的属性值来初始化自定义结构体对象成员 ... pl061->regBase = OsalIoRemap(pl061->phyBase, pl061->groupNum * pl061->regStep);//地址映射 ... @@ -251,11 +249,11 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ... } ``` - - Release 函数参考 + - Release函数参考 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: @@ -263,7 +261,7 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, 函数说明: - 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release 接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 ``` @@ -273,13 +271,13 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, struct Pl061GpioCntlr *pl061 = NULL; ... cntlr = GpioCntlrFromDevice(device);//【必要】通过强制转换获取核心层控制对象 - //return (device == NULL) ? NULL : (struct GpioCntlr *)device->service; + // return (device == NULL) ? NULL : (struct GpioCntlr *)device->service; ... #ifdef PL061_GPIO_USER_SUPPORT GpioRemoveVfs();//与Init中GpioAddVfs相反 #endif GpioCntlrRemove(cntlr); //【必要】取消设备信息、服务等内容在核心层上的挂载 - pl061 = ToPl061GpioCntlr(cntlr); //return (struct Pl061GpioCntlr *)cntlr; + pl061 = ToPl061GpioCntlr(cntlr); // return (struct Pl061GpioCntlr *)cntlr; Pl061GpioRleaseCntlrMem(pl061); //【必要】锁和内存的释放 OsalIoUnmap((void *)pl061->regBase);//【必要】解除地址映射 pl061->regBase = NULL; diff --git a/zh-cn/device-dev/driver/driver-platform-hdmi-des.md b/zh-cn/device-dev/driver/driver-platform-hdmi-des.md index 5876a4dfdd..e67370bda2 100755 --- a/zh-cn/device-dev/driver/driver-platform-hdmi-des.md +++ b/zh-cn/device-dev/driver/driver-platform-hdmi-des.md @@ -5,15 +5,15 @@ ### 功能简介 -- HDMI(High Definition Multimedia Interface),即高清多媒体接口,主要用于DVD、机顶盒等音视频Source到TV、显示器等Sink设备的传输。 -- HDMI以主从方式工作,通常有一个Source端和一个Sink端。 -- HDMI接口定义了完成HDMI传输的通用方法集合,包括: +HDMI(High Definition Multimedia Interface),即高清多媒体接口,主要用于DVD、机顶盒等音视频Source到TV、显示器等Sink设备的传输。 +HDMI以主从方式工作,通常有一个Source端和一个Sink端。 +HDMI接口定义了完成HDMI传输的通用方法集合,包括: - - HDMI控制器管理:打开或关闭HDMI控制器 - - HDMI启动/停止传输:启动或停止HDMI传输 - - HDMI控制器设置:设置音频、视频及HDR属性,设置色彩深度、声音图像消隐等 - - HDMI读取EDID:读取Sink端原始的EDID数据 - - HDMI热插拔:注册/注销热插拔回调函数 +- HDMI控制器管理:打开或关闭HDMI控制器 +- HDMI启动/停止传输:启动或停止HDMI传输 +- HDMI控制器设置:设置音频、视频及HDR属性,设置色彩深度、声音图像消隐等 +- HDMI读取EDID:读取Sink端原始的EDID数据 +- HDMI热插拔:注册/注销热插拔回调函数 ### 基本概念 @@ -22,9 +22,9 @@ HDMI是Hitachi、Panasonic、Philips、Silicon Image、Sony、Thomson、Toshiba - TMDS(Transition Minimized Differential signal):过渡调制差分信号,也被称为最小化传输差分信号,用于发送音频、视频及各种辅助数据。 - DDC(Display Data Channel):显示数据通道,发送端与接收端可利用DDC通道得知彼此的发送与接收能力,但HDMI仅需单向获知接收端(显示器)的能力。 - CEC(Consumer Electronics Control):消费电子控制,该功能应该能够在连接HDMI的发送设备与接收设备之间实现交互操作。 -- FRL(Fixed Rate Link):TMDS 的架构进行讯号传输时,最高带宽可达 18Gbps,而 FRL 模式的带宽则提升到 48 Gbps。 +- FRL(Fixed Rate Link):TMDS 的架构进行讯号传输时,最高带宽可达 18Gbps,而FRL模式的带宽则提升到48 Gbps。 - HDCP(High-bandwidth Digital Content Protection):即高带宽数字内容保护技术,当用户对高清晰信号进行非法复制时,该技术会进行干扰,降低复制出来的影像的质量,从而对内容进行保护。 -- EDID(Extended Display Identification Data):扩展显示标识数据, 通常存储在显示器的固件中,标识供应商信息、EDID版本信息、最大图像大小、颜色设置、厂商预设置、频率范围的限制以及显示器名和序列号的字符串。 +- EDID(Extended Display Identification Data):扩展显示标识数据,通常存储在显示器的固件中,标识供应商信息、EDID版本信息、最大图像大小、颜色设置、厂商预设置、频率范围的限制以及显示器名和序列号的字符串。 ### 运作机制 @@ -38,7 +38,7 @@ HDMI物理连接如图1所示: ### 约束与限制 -HDMI模块当前仅支持轻量和小型系统内核(LiteOS) 。 +HDMI模块当前仅支持轻量和小型系统内核(LiteOS)。 ## 使用指导 @@ -92,7 +92,7 @@ DevHandle HdmiOpen(int16_t number); | NULL | 打开HDMI控制器失败 | | 控制器句柄 | 打开的HDMI控制器句柄 | -假设系统中存在2个HDMI控制器,编号从0到1,那么我们现在获取0号控制器: +假设系统中存在2个HDMI控制器,编号从0到1,以下代码示例为获取0号控制器: ```c DevHandle hdmiHandle = NULL; /* HDMI控制器句柄 / diff --git a/zh-cn/device-dev/driver/driver-platform-hdmi-develop.md b/zh-cn/device-dev/driver/driver-platform-hdmi-develop.md index 83f705b231..fd127d7c13 100755 --- a/zh-cn/device-dev/driver/driver-platform-hdmi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-hdmi-develop.md @@ -5,19 +5,17 @@ ### 功能简介 -HDMI(High Definition Multimedia Interface),即高清多媒体接口,主要用于DVD、机顶盒等音视频source到TV、显示器等Sink设备的传输。 +HDMI(High Definition Multimedia Interface),即高清多媒体接口,是Hitachi、Panasonic、Philips、Silicon Image、Sony、Thomson、Toshiba共同发布的一款音视频传输协议,主要用于DVD、机顶盒等音视频source到TV、显示器等Sink设备的传输。HDMI传输过程遵循TMDS(Transition Minimized Differential Signaling)协议。 ### 基本概念 -HDMI是Hitachi、Panasonic、Philips、Silicon Image、Sony、Thomson、Toshiba共同发布的一款音视频传输协议。传输过程遵循TMDS(Transition Minimized Differential Signaling)协议。 - - TMDS(Transition Minimized Differential signal):过渡调制差分信号,也被称为最小化传输差分信号,用于发送音频、视频及各种辅助数据。 - DDC(Display Data Channel):显示数据通道,发送端与接收端可利用DDC通道得知彼此的发送与接收能力,但HDMI仅需单向获知接收端(显示器)的能力。 - CEC(Consumer Electronics Control):消费电子控制,该功能应该能够在连接HDMI的发送设备与接收设备之间实现交互操作。 -- FRL(Fixed Rate Link):TMDS 的架构进行讯号传输时,最高带宽可达 18Gbps,而 FRL 模式的带宽则提升到 48 Gbps。 +- FRL(Fixed Rate Link):TMDS 的架构进行讯号传输时,最高带宽可达18Gbps,而 FRL 模式的带宽则提升到48Gbps。 - HDCP(High-bandwidth Digital Content Protection):即高带宽数字内容保护技术,当用户对高清晰信号进行非法复制时,该技术会进行干扰,降低复制出来的影像的质量,从而对内容进行保护。 @@ -85,57 +83,57 @@ struct HdmiCntlrOps { | 函数成员 | 入参 | 出参 | 返回值 | 功能 | | ------------------------ | ------------------------------------------------------------ | -------------------------------------- | ------------------ | -------------------------------------------------- | -| hardWareInit | **cntlr**: 结构体指针,核心层HDMI控制器; | 无 | 无 | 初始化HDMI硬件 | -| hardWareStatusGet | **cntlr**: 结构体指针,核心层HDMI控制器;
| **status**:HDMI硬件状态 ; | 无 | 获取HDMI当前硬件状态 | -| controllerReset | **cntlr**: 结构体指针,核心层HDMI控制器; | 无 | 无 | 复位HDMI控制器 | -| hotPlugStateGet | **cntlr**: 结构体指针,核心层HDMI控制器; | 无 | bool: HDMI热插拔状态 | 获取HDMI热插拔状态 | -| hotPlugInterruptStateGet | **cntlr**: 结构体指针,核心层HDMI控制器; | 无 | bool: HDMI热插拔中断状态 | 获取HDMI热插拔中断状态 | -| lowPowerSet | **cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能 | 无 | 无 | 使能/去使能低功耗 | -| tmdsModeSet | **cntlr**: 结构体指针,核心层HDMI控制器;
**mode**:TMDS模式 | 无 | 无 | 设置TMDS模式 | -|tmdsConfigSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**mode**: TMDS参数|无|HDF_STATUS相关状态|配置TMDS参数| -|infoFrameEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**infoFrameType**: packet类型
**enable**: bool,使能/去使能|无|无|使能/去使能infoFrame| -|infoFrameSend|**cntlr**: 结构体指针,核心层HDMI控制器;
**infoFrameType**: packet类型
**data**: infoFrame数据
**len**:数据长度|无|HDF_STATUS相关状态|发送infoFrame| -|cecMsgSend|**cntlr**: 结构体指针,核心层HDMI控制器;
**msg**: CEC消息|无|HDF_STATUS相关状态|发送CEC消息| -|audioPathEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|使能/去使能audio通路| -|audioPathSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**config**: 配置信息|无|无|设置audio通路配置信息| -|phyOutputEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|使能/去使能物理层输出状态| -|phyOutputSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**cfg**: 配置信息|无|无|设置物理层配置信息| -|blackDataSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|设置黑屏| -|videoMuteEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|使能/去使能video静音| -|videoPathSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**attr**: 配置信息|无|无|设置viedo通路配置信息| -|audioMuteEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|使能/去使能audio静音| -|avmuteSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|使能/去使能声音图像消隐| -|ddcTransfer|**cntlr**: 结构体指针,核心层HDMI控制器;
**ddcCfg**:DDC配置参数|**ddcCfg**:DDC配置参数|HDF_STATUS相关状态|读写DDC数据| -|scdcSourceScrambleGet|**cntlr**: 结构体指针,核心层HDMI控制器;|无|bool,加扰状态|获取source端的加扰状态| -|scdcSourceScrambleSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|HDF_STATUS相关状态|使能/去使能source端的加扰| -|frlEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|HDF_STATUS相关状态|使能/去使能FRL| -|audioNctsSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**cfg**:N/CTS配 置参数|无|HDF_STATUS相关状态|设置audio的N/CTS信息| -|frlTrainingConfigSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**cfg**:FRL Traning配置参数|无|无|设置FRL Traning配置信息| -|frlTrainingStart|**cntlr**: 结构体指针,核心层HDMI控制器;|无|无|开始FRL Traning流程| -|frlGetTriningRslt|**cntlr**: 结构体指针,核心层HDMI控制器;|**rslt**:FRL Traning结果|无|获取FRL Traning结果| -|hdcpRegInit|**cntlr**: 结构体指针,核心层HDMI控制器;|无|无|初始化HDCP流程相关的寄存器| -|hdcpGenerateAksvAndAn|**cntlr**: 结构体指针,核心层HDMI控制器;|无|HDF_STATUS相关状态|HDCP流程中生成aksv和an| -|hdcpOptReg|**cntlr**: 结构体指针,核心层HDMI控制器;
**type**: 操作类型
**data**: 寄存器数据
**len**: 数据长度|**data**: 寄存器数据|HDF_STATUS相关状态|HDCP流程中读写相关寄存器| -|hdrTimerSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**config**: timer配置信息|无|无|设置HDR相关的timer配置信息| +| hardWareInit | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 初始化HDMI硬件 | +| hardWareStatusGet | **cntlr**:结构体指针,核心层HDMI控制器
| **status**:HDMI硬件状态 ; | 无 | 获取HDMI当前硬件状态 | +| controllerReset | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 复位HDMI控制器 | +| hotPlugStateGet | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | bool: HDMI热插拔状态 | 获取HDMI热插拔状态 | +| hotPlugInterruptStateGet | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | bool: HDMI热插拔中断状态 | 获取HDMI热插拔中断状态 | +| lowPowerSet | **cntlr**:结构体指针,核心层HDMI控制器
**enable**: bool,使能/去使能 | 无 | 无 | 使能/去使能低功耗 | +| tmdsModeSet | **cntlr**:结构体指针,核心层HDMI控制器
**mode**:TMDS模式 | 无 | 无 | 设置TMDS模式 | +| tmdsConfigSet | **cntlr**:结构体指针,核心层HDMI控制器
**mode**: TMDS参数 | 无 | HDF_STATUS相关状态 | 配置TMDS参数 | +| infoFrameEnable | **cntlr**:结构体指针,核心层HDMI控制器
**infoFrameType**: packet类型
**enable**: bool,使能/去使能 | 无 | 无 | 使能/去使能infoFrame | +| infoFrameSend | **cntlr**:结构体指针,核心层HDMI控制器
**infoFrameType**: packet类型
**data**: infoFrame数据
**len**:数据长度 | 无 | HDF_STATUS相关状态 | 发送infoFrame | +| cecMsgSend | **cntlr**:结构体指针,核心层HDMI控制器
**msg**: CEC消息 | 无 | HDF_STATUS相关状态 | 发送CEC消息 | +| audioPathEnable | **cntlr**:结构体指针,核心层HDMI控制器
**enable**: bool,使能/去使能| 无 | 无 | 使能/去使能audio通路 | +| audioPathSet | **cntlr**:结构体指针,核心层HDMI控制器
**config**: 配置信息 | 无 | 无 | 设置audio通路配置信息 | +| phyOutputEnable | **cntlr**:结构体指针,核心层HDMI控制器
**enable**: bool,使能/去使能 | 无 | 无 | 使能/去使能物理层输出状态 | +| phyOutputSet | **cntlr**:结构体指针,核心层HDMI控制器
**cfg**: 配置信息 | 无 | 无 | 设置物理层配置信息 | +| blackDataSet | **cntlr**:结构体指针,核心层HDMI控制器
**enable**: bool,使能/去使能 | 无 | 无 | 设置黑屏 | +| videoMuteEnable | **cntlr**:结构体指针,核心层HDMI控制器
**enable**: bool,使能/去使能 | 无 | 无 | 使能/去使能video静音 | +| videoPathSet | **cntlr**:结构体指针,核心层HDMI控制器
**attr**:配置信息| 无 | 无 | 设置viedo通路配置信息 | +|audioMuteEnable | **cntlr**:结构体指针,核心层HDMI控制器
**enable**: bool,使能/去使能 | 无 | 无 | 使能/去使能audio静音 | +| avmuteSet | **cntlr**:结构体指针,核心层HDMI控制器
**enable**: bool,使能/去使能| 无 | 无 | 使能/去使能声音图像消隐 | +| ddcTransfer | **cntlr**:结构体指针,核心层HDMI控制器
**ddcCfg**:DDC配置参数 |**ddcCfg**:DDC配置参数 |HDF_STATUS相关状态 | 读写DDC数据 | +| scdcSourceScrambleGet | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | bool,加扰状态 | 获取source端的加扰状态 | +| scdcSourceScrambleSet | **cntlr**:结构体指针,核心层HDMI控制器
**enable**: bool,使能/去使能 | 无 | HDF_STATUS相关状态 | 使能/去使能source端的加扰 | +| frlEnable | **cntlr**:结构体指针,核心层HDMI控制器
**enable**: bool,使能/去使能 | 无 | HDF_STATUS相关状态 | 使能/去使能FRL | +| audioNctsSet | **cntlr**:结构体指针,核心层HDMI控制器
**cfg**:N/CTS配置参数 | 无 | HDF_STATUS相关状态 | 设置audio的N/CTS信息 | +| frlTrainingConfigSet | **cntlr**:结构体指针,核心层HDMI控制器
**cfg**:FRL Traning配置参数 | 无 | 无| 设置FRL Traning配置信息 | +| frlTrainingStart | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 开始FRL Traning流程 | +| frlGetTriningRslt | **cntlr**:结构体指针,核心层HDMI控制器 | **rslt**:FRL Traning结果 | 无 | 获取FRL Traning结果 | +| hdcpRegInit | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 初始化HDCP流程相关的寄存器 | +|hdcpGenerateAksvAndAn |**cntlr**:结构体指针,核心层HDMI控制器 | 无 | HDF_STATUS相关状态 | HDCP流程中生成aksv和an | +| hdcpOptReg | **cntlr**:结构体指针,核心层HDMI控制器
**type**: 操作类型
**data**: 寄存器数据
**len**: 数据长度 | **data**: 寄存器数据 | HDF_STATUS相关状态 | HDCP流程中读写相关寄存器 | +| hdrTimerSet | **cntlr**:结构体指针,核心层HDMI控制器
**config**: timer配置信息 | 无 | 无 | 设置HDR相关的timer配置信息 | ### 开发步骤 HDMI模块适配的三个环节是配置属性文件,实例化驱动入口以及实例化HDMI控制器对象。 -- **实例化驱动入口:** +- 实例化驱动入口: - 实例化HdfDriverEntry结构体成员。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 -- **配置属性文件:** +- 配置属性文件: - 在device_info.hcs文件中添加deviceNode描述。 - 【可选】添加hdmi_config.hcs器件属性文件。 -- **实例化HDMI控制器对象:** +- 实例化HDMI控制器对象: - 初始化HdmiCntlr成员。 - 实例化HdmiCntlr成员HdmiCntlrOps方法集合。 -1. **实例化驱动入口** +1. 实例化驱动入口 驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 @@ -151,16 +149,16 @@ HDMI模块适配的三个环节是配置属性文件,实例化驱动入口以 .Release = HdmiAdapterRelease, .moduleName = "adapter_hdmi_driver",//【必要】与HCS里面的名字匹配 }; - HDF_INIT(g_hdmiDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_hdmiDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 ``` -2. **配置属性文件** +2. 配置属性文件 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在hdmi_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层HdmiCntlr相关成员的默认值或限制范围有密切关系。 从第一个节点开始配置具体HDMI控制器信息,此节点并不表示某一路HDMI控制器,而是代表一个资源性质设备,用于描述一类HDMI控制器的信息。本例只有一个HDMI控制器,如有多个控制器,则需要在device_info文件增加deviceNode信息,以及在hdmi_config文件中增加对应的器件属性。 - - device_info.hcs 配置参考 + - device_info.hcs配置参考 ```c root { @@ -228,13 +226,13 @@ HDMI模块适配的三个环节是配置属性文件,实例化驱动入口以 } ``` -3. **实例化控制器对象** +3. 实例化控制器对象 最后一步,完成驱动入口注册之后,要以核心层HdmiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化HdmiCntlr成员HdmiCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 - 自定义结构体参考 - > ![](../public_sys-resources/icon-note.gif) **说明:** + > ![](../public_sys-resources/icon-note.gif) **说明:**
> 从驱动角度看,自定义结构体是参数和数据的载体。HDF会读取hdmi_config.hcs文件中的数值并通过DeviceResourceIface来初始化结构体成员,且其中一些重要数值(例如设备号、总线号等)也会被传递给核心层HdmiCntlr对象。 ```c @@ -316,17 +314,17 @@ HDMI模块适配的三个环节是配置属性文件,实例化驱动入口以 - Bind函数参考 **入参:** - HdfDeviceObject 是整个驱动对外呈现的接口参数,具备 HCS 配置文件的信息 + HdfDeviceObject是整个驱动对外呈现的接口参数,具备hcs配置文件的信息 **返回值:** - HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) + HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) |状态(值)|状态描述| |:-|:-| |HDF_ERR_INVALID_OBJECT|控制器对象非法| |HDF_ERR_INVALID_PARAM |参数非法| |HDF_ERR_MALLOC_FAIL |内存分配失败| - |HDF_ERR_IO |I/O 错误| + |HDF_ERR_IO |I/O错误| |HDF_SUCCESS |传输成功| |HDF_FAILURE |传输失败| @@ -355,13 +353,13 @@ HDMI模块适配的三个环节是配置属性文件,实例化驱动入口以 cntlr->ops = &g_hdmiHostOps; //【必要】HdmiCntlrOps的实例化对象的挂载 cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提 obj->service = &cntlr->service; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提 - ret = HdmiAdapterCntlrParse(cntlr, obj); //【必要】 初始化 cntlr. 失败则 goto __ERR; + ret = HdmiAdapterCntlrParse(cntlr, obj); //【必要】初始化cntlr,失败则 goto __ERR; ... - ret = HdmiAdapterHostParse(host, obj); //【必要】 初始化 host对象的相关属性,失败则 goto __ERR; + ret = HdmiAdapterHostParse(host, obj); //【必要】初始化host对象的相关属性,失败则 goto __ERR; ... - ret = HdmiAdapterHostInit(host, cntlr); //厂商自定义的初始化,失败则 goto __ERR; + ret = HdmiAdapterHostInit(host, cntlr); // 厂商自定义的初始化,失败则 goto __ERR; ... - ret = HdmiCntlrAdd(cntlr); //调用核心层函数 失败则 goto __ERR; + ret = HdmiCntlrAdd(cntlr); // 调用核心层函数 失败则 goto __ERR; ... HDF_LOGD("HdmiAdapterBind: success."); return HDF_SUCCESS; @@ -375,7 +373,7 @@ HDMI模块适配的三个环节是配置属性文件,实例化驱动入口以 - Init函数参考 **入参:** - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息 **返回值:** HDF_STATUS相关状态 @@ -394,25 +392,24 @@ HDMI模块适配的三个环节是配置属性文件,实例化驱动入口以 - Release 函数参考 **入参:** - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息 **返回值:** 无 **函数说明:** - 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。 ```c static void HdmiAdapterRelease(struct HdfDeviceObject *obj) { struct HdmiCntlr *cntlr = NULL; ... - cntlr = (struct HdmiCntlr *)obj->service;//这里有HdfDeviceObject到HdmiCntlr的强制转化,通过service成员,赋值见Bind函数 + cntlr = (struct HdmiCntlr *)obj->service;// 这里有HdfDeviceObject到HdmiCntlr的强制转化,通过service成员,赋值见Bind函数 ... - HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);//厂商自定义的内存释放函数,这里有HdmiCntlr到HimciAdapterHost的强制转化 + HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);// 厂商自定义的内存释放函数,这里有HdmiCntlr到HimciAdapterHost的强制转化 } ``` - > ![](../public_sys-resources/icon-note.gif) **说明:** - > 所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。 - + > ![](../public_sys-resources/icon-note.gif) **说明:**
+ > 所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。 \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-i2c-des.md b/zh-cn/device-dev/driver/driver-platform-i2c-des.md index aba92f09c9..c1bfaae6a2 100644 --- a/zh-cn/device-dev/driver/driver-platform-i2c-des.md +++ b/zh-cn/device-dev/driver/driver-platform-i2c-des.md @@ -3,17 +3,17 @@ ## 概述 -- I2C(Inter Integrated Circuit)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。 +I2C(Inter Integrated Circuit)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。 -- I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA(SerialData)串行数据线以及SCL(SerialClock)串行时钟线两根线相连,如图1所示。 +I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA(SerialData)串行数据线以及SCL(SerialClock)串行时钟线两根线相连,如图1所示。 -- I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。 +I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。 -- I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。 +I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。 -- I2C接口定义了完成I2C传输的通用方法集合,包括: - - I2C控制器管理: 打开或关闭I2C控制器 - - I2C消息传输:通过消息传输结构体数组进行自定义传输 +I2C接口定义了完成I2C传输的通用方法集合,包括: +- I2C控制器管理:打开或关闭I2C控制器 +- I2C消息传输:通过消息传输结构体数组进行自定义传输 **图1** I2C物理连线示意图 @@ -29,7 +29,7 @@ | I2C控制器管理接口 | - I2cOpen:打开I2C控制器
- I2cClose:关闭I2C控制器 | | I2C消息传输接口 | I2cTransfer:自定义传输 | -> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 @@ -60,7 +60,7 @@ DevHandle I2cOpen(int16_t number); | NULL | 打开I2C控制器失败 | | 设备句柄 | 打开的I2C控制器设备句柄 | -假设系统中存在8个I2C控制器,编号从0到7,那么我们现在获取3号控制器 +假设系统中存在8个I2C控制器,编号从0到7,以下代码示例为获取3号控制器: ``` @@ -128,7 +128,7 @@ if (ret != 2) { ### 关闭I2C控制器 -I2C通信完成之后,需要关闭I2C控制器,关闭函数如下所示: +I2C通信完成之后,需要关闭I2C控制器,关闭函数如下所述: void I2cClose(DevHandle handle); @@ -144,7 +144,7 @@ I2cClose(i2cHandle); /* 关闭I2C控制器 */ ``` -## 使用实例 +## 使用示例 本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。 @@ -158,8 +158,8 @@ I2cClose(i2cHandle); /* 关闭I2C控制器 */ 本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其内部寄存器进行随机读写,测试I2C通路是否正常。 -> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> 本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。 +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
+> 本示例重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。 示例如下: diff --git a/zh-cn/device-dev/driver/driver-platform-i2c-develop.md b/zh-cn/device-dev/driver/driver-platform-i2c-develop.md index 514cbcdd0d..ac716ed351 100755 --- a/zh-cn/device-dev/driver/driver-platform-i2c-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-i2c-develop.md @@ -19,9 +19,9 @@ I2cMethod和I2cLockMethod定义: struct I2cMethod { int32_t (*transfer)(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count); }; -struct I2cLockMethod {//锁机制操作结构体 - int32_t (*lock)(struct I2cCntlr *cntlr);//加锁 - void (*unlock)(struct I2cCntlr *cntlr); //解锁 +struct I2cLockMethod {// 锁机制操作结构体 + int32_t (*lock)(struct I2cCntlr *cntlr);// 加锁 + void (*unlock)(struct I2cCntlr *cntlr); // 解锁 }; ``` @@ -36,21 +36,21 @@ struct I2cLockMethod {//锁机制操作结构体 I2C模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 -1. **实例化驱动入口:** +1. 实例化驱动入口: - 实例化HdfDriverEntry结构体成员。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 -2. **配置属性文件:** +2. 配置属性文件: - 在device_info.hcs文件中添加deviceNode描述。 - 【可选】添加i2c_config.hcs器件属性文件。 -3. **实例化I2C控制器对象:** +3. 实例化I2C控制器对象: - 初始化I2cCntlr成员。 - 实例化I2cCntlr成员I2cMethod和I2cLockMethod。 - > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 实例化I2cCntlr成员I2cMethod和I2cLockMethod,详见[接口说明](#接口说明)。 -4. **驱动调试:** +4. 驱动调试: 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,消息传输的成功与否等。 @@ -73,17 +73,17 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, .moduleVersion = 1, .Init = Hi35xxI2cInit, .Release = Hi35xxI2cRelease, - .moduleName = "hi35xx_i2c_driver",//【必要且与config.hcs文件里面匹配】 + .moduleName = "hi35xx_i2c_driver",// 【必要且与config.hcs文件里面匹配】 }; - HDF_INIT(g_i2cDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_i2cDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 - //核心层i2c_core.c 管理器服务的驱动入口 + // 核心层i2c_core.c管理器服务的驱动入口 struct HdfDriverEntry g_i2cManagerEntry = { .moduleVersion = 1, .Bind = I2cManagerBind, .Init = I2cManagerInit, .Release = I2cManagerRelease, - .moduleName = "HDF_PLATFORM_I2C_MANAGER",//这与device_info文件中device0对应 + .moduleName = "HDF_PLATFORM_I2C_MANAGER",// 这与device_info文件中device0对应 }; HDF_INIT(g_i2cManagerEntry); ``` @@ -101,7 +101,7 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, | deviceMatchAttr | 没有使用,可忽略 | 从第二个节点开始配置具体I2C控制器信息,此节点并不表示某一路I2C控制器,而是代表一个资源性质设备,用于描述一类I2C控制器的信息。多个控制器之间相互区分的参数是busID和reg_pbase,这在i2c_config文件中有所体现。 - - device_info.hcs 配置参考。 + - device_info.hcs配置参考 ``` @@ -124,14 +124,14 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, moduleName = "hi35xx_i2c_driver"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; serviceName = "HI35XX_I2C_DRIVER"; //【必要】驱动对外发布服务的名称,必须唯一 deviceMatchAttr = "hisilicon_hi35xx_i2c";//【必要】用于配置控制器私有数据,要与i2c_config.hcs中对应控制器保持一致 - // 具体的控制器信息在 i2c_config.hcs 中 + // 具体的控制器信息在 i2c_config.hcs中 } } } } ``` - - i2c_config.hcs 配置参考。 + - i2c_config.hcs 配置参考 ``` @@ -140,12 +140,12 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, i2c_config { match_attr = "hisilicon_hi35xx_i2c";//【必要】需要和device_info.hcs中的deviceMatchAttr值一致 template i2c_controller { //模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 - bus = 0; //【必要】i2c 识别号 - reg_pbase = 0x120b0000; //【必要】物理基地址 - reg_size = 0xd1; //【必要】寄存器位宽 - irq = 0; //【可选】根据厂商需要来使用 - freq = 400000; //【可选】根据厂商需要来使用 - clk = 50000000; //【可选】根据厂商需要来使用 + bus = 0; // 【必要】i2c 识别号 + reg_pbase = 0x120b0000; // 【必要】物理基地址 + reg_size = 0xd1; // 【必要】寄存器位宽 + irq = 0; // 【可选】根据厂商需要来使用 + freq = 400000; // 【可选】根据厂商需要来使用 + clk = 50000000; // 【可选】根据厂商需要来使用 } controller_0x120b0000 :: i2c_controller { bus = 0; @@ -169,15 +169,15 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ``` // 厂商自定义功能结构体 struct Hi35xxI2cCntlr { - struct I2cCntlr cntlr; //【必要】是核心层控制对象,具体描述见下面 - OsalSpinlock spin; //【必要】厂商需要基于此锁变量对各个 i2c 操作函数实现对应的加锁解锁 - volatile unsigned char *regBase; //【必要】寄存器基地址 - uint16_t regSize; //【必要】寄存器位宽 - int16_t bus; //【必要】i2c_config.hcs 文件中可读取具体值 - uint32_t clk; //【可选】厂商自定义 - uint32_t freq; //【可选】厂商自定义 - uint32_t irq; //【可选】厂商自定义 - uint32_t regBasePhy; //【必要】寄存器物理基地址 + struct I2cCntlr cntlr; // 【必要】是核心层控制对象,具体描述见下面 + OsalSpinlock spin; // 【必要】厂商需要基于此锁变量对各个 i2c 操作函数实现对应的加锁解锁 + volatile unsigned char *regBase; // 【必要】寄存器基地址 + uint16_t regSize; // 【必要】寄存器位宽 + int16_t bus; // 【必要】i2c_config.hcs文件中可读取具体值 + uint32_t clk; // 【可选】厂商自定义 + uint32_t freq; // 【可选】厂商自定义 + uint32_t irq; // 【可选】厂商自定义 + uint32_t regBasePhy; // 【必要】寄存器物理基地址 }; // I2cCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 @@ -190,29 +190,29 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, const struct I2cLockMethod *lockOps; }; ``` - - I2cCntlr成员回调函数结构体I2cMethod的实例化,和锁机制回调函数结构体I2cLockMethod实例化,其他成员在Init函数中初始化。 + - I2cCntlr成员回调函数结构体I2cMethod的实例化,和锁机制回调函数结构体I2cLockMethod实例化,其他成员在Init函数中初始化。 ``` - // i2c_hi35xx.c 中的示例 + // i2c_hi35xx.c中的示例 static const struct I2cMethod g_method = { .transfer = Hi35xxI2cTransfer, }; static const struct I2cLockMethod g_lockOps = { - .lock = Hi35xxI2cLock, //加锁函数 - .unlock = Hi35xxI2cUnlock,//解锁函数 + .lock = Hi35xxI2cLock, // 加锁函数 + .unlock = Hi35xxI2cUnlock,// 解锁函数 }; ``` - Init函数参考 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: - HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。 + HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS定义)。 **表3** Init函数入参及返回值参考 @@ -234,7 +234,7 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device) { ... - //遍历、解析 i2c_config.hcs 中的所有配置节点,并分别进行初始化,需要调用Hi35xxI2cParseAndInit函数 + // 遍历、解析 i2c_config.hcs中的所有配置节点,并分别进行初始化,需要调用Hi35xxI2cParseAndInit函数 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { ret = Hi35xxI2cParseAndInit(device, childNode);//函数定义见下 ... @@ -252,18 +252,18 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ... Hi35xxI2cCntlrInit(hi35xx); // 【必要】i2c设备的初始化 - hi35xx->cntlr.priv = (void *)node; //【必要】存储设备属性 - hi35xx->cntlr.busId = hi35xx->bus; //【必要】初始化I2cCntlr成员busId - hi35xx->cntlr.ops = &g_method; //【必要】I2cMethod的实例化对象的挂载 - hi35xx->cntlr.lockOps = &g_lockOps; //【必要】I2cLockMethod的实例化对象的挂载 - (void)OsalSpinInit(&hi35xx->spin); //【必要】锁的初始化 - ret = I2cCntlrAdd(&hi35xx->cntlr); //【必要】调用此函数填充核心层结构体,返回成功信号后驱动才完全接入平台核心层 + hi35xx->cntlr.priv = (void *)node; // 【必要】存储设备属性 + hi35xx->cntlr.busId = hi35xx->bus; // 【必要】初始化I2cCntlr成员busId + hi35xx->cntlr.ops = &g_method; // 【必要】I2cMethod的实例化对象的挂载 + hi35xx->cntlr.lockOps = &g_lockOps; // 【必要】I2cLockMethod的实例化对象的挂载 + (void)OsalSpinInit(&hi35xx->spin); // 【必要】锁的初始化 + ret = I2cCntlrAdd(&hi35xx->cntlr); // 【必要】调用此函数填充核心层结构体,返回成功信号后驱动才完全接入平台核心层 ... #ifdef USER_VFS_SUPPORT - (void)I2cAddVfsById(hi35xx->cntlr.busId);//【可选】若支持用户级的虚拟文件系统,则接入 + (void)I2cAddVfsById(hi35xx->cntlr.busId);// 【可选】若支持用户级的虚拟文件系统,则接入 #endif return HDF_SUCCESS; - __ERR__: //不成功的话,需要反向执行初始化相关函数 + __ERR__: // 不成功的话,需要反向执行初始化相关函数 if (hi35xx != NULL) { if (hi35xx->regBase != NULL) { OsalIoUnmap((void *)hi35xx->regBase); @@ -275,11 +275,11 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, return ret; } ``` - - Release 函数参考 + - Release函数参考 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: @@ -287,28 +287,28 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, 函数说明: - 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。 ``` static void Hi35xxI2cRelease(struct HdfDeviceObject *device) { ... - //与Hi35xxI2cInit一样,需要将对每个节点分别进行释放 + // 与Hi35xxI2cInit一样,需要将对每个节点分别进行释放 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - Hi35xxI2cRemoveByNode(childNode);//函数定义见下 + Hi35xxI2cRemoveByNode(childNode);// 函数定义见下 } } static void Hi35xxI2cRemoveByNode(const struct DeviceResourceNode *node) { ... - //【必要】可以调用 I2cCntlrGet 函数通过设备的 busid 获取 I2cCntlr 对象, 以及调用 I2cCntlrRemove 函数来释放 I2cCntlr 对象的内容 + // 【必要】可以调用 I2cCntlrGet函数通过设备的busid获取I2cCntlr对象, 以及调用I2cCntlrRemove函数来释放I2cCntlr对象的内容 cntlr = I2cCntlrGet(bus); if (cntlr != NULL && cntlr->priv == node) { ... I2cCntlrRemove(cntlr); - //【必要】解除地址映射,锁和内存的释放 + // 【必要】解除地址映射,锁和内存的释放 hi35xx = (struct Hi35xxI2cCntlr *)cntlr; OsalIoUnmap((void *)hi35xx->regBase); (void)OsalSpinDestroy(&hi35xx->spin); diff --git a/zh-cn/device-dev/driver/driver-platform-i3c-des.md b/zh-cn/device-dev/driver/driver-platform-i3c-des.md index 7e40317218..7f7278cc13 100755 --- a/zh-cn/device-dev/driver/driver-platform-i3c-des.md +++ b/zh-cn/device-dev/driver/driver-platform-i3c-des.md @@ -1,41 +1,33 @@ # I3C -- [概述](#section1) - - [功能简介](#section2) - - [基本概念](#section3) - - [运作机制](#section4) - - [约束与限制](#section5) -- [使用指导](#section6) - - [场景介绍](#section7) - - [接口说明](#section8) - - [开发步骤](#section9) - - [使用实例](#section10) - ## 概述 ### 功能简介 I3C(Improved Inter Integrated Circuit)总线是由MIPI Alliance开发的一种简单、低成本的双向二线制同步串行总线。 -- I3C接口定义了完成I3C传输的通用方法集合,包括: - I3C控制器管理:打开或关闭I3C控制器。 - I3C控制器配置:获取或配置I3C控制器参数。 - I3C消息传输:通过消息传输结构体数组进行自定义传输。 - I3C带内中断:请求或释放带内中断。 +I3C是两线双向串行总线,针对多个传感器从设备进行了优化,并且一次只能由一个I3C主设备控制。相比于I2C,I3C总线拥有更高的速度、更低的功耗,支持带内中断、从设备热接入以及切换当前主设备,同时向后兼容I2C从设备。I3C增加了带内中断(In-Bind Interrupt)功能,支持I3C设备进行热接入操作,弥补了I2C总线需要额外增加中断线来完成中断的不足。I3C总线上允许同时存在I2C设备、I3C从设备和I3C次级主设备。 + +I3C接口定义了完成I3C传输的通用方法集合,包括: +- I3C控制器管理:打开或关闭I3C控制器。 +- I3C控制器配置:获取或配置I3C控制器参数。 +- I3C消息传输:通过消息传输结构体数组进行自定义传输。 +- I3C带内中断:请求或释放带内中断。 ### 基本概念 -- I3C是两线双向串行总线,针对多个传感器从设备进行了优化,并且一次只能由一个I3C主设备控制。 相比于I2C,I3C总线拥有更高的速度、更低的功耗,支持带内中断、从设备热接入以及切换当前主设备,同时向后兼容I2C从设备。 -- I3C增加了带内中断(In-Bind Interrupt)功能,支持I3C设备进行热接入操作,弥补了I2C总线需要额外增加中断线来完成中断的不足。 -- I3C总线上允许同时存在I2C设备、I3C从设备和I3C次级主设备。 -- I3C相关缩略词解释: - - IBI(In-Band Interrupt):带内中断。在SCL线没有启动信号时,I3C从设备可以通过拉低SDA线使主设备发出SCL启动信号,从而发出带内中断请求。若有多个从机同时发出中断请求,I3C主机则通过从机地址进行仲裁,低地址优先相应。 - - DAA(Dynamic Address Assignment):动态地址分配。I3C支持对从设备地址进行动态分配从而避免地址冲突。在分配动态地址之前,连接到I3C总线上的每个I3C设备都应以两种方式之一来唯一标识: +- IBI(In-Band Interrupt) +带内中断。在SCL线没有启动信号时,I3C从设备可以通过拉低SDA线使主设备发出SCL启动信号,从而发出带内中断请求。若有多个从机同时发出中断请求,I3C主机则通过从机地址进行仲裁,低地址优先相应。 + +- DAA(Dynamic Address Assignment):动态地址分配。I3C支持对从设备地址进行动态分配从而避免地址冲突。在分配动态地址之前,连接到I3C总线上的每个I3C设备都应以两种方式之一来唯一标识: 1)设备可能有一个符合I2C规范的静态地址,主机可以使用此静态地址; 2)在任何情况下,设备均应具有48位的临时ID。 除非设备具有静态地址且主机使用静态地址,否则主机应使用此48位临时ID。 - - CCC(Common Command Code) :通用命令代码,所有I3C设备均支持CCC,可以直接将其传输到特定的I3C从设备,也可以同时传输到所有I3C从设备。 - - BCR(Bus Characteristic Register):总线特性寄存器,每个连接到 I3C 总线的 I3C 设备都应具有相关的只读总线特性寄存器 (BCR),该寄存器描述了I3C兼容设备在动态地址分配和通用命令代码中的作用和功能。 - - DCR(Device Characteristic Register):设备特性寄存器,连接到 I3C 总线的每个 I3C 设备都应具有相关的只读设备特性寄存器 (DCR)。 该寄存器描述了用于动态地址分配和通用命令代码的 I3C 兼容设备类型(例如,加速度计、陀螺仪等)。 + +- CCC(Common Command Code):通用命令代码,所有I3C设备均支持CCC,可以直接将其传输到特定的I3C从设备,也可以同时传输到所有I3C从设备。 + +- BCR(Bus Characteristic Register):总线特性寄存器,每个连接到 I3C 总线的 I3C 设备都应具有相关的只读总线特性寄存器 (BCR),该寄存器描述了I3C兼容设备在动态地址分配和通用命令代码中的作用和功能。 + +- DCR(Device Characteristic Register):设备特性寄存器,连接到 I3C 总线的每个 I3C 设备都应具有相关的只读设备特性寄存器 (DCR)。 该寄存器描述了用于动态地址分配和通用命令代码的 I3C 兼容设备类型(例如,加速度计、陀螺仪等)。 ### 运作机制 @@ -48,7 +40,7 @@ I3C(Improved Inter Integrated Circuit)总线是由MIPI Alliance开发的一 ### 约束与限制 -I3C模块当前仅支持轻量和小型系统内核(LiteOS) 。 +I3C模块当前仅支持轻量和小型系统内核(LiteOS)。 ## 使用指导 @@ -74,7 +66,7 @@ I3C可连接单个或多个I3C、I2C从器件,它主要用于: | I3cRequestIbi | 请求带内中断 | | I3cFreeIbi | 释放带内中断 | ->![](../public_sys-resources/icon-note.gif) **说明:** +>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 ### 开发步骤 @@ -102,7 +94,7 @@ DevHandle I3cOpen(int16_t number); | NULL | 打开I3C控制器失败 | | 控制器句柄 | 打开的I3C控制器句柄 | -假设系统中存在8个I3C控制器,编号从0到7,那么我们现在打开1号控制器: +假设系统中存在8个I3C控制器,编号从0到7,以下示例代码为打开1号控制器: ```c DevHandle i3cHandle = NULL; /* I3C控制器句柄 / diff --git a/zh-cn/device-dev/driver/driver-platform-i3c-develop.md b/zh-cn/device-dev/driver/driver-platform-i3c-develop.md index 3fdf899756..00fbe1ee79 100755 --- a/zh-cn/device-dev/driver/driver-platform-i3c-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-i3c-develop.md @@ -1,38 +1,28 @@ # I3C -- [概述](#1) - - [功能简介](#2) - - [基本概念](#3) - - [运作机制](#4) - - [约束与限制](#5) -- [开发指导](#6) - - [场景介绍](#7) - - [接口说明](#8) - - [开发步骤](#9) - ## 概述 ### 功能简介 I3C(Improved Inter Integrated Circuit)总线是由MIPI Alliance开发的一种简单、低成本的双向二线制同步串行总线。 -### 基本概念 - I3C是两线双向串行总线,针对多个传感器从设备进行了优化,并且一次只能由一个I3C主设备控制。 相比于I2C,I3C总线拥有更高的速度、更低的功耗,支持带内中断、从设备热接入以及切换当前主设备,同时向后兼容I2C从设备。 +### 基本概念 + - IBI(In-Band Interrupt):带内中断。在SCL线没有启动信号时,I3C从设备可以通过拉低SDA线使主设备发出SCL启动信号,从而发出带内中断请求。若有多个从机同时发出中断请求,I3C主机则通过从机地址进行仲裁,低地址优先相应。 - DAA(Dynamic Address Assignment):动态地址分配。I3C支持对从设备地址进行动态分配从而避免地址冲突。在分配动态地址之前,连接到I3C总线上的每个I3C设备都应以两种方式之一来唯一标识: 1)设备可能有一个符合I2C规范的静态地址,主机可以使用此静态地址; 2)在任何情况下,设备均应具有48位的临时ID。 除非设备具有静态地址且主机使用静态地址,否则主机应使用此48位临时ID。 - CCC(Common Command Code) :通用命令代码(CCC),所有I3C设备均支持CCC,可以直接将其传输到特定的I3C从设备,也可以同时传输到所有I3C从设备。 -- BCR(Bus Characteristic Register):总线特性寄存器,每个连接到 I3C 总线的 I3C 设备都应具有相关的只读总线特性寄存器 (BCR),该寄存器描述了I3C兼容设备在动态地址分配和通用命令代码中的作用和功能。 -- DCR(Device Characteristic Register):设备特性寄存器,连接到 I3C 总线的每个 I3C 设备都应具有相关的只读设备特性寄存器 (DCR)。 该寄存器描述了用于动态地址分配和通用命令代码的 I3C 兼容设备类型(例如,加速度计、陀螺仪等)。 +- BCR(Bus Characteristic Register):总线特性寄存器,每个连接到I3C总线的 I3C 设备都应具有相关的只读总线特性寄存器(BCR),该寄存器描述了I3C兼容设备在动态地址分配和通用命令代码中的作用和功能。 +- DCR(Device Characteristic Register):设备特性寄存器,连接到I3C总线的每个 I3C 设备都应具有相关的只读设备特性寄存器(DCR)。该寄存器描述了用于动态地址分配和通用命令代码的I3C兼容设备类型(例如,加速度计、陀螺仪等)。 ### 运作机制 -在HDF框架中,同类型控制器对象较多时(可能同时存在十几个同类型控制器),如果采用独立服务模式则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。I3C模块接口适配模式采用统一服务模式(如[图1](#fig1)所示)。 +在HDF框架中,同类型控制器对象较多时(可能同时存在十几个同类型控制器),如果采用独立服务模式则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。I3C模块接口适配模式采用统一服务模式(如[图1](#fig1)所示)。 I3C模块各分层的作用为:接口层提供打开控制器、传输消息、获取和设置控制器参数以及关闭控制器的接口。核心层主要提供绑定设备、初始化设备以及释放设备的能力。适配层实现其他具体的功能。 @@ -70,35 +60,36 @@ struct I3cMethod { **表1** I3cMethod结构体成员的回调函数功能说明 |函数成员|入参|出参|返回值|功能| |-|-|-|-|-| -|sendCccCmd|**cntlr**: 结构体指针,核心层I3C控制器;
**ccc**:传入的通用命令代码结构体指针;|**ccc**:传出的通用命令代码结构体指针;|HDF_STATUS相关状态|发送CCC(Common command Code,即通用命令代码)| -|Transfer |**cntlr**: 结构体指针,核心层I3C控制器;
**msgs**:结构体指针,用户消息 ;
**count**:int16_t,消息数量|**msgs**:结构体指针,用户消息 ;|HDF_STATUS相关状态|使用I3C模式传递用户消息| -|i2cTransfer |**cntlr**: 结构体指针,核心层I3C控制器;
**msgs**:结构体指针,用户消息 ;
**count**:int16_t,消息数量|**msgs**:结构体指针,用户消息 ;|HDF_STATUS相关状态|使用I2C模式传递用户消息| -|setConfig|**cntlr**: 结构体指针,核心层I3C控制器;
**config**: 控制器配置参数|无|HDF_STATUS相关状态|设置I3C控制器配置参数| -|getConfig|**cntlr**: 结构体指针,核心层I3C控制器;|**config**: 控制器配置参数|HDF_STATUS相关状态|获取I3C控制器配置参数| -|requestIbi|**device**: 结构体指针,核心层I3C设备;|无|HDF_STATUS相关状态|为I3C设备请求IBI(In-Bind Interrupt,即带内中断)| -|freeIbi|**device**: 结构体指针,核心层I3C设备;|无|HDF_STATUS相关状态|释放IBI| +|sendCccCmd| **cntlr**: 结构体指针,核心层I3C控制器
**ccc**:传入的通用命令代码结构体指针 | **ccc**:传出的通用命令代码结构体指针 | HDF_STATUS相关状态|发送CCC(Common command Code,即通用命令代码)| +|Transfer | **cntlr**: 结构体指针,核心层I3C控制器
**msgs**:结构体指针,用户消息
**count**:int16_t,消息数量 | **msgs**:结构体指针,用户消息 + | HDF_STATUS相关状态 | 使用I3C模式传递用户消息 | +|i2cTransfer | **cntlr**: 结构体指针,核心层I3C控制器
**msgs**:结构体指针,用户消息
**count**:int16_t,消息数量 | **msgs**:结构体指针,用户消息 | HDF_STATUS相关状态 | 使用I2C模式传递用户消息 | +|setConfig| **cntlr**: 结构体指针,核心层I3C控制器
**config**: 控制器配置参数| 无 | HDF_STATUS相关状态 | 设置I3C控制器配置参数 | +|getConfig| **cntlr**: 结构体指针,核心层I3C控制器| **config**: 控制器配置参数 | HDF_STATUS相关状态 | 获取I3C控制器配置参数 | +|requestIbi| **device**: 结构体指针,核心层I3C设备| 无 | HDF_STATUS相关状态 | 为I3C设备请求IBI(In-Bind Interrupt,即带内中断) | +|freeIbi| **device**: 结构体指针,核心层I3C设备| 无 | HDF_STATUS相关状态 | 释放IBI | ### 开发步骤 I3C模块适配的四个环节是实例化驱动入口、配置属性文件、实例化I3C控制器对象以及注册中断处理子程序。 -- **实例化驱动入口:** +- 实例化驱动入口: - 实例化HdfDriverEntry结构体成员。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 -- **配置属性文件:** +- 配置属性文件: - 在device_info.hcs文件中添加deviceNode描述。 - 【可选】添加i3c_config.hcs器件属性文件。 -- **实例化I3C控制器对象:** +- 实例化I3C控制器对象: - 初始化I3cCntlr成员。 - 实例化I3cCntlr成员I3cMethod方法集合,其定义和成员函数说明见下文。 -- **注册中断处理子程序:** +- 注册中断处理子程序: 为控制器注册中断处理程序,实现设备热接入和IBI(带内中断)功能。 -1. **实例化驱动入口** +1. 实例化驱动入口 驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 @@ -115,21 +106,21 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 .moduleVersion = 1, .Init = VirtualI3cInit, .Release = VirtualI3cRelease, - .moduleName = "virtual_i3c_driver",//【必要且与 HCS 里面的名字匹配】 + .moduleName = "virtual_i3c_driver",// 【必要且与hcs文件中的名字匹配】 }; - HDF_INIT(g_virtualI3cDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_virtualI3cDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 /* 核心层i3c_core.c管理器服务的驱动入口 */ struct HdfDriverEntry g_i3cManagerEntry = { .moduleVersion = 1, .Init = I3cManagerInit, .Release = I3cManagerRelease, - .moduleName = "HDF_PLATFORM_I3C_MANAGER",//这与device_info文件中device0对应 + .moduleName = "HDF_PLATFORM_I3C_MANAGER",// 这与device_info文件中device0对应 }; HDF_INIT(g_i3cManagerEntry); ``` -2. **配置属性文件** +2. 配置属性文件 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在i3c_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层I3cCntlr相关成员的默认值或限制范围有密切关系。 @@ -144,7 +135,7 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 从第二个节点开始配置具体I3C控制器信息,此节点并不表示某一路I3C控制器,而是代表一个资源性质设备,用于描述一类I3C控制器的信息。本例只有一个I3C控制器,如有多个控制器,则需要在device_info文件增加deviceNode信息,以及在i3c_config文件中增加对应的器件属性。 - - device_info.hcs 配置参考 + - device_info.hcs配置参考 ```c root { @@ -161,9 +152,9 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 policy = 0; // 等于0,不需要发布服务 priority = 56; // 驱动启动优先级 permission = 0644; // 驱动创建设备节点权限 - moduleName = "virtual_i3c_driver"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; - serviceName = "VIRTUAL_I3C_DRIVER"; //【必要】驱动对外发布服务的名称,必须唯一 - deviceMatchAttr = "virtual_i3c"; //【必要】用于配置控制器私有数据,要与i3c_config.hcs中对应控制器保持一致 + moduleName = "virtual_i3c_driver"; // 【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; + serviceName = "VIRTUAL_I3C_DRIVER"; // 【必要】驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "virtual_i3c"; // 【必要】用于配置控制器私有数据,要与i3c_config.hcs中对应控制器保持一致 } // 具体的控制器信息在 i3c_config.hcs 中 } ``` @@ -174,17 +165,17 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 root { platform { i3c_config { - match_attr = "virtual_i3c"; //【必要】需要和device_info.hcs中的deviceMatchAttr值一致 + match_attr = "virtual_i3c"; // 【必要】需要和device_info.hcs中的deviceMatchAttr值一致 template i3c_controller { // 模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 - busId = 0; //【必要】i3c总线号 + busId = 0; // 【必要】i3c总线号 busMode = 0x0; // 总线模式,0x0:纯净; 0x1:混合高速; 0x2:混合受限; 0x3: 混合低速; - regBasePhy = 0x120b0000; //【必要】物理基地址 - regSize = 0xd1; //【必要】寄存器位宽 - IrqNum = 20; //【必要】中断号 - i3cMaxRate = 12900000; //【可选】i3c模式最大时钟速率 - i3cRate = 12500000; //【可选】i3c模式时钟速率 - i2cFmRate = 1000000; //【可选】i2c FM模式时钟速率 - i2cFmPlusRate = 400000; //【可选】i2c FM+模式时钟速率 + regBasePhy = 0x120b0000; // 【必要】物理基地址 + regSize = 0xd1; // 【必要】寄存器位宽 + IrqNum = 20; // 【必要】中断号 + i3cMaxRate = 12900000; // 【可选】i3c模式最大时钟速率 + i3cRate = 12500000; // 【可选】i3c模式时钟速率 + i2cFmRate = 1000000; // 【可选】i2c FM模式时钟速率 + i2cFmPlusRate = 400000; // 【可选】i2c FM+模式时钟速率 } controller_0 :: i3c_controller { busId = 18; @@ -195,7 +186,7 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 } ``` -3. **实例化I3C控制器对象** +3. 实例化I3C控制器对象 配置属性文件完成后,要以核心层I3cCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化I3cCntlr成员I3cMethod(让用户可以通过接口来调用驱动底层函数)。 @@ -207,11 +198,11 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 ```c struct VirtualI3cCntlr { - struct I3cCntlr cntlr; //【必要】是核心层控制对象,具体描述见下面 - volatile unsigned char *regBase;//【必要】寄存器基地址 - uint32_t regBasePhy; //【必要】寄存器物理基地址 - uint32_t regSize; //【必要】寄存器位宽 - uint16_t busId; //【必要】设备号 + struct I3cCntlr cntlr; // 【必要】是核心层控制对象,具体描述见下面 + volatile unsigned char *regBase;// 【必要】寄存器基地址 + uint32_t regBasePhy; // 【必要】寄存器物理基地址 + uint32_t regSize; // 【必要】寄存器位宽 + uint16_t busId; // 【必要】设备号 uint16_t busMode; uint16_t IrqNum; uint32_t i3cMaxRate; @@ -261,34 +252,34 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 static int32_t VirtualI3cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) { int32_t ret; - struct VirtualI3cCntlr *virtual = NULL; //【必要】自定义结构体对象 + struct VirtualI3cCntlr *virtual = NULL; // 【必要】自定义结构体对象 (void)device; - virtual = (struct VirtualI3cCntlr *)OsalMemCalloc(sizeof(*virtual)); //【必要】内存分配 + virtual = (struct VirtualI3cCntlr *)OsalMemCalloc(sizeof(*virtual)); // 【必要】内存分配 if (virtual == NULL) { HDF_LOGE("%s: Malloc virtual fail!", __func__); return HDF_ERR_MALLOC_FAIL; } - ret = VirtualI3cReadDrs(virtual, node); //【必要】将i3c_config文件的默认值填充到结构体中 + ret = VirtualI3cReadDrs(virtual, node); // 【必要】将i3c_config文件的默认值填充到结构体中 if (ret != HDF_SUCCESS) { HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret); goto __ERR__; } ... - virtual->regBase = OsalIoRemap(virtual->regBasePhy, virtual->regSize);//【必要】地址映射 + virtual->regBase = OsalIoRemap(virtual->regBasePhy, virtual->regSize);// 【必要】地址映射 ret = OsalRegisterIrq(hi35xx->softIrqNum, OSAL_IRQF_TRIGGER_NONE, I3cIbiHandle, "I3C", virtual); //【必要】注册中断程序 if (ret != HDF_SUCCESS) { HDF_LOGE("%s: register irq failed!", __func__); return ret; } ... - VirtualI3cCntlrInit(virtual); //【必要】I3C设备的初始化 - virtual->cntlr.priv = (void *)node; //【必要】存储设备属性 - virtual->cntlr.busId = virtual->busId; //【必要】初始化I3cCntlr成员 - virtual->cntlr.ops = &g_method; //【必要】I3cMethod的实例化对象的挂载 + VirtualI3cCntlrInit(virtual); // 【必要】I3C设备的初始化 + virtual->cntlr.priv = (void *)node; // 【必要】存储设备属性 + virtual->cntlr.busId = virtual->busId; // 【必要】初始化I3cCntlr成员 + virtual->cntlr.ops = &g_method; // 【必要】I3cMethod的实例化对象的挂载 (void)OsalSpinInit(&virtual->spin); - ret = I3cCntlrAdd(&virtual->cntlr); //【必要且重要】调用此函数将控制器添加至核心,返回成功信号后驱动才完全接入平台核心层 + ret = I3cCntlrAdd(&virtual->cntlr); // 【必要且重要】调用此函数将控制器添加至核心,返回成功信号后驱动才完全接入平台核心层 if (ret != HDF_SUCCESS) { HDF_LOGE("%s: add i3c controller failed! ret = %d", __func__, ret); (void)OsalSpinDestroy(&virtual->spin); @@ -296,7 +287,7 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 } return HDF_SUCCESS; - __ERR__: //若控制器添加失败,需要执行去初始化相关函数 + __ERR__: // 若控制器添加失败,需要执行去初始化相关函数 if (virtual != NULL) { OsalMemFree(virtual); virtual = NULL; @@ -326,16 +317,16 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 } ``` - - Release 函数参考 + - Release函数参考 **入参:** - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 。 + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备hcs配置文件的信息 。 **返回值:** 无。 **函数说明:** - 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 ```c static void VirtualI3cRemoveByNode(const struct DeviceResourceNode *node) @@ -362,8 +353,8 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 cntlr = I3cCntlrGet(busId); if (cntlr != NULL && cntlr->priv == node) { I3cCntlrPut(cntlr); - I3cCntlrRemove(cntlr); //【必要】主要是从管理器驱动那边移除I3cCntlr对象 - virtual = (struct VirtualI3cCntlr *)cntlr;//【必要】通过强制转换获取自定义的对象并进行release操作 + I3cCntlrRemove(cntlr); // 【必要】主要是从管理器驱动那边移除I3cCntlr对象 + virtual = (struct VirtualI3cCntlr *)cntlr;// 【必要】通过强制转换获取自定义的对象并进行release操作 (void)OsalSpinDestroy(&virtual->spin); OsalMemFree(virtual); } @@ -381,14 +372,14 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、 return; } ... - //遍历、解析i3c_config.hcs中的所有配置节点,并分别进行release操作 + // 遍历、解析i3c_config.hcs中的所有配置节点,并分别进行release操作 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { VirtualI3cRemoveByNode(childNode); //函数定义如上 } } ``` -4. **注册中断处理子程序** +4. 注册中断处理子程序 在中断处理程序中通过判断中断产生的地址,实现热接入、IBI等操作。 diff --git a/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md b/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md index 52fbc88dfe..7fb0abc67f 100755 --- a/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md +++ b/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md @@ -3,11 +3,11 @@ ## 概述 -- CSI(Camera Serial Interface)是由MIPI联盟下Camera工作组指定的接口标准。CSI-2是MIPI CSI第二版,主要由应用层、协议层、物理层组成,最大支持4通道数据传输、单线传输速度高达1Gb/s。 +CSI(Camera Serial Interface)是由MIPI联盟下Camera工作组指定的接口标准。CSI-2是MIPI CSI第二版,主要由应用层、协议层、物理层组成,最大支持4通道数据传输、单线传输速度高达1Gb/s。 -- 物理层支持HS(High Speed)和LP(Low Power)两种工作模式。HS模式下采用低压差分信号,功耗较大,但数据传输速率可以很高(数据速率为80M~1Gbps);LP模式下采用单端信号,数据速率很低(<10Mbps),但是相应的功耗也很低。两种模式的结合保证了MIPI总线在需要传输大量数据(如图像)时可以高速传输,而在不需要传输大数据量时又能够减少功耗。 +物理层支持HS(High Speed)和LP(Low Speed)两种工作模式。HS模式下采用低压差分信号,功耗较大,但数据传输速率可以很高(数据速率为80M~1Gbps);LP模式下采用单端信号,数据速率很低(<10Mbps),但是相应的功耗也很低。两种模式的结合保证了MIPI总线在需要传输大量数据(如图像)时可以高速传输,而在不需要传输大数据量时又能够减少功耗。 -- 图1显示了简化的CSI接口。D-PHY采用1对源同步的差分时钟和1~4对差分数据线来进行数据传输。数据传输采用DDR方式,即在时钟的上下边沿都有数据传输。 +图1显示了简化的CSI接口。D-PHY采用1对源同步的差分时钟和1~4对差分数据线来进行数据传输。数据传输采用DDR方式,即在时钟的上下边沿都有数据传输。 **图 1** CSI发送、接收接口 ![](figures/CSI发送-接收接口.png) @@ -567,7 +567,7 @@ void PalMipiCsiTestSample(void) /* lane模式参数为0 */ mode = LANE_DIVIDE_MODE_0; - /* 设置MIPI RX的 Lane分布 */ + /* 设置MIPI RX的Lane分布 */ ret = MipiCsiSetHsMode(MipiCsiHandle, mode); if (ret != 0) { HDF_LOGE("%s: MipiCsiSetHsMode fail! ret=%d\n", __func__, ret); diff --git a/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md b/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md index ac5cc6654d..517e780a67 100755 --- a/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md @@ -2,7 +2,7 @@ ## 概述 -CSI(Camera Serial Interface)是由MIPI(Mobile Industry Processor Interface )联盟下Camera工作组指定的接口标准。在HDF框架中,MIPI CSI的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,MIPI CSI的接口关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 +CSI(Camera Serial Interface)是由MIPI(Mobile Industry Processor Interface)联盟下Camera工作组指定的接口标准。在HDF框架中,MIPI CSI的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,MIPI CSI的接口关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 图 1 无服务模式结构图 @@ -10,7 +10,7 @@ CSI(Camera Serial Interface)是由MIPI(Mobile Industry Processor Interface ## 接口说明 -MipiCsiCntlrMethod定义 +MipiCsiCntlrMethod定义: ```c struct MipiCsiCntlrMethod { @@ -35,12 +35,12 @@ struct MipiCsiCntlrMethod { | setPhyCmvmode | **cntlr**:结构体指针,MipiCsi控制器 ;
**devno**:uint8_t,设备编号;
**cmvMode**:枚举类型,共模电压模式参数 | 无 | HDF_STATUS相关状态 | 设置共模电压模式 | | setExtDataType | **cntlr**:结构体指针,MipiCsi控制器 ;
**dataType**:结构体指针,定义YUV和原始数据格式以及位深度 | 无 | HDF_STATUS相关状态 | 设置YUV和RAW数据格式和位深 | | setHsMode | **cntlr**:结构体指针,MipiCsi控制器 ;
**laneDivideMode**:枚举类型,lane模式参数 | 无 | HDF_STATUS相关状态 | 设置MIPI RX的Lane分布 | -| enableClock | **cntlr**:结构体指针,MipiCsi控制器 ;
**comboDev**:uint8_t,通路序号 | 无 | HDF_STATUS相关状态 | 使能mipi的时钟 | -| disableClock | **cntlr**:结构体指针,MipiCsi控制器 ;
**comboDev**:uint8_t,通路序号 | 无 | HDF_STATUS相关状态 | 关闭mipi的时钟 | +| enableClock | **cntlr**:结构体指针,MipiCsi控制器 ;
**comboDev**:uint8_t,通路序号 | 无 | HDF_STATUS相关状态 | 使能MIPI的时钟 | +| disableClock | **cntlr**:结构体指针,MipiCsi控制器 ;
**comboDev**:uint8_t,通路序号 | 无 | HDF_STATUS相关状态 | 关闭MIPI的时钟 | | resetRx | **cntlr**:结构体指针,MipiCsi控制器 ;
**comboDev**:uint8_t,通路序号 | 无 | HDF_STATUS相关状态 | 复位MIPI RX | | unresetRx | **cntlr**:结构体指针,MipiCsi控制器 ;
**comboDev**:uint8_t,通路序号 | 无 | HDF_STATUS相关状态 | 撤销复位MIPI RX | -| enableSensorClock | **cntlr**:结构体指针,MipiCsi控制器 ;
**snsClkSource**:uint8_t,传感器的时钟信号线号 | 无 | HDF_STATUS相关状态 | 使能mipi上的Sensor时钟 | -| disableSensorClock | **cntlr**:结构体指针,MipiCsi控制器 ;
**snsClkSource**:uint8_t,传感器的时钟信号线号 | 无 | HDF_STATUS相关状态 | 关闭mipi上的Sensor时钟 | +| enableSensorClock | **cntlr**:结构体指针,MipiCsi控制器 ;
**snsClkSource**:uint8_t,传感器的时钟信号线号 | 无 | HDF_STATUS相关状态 | 使能MIPI上的Sensor时钟 | +| disableSensorClock | **cntlr**:结构体指针,MipiCsi控制器 ;
**snsClkSource**:uint8_t,传感器的时钟信号线号 | 无 | HDF_STATUS相关状态 | 关闭MIPI上的Sensor时钟 | | resetSensor | **cntlr**:结构体指针,MipiCsi控制器 ;
**snsClkSource**:uint8_t,传感器的时钟信号线号 | 无 | HDF_STATUS相关状态 | 复位Sensor | | unresetSensor | **cntlr**:结构体指针,MipiCsi控制器 ;
**snsClkSource**:uint8_t,传感器的时钟信号线号 | 无 | HDF_STATUS相关状态 | 撤销复位Sensor | @@ -60,7 +60,7 @@ MIPI CSI模块适配的三个环节是配置属性文件、实例化驱动入、 3. **实例化MIPICSI控制器对象:** - 初始化MipiCsiCntlr成员。 - 实例化MipiCsiCntlr成员MipiCsiCntlrMethod。 - >![](../public_sys-resources/icon-note.gif) **说明:** + >![](../public_sys-resources/icon-note.gif) **说明:**
>实例化MipiCsiCntlr成员MipiCsiCntlrMethod,其定义和成员说明见[接口说明](#section2_MIPI_CSIDevelop)。 4. **驱动调试:** @@ -90,8 +90,8 @@ MIPI CSI模块适配的三个环节是配置属性文件、实例化驱动入、 policy = 0; priority = 160; permission = 0644; - moduleName = "HDF_MIPI_RX"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; - serviceName = "HDF_MIPI_RX"; //【必要且唯一】驱动对外发布服务的名称 + moduleName = "HDF_MIPI_RX"; // 【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; + serviceName = "HDF_MIPI_RX"; // 【必要且唯一】驱动对外发布服务的名称 } } } @@ -108,11 +108,11 @@ MIPI CSI模块适配的三个环节是配置属性文件、实例化驱动入、 ```c struct HdfDriverEntry g_mipiCsiDriverEntry = { .moduleVersion = 1, - .Init = Hi35xxMipiCsiInit, //见Init参考 - .Release = Hi35xxMipiCsiRelease, //见Release参考 - .moduleName = "HDF_MIPI_RX", //【必要】需要与device_info.hcs 中保持一致。 + .Init = Hi35xxMipiCsiInit, // 见Init参考 + .Release = Hi35xxMipiCsiRelease, // 见Release参考 + .moduleName = "HDF_MIPI_RX", // 【必要】需要与device_info.hcs 中保持一致。 }; - HDF_INIT(g_mipiCsiDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_mipiCsiDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 ``` 3. 完成驱动入口注册之后,最后一步就是以核心层MipiCsiCntlr对象的初始化为核心,实现HdfDriverEntry成员函数(Bind,Init,Release)。MipiCsiCntlr对象的初始化包括厂商自定义结构体(用于传递参数和数据)和实例化MipiCsiCntlr成员MipiCsiCntlrMethod(让用户可以通过接口来调用驱动底层函数)。 @@ -151,7 +151,7 @@ MIPI CSI模块适配的三个环节是配置属性文件、实例化驱动入、 }; } ComboDevAttr; - //MipiCsiCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 + // MipiCsiCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 struct MipiCsiCntlr { /** 当驱动程序绑定到HDF框架时,将发送此控制器提供的服务 */ struct IDeviceIoService service; @@ -196,10 +196,10 @@ MIPI CSI模块适配的三个环节是配置属性文件、实例化驱动入、 - **Init函数参考** **入参:** - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备hcs配置文件的信息 **返回值:** - HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) + HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) | 状态(值) | 问题描述 | @@ -221,21 +221,21 @@ MIPI CSI模块适配的三个环节是配置属性文件、实例化驱动入、 int32_t ret; HDF_LOGI("%s: enter!", __func__); - g_mipiCsi.priv = NULL; //g_mipiTx是定义的全局变量 - //static struct MipiCsiCntlr g_mipiCsi = { - //.devNo = 0 + g_mipiCsi.priv = NULL; // g_mipiTx是定义的全局变量 + // static struct MipiCsiCntlr g_mipiCsi = { + // .devNo = 0 //}; g_mipiCsi.ops = &g_method; //MipiCsiCntlrMethod的实例化对象的挂载 #ifdef CONFIG_HI_PROC_SHOW_SUPPORT g_mipiCsi.debugs = &g_debugMethod; #endif - ret = MipiCsiRegisterCntlr(&g_mipiCsi, device); //【必要】调用核心层函数和g_mipiTx初始化核心层全局变量 + ret = MipiCsiRegisterCntlr(&g_mipiCsi, device); // 【必要】调用核心层函数和g_mipiTx初始化核心层全局变量 if (ret != HDF_SUCCESS) { HDF_LOGE("%s: [MipiCsiRegisterCntlr] failed!", __func__); return ret; } - ret = MipiRxDrvInit(); //【必要】厂商对设备的初始化,形式不限 + ret = MipiRxDrvInit(); // 【必要】厂商对设备的初始化,形式不限 if (ret != HDF_SUCCESS) { HDF_LOGE("%s: [MipiRxDrvInit] failed.", __func__); return ret; @@ -254,19 +254,19 @@ MIPI CSI模块适配的三个环节是配置属性文件、实例化驱动入、 return ret; } - //mipi_dsi_core.c核心层 + // mipi_dsi_core.c核心层 int32_t MipiCsiRegisterCntlr(struct MipiCsiCntlr *cntlr, struct HdfDeviceObject *device) { ... - //定义的全局变量:static struct MipiCsiHandle g_mipiCsihandle[MAX_CNTLR_CNT]; + // 定义的全局变量:static struct MipiCsiHandle g_mipiCsihandle[MAX_CNTLR_CNT]; if (g_mipiCsihandle[cntlr->devNo].cntlr == NULL) { (void)OsalMutexInit(&g_mipiCsihandle[cntlr->devNo].lock); (void)OsalMutexInit(&(cntlr->lock)); - g_mipiCsihandle[cntlr->devNo].cntlr = cntlr; //初始化MipiCsiHandle成员 + g_mipiCsihandle[cntlr->devNo].cntlr = cntlr; // 初始化MipiCsiHandle成员 g_mipiCsihandle[cntlr->devNo].priv = NULL; - cntlr->device = device; //使HdfDeviceObject与MipiCsiHandle可以相互转化的前提 - device->service = &(cntlr->service); //使HdfDeviceObject与MipiCsiHandle可以相互转化的前提 + cntlr->device = device; // 使HdfDeviceObject与MipiCsiHandle可以相互转化的前提 + device->service = &(cntlr->service); // 使HdfDeviceObject与MipiCsiHandle可以相互转化的前提 cntlr->priv = NULL; HDF_LOGI("%s: success.", __func__); @@ -294,16 +294,16 @@ MIPI CSI模块适配的三个环节是配置属性文件、实例化驱动入、 { struct MipiCsiCntlr *cntlr = NULL; ... - cntlr = MipiCsiCntlrFromDevice(device); //这里有HdfDeviceObject到MipiCsiCntlr的强制转化 - //return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service; + cntlr = MipiCsiCntlrFromDevice(device); // 这里有HdfDeviceObject到MipiCsiCntlr的强制转化 + // return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service; ... OsalSpinDestroy(&cntlr->ctxLock); #ifdef MIPICSI_VFS_SUPPORT MipiCsiDevModuleExit(cntlr->devNo); #endif - MipiRxDrvExit(); //【必要】对厂商设备所占资源的释放 - MipiCsiUnregisterCntlr(&g_mipiCsi); //空函数 + MipiRxDrvExit(); // 【必要】对厂商设备所占资源的释放 + MipiCsiUnregisterCntlr(&g_mipiCsi); // 空函数 g_mipiCsi.priv = NULL; HDF_LOGI("%s: unload mipi csi driver success!", __func__); diff --git a/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md b/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md index 44ca06b5bb..55c9daabd3 100644 --- a/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md +++ b/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md @@ -3,11 +3,11 @@ ## 概述 -- DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设(通常是LCD或者类似的显示设备),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议。 +DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设(通常是LCD或者类似的显示设备),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议。 -- MIPI DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号。 +MIPI DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号。 -- 图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。 +图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。 **图1** DSI发送、接收接口 @@ -25,7 +25,7 @@ | 设置MIPI DSI进入Low power模式/High speed模式 | - MipiDsiSetLpMode:设置MIPI DSI进入Low power模式
- MipiDsiSetHsMode:设置MIPI DSI进入High speed模式 | | MIPI DSI发送/回读指令 | - MipiDsiTx:MIPI DSI发送相应指令的接口
- MipiDsiRx:MIPI DSI按期望长度回读的接口 | -> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 diff --git a/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md b/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md index 6a626d65cd..2a6baf0e23 100755 --- a/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md @@ -22,10 +22,10 @@ struct MipiDsiCntlrMethod { // 核心层结构体的成员函数 int32_t (*getCmd)(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out); void (*toHs)(struct MipiDsiCntlr *cntlr); void (*toLp)(struct MipiDsiCntlr *cntlr); - void (*enterUlps)(struct MipiDsiCntlr *cntlr);//【可选】进入超低功耗模式 - void (*exitUlps)(struct MipiDsiCntlr *cntlr); //【可选】退出超低功耗模式 + void (*enterUlps)(struct MipiDsiCntlr *cntlr);// 【可选】进入超低功耗模式 + void (*exitUlps)(struct MipiDsiCntlr *cntlr); // 【可选】退出超低功耗模式 int32_t (*powerControl)(struct MipiDsiCntlr *cntlr, uint8_t enable);//【可选】使能/去使能功耗控制 - int32_t (*attach)(struct MipiDsiCntlr *cntlr);//【可选】将一个DSI设备连接上host + int32_t (*attach)(struct MipiDsiCntlr *cntlr);// 【可选】将一个DSI设备连接上host }; ``` @@ -33,11 +33,11 @@ struct MipiDsiCntlrMethod { // 核心层结构体的成员函数 | 成员函数 | 入参 | 出参 | 返回状态 | 功能 | | -------- | -------- | -------- | -------- | -------- | -| setCntlrCfg | cntlr:结构体指针,MipiDsi控制器  | 无 | HDF_STATUS相关状态 | 设置控制器参数 | -| setCmd | cntlr:结构体指针,MipiDsi控制器;
cmd:结构体指针,指令传入值; | 无 | HDF_STATUS相关状态 | 向显示设备发送指令 | -| getCmd | cntlr:结构体指针,MipiDsi控制器;
cmd:传入的命令描述结构体指针;
readLen:读取的数据大小; | out:结构体指针,用于存储读取的数据。 | HDF_STATUS相关状态 | 通过发送指令读取数据 | -| toHs | cntlr: 结构体指针,MipiDsi控制器 ; | 无 | HDF_STATUS相关状态 | 设置为高速模式 | -| toLp | cntlr: 结构体指针,MipiDsi控制器 ; | 无 | HDF_STATUS相关状态 | 设置为低电模式 | +| setCntlrCfg | cntlr:结构体指针,MipiDsi控制器 | 无 | HDF_STATUS相关状态 | 设置控制器参数 | +| setCmd | cntlr:结构体指针,MipiDsi控制器
cmd:结构体指针,指令传入值 | 无 | HDF_STATUS相关状态 | 向显示设备发送指令 | +| getCmd | cntlr:结构体指针,MipiDsi控制器
cmd:传入的命令描述结构体指针
readLen:读取的数据大小 | out:结构体指针,用于存储读取的数据 | HDF_STATUS相关状态 | 通过发送指令读取数据 | +| toHs | cntlr:结构体指针,MipiDsi控制器 | 无 | HDF_STATUS相关状态 | 设置为高速模式 | +| toLp | cntlr:结构体指针,MipiDsi控制器 | 无 | HDF_STATUS相关状态 | 设置为低电模式 | ## 开发步骤 @@ -55,7 +55,7 @@ MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口 3. **实例化MIPIDSI控制器对象:** - 初始化MipiDsiCntlr成员。 - 实例化MipiDsiCntlr成员MipiDsiCntlrMethod。 - > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 实例化MipiDsiCntlr成员MipiDsiCntlrMethod,其定义和成员说明见[接口说明](#接口说明)。 4. **驱动调试:** @@ -66,7 +66,7 @@ MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口 下方将以mipi_tx_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 -1. 一般来说,驱动开发首先需要在 xx_config.hcs 中配置器件属性,并在device_info.hcs文件中添加deviceNode描述。器件属性值与核心层MipiDsiCntlr 成员的默认值或限制范围有密切关系,deviceNode信息与驱动入口注册相关。 +1. 一般来说,驱动开发首先需要在xx_config.hcs中配置器件属性,并在device_info.hcs文件中添加deviceNode描述。器件属性值与核心层MipiDsiCntlr成员的默认值或限制范围有密切关系,deviceNode信息与驱动入口注册相关。 但本例中MIPI控制器无需配置额外属性,如有厂商需要,则需要在device_info文件的deviceNode增加deviceMatchAttr信息,以及增加mipidsi_config文件。 @@ -84,7 +84,7 @@ MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口 policy = 0; priority = 150; permission = 0644; - moduleName = "HDF_MIPI_TX"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; + moduleName = "HDF_MIPI_TX"; // 【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致 serviceName = "HDF_MIPI_TX"; // 【必要且唯一】驱动对外发布服务的名称 } } @@ -96,20 +96,20 @@ MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口 2. 完成器件属性文件的配置之后,下一步请实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HdfDriverEntry结构体的函数指针成员会被厂商操作函数填充,HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组,方便调用。 一般在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - - MIPI DSI驱动入口参考。 + - MIPI DSI驱动入口参考 ``` struct HdfDriverEntry g_mipiTxDriverEntry = { .moduleVersion = 1, - .Init = Hi35xxMipiTxInit, //见Init参考 - .Release = Hi35xxMipiTxRelease,//见Release参考 - .moduleName = "HDF_MIPI_TX", //【必要】需要与device_info.hcs 中保持一致。 + .Init = Hi35xxMipiTxInit, // 见Init参考 + .Release = Hi35xxMipiTxRelease,// 见Release参考 + .moduleName = "HDF_MIPI_TX", // 【必要】需要与device_info.hcs 中保持一致。 }; - HDF_INIT(g_mipiTxDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_mipiTxDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 ``` 3. 完成驱动入口注册之后,最后一步就是以核心层MipiDsiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化MipiDsiCntlr成员MipiDsiCntlrMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 - - 自定义结构体参考。 + - 自定义结构体参考 从驱动的角度看,自定义结构体是参数和数据的载体,一般来说,config文件中的数值也会用来初始化结构体成员,但本例的mipidsi无器件属性文件,故基本成员结构与MipiDsiCntlr无太大差异。 @@ -120,10 +120,10 @@ MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口 short laneId[LANE_MAX_NUM]; // lane号 OutPutModeTag outputMode; // 输出模式选择:刷新模式,命令行模式和视频流模式 VideoModeTag videoMode; // 显示设备的同步模式 - OutputFormatTag outputFormat; // 输出DSI图像数据格式:RGB or YUV + OutputFormatTag outputFormat; // 输出DSI图像数据格式:RGB或YUV SyncInfoTag syncInfo; // 时序相关的设置 - unsigned int phyDataRate; // mbps - unsigned int pixelClk; // KHz + unsigned int phyDataRate; // 数率:mbps + unsigned int pixelClk; // 时钟:KHz } ComboDevCfgTag; // MipiDsiCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 @@ -153,7 +153,7 @@ MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: @@ -178,29 +178,29 @@ MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口 static int32_t Hi35xxMipiTxInit(struct HdfDeviceObject *device) { int32_t ret; - g_mipiTx.priv = NULL; //g_mipiTx是定义的全局变量 - //static struct MipiDsiCntlr g_mipiTx { + g_mipiTx.priv = NULL; // g_mipiTx是定义的全局变量 + // static struct MipiDsiCntlr g_mipiTx { // .devNo=0 //}; - g_mipiTx.ops = &g_method;//MipiDsiCntlrMethod的实例化对象的挂载 - ret = MipiDsiRegisterCntlr(&g_mipiTx, device);//【必要】调用核心层函数和g_mipiTx初始化核心层全局变量 + g_mipiTx.ops = &g_method;// MipiDsiCntlrMethod的实例化对象的挂载 + ret = MipiDsiRegisterCntlr(&g_mipiTx, device);// 【必要】调用核心层函数和g_mipiTx初始化核心层全局变量 ... - return MipiTxDrvInit(0); //【必要】厂商对设备的初始化,形式不限 + return MipiTxDrvInit(0); // 【必要】厂商对设备的初始化,形式不限 } - //mipi_dsi_core.c核心层 + // mipi_dsi_core.c核心层 int32_t MipiDsiRegisterCntlr(struct MipiDsiCntlr *cntlr, struct HdfDeviceObject *device) { ... - //定义的全局变量:static struct MipiDsiHandle g_mipiDsihandle[MAX_CNTLR_CNT]; + // 定义的全局变量:static struct MipiDsiHandle g_mipiDsihandle[MAX_CNTLR_CNT]; if (g_mipiDsihandle[cntlr->devNo].cntlr == NULL) { (void)OsalMutexInit(&g_mipiDsihandle[cntlr->devNo].lock); (void)OsalMutexInit(&(cntlr->lock)); - g_mipiDsihandle[cntlr->devNo].cntlr = cntlr;//初始化MipiDsiHandle成员 + g_mipiDsihandle[cntlr->devNo].cntlr = cntlr;// 初始化MipiDsiHandle成员 g_mipiDsihandle[cntlr->devNo].priv = NULL; - cntlr->device = device; //使HdfDeviceObject与MipiDsiHandle可以相互转化的前提 - device->service = &(cntlr->service); //使HdfDeviceObject与MipiDsiHandle可以相互转化的前提 + cntlr->device = device; // 使HdfDeviceObject与MipiDsiHandle可以相互转化的前提 + device->service = &(cntlr->service); // 使HdfDeviceObject与MipiDsiHandle可以相互转化的前提 cntlr->priv = NULL; ... return HDF_SUCCESS; @@ -213,7 +213,7 @@ MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: @@ -221,7 +221,7 @@ MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口 函数说明: - 该函数需要在驱动入口结构体中赋值给 Release 接口, 当 HDF 框架调用 Init 函数初始化驱动失败时,可以调用 Release 释放驱动资源, 该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。 + 该函数需要在驱动入口结构体中赋值给Release接口,当DF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源,该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。 ``` @@ -229,11 +229,11 @@ MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口 { struct MipiDsiCntlr *cntlr = NULL; ... - cntlr = MipiDsiCntlrFromDevice(device);//这里有HdfDeviceObject到MipiDsiCntlr的强制转化 - //return (device == NULL) ? NULL : (struct MipiDsiCntlr *)device->service; + cntlr = MipiDsiCntlrFromDevice(device);// 这里有HdfDeviceObject到MipiDsiCntlr的强制转化 + // return (device == NULL) ? NULL : (struct MipiDsiCntlr *)device->service; ... - MipiTxDrvExit(); //【必要】对厂商设备所占资源的释放 - MipiDsiUnregisterCntlr(&g_mipiTx); //空函数 + MipiTxDrvExit(); // 【必要】对厂商设备所占资源的释放 + MipiDsiUnregisterCntlr(&g_mipiTx); // 空函数 g_mipiTx.priv = NULL; HDF_LOGI("%s: unload mipi_tx driver 1212!", __func__); } diff --git a/zh-cn/device-dev/driver/driver-platform-mmc-develop.md b/zh-cn/device-dev/driver/driver-platform-mmc-develop.md index 2b586b8eeb..8c454e5bf6 100755 --- a/zh-cn/device-dev/driver/driver-platform-mmc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-mmc-develop.md @@ -3,7 +3,7 @@ ## 概述 -MMC(MultiMedia Card),即多媒体卡,在HDF框架中,MMC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 +MMC(MultiMedia Card)即多媒体卡。在HDF框架中,MMC的接口适配模式采用独立服务模式。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 **图1** MMC独立服务模式结构图 @@ -39,21 +39,21 @@ struct MmcCntlrOps { | 成员函数 | 入参 | 返回值 | 功能 | | -------- | -------- | -------- | -------- | -| doRequest | cntlr: 核心层结构体指针;mmc控制器 ;cmd: 结构体指针,传入命令值 | HDF_STATUS相关状态 | request相应处理 | -| setClock | cntlr: 核心层结构体指针;mmc控制器 ;clock: 时钟传入值 | HDF_STATUS相关状态 | 设置时钟频率 | -| setPowerMode | cntlr: 核心层结构体指针;mmc控制器 ;mode: 枚举值(见MmcPowerMode定义),功耗模式 | HDF_STATUS相关状态 | 设置功耗模式 | -| setBusWidth | cntlr: 核心层结构体指针;mmc控制器 ;width: 枚举值(见MmcBusWidth定义),总线带宽 | HDF_STATUS相关状态 | 设置总线带宽 | -| setBusTiming | cntlr: 核心层结构体指针;mmc控制器 ;timing: 枚举值(见MmcBusTiming定义),总线时序 | HDF_STATUS相关状态 | 设置总线时序 | -| setSdioIrq | cntlr: 核心层结构体指针;mmc控制器 ;enable: 布尔值,控制中断 | HDF_STATUS相关状态 | 使能/去使能SDIO中断 | -| hardwareReset | cntlr: 核心层结构体指针;mmc控制器 ; | HDF_STATUS相关状态 | 复位硬件 | -| systemInit | cntlr: 核心层结构体指针;mmc控制器 ; | HDF_STATUS相关状态 | 系统初始化 | -| setEnhanceSrobe | cntlr: 核心层结构体指针,mmc控制器 ;enable: 布尔值,设置功能 | HDF_STATUS相关状态 | 设置增强选通 | -| switchVoltage | cntlr: 核心层结构体指针;mmc控制器 ;volt: 枚举值,电压值(3.3,1.8,1.2V); | HDF_STATUS相关状态 | 设置电压值 | -| devReadOnly | cntlr: 核心层结构体指针;mmc控制器 ; | 布尔值 | 检验设备是否只读 | -| cardPluged | cntlr: 核心层结构体指针;mmc控制器 ; | 布尔值 | 检验设备是否拔出 | -| devBusy | cntlr: 核心层结构体指针;mmc控制器 ; | 布尔值 | 检验设备是否忙碌 | -| tune | cntlr: 核心层结构体指针;mmc控制器 ;cmdCode: uint32_t,命令代码; | HDF_STATUS相关状态 | 调谐 | -| rescanSdioDev | cntlr: 核心层结构体指针;mmc控制器 ; | HDF_STATUS相关状态 | 扫描并添加SDIO设备 | +| doRequest | cntlr:核心层结构体指针,MMC控制器
cmd:结构体指针,传入命令值 | HDF_STATUS相关状态 | request相应处理 | +| setClock | cntlr:核心层结构体指针,MMC控制器
clock:时钟传入值 | HDF_STATUS相关状态 | 设置时钟频率 | +| setPowerMode | cntlr:核心层结构体指针,MMC控制器
mode:枚举值(见MmcPowerMode定义),功耗模式 | HDF_STATUS相关状态 | 设置功耗模式 | +| setBusWidth | cntlr:核心层结构体指针,MMC控制器
width:枚举值(见MmcBusWidth定义),总线带宽 | HDF_STATUS相关状态 | 设置总线带宽 | +| setBusTiming | cntlr:核心层结构体指针,MMC控制器
timing:枚举值(见MmcBusTiming定义),总线时序 | HDF_STATUS相关状态 | 设置总线时序 | +| setSdioIrq | cntlr:核心层结构体指针,MMC控制器
enable:布尔值,控制中断 | HDF_STATUS相关状态 | 使能/去使能SDIO中断 | +| hardwareReset | cntlr:核心层结构体指针,MMC控制器 | HDF_STATUS相关状态 | 复位硬件 | +| systemInit | cntlr:核心层结构体指针,MMC控制器 | HDF_STATUS相关状态 | 系统初始化 | +| setEnhanceSrobe | cntlr:核心层结构体指针,MMC控制器
enable:布尔值,设置功能 | HDF_STATUS相关状态 | 设置增强选通 | +| switchVoltage | cntlr:核心层结构体指针,MMC控制器
volt:枚举值,电压值(3.3,1.8,1.2V) | HDF_STATUS相关状态 | 设置电压值 | +| devReadOnly | cntlr:核心层结构体指针,MMC控制器 | 布尔值 | 检验设备是否只读 | +| cardPluged | cntlr:核心层结构体指针,MMC控制器 | 布尔值 | 检验设备是否拔出 | +| devBusy | cntlr:核心层结构体指针,MMC控制器 | 布尔值 | 检验设备是否忙碌 | +| tune | cntlr:核心层结构体指针,MMC控制器
cmdCode:uint32_t,命令代码 | HDF_STATUS相关状态 | 调谐 | +| rescanSdioDev | cntlr:核心层结构体指针,MMC控制器 | HDF_STATUS相关状态 | 扫描并添加SDIO设备 | ## 开发步骤 @@ -71,7 +71,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, 3. **实例化MMC控制器对象:** - 初始化MmcCntlr成员。 - 实例化MmcCntlr成员MmcCntlrOps。 - > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 实例化MmcCntlr成员MmcCntlrOps,其定义和成员说明见[接口说明](#接口说明)。 4. **驱动调试:** @@ -91,17 +91,17 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ``` struct HdfDriverEntry g_mmcDriverEntry = { .moduleVersion = 1, - .Bind = HimciMmcBind, //见Bind参考 - .Init = HimciMmcInit, //见Init参考 - .Release = HimciMmcRelease, //见Release参考 - .moduleName = "hi3516_mmc_driver",//【必要且与HCS文件中里面的moduleName匹配】 + .Bind = HimciMmcBind, // 见Bind参考 + .Init = HimciMmcInit, // 见Init参考 + .Release = HimciMmcRelease, // 见Release参考 + .moduleName = "hi3516_mmc_driver",// 【必要且与HCS文件中里面的moduleName匹配】 }; - HDF_INIT(g_mmcDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_mmcDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 ``` 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在mmc_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层MmcCntlr成员的默认值或限制范围有密切关系。 如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在mmc_config文件中增加对应的器件属性**。** - - device_info.hcs 配置参考。 + - device_info.hcs 配置参考 ``` @@ -116,9 +116,9 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, policy = 2; priority = 10; permission = 0644; - moduleName = "hi3516_mmc_driver"; //【必要】用于指定驱动名称,需要与驱动Entry中的moduleName一致; - serviceName = "HDF_PLATFORM_MMC_0"; //【必要】驱动对外发布服务的名称,必须唯一 - deviceMatchAttr = "hi3516_mmc_emmc";//【必要】用于配置控制器私有数据,要与 mmc_config.hcs 中对应控制器保持一致 + moduleName = "hi3516_mmc_driver"; // 【必要】用于指定驱动名称,需要与驱动Entry中的moduleName一致; + serviceName = "HDF_PLATFORM_MMC_0"; // 【必要】驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "hi3516_mmc_emmc";// 【必要】用于配置控制器私有数据,要与 mmc_config.hcs 中对应控制器保持一致 } device1 :: deviceNode { policy = 1; @@ -126,7 +126,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, permission = 0644; moduleName = "hi3516_mmc_driver"; serviceName = "HDF_PLATFORM_MMC_1"; - deviceMatchAttr = "hi3516_mmc_sd"; //SD类型 + deviceMatchAttr = "hi3516_mmc_sd"; // SD类型 } device2 :: deviceNode { policy = 1; @@ -134,7 +134,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, permission = 0644; moduleName = "hi3516_mmc_driver"; serviceName = "HDF_PLATFORM_MMC_2"; - deviceMatchAttr = "hi3516_mmc_sdio";//SDIO类型 + deviceMatchAttr = "hi3516_mmc_sdio";// SDIO类型 } } } @@ -142,32 +142,32 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, } ``` - - mmc_config.hcs 配置参考。 + - mmc_config.hcs配置参考 ``` root { platform { mmc_config { - template mmc_controller {//模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 + template mmc_controller {// 模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 match_attr = ""; voltDef = 0; // 3.3V - freqMin = 50000; //【必要】最小频率值 - freqMax = 100000000; //【必要】最大频率值 - freqDef = 400000; //【必要】默认频率值 - maxBlkNum = 2048; //【必要】最大的block号 - maxBlkSize = 512; //【必要】最大的block个数 - ocrDef = 0x300000; //【必要】工作电压设置相关 - caps2 = 0; //【必要】属性寄存器相关,见mmc_caps.h 中 MmcCaps2 定义 - regSize = 0x118; //【必要】寄存器位宽 - hostId = 0; //【必要】主机号 - regBasePhy = 0x10020000;//【必要】寄存器物理基地址 - irqNum = 63; //【必要】中断号 - devType = 2; //【必要】模式选择:emmc, SD, SDIO ,COMBO - caps = 0x0001e045; //【必要】属性寄存器相关,见mmc_caps.h 中 MmcCaps 定义 + freqMin = 50000; // 【必要】最小频率值 + freqMax = 100000000; // 【必要】最大频率值 + freqDef = 400000; // 【必要】默认频率值 + maxBlkNum = 2048; // 【必要】最大的block号 + maxBlkSize = 512; // 【必要】最大的block个数 + ocrDef = 0x300000; // 【必要】工作电压设置相关 + caps2 = 0; // 【必要】属性寄存器相关,见mmc_caps.h中MmcCaps2定义 + regSize = 0x118; // 【必要】寄存器位宽 + hostId = 0; // 【必要】主机号 + regBasePhy = 0x10020000;// 【必要】寄存器物理基地址 + irqNum = 63; // 【必要】中断号 + devType = 2; // 【必要】模式选择:emmc, SD, SDIO ,COMBO + caps = 0x0001e045; // 【必要】属性寄存器相关,见mmc_caps.h 中 MmcCaps 定义 } controller_0x10100000 :: mmc_controller { - match_attr = "hi3516_mmc_emmc";//【必要】需要和device_info.hcs中的deviceMatchAttr值一致 + match_attr = "hi3516_mmc_emmc";// 【必要】需要和device_info.hcs中的deviceMatchAttr值一致 hostId = 0; regBasePhy = 0x10100000; irqNum = 96; @@ -180,7 +180,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, hostId = 1; regBasePhy = 0x100f0000; irqNum = 62; - devType = 1; // sd类型 + devType = 1; // SD类型 caps = 0xd001e005; } controller_0x10020000 :: mmc_controller { @@ -188,7 +188,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, hostId = 2; regBasePhy = 0x10020000; irqNum = 63; - devType = 2; // sdio类型 + devType = 2; // SDIO类型 caps = 0x0001e04d; } } @@ -197,16 +197,16 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ``` 3. 完成驱动入口注册之后,最后一步就是以核心层MmcCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化MmcCntlr成员MmcCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 - - 自定义结构体参考。 + - 自定义结构体参考 从驱动的角度看,自定义结构体是参数和数据的载体,而且mmc_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员 ,一些重要数值也会传递给核心层对象。 ``` struct HimciHost { - struct MmcCntlr *mmc;//【必要】核心层结构体 - struct MmcCmd *cmd; //【必要】核心层结构体,传递命令的,相关命令见枚举量 MmcCmdCode - //【可选】根据厂商驱动需要添加 + struct MmcCntlr *mmc;// 【必要】核心层结构体 + struct MmcCmd *cmd; // 【必要】核心层结构体,传递命令的,相关命令见枚举量 MmcCmdCode + // 【可选】根据厂商驱动需要添加 void *base; enum HimciPowerStatus powerStatus; uint8_t *alignedBuff; @@ -223,7 +223,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, bool waitForEvent; HIMCI_EVENT himciEvent; }; - //MmcCntlr是核心层控制器结构体,其中的成员在bind函数中会被赋值 + // MmcCntlr是核心层控制器结构体,其中的成员在bind函数中会被赋值 struct MmcCntlr { struct IDeviceIoService service; struct HdfDeviceObject *hdfDevObj; @@ -278,11 +278,11 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, 入参**:** - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: - HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。 + HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。 | 状态(值) | 问题描述 | | -------- | -------- | @@ -307,20 +307,20 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr)); host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost)); - host->mmc = cntlr; //【必要】使HimciHost与MmcCntlr可以相互转化的前提 - cntlr->priv = (void *)host; //【必要】使HimciHost与MmcCntlr可以相互转化的前提 - cntlr->ops = &g_himciHostOps; //【必要】MmcCntlrOps的实例化对象的挂载 - cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 - obj->service = &cntlr->service; //【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 - ret = MmcCntlrParse(cntlr, obj); //【必要】 初始化 cntlr. 失败就 goto _ERR; + host->mmc = cntlr; // 【必要】使HimciHost与MmcCntlr可以相互转化的前提 + cntlr->priv = (void *)host; // 【必要】使HimciHost与MmcCntlr可以相互转化的前提 + cntlr->ops = &g_himciHostOps; // 【必要】MmcCntlrOps的实例化对象的挂载 + cntlr->hdfDevObj = obj; // 【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 + obj->service = &cntlr->service; // 【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 + ret = MmcCntlrParse(cntlr, obj); // 【必要】 初始化 cntlr,失败就goto _ERR; ... - ret = HimciHostParse(host, obj); //【必要】 初始化 host对象的相关属性,失败就 goto _ERR; + ret = HimciHostParse(host, obj); // 【必要】 初始化host对象的相关属性,失败就goto _ERR; ... - ret = HimciHostInit(host, cntlr);//厂商自定义的初始化,失败就 goto _ERR; + ret = HimciHostInit(host, cntlr);// 厂商自定义的初始化,失败就 goto _ERR; ... - ret = MmcCntlrAdd(cntlr); //调用核心层函数 失败就 goto _ERR; + ret = MmcCntlrAdd(cntlr); // 调用核心层函数 失败就goto _ERR; ... - (void)MmcCntlrAddDetectMsgToQueue(cntlr);//将卡检测消息添加到队列中。 + (void)MmcCntlrAddDetectMsgToQueue(cntlr);// 将卡检测消息添加到队列中。 HDF_LOGD("HimciMmcBind: success."); return HDF_SUCCESS; _ERR: @@ -334,7 +334,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, 入参: - HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: @@ -364,7 +364,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: @@ -380,8 +380,8 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, { struct MmcCntlr *cntlr = NULL; ... - cntlr = (struct MmcCntlr *)obj->service;//这里有HdfDeviceObject到MmcCntlr的强制转化,通过service成员,赋值见Bind函数 + cntlr = (struct MmcCntlr *)obj->service;// 这里有HdfDeviceObject到MmcCntlr的强制转化,通过service成员,赋值见Bind函数 ... - HimciDeleteHost((struct HimciHost *)cntlr->priv);//厂商自定义的内存释放函数,这里有MmcCntlr到HimciHost的强制转化 + HimciDeleteHost((struct HimciHost *)cntlr->priv);// 厂商自定义的内存释放函数,这里有MmcCntlr到HimciHost的强制转化 } ``` diff --git a/zh-cn/device-dev/driver/driver-platform-pin-des.md b/zh-cn/device-dev/driver/driver-platform-pin-des.md index 88d20ee83e..b81839ada1 100644 --- a/zh-cn/device-dev/driver/driver-platform-pin-des.md +++ b/zh-cn/device-dev/driver/driver-platform-pin-des.md @@ -1,26 +1,15 @@ # PIN -- [概述](#section1) - - [功能简介](#section2) - - [基本概念](#section3) - - [运作机制](#section4) - - [约束与限制](#section5) -- [使用指导](#section6) - - [场景介绍](#section7) - - [接口说明](#section8) - - [开发步骤](#section9) - - [使用实例](#section10) - ## 概述 ### 功能简介 -- PIN即管脚控制器,用于统一管理各SoC厂商管脚资源,对外提供管脚复用功能:包括管脚推拉方式、管脚推拉强度以及管脚功能。 -- PIN接口定义了操作PIN管脚的通用方法集合,包括: - - 获取/释放管脚描述句柄: 传入管脚名与链表中每个控制器下管脚名进行匹配,匹配则会获取一个管脚描述句柄,操作完PIN管脚后释放该管脚描述句柄。 - - 设置/获取管脚推拉方式:推拉方式可以是上拉、下拉以及悬空。 - - 设置/获取管脚推拉强度:用户可根据实际设置管脚推拉强度大小。 - - 设置/获取管脚功能:通过管脚功能名设置/获取管脚功能,实现管脚复用。 +PIN即管脚控制器,用于统一管理各SoC厂商管脚资源,对外提供管脚复用功能:包括管脚推拉方式、管脚推拉强度以及管脚功能。 +PIN接口定义了操作PIN管脚的通用方法集合,包括: +- 获取/释放管脚描述句柄: 传入管脚名与链表中每个控制器下管脚名进行匹配,匹配则会获取一个管脚描述句柄,操作完PIN管脚后释放该管脚描述句柄。 +- 设置/获取管脚推拉方式:推拉方式可以是上拉、下拉以及悬空。 +- 设置/获取管脚推拉强度:用户可根据实际设置管脚推拉强度大小。 +- 设置/获取管脚功能:通过管脚功能名设置/获取管脚功能,实现管脚复用。 ### 基本概念 PIN是一个软件层面的概念,目的是为了统一各SoC厂商PIN管脚管理,对外提供管脚复用功能,配置PIN管脚的电气特性。 @@ -35,9 +24,12 @@ PIN是一个软件层面的概念,目的是为了统一各SoC厂商PIN管脚 ### 运作机制 -在HDF框架中,PIN模块暂不支持用户态,所以不需要发布服务,接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 +在HDF框架中,PIN模块暂不支持用户态,所以不需要发布服务。接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型。对于没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 -PIN模块各分层作用:接口层提供获取PIN管脚、设置PIN管脚推拉方式、获取PIN管脚推拉方式、设置PIN管脚推拉强度、获取PIN管脚推拉强度、设置PIN管脚功能、获取PIN管脚功能、释放PIN管脚的接口。核心层主要提供PIN管脚资源匹配,PIN管脚控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互。适配层主要是将钩子函数的功能实例化,实现具体的功能。 +PIN模块各分层作用: +- 接口层提供获取PIN管脚、设置PIN管脚推拉方式、获取PIN管脚推拉方式、设置PIN管脚推拉强度、获取PIN管脚推拉强度、设置PIN管脚功能、获取PIN管脚功能、释放PIN管脚的接口。 +- 核心层主要提供PIN管脚资源匹配,PIN管脚控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互。 +- 适配层主要是将钩子函数的功能实例化,实现具体的功能。 **图 1** PIN无服务模式 ![](figures/无服务模式结构图.png "PIN无服务模式") @@ -67,10 +59,10 @@ PIN模块提供的主要接口如[表1](#table1)所示,更多关于接口的 | int32_t PinGetPull(DevHandle handle, enum PinPullType *pullType); | 获取管脚推拉方式 | | int32_t PinSetStrength(DevHandle handle, uint32_t strength); | 设置管脚推拉强度 | | int32_t PinGetStrength(DevHandle handle, uint32_t *strength); | 获取管脚推拉强度 | -| int32_t PinSetFunc(DevHandle handle, const char *funcName); | 设置管脚功能 | -| int32_t PinGetFunc(DevHandle handle, const char **funcName); | 获取管脚功能 | +| int32_t PinSetFunc(DevHandle handle, const char *funcName); | 设置管脚功能 | +| int32_t PinGetFunc(DevHandle handle, const char **funcName); | 获取管脚功能 | ->![](../public_sys-resources/icon-note.gif) **说明:** +>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 ### 开发步骤 @@ -88,14 +80,14 @@ PIN模块提供的主要接口如[表1](#table1)所示,更多关于接口的 DevHandle PinGet(const char *pinName); ``` -**表 2** PinGet参数和返回值描述 +**表 2** PinGet参数和描述 -| 参数 | 参数描述 | +| 参数 | 描述 | | ---------- | ----------------------- | | pinName | 管脚名 | -| **返回值** | **返回值描述** | +| **返回值** | **描述** | | NULL | 获取PIN管脚描述句柄失败 | | handle | PIN管脚描述句柄 | @@ -119,15 +111,15 @@ PIN设置管脚推拉方式的函数如下所示: int32_t PinSetPull(DevHandle handle, enum PinPullType pullType); ``` -**表 3** 参数和返回值描述 +**表 3** 参数和描述 -| 参数 | 参数描述 | +| 参数 | 描述 | | ---------- | ----------------------- | | handle | PIN管脚描述句柄 | | pullType | PIN管脚推拉方式 | -| **返回值** | **返回值描述** | +| **返回值** | **描述** | | 0 | PIN设置管脚推拉方式成功 | | 负数 | PIN设置管脚推拉方式失败 | @@ -153,15 +145,15 @@ PIN获取管脚推拉方式的函数如下所示: int32_t PinGetPull(DevHandle handle, enum PinPullType *pullType); ``` -**表 4** PinGetPull参数和返回值描述 +**表 4** PinGetPull参数和描述 -| 参数 | 参数描述 | +| 参数 | 描述 | | ---------- | ------------------------- | | handle | PIN管脚描述句柄 | | pullType | 接收PIN管脚推拉方式的指针 | -| **返回值** | **返回值描述** | +| **返回值** | **描述** | | 0 | PIN获取管脚推拉方式成功 | | 负数 | PIN获取管脚推拉方式失败 | @@ -186,15 +178,15 @@ PIN设置管脚推拉强度函数如下所示: int32_t PinSetStrength(DevHandle handle, uint32_t strength); ``` -**表 5** PinSetStrength参数和返回值描述 +**表 5** PinSetStrength参数和描述 -| 参数 | 参数描述 | +| 参数 | 描述 | | ---------- | ----------------------- | | handle | 管脚描述句柄 | | strength | PIN管脚推拉强度 | -| **返回值** | **返回值描述** | +| **返回值** | **描述** | | 0 | PIN设置管脚推拉强度成功 | | 负数 | PIN设置管脚推拉强度失败 | @@ -220,15 +212,15 @@ PIN设置管脚推拉强度后,可以通过PIN获取管脚推拉强度接口 int32_t PinGetStrength(DevHandle handle, uint32_t *strength); ``` -**表 6** PinGetStrength参数和返回值描述 +**表 6** PinGetStrength参数和描述 -| 参数 | 参数描述 | +| 参数 | 描述 | | ---------- | ------------------------- | | handle | 管脚描述句柄 | | strength | 接收PIN管脚推拉强度的指针 | -| **返回值** | **返回值描述** | +| **返回值** | **描述** | | 0 | PIN获取管脚推拉强度成功 | | 负数 | PIN获取管脚推拉强度失败 | @@ -255,15 +247,15 @@ PIN设置管脚功能函数如下所示: int32_t PinSetFunc(DevHandle handle, const char *funcName); ``` -**表 7** PinSetFunc参数和返回值描述 +**表 7** PinSetFunc参数和描述 -| 参数 | 参数描述 | +| 参数 | 描述 | | ---------- | ------------------- | | handle | 管脚描述句柄 | | funcName | PIN管脚功能名 | -| **返回值** | **返回值描述** | +| **返回值** | **描述** | | 0 | PIN设置管脚功能成功 | | 负数 | PIN设置管脚功能失败 | @@ -288,15 +280,15 @@ PIN设置管脚功能后,可以通过PIN获取管脚功能接口来查看PIN int32_t PinGetFunc(DevHandle handle, const char **funcName); ``` -**表 8** PinGetFunc参数和返回值描述 +**表 8** PinGetFunc参数和描述 -| 参数 | 参数描述 | +| 参数 | 描述 | | ---------- | --------------------- | | handle | 管脚描述句柄 | | funcName | 接收PIN管脚功能名指针 | -| **返回值** | **返回值描述** | +| **返回值** | **描述** | | 0 | PIN获取管脚功能成功 | | 负数 | PIN获取管脚功能失败 | @@ -321,14 +313,14 @@ PIN不再进行任何操作后,需要释放PIN管脚描述管脚句柄,函 void PinPut(DevHandle handle); ``` -**表 9** PinPut参数和返回值描述 +**表 9** PinPut参数和描述 -| 参数 | 参数描述 | +| 参数 | 描述 | | ---------- | -------------- | | handle | 管脚描述句柄 | -| **返回值** | **返回值描述** | +| **返回值** | **描述** | | NA | 无返回值 | PIN销毁管脚描述句柄实例如下: @@ -339,7 +331,7 @@ PinPut(handle); ## 使用实例 -使用PIN设置管脚相关属性完整使用可以参考如下示例代码,示例代码步骤主要如下: +使用PIN设置管脚相关属性完整使用可以参考如下示例代码,步骤主要如下: 1. 传入要设置的管脚名,获取PIN管脚描述句柄。 2. 通过PIN管脚描述句柄以及推拉方式pullTypeNum设置管脚推拉方式,如果操作失败则释放PIN管脚描述句柄。 3. 通过PIN管脚描述句柄,并用pullTypeNum承接获取的管脚推拉方式,如果操作失败则释放PIN管脚描述句柄。 @@ -413,4 +405,4 @@ ERR: /* 释放PIN管脚描述句柄 */ PinPut(handle); return ret; -} +} \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-pin-develop.md b/zh-cn/device-dev/driver/driver-platform-pin-develop.md index c9c687a7d0..1b5acee3ad 100755 --- a/zh-cn/device-dev/driver/driver-platform-pin-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-pin-develop.md @@ -20,9 +20,12 @@ PIN是一个软件层面的概念,目的是为了统一各SoC厂商PIN管脚 ### 运作机制 -在HDF框架中,PIN模块暂不支持用户态,所以不需要发布服务,接口适配模式采用无服务模式(如图1所示),用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 +在HDF框架中,PIN模块暂不支持用户态,所以不需要发布服务。接口适配模式采用无服务模式(如图1所示),用于不需要在用户态提供API的设备类型。对于没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 -PIN模块各分层作用:接口层提供获取PIN管脚、设置PIN管脚推拉方式、获取PIN管脚推拉方式、设置PIN管脚推拉强度、获取PIN管脚推拉强度、设置PIN管脚功能、获取PIN管脚功能、释放PIN管脚的接口。核心层主要提供PIN管脚资源匹配,PIN管脚控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互。适配层主要是将钩子函数的功能实例化,实现具体的功能。 +PIN模块各分层作用: +- 接口层提供获取PIN管脚、设置PIN管脚推拉方式、获取PIN管脚推拉方式、设置PIN管脚推拉强度、获取PIN管脚推拉强度、设置PIN管脚功能、获取PIN管脚功能、释放PIN管脚的接口。 +- 核心层主要提供PIN管脚资源匹配,PIN管脚控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互。 +- 适配层主要是将钩子函数的功能实例化,实现具体的功能。 **图 1** 无服务模式结构图 @@ -58,12 +61,12 @@ struct PinCntlrMethod { | 成员函数 | 入参 | 出参 | 返回值 | 功能 | | ------------ | ------------------------------------------- | ------ | ---- | ---- | -| SetPinPull | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号;
**pullType**:枚举常量,Pin管脚推拉方式; | 无 |HDF_STATUS相关状态|PIN设置管脚推拉方式| -| GetPinPull | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号; | **pullType**:枚举常量指针,传出Pin管脚推拉方式; | HDF_STATUS相关状态 | PIN获取管脚推拉方式 | -| SetPinStrength | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号;
**strength**:uint32_t变量,Pin推拉强度; | 无 | HDF_STATUS相关状态 | PIN设置推拉强度 | -| GetPinStrength | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号; | **strength**:uint32_t变量指针,传出Pin推拉强度; | HDF_STATUS相关状态 | PIN获取推拉强度 | -| SetPinFunc | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号;
**funcName**:char指针常量,传入Pin管脚功能; | 无 | HDF_STATUS相关状态 | PIN设置管脚功能 | -| GetPinFunc | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号; | **funcName**:char双重指针常量,传出Pin管脚功能; | HDF_STATUS相关状态 | PIN获取管脚功能 | +| SetPinPull | **cntlr**:结构体指针,核心层Pin控制器
**index**:uint32_t变量,管脚索引号
**pullType**:枚举常量,Pin管脚推拉方式 | 无 |HDF_STATUS相关状态|PIN设置管脚推拉方式| +| GetPinPull | **cntlr**:结构体指针,核心层Pin控制器
**index**:uint32_t变量,管脚索引号 | **pullType**:枚举常量指针,传出Pin管脚推拉方式 | HDF_STATUS相关状态 | PIN获取管脚推拉方式 | +| SetPinStrength | **cntlr**:结构体指针,核心层Pin控制器
**index**:uint32_t变量,管脚索引号
**strength**:uint32_t变量,Pin推拉强度 | 无 | HDF_STATUS相关状态 | PIN设置推拉强度 | +| GetPinStrength | **cntlr**:结构体指针,核心层Pin控制器
**index**:uint32_t变量,管脚索引号 | **strength**:uint32_t变量指针,传出Pin推拉强度 | HDF_STATUS相关状态 | PIN获取推拉强度 | +| SetPinFunc | **cntlr**:结构体指针,核心层Pin控制器
**index**:uint32_t变量,管脚索引号
**funcName**:char指针常量,传入Pin管脚功能 | 无 | HDF_STATUS相关状态 | PIN设置管脚功能 | +| GetPinFunc | **cntlr**:结构体指针,核心层Pin控制器
**index**:uint32_t变量,管脚索引号 | **funcName**:char双重指针常量,传出Pin管脚功能 | HDF_STATUS相关状态 | PIN获取管脚功能 | ### 开发步骤 @@ -125,7 +128,7 @@ PIN模块适配包含以下四个步骤: } ``` - 添加pin_config.hcs器件属性文件。 - 在device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs目录下配置器件属性 ,其中配置参数如下: + 在device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs目录下配置器件属性,其中配置参数如下: ```c root { platform { @@ -162,7 +165,7 @@ PIN模块适配包含以下四个步骤: } ...... // 对应管脚控制器下的每个管脚,按实际添加 } - ......//每个管脚控制器对应一个controller节点,如存在多个Pin控制器,请依次添加对应的controller节点。 + ......// 每个管脚控制器对应一个controller节点,如存在多个Pin控制器,请依次添加对应的controller节点 } } } @@ -281,7 +284,7 @@ PIN模块适配包含以下四个步骤: - Init函数 入参: - HdfDeviceObject这个是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 + HdfDeviceObject这个是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: HDF\_STATUS相关状态(下表为部分展示,如需使用其他状态,可见/drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 @@ -371,11 +374,11 @@ PIN模块适配包含以下四个步骤: } ``` - - Release 函数 + - Release函数 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备hcs配置文件的信息。 返回值: @@ -383,7 +386,7 @@ PIN模块适配包含以下四个步骤: 函数说明: - 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口。当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。 ```c static void Hi35xxPinRelease(struct HdfDeviceObject *device) diff --git a/zh-cn/device-dev/driver/driver-platform-rtc-des.md b/zh-cn/device-dev/driver/driver-platform-rtc-des.md index fedf6251ca..d1be538366 100644 --- a/zh-cn/device-dev/driver/driver-platform-rtc-des.md +++ b/zh-cn/device-dev/driver/driver-platform-rtc-des.md @@ -3,29 +3,22 @@ ## 概述 -RTC(real-time clock)为操作系统中的实时时钟设备,为操作系统提供精准的实时时间和定时报警功能。当设备下电后,通过外置电池供电,RTC继续记录操作系统时间;设备上电后,RTC提供实时时钟给操作系统,确保断电后系统时间的连续性。 +RTC(real-time clock)为操作系统中的实时时钟设备,为操作系统提供精准的实时时间和定时报警功能。当设备下电后,通过外置电池供电,RTC继续记录操作系统时间;设备上电后,RTC提供实时时钟给操作系统,确保断电后系统时间的连续性。 ## 接口说明 **表1** RTC设备API接口功能介绍 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| RTC句柄操作 | RtcOpen:获取RTC设备驱动句柄
RtcClose:释放RTC设备驱动句柄 | 获取RTC设备驱动句柄 | -| RTC时间操作接口 | RtcReadTime | 读RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒 | -| RtcWriteTime | 写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒 | -| RTC报警操作接口 | RtcReadAlarm | 读RTC报警时间信息 | -| RtcWriteAlarm | 写RTC报警时间信息 | -| RtcRegisterAlarmCallback | 注册报警超时回调函数 | -| RtcAlarmInterruptEnable | 使能/去使能RTC报警中断 | -| RTC配置操作 | RtcGetFreq | 读RTC外接晶振频率 | -| RtcSetFreq | 配置RTC外接晶振频率 | -| RtcReset | RTC复位 | -| 读写用户定义寄存器 | RtcReadReg | 读用户自定义寄存器 | -| RtcWriteReg | 写用户自定义寄存器 | - -> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +| 功能分类 | 接口描述 | +| -------- | -------- | +| RTC句柄操作 | RtcOpen:获取RTC设备驱动句柄
RtcClose:释放RTC设备驱动句柄 | +| RTC时间操作接口 | RtcReadTime:读RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒
RtcWriteTime:写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒 | +| RTC报警操作接口 | RtcReadAlarm:读RTC报警时间信息
RtcWriteAlarm:写RTC报警时间信息
RtcRegisterAlarmCallback:注册报警超时回调函数
RtcAlarmInterruptEnable:使能/去使能RTC报警中断 | +| RTC配置操作 | RtcGetFreq:读RTC外接晶振频率
RtcSetFreq:配置RTC外接晶振频率
RtcReset:RTC复位 | +| 读写用户定义寄存器 | RtcReadReg:读用户自定义寄存器
RtcWriteReg:写用户自定义寄存器 | + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 @@ -45,21 +38,21 @@ RTC(real-time clock)为操作系统中的实时时钟设备,为操作系统提 ### 创建RTC设备句柄 -RTC驱动加载成功后,驱动开发者使用驱动框架提供的查询接口并调用RTC设备驱动接口。 +RTC驱动加载成功后,使用驱动框架提供的查询接口并调用RTC设备驱动接口。 -> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 当前操作系统支持一个RTC设备。 DevHandle RtcOpen(void); **表2** RtcOpen参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| void | NA | -| **返回值** | **返回值描述** | -| handle | 操作成功返回  指针类型 | -| NULL | 操作失败 | +| void | NA | +| **返回值** | **描述** | +| handle | 操作成功返回  指针类型 | +| NULL | 操作失败 | ``` @@ -81,9 +74,9 @@ void RtcClose(DevHandle handle); **表3** RtcClose参数描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| handle | RTC设备句柄 | +| handle | RTC设备句柄 | ``` @@ -100,12 +93,12 @@ int32_t RtcRegisterAlarmCallback(DevHandle handle, enum RtcAlarmIndex alarmIndex **表4** RtcRegisterAlarmCallback参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | | handle | RTC设备句柄 | | alarmIndex | 报警索引 | | cb | 定时报警回调函数 | -| **返回值** | **返回值描述** | +| **返回值** | **描述** | | 0 | 操作成功 | | 负数 | 操作失败 | @@ -143,11 +136,11 @@ int32_t RtcReadTime(DevHandle handle, struct RtcTime \*time); **表5** RtcReadTime参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | | handle | RTC设备句柄 | | time | RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒 | -| **返回值** | **返回值描述** | +| **返回值** | **描述** | | 0 | 操作成功 | | 负数 | 操作失败 | @@ -171,15 +164,15 @@ int32_t RtcWriteTime(DevHandle handle, struct RtcTime \*time); **表6** RtcWriteTime参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| handle | RTC设备句柄 | -| time | 写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒 | -| **返回值** | **返回值描述** | -| 0 | 操作成功 | -| 负数 | 操作失败 | +| handle | RTC设备句柄 | +| time | 写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒 | +| **返回值** | **描述** | +| 0 | 操作成功 | +| 负数 | 操作失败 | -> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。 @@ -210,14 +203,14 @@ int32_t RtcReadAlarm(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct Rtc **表7** RtcReadAlarm参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| handle | RTC设备句柄 | -| alarmIndex | 报警索引 | -| time | RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒 | -| **返回值** | **返回值描述** | -| 0 | 操作成功 | -| 负数 | 操作失败 | +| handle | RTC设备句柄 | +| alarmIndex | 报警索引 | +| time | RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒 | +| **返回值** | **描述** | +| 0 | 操作成功 | +| 负数 | 操作失败 | ``` @@ -239,16 +232,16 @@ int32_t RtcWriteAlarm(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct R **表8** RtcWriteAlarm参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| handle | RTC设备句柄 | -| alarmIndex | 报警索引 | -| time | RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒 | -| **返回值** | **返回值描述** | -| 0 | 操作成功 | -| 负数 | 操作失败 | - -> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +| handle | RTC设备句柄 | +| alarmIndex | 报警索引 | +| time | RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒 | +| **返回值** | **描述** | +| 0 | 操作成功 | +| 负数 | 操作失败 | + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。 @@ -279,14 +272,14 @@ int32_t RtcAlarmInterruptEnable(DevHandle handle, enum RtcAlarmIndex alarmIndex, **表9** RtcAlarmInterruptEnable参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| handle | RTC设备句柄 | -| alarmIndex | 报警索引 | +| handle | RTC设备句柄 | +| alarmIndex | 报警索引 | | enable | RTC报警中断配置,1:使能,0:去使能 | -| **返回值** | **返回值描述** | -| 0 | 操作成功 | -| 负数 | 操作失败 | +| **返回值** | **描述** | +| 0 | 操作成功 | +| 负数 | 操作失败 | ``` @@ -307,13 +300,13 @@ int32_t RtcGetFreq(DevHandle handle, uint32_t \*freq); **表10** RtcGetFreq参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| handle | RTC设备句柄 | -| freq | RTC的外接晶体振荡频率,单位(HZ) | -| **返回值** | **返回值描述** | -| 0 | 操作成功 | -| 负数 | 操作失败 | +| handle | RTC设备句柄 | +| freq | RTC的外接晶体振荡频率,单位(HZ) | +| **返回值** | **描述** | +| 0 | 操作成功 | +| 负数 | 操作失败 | ``` @@ -335,13 +328,13 @@ int32_t RtcSetFreq(DevHandle handle, uint32_t freq); **表11** RtcSetFreq参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| handle | RTC设备句柄 | -| freq | RTC的外接晶体振荡频率,单位(HZ) | -| **返回值** | **返回值描述** | -| 0 | 操作成功 | -| 负数 | 操作失败 | +| handle | RTC设备句柄 | +| freq | RTC的外接晶体振荡频率,单位(HZ) | +| **返回值** | **描述** | +| 0 | 操作成功 | +| 负数 | 操作失败 | ``` @@ -363,18 +356,18 @@ int32_t RtcReset(DevHandle handle); **表12** RtcReset参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| handle | RTC设备句柄 | -| **返回值** | **返回值描述** | -| 0 | 操作成功 | -| 负数 | 操作失败 | +| handle | RTC设备句柄 | +| **返回值** | **描述** | +| 0 | 操作成功 | +| 负数 | 操作失败 | ``` int32_t ret; -/* 复位RTC,复位RTC后各配置寄存器恢复默认值 */ +/* 复位RTC,各配置寄存器恢复默认值 */ ret = RtcReset(handle); if (ret != 0) { /* 错误处理 */ @@ -389,14 +382,14 @@ int32_t RtcReadReg(DevHandle handle, uint8_t usrDefIndex, uint8_t \*value); **表13** RtcReadReg参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| handle | RTC设备句柄 | +| handle | RTC设备句柄 | | usrDefIndex | 用户定义的寄存器对应索引 | -| value | 寄存器值 | -| **返回值** | **返回值描述** | -| 0 | 操作成功 | -| 负数 | 操作失败 | +| value | 寄存器值 | +| **返回值** | **描述** | +| 0 | 操作成功 | +| 负数 | 操作失败 | ``` @@ -419,14 +412,14 @@ int32_t RtcWriteReg(DevHandle handle, uint8_t usrDefIndex, uint8_t value); **表14** RtcWriteReg参数和返回值描述 -| **参数** | **参数描述** | +| **参数** | **描述** | | -------- | -------- | -| handle | RTC设备句柄 | +| handle | RTC设备句柄 | | usrDefIndex | 用户定义的寄存器对应索引 | -| value | 寄存器值 | -| **返回值** | **返回值描述** | -| 0 | 操作成功 | -| 负数 | 操作失败 | +| value | 寄存器值 | +| **返回值** | **描述** | +| 0 | 操作成功 | +| 负数 | 操作失败 | ``` @@ -541,4 +534,4 @@ void RtcTestSample(void) /* 销毁RTC设备句柄 */ RtcClose(handle); } -``` +``` \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-rtc-develop.md b/zh-cn/device-dev/driver/driver-platform-rtc-develop.md index bb3cba8e52..c03e224530 100755 --- a/zh-cn/device-dev/driver/driver-platform-rtc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-rtc-develop.md @@ -3,7 +3,7 @@ ## 概述 -RTC(real-time clock)为操作系统中的实时时钟设备,在HDF框架中,RTC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 +RTC(real-time clock)为操作系统中的实时时钟设备。在HDF框架中,RTC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 **图1** RTC独立服务模式结构图 @@ -35,17 +35,17 @@ struct RtcMethod { | 函数 | 入参 | 出参 | 返回值 | 功能 | | -------- | -------- | -------- | -------- | -------- | -| ReadTime | host: 结构体指针,核心层RTC控制器 ; | time: 结构体指针,传出的时间值; | HDF_STATUS相关状态 | 读RTC时间信息 | -| WriteTime | host: 结构体指针,核心层RTC控制器 ;time: 结构体指针,时间传入值; | 无 | HDF_STATUS相关状态 | 写RTC时间信息(包括毫秒~年) | -| ReadAlarm | host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ; | time: 结构体指针,传出的时间值; | HDF_STATUS相关状态 | 读RTC报警时间信息 | -| WriteAlarm | host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;time: 结构体指针,时间传入值; | 无 | HDF_STATUS相关状态 | 写RTC报警时间信息 | -| RegisterAlarmCallback | host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;cb:函数指针,回调函数; | 无 | HDF_STATUS相关状态 | 注册报警超时回调函数 | -| AlarmInterruptEnable | host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;enable: 布尔值,控制报警; | 无 | HDF_STATUS相关状态 | 使能/去使能RTC报警中断 | -| GetFreq | host: 结构体指针,核心层RTC控制器 ; | freq: uint32_t指针,传出的频率值; | HDF_STATUS相关状态 | 读RTC外接晶振频率 | -| SetFreq | host: 结构体指针,核心层RTC控制器 ;freq: uint32_t,频率传入值; | 无 | HDF_STATUS相关状态 | 配置RTC外接晶振频率 | -| Reset | host: 结构体指针,核心层RTC控制器 ; | 无 | HDF_STATUS相关状态 | RTC复位 | -| ReadReg | host: 结构体指针,核心层RTC控制器 ;usrDefIndex: 结构体,用户自定义寄存器索引; | value: uint8_t指针,传出的寄存器值; | HDF_STATUS相关状态 | 按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值 | -| WriteReg | host: 结构体指针,核心层RTC控制器 ;usrDefIndex: 结构体,用户自定义寄存器索引;value: uint8_t,寄存器传入值; | 无 | HDF_STATUS相关状态 | 按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值 | +| ReadTime | host:结构体指针,核心层RTC控制器 | time:结构体指针,传出的时间值 | HDF_STATUS相关状态 | 读RTC时间信息 | +| WriteTime | host:结构体指针,核心层RTC控制器
time:结构体指针,时间传入值 | 无 | HDF_STATUS相关状态 | 写RTC时间信息(包括毫秒~年) | +| ReadAlarm | host:结构体指针,核心层RTC控制器
alarmIndex:枚举值,闹钟报警索引 | time:结构体指针,传出的时间值 | HDF_STATUS相关状态 | 读RTC报警时间信息 | +| WriteAlarm | host:结构体指针,核心层RTC控制器
alarmIndex:枚举值,闹钟报警索引
time:结构体指针,时间传入值 | 无 | HDF_STATUS相关状态 | 写RTC报警时间信息 | +| RegisterAlarmCallback | host:结构体指针,核心层RTC控制器
alarmIndex:枚举值,闹钟报警索引
cb:函数指针,回调函数 | 无 | HDF_STATUS相关状态 | 注册报警超时回调函数 | +| AlarmInterruptEnable | host:结构体指针,核心层RTC控制器
alarmIndex:枚举值,闹钟报警索引
enable:布尔值,控制报警 | 无 | HDF_STATUS相关状态 | 使能/去使能RTC报警中断 | +| GetFreq | host:结构体指针,核心层RTC控制器 | freq:uint32_t指针,传出的频率值 | HDF_STATUS相关状态 | 读RTC外接晶振频率 | +| SetFreq | host:结构体指针,核心层RTC控制器
freq:uint32_t,频率传入值 | 无 | HDF_STATUS相关状态 | 配置RTC外接晶振频率 | +| Reset | host:结构体指针,核心层RTC控制器 | 无 | HDF_STATUS相关状态 | RTC复位 | +| ReadReg | host:结构体指针,核心层RTC控制器
usrDefIndex:结构体,用户自定义寄存器索引 | value:uint8_t指针,传出的寄存器值 | HDF_STATUS相关状态 | 按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值 | +| WriteReg | host:结构体指针,核心层RTC控制器
usrDefIndex:结构体,用户自定义寄存器索引
value:uint8_t,寄存器传入值 | 无 | HDF_STATUS相关状态 | 按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值 | ## 开发步骤 @@ -63,7 +63,7 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 3. **实例化RTC控制器对象:** - 初始化RtcHost成员。 - 实例化RtcHost成员RtcMethod。 - > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 实例化RtcHost成员RtcMethod,其定义和成员说明见[接口说明](#接口说明)。 4. **驱动调试:** @@ -82,10 +82,10 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ``` struct HdfDriverEntry g_rtcDriverEntry = { .moduleVersion = 1, - .Bind = HiRtcBind, //见Bind参考 - .Init = HiRtcInit, //见Init参考 - .Release = HiRtcRelease, //见Release参考 - .moduleName = "HDF_PLATFORM_RTC",//【必要】且与 HCS 里面的名字匹配 + .Bind = HiRtcBind, // 见Bind参考 + .Init = HiRtcInit, // 见Init参考 + .Release = HiRtcRelease, // 见Release参考 + .moduleName = "HDF_PLATFORM_RTC",// 【必要】且与 HCS 里面的名字匹配 }; //调用HDF_INIT将驱动入口注册到HDF框架中 HDF_INIT(g_rtcDriverEntry); @@ -102,12 +102,12 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 platform :: host { device_rtc :: device { device0 :: deviceNode { - policy = 1; //2:用户态可见,1:内核态可见,0:不需要发布服务 - priority = 30; //优先级越大,值越小 - permission = 0644; //驱动创建设备节点权限 - moduleName = "HDF_PLATFORM_RTC"; //【必要】用于指定驱动名称,需要与驱动Entry中的moduleName一致 - serviceName = "HDF_PLATFORM_RTC"; //【必要】驱动对外发布服务的名称,必须唯一 - deviceMatchAttr = "hisilicon_hi35xx_rtc";//【必要】需要与设备hcs文件中的 match_attr 匹配 + policy = 1; // 2:用户态可见,1:内核态可见,0:不需要发布服务 + priority = 30; // 值越小,优先级越高 + permission = 0644; // 驱动创建设备节点权限 + moduleName = "HDF_PLATFORM_RTC"; // 【必要】用于指定驱动名称,需要与驱动Entry中的moduleName一致 + serviceName = "HDF_PLATFORM_RTC"; // 【必要】驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "hisilicon_hi35xx_rtc";// 【必要】需要与设备hcs文件中的 match_attr 匹配 } } } @@ -115,7 +115,7 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 } ``` - - rtc_config.hcs 配置参考。 + - rtc_config.hcs配置参考。 ``` @@ -123,10 +123,10 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 platform { rtc_config { controller_0x12080000 { - match_attr = "hisilicon_hi35xx_rtc";//【必要】需要和device_info.hcs中的deviceMatchAttr值一致 - rtcSpiBaseAddr = 0x12080000; //地址映射相关 - regAddrLength = 0x100; //地址映射相关 - irq = 37; //中断号 + match_attr = "hisilicon_hi35xx_rtc";// 【必要】需要和device_info.hcs中的deviceMatchAttr值一致 + rtcSpiBaseAddr = 0x12080000; // 地址映射相关 + regAddrLength = 0x100; // 地址映射相关 + irq = 37; // 中断号 supportAnaCtrl = false; supportLock = false; anaCtrlAddr = 0xff; @@ -148,17 +148,17 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ``` struct RtcConfigInfo { - uint32_t spiBaseAddr; //地址映射相关 - volatile void *remapBaseAddr; //地址映射相关 - uint16_t regAddrLength; //地址映射相关 - uint8_t supportAnaCtrl; //是否支持anactrl - uint8_t supportLock; //是否支持锁 - uint8_t irq; //中断号 - uint8_t alarmIndex; //闹钟索引 - uint8_t anaCtrlAddr; //anactrl地址 - struct RtcLockAddr lockAddr; //锁地址 - RtcAlarmCallback cb; //回调函数 - struct OsalMutex mutex; //互斥锁 + uint32_t spiBaseAddr; // 地址映射相关 + volatile void *remapBaseAddr; // 地址映射相关 + uint16_t regAddrLength; // 地址映射相关 + uint8_t supportAnaCtrl; // 是否支持anactrl + uint8_t supportLock; // 是否支持锁 + uint8_t irq; // 中断号 + uint8_t alarmIndex; // 闹钟索引 + uint8_t anaCtrlAddr; // anactrl地址 + struct RtcLockAddr lockAddr; // 锁地址 + RtcAlarmCallback cb; // 回调函数 + struct OsalMutex mutex; // 互斥锁 }; // RtcHost是核心层控制器结构体,其中的成员在Init函数中会被赋值 @@ -173,7 +173,7 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ``` - // rtc_hi35xx.c 中的示例:钩子函数的填充 + // rtc_hi35xx.c中的示例:钩子函数的填充 static struct RtcMethod g_method = { .ReadTime = HiRtcReadTime, .WriteTime = HiRtcWriteTime, @@ -193,13 +193,13 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 返回值: - HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。 + HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS定义)。 - **表2** Bind 函数入参及返回值对照表 + **表2** HDF_STATUS返回值描述 | 状态(值) | 问题描述 | | -------- | -------- | @@ -219,11 +219,11 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 static int32_t HiRtcBind(struct HdfDeviceObject *device) { struct RtcHost *host = NULL; - host = RtcHostCreate(device); //实际是申请内存并挂接device: host->device = device; - //使HdfDeviceObject与RtcHost可以相互转化的前提 + host = RtcHostCreate(device); // 实际是申请内存并挂接device: host->device = device; + // 使HdfDeviceObject与RtcHost可以相互转化的前提 ... - device->service = &host->service;//使HdfDeviceObject与RtcHost可以相互转化的前提 - //方便后续通过调用RtcHostFromDevice 实现全局性质的host 使用 + device->service = &host->service;// 使HdfDeviceObject与RtcHost可以相互转化的前提 + // 方便后续通过调用RtcHostFromDevice 实现全局性质的host 使用 return HDF_SUCCESS; } ``` @@ -232,7 +232,7 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 返回值: @@ -249,23 +249,23 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 struct RtcHost *host = NULL; struct RtcConfigInfo *rtcInfo = NULL; ... - host = RtcHostFromDevice(device);//这里有HdfDeviceObject到RtcHost的强制转化 + host = RtcHostFromDevice(device);// 这里有HdfDeviceObject到RtcHost的强制转化 rtcInfo = OsalMemCalloc(sizeof(*rtcInfo)); ... - //HiRtcConfigData 会从设备配置树中读取属性填充rtcInfo 的supportAnaCtrl, supportLock, spiBaseAddr, regAddrLength, irq - //为HiRtcSwInit 和HiRtcSwInit 提供参数,...函数内部处理失败后内存释放等操作 + // HiRtcConfigData 会从设备配置树中读取属性填充rtcInfo 的supportAnaCtrl, supportLock, spiBaseAddr, regAddrLength, irq + // 为HiRtcSwInit和HiRtcSwInit提供参数,...函数内部处理失败后内存释放等操作 if (HiRtcConfigData(rtcInfo, device->property) != 0) { ... } - if (HiRtcSwInit(rtcInfo) != 0) {//地址映射以及中断注册相关 + if (HiRtcSwInit(rtcInfo) != 0) {// 地址映射以及中断注册相关 ... } - if (HiRtcHwInit(rtcInfo) != 0) {//初始化anaCtrl 和 lockAddr 相关内容 + if (HiRtcHwInit(rtcInfo) != 0) {// 初始化anaCtrl 和 lockAddr 相关内容 ... } host->method = &g_method;//RtcMethod的实例化对象的挂载 - host->data = rtcInfo; //使RtcConfigInfo与RtcHost可以相互转化的前提 + host->data = rtcInfo; // 使RtcConfigInfo与RtcHost可以相互转化的前提 HDF_LOGI("Hdf dev service:%s init success!", HdfDeviceGetServiceName(device)); return HDF_SUCCESS; } @@ -274,7 +274,7 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 入参: - HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 返回值: @@ -282,7 +282,7 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 函数说明: - 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作前提是在Init或Bind函数中具备对应赋值的操作。 + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。所有强制转换获取相应对象的操作前提是在Init或Bind函数中具备对应赋值的操作。 ``` @@ -291,13 +291,13 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 struct RtcHost *host = NULL; struct RtcConfigInfo *rtcInfo = NULL; ... - host = RtcHostFromDevice(device); //这里有HdfDeviceObject到RtcHost的强制转化 - rtcInfo = (struct RtcConfigInfo *)host->data;//这里有RtcHost到RtcConfigInfo的强制转化 + host = RtcHostFromDevice(device); // 这里有HdfDeviceObject到RtcHost的强制转化 + rtcInfo = (struct RtcConfigInfo *)host->data;// 这里有RtcHost到RtcConfigInfo的强制转化 if (rtcInfo != NULL) { HiRtcSwExit(rtcInfo); - OsalMemFree(rtcInfo); //释放RtcConfigInfo + OsalMemFree(rtcInfo); // 释放RtcConfigInfo host->data = NULL; } - RtcHostDestroy(host); //释放RtcHost + RtcHostDestroy(host); // 释放RtcHost } ``` diff --git "a/zh-cn/device-dev/driver/figures/pin_auth\346\234\215\345\212\241\344\270\216\351\251\261\345\212\250\344\272\244\344\272\222.png" "b/zh-cn/device-dev/driver/figures/pin_auth\346\234\215\345\212\241\344\270\216\351\251\261\345\212\250\344\272\244\344\272\222.png" index 2d806ab0bfde6fa32b54d31df698c3276c8c0978..93a5ec6eb0f3cde6f8cfe174b3676b1a7a0e8a1f 100644 GIT binary patch literal 31702 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 b+z1j>_~XruH53C`+^-}=Wk99EdVc={k%|m@ literal 29822 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 diff --git "a/zh-cn/readme/DeviceProfile\345\255\220\347\263\273\347\273\237.md" "b/zh-cn/readme/DeviceProfile\345\255\220\347\263\273\347\273\237.md" index bd0af55222..bdae748d35 100755 --- "a/zh-cn/readme/DeviceProfile\345\255\220\347\263\273\347\273\237.md" +++ "b/zh-cn/readme/DeviceProfile\345\255\220\347\263\273\347\273\237.md" @@ -4,11 +4,13 @@ - [目录](#section1464106163817) - [约束](#section1718733212019) - [使用](#section10729231131110) -- [涉及仓](#section176111311166) +- [相关仓](#section176111311166) ## 简介 -DeviceProfile是设备硬件能力和系统软件特征的管理器,典型的Profile有设备类型、设备名称、设备OS类型、OS版本号等。DeviceProfile提供快速访问本地和远端设备Profile的能力,是发起分布式业务的基础。主要功能如下: +DeviceProfile是设备硬件能力和系统软件特征的管理器,典型的Profile有设备类型、设备名称、设备OS类型、OS版本号等。 + +DeviceProfile提供快速访问本地和远端设备Profile的能力,是发起分布式业务的基础。主要功能如下: - 本地设备Profile的查询、插入、删除。 - 远程设备Profile的查询。 @@ -188,7 +190,7 @@ DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvents(profileEv callback, failedEvents); ``` -## 涉及仓 +## 相关仓 **DeviceProfile子系统** diff --git "a/zh-cn/readme/JS-UI\346\241\206\346\236\266\345\255\220\347\263\273\347\273\237.md" "b/zh-cn/readme/JS-UI\346\241\206\346\236\266\345\255\220\347\263\273\347\273\237.md" index 500913347a..9cd39bd02f 100644 --- "a/zh-cn/readme/JS-UI\346\241\206\346\236\266\345\255\220\347\263\273\347\273\237.md" +++ "b/zh-cn/readme/JS-UI\346\241\206\346\236\266\345\255\220\347\263\273\347\273\237.md" @@ -60,7 +60,7 @@ JS UI开发框架源代码在/foundation/ace下,目录结构如下图所示: 在工程目录中:i18n下存放多语言的json文件;pages文件夹下存放多个页面,每个页面由hml、css和js文件组成。 -- **main \> js \> default \> i18n \> en-US.json:**此文件定义了在英文模式下页面显示的变量内容。同理,zh-CN.json中定义了中文模式下的页面内容。 +- **main \> js \> default \> i18n \> en-US.json** :此文件定义了在英文模式下页面显示的变量内容。同理,zh-CN.json中定义了中文模式下的页面内容。 ``` { @@ -71,7 +71,7 @@ JS UI开发框架源代码在/foundation/ace下,目录结构如下图所示: } ``` -- **main \> js \> default \> pages \> index \> index.hml:**此文件定义了index页面的布局、index页面中用到的组件,以及这些组件的层级关系。例如:index.hml文件中包含了一个text组件,内容为“Hello World”文本。 +- **main \> js \> default \> pages \> index \> index.hml** :此文件定义了index页面的布局、index页面中用到的组件,以及这些组件的层级关系。例如:index.hml文件中包含了一个text组件,内容为“Hello World”文本。 ```
@@ -81,7 +81,7 @@ JS UI开发框架源代码在/foundation/ace下,目录结构如下图所示:
``` -- **main \> js \> default \> pages \> index \> index.css:**此文件定义了index页面的样式。例如:index.css文件定义了“container”和“title”的样式。 +- **main \> js \> default \> pages \> index \> index.css** :此文件定义了index页面的样式。例如:index.css文件定义了“container”和“title”的样式。 ``` .container { @@ -94,7 +94,7 @@ JS UI开发框架源代码在/foundation/ace下,目录结构如下图所示: } ``` -- **main \> js \> default \> pages \> index \> index.js:**此文件定义了index页面的业务逻辑,比如数据绑定、事件处理等。例如:变量“title”赋值为字符串“World”。 +- **main \> js \> default \> pages \> index \> index.js** :此文件定义了index页面的业务逻辑,比如数据绑定、事件处理等。例如:变量“title”赋值为字符串“World”。 ``` export default { diff --git "a/zh-cn/readme/\345\233\276\345\275\242\345\255\220\347\263\273\347\273\237.md" "b/zh-cn/readme/\345\233\276\345\275\242\345\255\220\347\263\273\347\273\237.md" index 26bc52548d..2249591b09 100644 --- "a/zh-cn/readme/\345\233\276\345\275\242\345\255\220\347\263\273\347\273\237.md" +++ "b/zh-cn/readme/\345\233\276\345\275\242\345\255\220\347\263\273\347\273\237.md" @@ -64,13 +64,13 @@ **图形子系统** -graphic\_surface +[graphic\_surface](https://gitee.com/openharmony/graphic_surface) -graphic\_ui +[graphic\_ui](https://gitee.com/openharmony/graphic_ui) -graphic\_wms +[graphic\_wms](https://gitee.com/openharmony/graphic_wms) -graphic\_utils +[graphic\_utils](https://gitee.com/openharmony/graphic_utils) ## 1.2 标准系统 diff --git "a/zh-cn/readme/\345\244\232\346\250\241\350\276\223\345\205\245\345\255\220\347\263\273\347\273\237.md" "b/zh-cn/readme/\345\244\232\346\250\241\350\276\223\345\205\245\345\255\220\347\263\273\347\273\237.md" index 10d2753d67..e8bfac49d9 100644 --- "a/zh-cn/readme/\345\244\232\346\250\241\350\276\223\345\205\245\345\255\220\347\263\273\347\273\237.md" +++ "b/zh-cn/readme/\345\244\232\346\250\241\350\276\223\345\205\245\345\255\220\347\263\273\347\273\237.md" @@ -32,5 +32,5 @@ OpenHarmony旨在为开发者提供NUI(Natural User Interface)的交互方 **多模输入子系统** -multimodalinput\_input +[multimodalinput_input](https://gitee.com/openharmony/multimodalinput_input) -- GitLab