diff --git a/docker/standard/Readme-en.md b/docker/standard/Readme-en.md index cd12fd5a04d5b06ced9ee6fa911c1a53d8761eb5..35281709b333151b3cdcc6eeb188f6af75254568 100755 --- a/docker/standard/Readme-en.md +++ b/docker/standard/Readme-en.md @@ -40,7 +40,7 @@ Run the following script to start building for Standard-System Devices (referenc ./build.sh --product-name {product_name} ``` **{product_name}** indicates the platform supported by the current distribution, for example, Hi3516DV300. -Files generated during compilation are stored in the **out/ohos-arm-release/** directory, and the generated image is stored in the **out/ohos-arm-release/packages/phone/images/** directory. +Files generated during compilation are stored in the **out/{device_name}/** directory, and the generated image is stored in the **out/{device_name}/packages/phone/images/** directory. diff --git a/docker/standard/Readme.md b/docker/standard/Readme.md index ffedcc403d0747ac7cfa82123d18bbc6a7ecd71a..d13820b59111b736c3777b988453a620fa95a186 100755 --- a/docker/standard/Readme.md +++ b/docker/standard/Readme.md @@ -40,7 +40,7 @@ docker run -it -v $(pwd):/home/openharmony openharmony-docker-standard:0.0.5 ./build.sh --product-name {product_name} ``` {product_name}为当前版本支持的平台。比如:Hi3516DV300等。 -编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 +编译所生成的文件都归档在out/{device_name}/目录下,结果镜像输出在 out/{device_name}/packages/phone/images/ 目录下。 diff --git a/en/application-dev/Readme-EN.md b/en/application-dev/Readme-EN.md index 7ec1ae37bf4557c9dba670503292b2bc289f1cd4..cd0d8d87e1c62cc4cbebe9e1fd2b3e95ab36eae8 100644 --- a/en/application-dev/Readme-EN.md +++ b/en/application-dev/Readme-EN.md @@ -2,19 +2,15 @@ - [Application Development Overview](application-dev-guide.md) - [DevEco Studio \(OpenHarmony\) User Guide](quick-start/deveco-studio-user-guide-for-openharmony.md) - - [Directory Structure](quick-start/package-structure.md) - [Getting Started](quick-start/start.md) - - [ArkUI](ui/ui-arkui.md) - [JavaScript-based Web-like Development Paradigm](ui/ui-arkui-js.md) - [TypeScript-based Declarative Development Paradigm](ui/ui-arkui-ts.md) - - [Audio](media/audio.md) - - [IPC & RPC](connectivity/ipc-rpc.md) - +- [Application Event Logging](application-event-logging/hiappevent.md) - [JavaScript Development References](js-reference/js-reference.md) - [JavaScript-based Web-like Development Paradigm](js-reference/js-based-web-like-development-paradigm/js-web-development-like.md) diff --git a/en/application-dev/application-event-logging/hiappevent-guidelines.md b/en/application-dev/application-event-logging/hiappevent-guidelines.md new file mode 100644 index 0000000000000000000000000000000000000000..96222dc59426806989235632bcb1090006ebc1ff --- /dev/null +++ b/en/application-dev/application-event-logging/hiappevent-guidelines.md @@ -0,0 +1,123 @@ +# Development Guidelines on Application Event Logging + +## When to Use + +The event logging function helps applications log various information generated during running. + +## Available APIs + +JS application event logging APIs are provided by the **hiAppEvent** module. + +**APIs for event logging:** + +| API | Return Value | Description | +| ------------------------------------------------------------ | -------------- | ------------------------------------------------------------ | +| write(string eventName, EventType type, object keyValues, AsyncCallback\ callback): void | void | Logs application events in asynchronous mode. This method uses an asynchronous callback to return the result. | +| write(string eventName, EventType type, object keyValues): Promise\ | Promise\ | Logs application events in asynchronous mode. This method uses a promise to return the result. | + +- **eventName**: event name you customized. The event name can contain a maximum of 48 characters, including digits (0 to 9), letters (a to z), and underscores (\_). It must start with a letter. + +- **type**: event type enumerated by **EventType**. + + | Type | Description | + | --------- | ----------------- | + | FAULT | Fault event | + | STATISTIC | Statistical event | + | SECURITY | Security event | + | BEHAVIOR | Behavior event | + +- **keyValues**: event parameter key-value pair. For a variable-length parameter, enter each pair of parameter name and value in sequence. For a JSON parameter, enter the parameter name as the key and parameter value as the value. + - A parameter name must be a string, and a parameter value must be a string, number, boolean, or array (which is a basic element). + - The number of event parameters must be less than or equal to 32. + - The parameter name can contain a maximum of 16 characters, including digits (0 to 9), letters (a to z), and underscores (\_). It must start with a letter and cannot end with an underscore (\_). + - A string value can contain a maximum of 8*1024 characters. + - An array value can contain a maximum of 100 elements. Excess elements will be truncated. +- **callback**: callback function used to process the received return value. The value **0** indicates that the event parameter verification is successful, and the event will be written to the event file asynchronously. A value greater than **0** indicates that invalid parameters are present in the event, and the event will be written to the event file asynchronously after the invalid parameters are ignored. A value smaller than **0** indicates that the event parameter verification fails, and the event will not be written to the event file asynchronously. + +When an asynchronous callback is used, the return value can be processed directly in the callback. When a promise is used, the return value can also be processed in the promise in a similar way. For details about the result codes, see [Event Verification Result Codes](hiappevent-overview.md#Event Verification Result Codes). + +**APIs for event logging configuration:** + +| API | Return Value | Description | +| ------------------------------ | ------------ | ------------------------------------------------------------ | +| configure(ConfigOption config) | boolean | Sets the configuration options for application event logging.
The value **true** indicates that the operation is successful, and value **false** indicates the opposite. | + +- **config**: configuration options for application event logging. + + Configuration options for application event logging (**ConfigOption**) + + | Name | Type | Mandatory | Description | + | ---------- | ------- | --------- | ------------------------------------------------------------ | + | disable | boolean | No | Sets the application event logging switch. The value **true** means to disable the application event logging function, and value **false** means the opposite. | + | maxStorage | string | No | Specifies the maximum size of the event file storage directory. The default value is 10M. | + +**Predefined event name constants (Event)**: + +| Constant | Type | Description | +| ------------------------- | ------ | ---------------------------------------------- | +| USER_LOGIN | string | Name of the user login event. | +| USER_LOGOUT | string | Name of the user logout event. | +| DISTRIBUTED_SERVICE_START | string | Name of the distributed service startup event. | + + + +**Predefined parameter name constants (Param):** + +| Constant | Type | Description | +| ------------------------------- | ------ | -------------------------------- | +| USER_ID | string | Custom user ID. | +| DISTRIBUTED_SERVICE_NAME | string | Distributed service name. | +| DISTRIBUTED_SERVICE_INSTANCE_ID | string | Distributed service instance ID. | + + + +## How to Develop + +In this example, an application event is logged after the application startup execution page is loaded. + +1. Create a JS application project. In the displayed Project window, choose **entry > src > main** > **js** > **default** > **pages > index**, and double-click index.js. Add the code to log the initial application event after page loading. The sample code is as follows: + + ```js + import hiAppEvent from '@ohos.hiAppEvent' + + export default { + data: { + title: "" + }, + onInit() { + this.title = this.$t('strings.world'); + + // 1. Callback mode + hiAppEvent.write("start_event", hiAppEvent.EventType.BEHAVIOR, {"int_data":100, "str_data":"strValue"}, (err, value) => { + if (err) { + console.error(`failed to write event because ${err.code}`); + return; + } + console.log(`success to write event: ${value}`); + }); + + // 2. Promise mode + hiAppEvent.write("start_event", hiAppEvent.EventType.BEHAVIOR, {"int_data":100, "str_data":"strValue"}) + .then((value) => { + console.log(`success to write event: ${value}`); + }).catch((err) => { + console.error(`failed to write event because ${err.code}`); + }); + }); + + // 3. Set the application event logging switch. + hiAppEvent.configure({ + disable: true + }); + + // 4. Set the maximum size of the event file storage directory. The default value is 10M. + hiAppEvent.configure({ + maxStorage: '100M' + }); + } + } + ``` + +2. Tap the run button on the application UI to run the project. + + diff --git a/en/application-dev/application-event-logging/hiappevent-overview.md b/en/application-dev/application-event-logging/hiappevent-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..7d3f414331c99f06e2470f6dce14586a50448a33 --- /dev/null +++ b/en/application-dev/application-event-logging/hiappevent-overview.md @@ -0,0 +1,28 @@ +# Overview of Application Event Logging + +HiAppEvent provides event logging APIs for applications to log the fault, statistical, security, and user behavior events reported during running. Based on event information, you will be able to analyze the running status of your application. + +## Basic Concepts + +The HiAppEvent module of OpenHarmony can be used to develop application event services and provide functions related to application events, including flushing application events to a disk and querying historical application event data. + +- **Logging** + + Logs changes caused by user operations to provide service data for development, product, and O&M analysis. + +## Event Verification Result Codes + +| Result Code | Cause | Check Rule | Processing Method | +| ----------- | ---------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | +| 0 | None | Event verification is successful. | Event logging is normal. No action is required. | +| -1 | Invalid event name | The event name is not empty and contains a maximum of 48 characters.
The event name consists of only the following characters: digits (0 to 9), letters (a to z), and underscore (\_).
The event name does not start with a digit or underscore (_). | Ignore this event and do not perform logging. | +| -2 | Invalid event parameter type | The event name must be a string.
The event type must be a number.
The key value must be an object. | Ignore this event and do not perform logging. | +| -99 | Application event logging disabled | The application event logging function is disabled. | Ignore this event and do not perform logging. | +| -100 | Unknown error | None | Ignore this event and do not perform logging. | +| 1 | Invalid key name | The key name is not empty and contains a maximum of 16 characters.
The key name consists of only the following characters: digits (0 to 9), letters (a to z), and underscore (\_).
The key name does not start with a digit or underscore (\_).
The key name does not end with an underscore (_). | Ignore the key-value pair and continue to perform logging. | +| 2 | Invalid key type | The key must be a string. | Ignore the key-value pair and continue to perform logging. | +| 3 | Invalid value type | The supported value types vary depending on the programming language:
boolean, number, string, or Array [basic element] | Ignore the key-value pair and continue to perform logging. | +| 4 | Value too long | The value can contain a maximum of 8*1024 characters. | Ignore the key-value pair and continue to perform logging. | +| 5 | Excess key-value pairs | The number of key-value pairs must be less than or equal to 32. | Ignore the excess key-value pairs and continue to perform logging. | +| 6 | Excess elements in a list value | The number of elements in a list value must be less than or equal to 100. | Truncate the list with only the first 100 elements retained, and continue to perform logging. | +| 7 | Invalid list value | A list value can only be a basic element.
The elements in a list value must be of the same type. | Ignore the key-value pair and continue to perform logging. | \ No newline at end of file diff --git a/en/application-dev/application-event-logging/hiappevent.md b/en/application-dev/application-event-logging/hiappevent.md new file mode 100644 index 0000000000000000000000000000000000000000..9f71ed849a4b10d7d0c9389fef7b761dbaf8782c --- /dev/null +++ b/en/application-dev/application-event-logging/hiappevent.md @@ -0,0 +1,5 @@ +# Application Event Logging + +- [Overview of Application Event Logging](hiappevent-overview.md) +- [Development Guidelines on Application Event Logging](hiappevent-guidelines.md) + diff --git a/en/application-dev/js-reference/apis/audio-management.md b/en/application-dev/js-reference/apis/audio-management.md deleted file mode 100644 index a58634ba548ee4d6594d61287c0327411bc38d2f..0000000000000000000000000000000000000000 --- a/en/application-dev/js-reference/apis/audio-management.md +++ /dev/null @@ -1,2004 +0,0 @@ -# Audio Management - - -## Modules to Import - -``` -import audio from '@ohos.multimedia.audio'; -``` - -## Required Permissions - -None - -## getAudioManager\(\): AudioManager - -Obtains an **AudioManager** instance. - -**Return values** - - - - - - - - - - -

Type

-

Description

-

AudioManager

-

Audio manager

-
- - -**Example** - -``` -var audioManager = audio.getAudioManager(); -``` - -## AudioVolumeType - -Enumerates audio stream types. - - - - - - - - - - - - - - - - -

Name

-

Default Value

-

Description

-

RINGTONE

-

2

-

Audio stream for ringtones

-

MEDIA

-

3

-

Audio stream for media purpose

-
- -## DeviceFlag - -Enumerates audio device flags. - - - - - - - - - - - - - - - - - - - - -

Name

-

Default Value

-

Description

-

OUTPUT_DEVICES_FLAG

-

1

-

Output device

-

INPUT_DEVICES_FLAG

-

2

-

Input device

-

ALL_DEVICES_FLAG

-

3

-

All devices

-
- -## DeviceRole - -Enumerates audio device roles. - - - - - - - - - - - - - - - - -

Name

-

Default Value

-

Description

-

INPUT_DEVICE

-

1

-

Input role

-

OUTPUT_DEVICE

-

2

-

Output role

-
- -## DeviceType - -Enumerates audio device types. - -| Name | Default Value | Description | -| -------------- | ------------- | --------------------------------------------------------------------- | -| INVALID | 0 | Invalid device | -| EARPIECE | 1 | Earpiece | -| SPEAKER | 2 | Speaker | -| WIRED_HEADSET | 3 | Wired headset | -| BLUETOOTH_SCO | 7 | Bluetooth device using the synchronous connection oriented (SCO) link | -| BLUETOOTH_A2DP | 8 | Bluetooth device using the advanced audio distribution profile (A2DP) | -| MIC | 15 | Microphone | - - -## ActiveDeviceType7+ - -Enumerates active device types. - -| Name | Default Value | Description | -| ------------- | ------------- | --------------------------------------------------------------------- | -| SPEAKER | 2 | Speaker | -| BLUETOOTH_SCO | 7 | Bluetooth device using the synchronous connection oriented (SCO) link | - -## AudioRingMode7+ - -Enumerates ringer modes. - - - - - - - - - - - - - - - - - - - - -

Name

-

Default Value

-

Description

-

RINGER_MODE_SILENT

-

0

-

Silence mode

-

RINGER_MODE_VIBRATE

-

1

-

Vibration mode

-

RINGER_MODE_NORMAL

-

2

-

Normal mode

-
- -## AudioManager - -Implements audio volume and audio device management. - -### setVolume\(volumeType: AudioVolumeType, volume: number, callback: AsyncCallback\): void - -Sets the volume for a stream. This method uses an asynchronous callback to return the execution result. - -**Parameters** - - - - - - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-

volume

-

number

-

Yes

-

Volume to set. The value range can be obtained by calling getMinVolume and getMaxVolume.

-

callback

-

AsyncCallback<void>

-

Yes

-

Callback used to return the execution result

-
- -**Return values** - -None - -**Example** - -``` -audioManager.setVolume(audio.AudioVolumeType.MEDIA, 10, (err)=>{ - if (err) { - console.error('Failed to set the volume. ${err.message}'); - return; - } - console.log('Callback invoked to indicate a successful volume setting.'); -}) -``` - -### setVolume\(volumeType: AudioVolumeType, volume: number\): Promise - -Sets the volume for a stream. This method uses a promise to return the execution result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-

volume

-

number

-

Yes

-

Volume to set. The value range can be obtained by calling getMinVolume and getMaxVolume.

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<void>

-

Promise used to return the execution result

-
- -**Example** - -``` -audioManager.setVolume(audio.AudioVolumeType.MEDIA, 10).then(()=> - console.log('Promise returned to indicate a successful volume setting.'); -) -``` - -### getVolume\(volumeType: AudioVolumeType, callback: AsyncCallback\): void - -Obtains the volume of a stream. This method uses an asynchronous callback to return the query result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-

callback

-

AsyncCallback<number>

-

Yes

-

Callback used to return the volume

-
- -**Return values** - -None - -**Example** - -``` -audioManager.getVolume(audio.AudioVolumeType.MEDIA, (err, value) => { - if (err) { - console.error('Failed to obtain the volume. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the volume is obtained.'); -}) -``` - -### getVolume\(volumeType: AudioVolumeType\): Promise - -Obtains the volume of a stream. This method uses a promise to return the query result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<number>

-

Promise used to return the volume

-
- -**Example** - -``` -audioManager.getVolume(audio.AudioVolumeType.MEDIA).then((value) => - console.log('Promise returned to indicate that the volume is obtained.' + value); -) -``` - -### getMinVolume\(volumeType: AudioVolumeType, callback: AsyncCallback\): void - -Obtains the minimum volume allowed for a stream. This method uses an asynchronous callback to return the query result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-

callback

-

AsyncCallback<number>

-

Yes

-

Callback used to return the minimum volume

-
- -**Return values** - -None - -**Example** - -``` -audioManager.getMinVolume(audio.AudioVolumeType.MEDIA, (err, value) => { - if (err) { - console.error('Failed to obtain the minimum volume. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the minimum volume is obtained.' + value); -}) -``` - -### getMinVolume\(volumeType: AudioVolumeType\): Promise - -Obtains the minimum volume allowed for a stream. This method uses a promise to return the query result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<number>

-

Promise used to return the minimum volume

-
- -**Example** - -``` -audioManager.getMinVolume(audio.AudioVolumeType.MEDIA).then((value) => - console.log('Promised returned to indicate that the minimum volume is obtained.' + value); -) -``` - -### getMaxVolume\(volumeType: AudioVolumeType, callback: AsyncCallback\): void - -Obtains the maximum volume allowed for a stream. This method uses an asynchronous callback to return the query result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-

callback

-

AsyncCallback<number>

-

Yes

-

Callback used to return the maximum volume

-
- -**Return values** - -None - -**Example** - -``` -audioManager.getMaxVolume(audio.AudioVolumeType.MEDIA, (err, value) => { - if (err) { - console.error('Failed to obtain the maximum volume. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the maximum volume is obtained.' + value); -}) -``` - -### getMaxVolume\(volumeType: AudioVolumeType\): Promise - -Obtains the maximum volume allowed for a stream. This method uses a promise to return the query result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<number>

-

Promise used to return the maximum volume

-
- -**Example** - -``` -audioManager.getMaxVolume(audio.AudioVolumeType.MEDIA).then((data)=> - console.log('Promised returned to indicate that the maximum volume is obtained.'); -) -``` - -### mute\(volumeType: AudioVolumeType, mute: boolean, callback: AsyncCallback\): void7+ - -Mutes a stream. This method uses an asynchronous callback to return the execution result. - -**Parameters** - - - - - - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-

mute

-

boolean

-

Yes

-

Mute status to set. The value true means to mute the stream, and false means the opposite.

-

callback

-

AsyncCallback<void>

-

Yes

-

Callback used to return the execution result

-
- -**Return values** - -None - -**Example** - -``` -audioManager.mute(audio.AudioVolumeType.MEDIA, true, (err) => { - if (err) { - console.error('Failed to mute the stream. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the stream is muted.'); -}) -``` - -### mute\(volumeType: AudioVolumeType, mute: boolean\): Promise7+ - -Mutes a stream. This method uses a promise to return the execution result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-

mute

-

boolean

-

Yes

-

Mute status to set. The value true means to mute the stream, and false means the opposite.

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<void>

-

Promise used to return the execution result

-
- -**Example** - -``` -audioManager.mute(audio.AudioVolumeType.MEDIA, true).then(() => - console.log('Promise returned to indicate that the stream is muted.'); -) -``` - -### isMute\(volumeType: AudioVolumeType, callback: AsyncCallback\): void7+ - -Checks whether a stream is muted. This method uses an asynchronous callback to return the query result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-

callback

-

AsyncCallback<boolean>

-

Yes

-

Callback used to return the mute status of the stream. The value true means that the stream is muted, and false means the opposite.

-
- -**Return values** - -None - -**Example** - -``` -audioManager.isMute(audio.AudioVolumeType.MEDIA, (err, value) => { - if (err) { - console.error('Failed to obtain the mute status. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the mute status of the stream is obtained.' + value); -}) -``` - -### isMute\(volumeType: AudioVolumeType\): Promise7+ - -Checks whether a stream is muted. This method uses a promise to return the execution result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<boolean>

-

Promise used to return the mute status of the stream. The value true means that the stream is muted, and false means the opposite.

-
- -**Example** - -``` -audioManager.isMute(audio.AudioVolumeType.MEDIA).then((value) => - console.log('Promise returned to indicate that the mute status of the stream is obtained.' + value); -) -``` - -### isActive\(volumeType: AudioVolumeType, callback: AsyncCallback\): void7+ - -Checks whether a stream is active. This method uses an asynchronous callback to return the query result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-

callback

-

AsyncCallback<boolean>

-

Yes

-

Callback used to return the active status of the stream. The value true means that the stream is active, and false means the opposite.

-
- -**Return values** - -None - -**Example** - -``` -audioManager.isActive(audio.AudioVolumeType.MEDIA, (err, value) => { - if (err) { - console.error('Failed to obtain the active status of the stream. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the active status of the stream is obtained.' + value); -}) -``` - -### isActive\(volumeType: AudioVolumeType\): Promise7+ - -Checks whether a stream is active. This method uses a promise to return the query result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

volumeType

-

AudioVolumeType

-

Yes

-

Audio stream type

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<boolean>

-

Promise used to return the active status of the stream. The value true means that the stream is active, and false means the opposite.

-
- -**Example** - -``` -audioManager.isActive(audio.AudioVolumeType.MEDIA).then((value) => - console.log('Promise returned to indicate that the active status of the stream is obtained.' + value); -) -``` - -### setRingerMode\(mode: AudioRingMode, callback: AsyncCallback\): void7+ - -Sets the ringer mode. This method uses an asynchronous callback to return the execution result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

mode

-

AudioRingMode

-

Yes

-

Ringer mode

-

callback

-

AsyncCallback<void>

-

Yes

-

Callback used to return the execution result

-
- -**Return values** - -None - -**Example** - -``` -audioManager.setRingerMode(audio.AudioRingMode.RINGER_MODE_NORMAL, (err) => { - if (err) { - console.error('Failed to set the ringer mode.​ ${err.message}'); - return; - } - console.log('Callback invoked to indicate a successful setting of the ringer mode.'); -}) -``` - -### setRingerMode\(mode: AudioRingMode\): Promise7+ - -Sets the ringer mode. This method uses a promise to return the execution result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

mode

-

AudioRingMode

-

Yes

-

Ringer mode

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<void>

-

Promise used to return the execution result

-
- -**Example** - -``` -audioManager.setRingerMode(audio.AudioRingMode.RINGER_MODE_NORMAL).then(() => - console.log('Promise returned to indicate a successful setting of the ringer mode.'); -) -``` - -### getRingerMode\(callback: AsyncCallback\): void7+ - -Obtains the ringer mode. This method uses an asynchronous callback to return the query result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

callback

-

AsyncCallback<AudioRingMode>

-

Yes

-

Callback used to return the ringer mode

-
- -**Return values** - -None - -**Example** - -``` -audioManager.getRingerMode((err, value) => { - if (err) { - console.error('Failed to obtain the ringer mode.​ ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the ringer mode is obtained.' + value); -}) -``` - -### getRingerMode\(\): Promise7+ - -Obtains the ringer mode. This method uses a promise to return the query result. - -**Parameters** - -None - -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<AudioRingMode>

-

Promise used to return the ringer mode

-
- -**Example** - -``` -audioManager.getRingerMode().then((value) => - console.log('Promise returned to indicate that the ringer mode is obtained.' + value); -) -``` - -### setAudioParameter\(key: string, value: string, callback: AsyncCallback\): void7+ - -Sets an audio parameter. This method uses an asynchronous callback to return the execution result. - -**Parameters** - - - - - - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

key

-

string

-

Yes

-

Key of the audio parameter to set

-

value

-

string

-

Yes

-

Value of the audio parameter to set

-

callback

-

AsyncCallback<void>

-

Yes

-

Callback used to return the execution result

-
- -**Return values** - -None - -**Example** - -``` -audioManager.setAudioParameter('PBits per sample', '8 bit', (err) => { - if (err) { - console.error('Failed to set the audio parameter. ${err.message}'); - return; - } - console.log('Callback invoked to indicate a successful setting of the audio parameter.'); -}) -``` - -### setAudioParameter\(key: string, value: string\): Promise7+ - -Sets an audio parameter. This method uses a promise to return the execution result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

key

-

string

-

Yes

-

Key of the audio parameter to set

-

value

-

string

-

Yes

-

Value of the audio parameter to set

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<void>

-

Promise used to return the execution result

-
- -**Example** - -``` -audioManager.setAudioParameter('PBits per sample', '8 bit').then(() => - console.log('Promise returned to indicate a successful setting of the audio parameter.'); -) -``` - -### getAudioParameter\(key: string, callback: AsyncCallback\): void7+ - -Obtains the value of an audio parameter. This method uses an asynchronous callback to return the query result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

key

-

string

-

Yes

-

Key of the audio parameter whose value is to be obtained

-

callback

-

AsyncCallback<string>

-

Yes

-

Callback used to return the value of the audio parameter

-
- -**Return values** - -None - -**Example** - -``` -audioManager.getAudioParameter('PBits per sample', (err, value) => { - if (err) { - console.error('Failed to obtain the value of the audio parameter. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the value of the audio parameter is obtained.' + value); -}) -``` - -### getAudioParameter\(key: string\): Promise7+ - -Obtains the value of an audio parameter. This method uses a promise to return the query result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

key

-

string

-

Yes

-

Key of the audio parameter whose value is to be obtained

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<string>

-

Promise used to return the value of the audio parameter

-
- -**Example** - -``` -audioManager.getAudioParameter('PBits per sample').then((value) => - console.log('Promise returned to indicate that the value of the audio parameter is obtained.' + value); -) -``` - -### getDevices\(deviceFlag: DeviceFlag, callback: AsyncCallback\): void - -Obtains the audio devices with a specific flag. This method uses an asynchronous callback to return the query result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

deviceFlag

-

DeviceFlag

-

Yes

-

Audio device flag

-

callback

-

AsyncCallback<AudioDeviceDescriptors>

-

Yes

-

Callback used to return the device list

-
- -**Return values** - -None - -**Example** - -``` -audioManager.getDevices(audio.DeviceFlag.OUTPUT_DEVICES_FLAG, (err, value)=>{ - if (err) { - console.error('Failed to obtain the device list. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the device list is obtained.'); -}) -``` - -### getDevices\(deviceFlag: DeviceFlag\): Promise - -Obtains the audio devices with a specific flag. This method uses a promise to return the query result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

deviceFlag

-

DeviceFlag

-

Yes

-

Audio device flag

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<AudioDeviceDescriptors>

-

Promise used to return the device list

-
- -**Example** - -``` -audioManager.getDevices(audio.DeviceFlag.OUTPUT_DEVICES_FLAG).then((data)=> - console.log('Promise returned to indicate that the device list is obtained.'); -) -``` - -### setDeviceActive\(deviceType: ActiveDeviceType, active: boolean, callback: AsyncCallback\): void7+ - -Sets a device to the active state. This method uses an asynchronous callback to return the execution result. - -**Parameters** - - - - - - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

deviceType

-

ActiveDeviceType

-

Yes

-

Audio device type

-

active

-

boolean

-

Yes

-

Active status to set. The value true means to set the device to the active status, and false means the opposite.

-

callback

-

AsyncCallback<void>

-

Yes

-

Callback used to return the execution result

-
- -**Return values** - -None - -**Example** - -``` -audioManager.setDeviceActive(audio.ActiveDeviceType.SPEAKER, true, (err)=> { - if (err) { - console.error('Failed to set the active status of the device. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the device is set to the active status.'); -}) -``` - -### setDeviceActive\(deviceType: ActiveDeviceType, active: boolean\): Promise7+ - -Sets a device to the active state. This method uses a promise to return the execution result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

deviceType

-

ActiveDeviceType

-

Yes

-

Audio device type

-

active

-

boolean

-

Yes

-

Active status to set. The value true means to set the device to the active status, and false means the opposite.

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<void>

-

Promise used to return the execution result

-
- -**Example** - -``` -audioManager.setDeviceActive(audio.ActiveDeviceType.SPEAKER, true).then(()=> - console.log('Promise returned to indicate that the device is set to the active status.'); -) -``` - -### isDeviceActive\(deviceType: DeviceType, callback: AsyncCallback\): void7+ - -Checks whether a device is active. This method uses an asynchronous callback to return the query result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

deviceType

-

ActiveDeviceType

-

Yes

-

Audio device type

-

callback

-

AsyncCallback<boolean>

-

Yes

-

Callback used to return the active status of the device

-
- -**Return values** - -None - -**Example** - -``` -audioManager.isDeviceActive(audio.ActiveDeviceType.SPEAKER, (err, value) => { - if (err) { - console.error('Failed to obtain the active status of the device. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the active status of the device is obtained.'); -}) -``` - -### isDeviceActive\(deviceType: ActiveDeviceType\): Promise7+ - -Checks whether a device is active. This method uses a promise to return the query result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

deviceType

-

ActiveDeviceType

-

Yes

-

Audio device type

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<boolean>

-

Promise used to return the active status of the device

-
- -**Example** - -``` -audioManager.isDeviceActive(audio.ActiveDeviceType.SPEAKER).then((value) => - console.log('Promise returned to indicate that the active status of the device is obtained.' + value); -) -``` - -### setMicrophoneMute\(mute: boolean, callback: AsyncCallback\): void7+ - -Mutes or unmutes the microphone. This method uses an asynchronous callback to return the execution result. - -**Parameters** - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

mute

-

boolean

-

Yes

-

Mute status to set. The value true means to mute the microphone, and false means the opposite.

-

callback

-

AsyncCallback<void>

-

Yes

-

Callback used to return the execution result

-
- -**Return values** - -None - -**Example** - -``` -audioManager.setMicrophoneMute(true, (err) => { - if (err) { - console.error('Failed to mute the microphone. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the microphone is muted.'); -}) -``` - -### setMicrophoneMute\(mute: boolean\): Promise7+ - -Mutes or unmutes the microphone. This method uses a promise to return the execution result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

mute

-

boolean

-

Yes

-

Mute status to set. The value true means to mute the microphone, and false means the opposite.

-
- -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<void>

-

Promise used to return the execution result

-
- -**Example** - -``` -audioManager.setMicrophoneMute(true).then(() => - console.log('Promise returned to indicate that the microphone is muted.'); -) -``` - -### isMicrophoneMute\(callback: AsyncCallback\): void7+ - -Checks whether the microphone is muted. This method uses an asynchronous callback to return the query result. - -**Parameters** - - - - - - - - - - - - - - -

Name

-

Type

-

Mandatory

-

Description

-

callback

-

AsyncCallback<boolean>

-

Yes

-

Callback used to return the mute status of the microphone. The value true means that the microphone is muted, and false means the opposite.

-
- -**Return values** - -None - -**Example** - -``` -audioManager.isMicrophoneMute((err, value) => { - if (err) { - console.error('Failed to obtain the mute status of the microphone. ${err.message}'); - return; - } - console.log('Callback invoked to indicate that the mute status of the microphone is obtained.' + value); -}) -``` - -### isMicrophoneMute\(\): Promise7+ - -Checks whether the microphone is muted. This method uses a promise to return the query result. - -**Parameters** - -None - -**Return values** - - - - - - - - - - -

Type

-

Description

-

Promise<boolean>

-

Promise used to return the mute status of the microphone. The value true means that the microphone is muted, and false means the opposite.

-
- -**Example** - -``` -audioManager.isMicrophoneMute().then((value) => - console.log('Promise returned to indicate that the mute status of the microphone is obtained.', + value); -) -``` - -## AudioDeviceDescriptor - -Describes an audio device. - -### Attributes - - - - - - - - - - - - - - - - - - - - - - -

Name

-

Type

-

Readable

-

Writable

-

Description

-

deviceRole

-

DeviceRole

-

Yes

-

No

-

Audio device role

-

deviceType

-

DeviceType

-

Yes

-

No

-

Audio device type

-
- -## AudioDeviceDescriptors - - - - - - - - - - -

Name

-

Description

-

Device attribute array

-

Array of AudioDeviceDescriptors, which is read-only

-
- diff --git a/en/application-dev/js-reference/apis/js-apis-audio.md b/en/application-dev/js-reference/apis/js-apis-audio.md new file mode 100644 index 0000000000000000000000000000000000000000..facaa2410ce43a3d3b3858097fc660fe62eb10a4 --- /dev/null +++ b/en/application-dev/js-reference/apis/js-apis-audio.md @@ -0,0 +1,939 @@ +# Audio Management + + +## Modules to Import + +``` +import audio from '@ohos.multimedia.audio'; +``` + +## Required Permissions + +None + +## getAudioManager\(\): AudioManager + +Obtains an **AudioManager** instance. + +**Return values** + +| Type | Description | +| -------------- | -------------------------- | +| AudioManager | Audio manager. | + + +**Example** + +``` +var audioManager = audio.getAudioManager(); +``` + +## AudioVolumeType + +Enumerates audio stream types. + +| Name | Default Value | Description | +| -------------- | ------------- | --------------------------------------------------------------------- | +| RINGTONE | 2 | Audio stream for ringtones. | +| MEDIA | 3 | Audio stream for media purpose. | + +## DeviceFlag + +Enumerates audio device flags. + +| Name | Default Value | Description | +| -------------- | ------------- | --------------------------------------------------------------------- | +| OUTPUT_DEVICES_FLAG | 1 | Output device. | +| INPUT_DEVICES_FLAG | 2 | Input device. | +| ALL_DEVICES_FLAG | 3 | All devices. | + + +## DeviceRole + +Enumerates audio device roles. + +| Name | Default Value | Description | +| -------------- | ------------- | --------------------------------------------------------------------- | +| INPUT_DEVICE | 1 | Input role. | +| OUTPUT_DEVICE | 2 | Output role. | + +## DeviceType + +Enumerates audio device types. + +| Name | Default Value | Description | +| -------------- | ------------- | --------------------------------------------------------------------- | +| INVALID | 0 | Invalid device. | +| EARPIECE | 1 | Earpiece. | +| SPEAKER | 2 | Speaker. | +| WIRED_HEADSET | 3 | Wired headset. | +| BLUETOOTH_SCO | 7 | Bluetooth device using the synchronous connection oriented (SCO) link. | +| BLUETOOTH_A2DP | 8 | Bluetooth device using the advanced audio distribution profile (A2DP). | +| MIC | 15 | Microphone. | + + +## ActiveDeviceType7+ + +Enumerates active device types. + +| Name | Default Value | Description | +| -------------- | ------------- | --------------------------------------------------------------------- | +| SPEAKER | 2 | Speaker. | +| BLUETOOTH_SCO | 7 | Bluetooth device using the SCO link. | + +## AudioRingMode7+ + +Enumerates ringer modes. + +| Name | Default Value | Description | +| ------------- | ------------- | --------------------------------------------------------------------- | +| RINGER_MODE_SILENT | 0 | Silence mode. | +| RINGER_MODE_VIBRATE | 1 | Vibration mode. | +| RINGER_MODE_NORMAL | 2 | Normal mode. | + +## AudioManager + +Implements audio volume and audio device management. + +### setVolume\(volumeType: AudioVolumeType, volume: number, callback: AsyncCallback\): void + +Sets the volume for a stream. This method uses an asynchronous callback to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | +| volume | number | Yes | Volume to set. The value range can be obtained by calling **getMinVolume** and **getMaxVolume**. | +| callback | AsyncCallback | Yes | Callback used to return the execution result. | + +**Return values** + +None + +**Example** + +``` +audioManager.setVolume(audio.AudioVolumeType.MEDIA, 10, (err)=>{ + if (err) { + console.error('Failed to set the volume. ${err.message}'); + return; + } + console.log('Callback invoked to indicate a successful volume setting.'); +}) +``` + +### setVolume\(volumeType: AudioVolumeType, volume: number\): Promise + +Sets the volume for a stream. This method uses a promise to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | +| volume | number | Yes | Volume to set. The value range can be obtained by calling **getMinVolume** and **getMaxVolume**. | + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the execution result. | + +**Example** + +``` +audioManager.setVolume(audio.AudioVolumeType.MEDIA, 10).then(()=> + console.log('Promise returned to indicate a successful volume setting.'); +) +``` + +### getVolume\(volumeType: AudioVolumeType, callback: AsyncCallback\): void + +Obtains the volume of a stream. This method uses an asynchronous callback to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | +| callback | AsyncCallback | Yes | Callback used to return the volume. | + +**Return values** + +None + +**Example** + +``` +audioManager.getVolume(audio.AudioVolumeType.MEDIA, (err, value) => { + if (err) { + console.error('Failed to obtain the volume. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the volume is obtained.'); +}) +``` + +### getVolume\(volumeType: AudioVolumeType\): Promise + +Obtains the volume of a stream. This method uses a promise to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the volume. | + +**Example** + +``` +audioManager.getVolume(audio.AudioVolumeType.MEDIA).then((value) => + console.log('Promise returned to indicate that the volume is obtained.' + value); +) +``` + +### getMinVolume\(volumeType: AudioVolumeType, callback: AsyncCallback\): void + +Obtains the minimum volume allowed for a stream. This method uses an asynchronous callback to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | +| callback | AsyncCallback | Yes | Callback used to return the minimum volume. | + +**Return values** + +None + +**Example** + +``` +audioManager.getMinVolume(audio.AudioVolumeType.MEDIA, (err, value) => { + if (err) { + console.error('Failed to obtain the minimum volume. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the minimum volume is obtained.' + value); +}) +``` + +### getMinVolume\(volumeType: AudioVolumeType\): Promise + +Obtains the minimum volume allowed for a stream. This method uses a promise to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the minimum volume. | + + +**Example** + +``` +audioManager.getMinVolume(audio.AudioVolumeType.MEDIA).then((value) => + console.log('Promised returned to indicate that the minimum volume is obtained.' + value); +) +``` + +### getMaxVolume\(volumeType: AudioVolumeType, callback: AsyncCallback\): void + +Obtains the maximum volume allowed for a stream. This method uses an asynchronous callback to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | +| callback | AsyncCallback | Yes | Callback used to return the maximum volume. | + +**Return values** + +None + +**Example** + +``` +audioManager.getMaxVolume(audio.AudioVolumeType.MEDIA, (err, value) => { + if (err) { + console.error('Failed to obtain the maximum volume. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the maximum volume is obtained.' + value); +}) +``` + +### getMaxVolume\(volumeType: AudioVolumeType\): Promise + +Obtains the maximum volume allowed for a stream. This method uses a promise to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | + + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the maximum volume. | + +**Example** + +``` +audioManager.getMaxVolume(audio.AudioVolumeType.MEDIA).then((data)=> + console.log('Promised returned to indicate that the maximum volume is obtained.'); +) +``` + +### mute\(volumeType: AudioVolumeType, mute: boolean, callback: AsyncCallback\): void7+ + +Mutes a stream. This method uses an asynchronous callback to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | +| mute | boolean | Yes | Mute status to set. The value **true** means to mute the stream, and **false** means the opposite. | +| callback | AsyncCallback | Yes | Callback used to return the execution result. | + +**Return values** + +None + +**Example** + +``` +audioManager.mute(audio.AudioVolumeType.MEDIA, true, (err) => { + if (err) { + console.error('Failed to mute the stream. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the stream is muted.'); +}) +``` + +### mute\(volumeType: AudioVolumeType, mute: boolean\): Promise7+ + +Mutes a stream. This method uses a promise to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | +| mute | boolean | Yes | Mute status to set. The value **true** means to mute the stream, and **false** means the opposite. | + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the execution result. | + +**Example** + +``` +audioManager.mute(audio.AudioVolumeType.MEDIA, true).then(() => + console.log('Promise returned to indicate that the stream is muted.'); +) +``` + +### isMute\(volumeType: AudioVolumeType, callback: AsyncCallback\): void7+ + +Checks whether a stream is muted. This method uses an asynchronous callback to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | +| callback | AsyncCallback | Yes | Callback used to return the mute status of the stream. The value **true** means that the stream is muted, and **false** means the opposite. | + +**Return values** + +None + +**Example** + +``` +audioManager.isMute(audio.AudioVolumeType.MEDIA, (err, value) => { + if (err) { + console.error('Failed to obtain the mute status. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the mute status of the stream is obtained.' + value); +}) +``` + +### isMute\(volumeType: AudioVolumeType\): Promise7+ + +Checks whether a stream is muted. This method uses a promise to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | + + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the mute status of the stream. The value **true** means that the stream is muted, and **false** means the opposite. | + +**Example** + +``` +audioManager.isMute(audio.AudioVolumeType.MEDIA).then((value) => + console.log('Promise returned to indicate that the mute status of the stream is obtained.' + value); +) +``` + +### isActive\(volumeType: AudioVolumeType, callback: AsyncCallback\): void7+ + +Checks whether a stream is active. This method uses an asynchronous callback to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | +| callback | AsyncCallback | Yes | Callback used to return the active status of the stream. The value **true** means that the stream is active, and **false** means the opposite. | + +**Return values** + +None + +**Example** + +``` +audioManager.isActive(audio.AudioVolumeType.MEDIA, (err, value) => { + if (err) { + console.error('Failed to obtain the active status of the stream. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the active status of the stream is obtained.' + value); +}) +``` + +### isActive\(volumeType: AudioVolumeType\): Promise7+ + +Checks whether a stream is active. This method uses a promise to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| volumeType | AudioVolumeType | Yes | Audio stream type. | + +**Return values** + + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the active status of the stream. The value **true** means that the stream is active, and **false** means the opposite. | + +**Example** + +``` +audioManager.isActive(audio.AudioVolumeType.MEDIA).then((value) => + console.log('Promise returned to indicate that the active status of the stream is obtained.' + value); +) +``` + +### setRingerMode\(mode: AudioRingMode, callback: AsyncCallback\): void7+ + +Sets the ringer mode. This method uses an asynchronous callback to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| mode | AudioRingMode | Yes | Ringer mode. | +| callback | AsyncCallback | Yes | Callback used to return the execution result. | + +**Return values** + +None + +**Example** + +``` +audioManager.setRingerMode(audio.AudioRingMode.RINGER_MODE_NORMAL, (err) => { + if (err) { + console.error('Failed to set the ringer mode.​ ${err.message}'); + return; + } + console.log('Callback invoked to indicate a successful setting of the ringer mode.'); +}) +``` + +### setRingerMode\(mode: AudioRingMode\): Promise7+ + +Sets the ringer mode. This method uses a promise to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| mode | AudioRingMode | Yes | Ringer mode. | + + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the execution result. | + +**Example** + +``` +audioManager.setRingerMode(audio.AudioRingMode.RINGER_MODE_NORMAL).then(() => + console.log('Promise returned to indicate a successful setting of the ringer mode.'); +) +``` + +### getRingerMode\(callback: AsyncCallback\): void7+ + +Obtains the ringer mode. This method uses an asynchronous callback to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| callback | AsyncCallback<AudioRingMode> | Yes | Callback used to return the ringer mode. | + +**Return values** + +None + +**Example** + +``` +audioManager.getRingerMode((err, value) => { + if (err) { + console.error('Failed to obtain the ringer mode.​ ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the ringer mode is obtained.' + value); +}) +``` + +### getRingerMode\(\): Promise7+ + +Obtains the ringer mode. This method uses a promise to return the query result. + +**Parameters** + +None + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise<AudioRingMode> | Promise used to return the ringer mode. | + +**Example** + +``` +audioManager.getRingerMode().then((value) => + console.log('Promise returned to indicate that the ringer mode is obtained.' + value); +) +``` + +### setAudioParameter\(key: string, value: string, callback: AsyncCallback\): void7+ + +Sets an audio parameter. This method uses an asynchronous callback to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| key | string | Yes | Key of the audio parameter to set. | +| value | string | Yes | Value of the audio parameter to set. | +| callback | AsyncCallback | Yes | Callback used to return the execution result. | + +**Return values** + +None + +**Example** + +``` +audioManager.setAudioParameter('PBits per sample', '8 bit', (err) => { + if (err) { + console.error('Failed to set the audio parameter. ${err.message}'); + return; + } + console.log('Callback invoked to indicate a successful setting of the audio parameter.'); +}) +``` + +### setAudioParameter\(key: string, value: string\): Promise7+ + +Sets an audio parameter. This method uses a promise to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| key | string | Yes | Key of the audio parameter to set. | +| value | string | Yes | Value of the audio parameter to set. | + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the execution result. | + +**Example** + +``` +audioManager.setAudioParameter('PBits per sample', '8 bit').then(() => + console.log('Promise returned to indicate a successful setting of the audio parameter.'); +) +``` + +### getAudioParameter\(key: string, callback: AsyncCallback\): void7+ + +Obtains the value of an audio parameter. This method uses an asynchronous callback to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| key | string | Yes | Key of the audio parameter whose value is to be obtained. | +| callback | AsyncCallback | Yes | Callback used to return the value of the audio parameter. | + +**Return values** + +None + +**Example** + +``` +audioManager.getAudioParameter('PBits per sample', (err, value) => { + if (err) { + console.error('Failed to obtain the value of the audio parameter. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the value of the audio parameter is obtained.' + value); +}) +``` + +### getAudioParameter\(key: string\): Promise7+ + +Obtains the value of an audio parameter. This method uses a promise to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| key | string | Yes | Key of the audio parameter whose value is to be obtained. | + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the value of the audio parameter. | + +**Example** + +``` +audioManager.getAudioParameter('PBits per sample').then((value) => + console.log('Promise returned to indicate that the value of the audio parameter is obtained.' + value); +) +``` + +### getDevices\(deviceFlag: DeviceFlag, callback: AsyncCallback\): void + +Obtains the audio devices with a specific flag. This method uses an asynchronous callback to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| deviceFlag | DeviceFlag | Yes | Audio device flag. | +| callback | AsyncCallback<AudioDeviceDescriptors> | Yes | Callback used to return the device list. | + +**Return values** + +None + +**Example** + +``` +audioManager.getDevices(audio.DeviceFlag.OUTPUT_DEVICES_FLAG, (err, value)=>{ + if (err) { + console.error('Failed to obtain the device list. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the device list is obtained.'); +}) +``` + +### getDevices\(deviceFlag: DeviceFlag\): Promise + +Obtains the audio devices with a specific flag. This method uses a promise to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| deviceFlag | DeviceFlag | Yes | Audio device flag. | + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise<AudioDeviceDescriptors> | Promise used to return the device list. | + +**Example** + +``` +audioManager.getDevices(audio.DeviceFlag.OUTPUT_DEVICES_FLAG).then((data)=> + console.log('Promise returned to indicate that the device list is obtained.'); +) +``` + +### setDeviceActive\(deviceType: ActiveDeviceType, active: boolean, callback: AsyncCallback\): void7+ + +Sets a device to the active state. This method uses an asynchronous callback to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| deviceType | ActiveDeviceType | Yes | Audio device type. | +| active | boolean | Yes | Active status to set. The value **true** means to set the device to the active status, and **false** means the opposite. | +| callback | AsyncCallback | Yes | Callback used to return the execution result. | + +**Return values** + +None + +**Example** + +``` +audioManager.setDeviceActive(audio.ActiveDeviceType.SPEAKER, true, (err)=> { + if (err) { + console.error('Failed to set the active status of the device. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the device is set to the active status.'); +}) +``` + +### setDeviceActive\(deviceType: ActiveDeviceType, active: boolean\): Promise7+ + +Sets a device to the active state. This method uses a promise to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| deviceType | ActiveDeviceType | Yes | Audio device type. | +| active | boolean | Yes | Active status to set. The value **true** means to set the device to the active status, and **false** means the opposite. | + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the execution result. | + +**Example** + +``` +audioManager.setDeviceActive(audio.ActiveDeviceType.SPEAKER, true).then(()=> + console.log('Promise returned to indicate that the device is set to the active status.'); +) +``` + +### isDeviceActive\(deviceType: DeviceType, callback: AsyncCallback\): void7+ + +Checks whether a device is active. This method uses an asynchronous callback to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| deviceType | ActiveDeviceType | Yes | Audio device type. | +| callback | AsyncCallback | Yes | Callback used to return the active status of the device. | + +**Return values** + +None + +**Example** + +``` +audioManager.isDeviceActive(audio.ActiveDeviceType.SPEAKER, (err, value) => { + if (err) { + console.error('Failed to obtain the active status of the device. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the active status of the device is obtained.'); +}) +``` + +### isDeviceActive\(deviceType: ActiveDeviceType\): Promise7+ + +Checks whether a device is active. This method uses a promise to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| deviceType | ActiveDeviceType | Yes | Audio device type. | + + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the active status of the device. | + +**Example** + +``` +audioManager.isDeviceActive(audio.ActiveDeviceType.SPEAKER).then((value) => + console.log('Promise returned to indicate that the active status of the device is obtained.' + value); +) +``` + +### setMicrophoneMute\(mute: boolean, callback: AsyncCallback\): void7+ + +Mutes or unmutes the microphone. This method uses an asynchronous callback to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| mute | boolean | Yes | Mute status to set. The value **true** means to mute the microphone, and **false** means the opposite. | +| callback | AsyncCallback | Yes | Callback used to return the execution result. | + +**Return values** + +None + +**Example** + +``` +audioManager.setMicrophoneMute(true, (err) => { + if (err) { + console.error('Failed to mute the microphone. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the microphone is muted.'); +}) +``` + +### setMicrophoneMute\(mute: boolean\): Promise7+ + +Mutes or unmutes the microphone. This method uses a promise to return the execution result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| mute | boolean | Yes | Mute status to set. The value **true** means to mute the microphone, and **false** means the opposite. | + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the execution result. | + +**Example** + +``` +audioManager.setMicrophoneMute(true).then(() => + console.log('Promise returned to indicate that the microphone is muted.'); +) +``` + +### isMicrophoneMute\(callback: AsyncCallback\): void7+ + +Checks whether the microphone is muted. This method uses an asynchronous callback to return the query result. + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------------- | ------------- | ---------------|------------------------------------------------------ | +| callback | AsyncCallback | Yes | Callback used to return the mute status of the microphone. The value **true** means that the microphone is muted, and **false** means the opposite. | + +**Return values** + +None + +**Example** + +``` +audioManager.isMicrophoneMute((err, value) => { + if (err) { + console.error('Failed to obtain the mute status of the microphone. ${err.message}'); + return; + } + console.log('Callback invoked to indicate that the mute status of the microphone is obtained.' + value); +}) +``` + +### isMicrophoneMute\(\): Promise7+ + +Checks whether the microphone is muted. This method uses a promise to return the query result. + +**Parameters** + +None + +**Return values** + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Promise | Promise used to return the mute status of the microphone. The value **true** means that the microphone is muted, and **false** means the opposite. | + +**Example** + +``` +audioManager.isMicrophoneMute().then((value) => + console.log('Promise returned to indicate that the mute status of the microphone is obtained.', + value); +) +``` + +## AudioDeviceDescriptor + +Describes an audio device. + +### Attributes + +| Name | Type | Readable | Writable | Description | +| ------------- | ------------- | ---------------|--------------------------------|------------------------ | +| deviceRole | DeviceRole | Yes | No | Audio device role. | +| deviceType | DeviceType | Yes | No | Audio device type. | + +## AudioDeviceDescriptors + +| Name | Description | +| ------------- | -------------------------------------------------------- | +| Device attribute array | Array of **AudioDeviceDescriptors**, which is read-only. | + + diff --git a/en/application-dev/js-reference/apis/js-apis-call.md b/en/application-dev/js-reference/apis/js-apis-call.md new file mode 100644 index 0000000000000000000000000000000000000000..16d5ceb279a670886be407b0f02e0b9a6a0b6e84 --- /dev/null +++ b/en/application-dev/js-reference/apis/js-apis-call.md @@ -0,0 +1,439 @@ +# Call + +>**Note:** +> +>- The APIs of this module are supported since API version 6. +> +>- APIs marked with 7+ are supported since API version 7. + + +## Modules to Import + +``` +import call from '@ohos.telephony.call'; +``` + +## call.dial + +dial\(phoneNumber: string, callback: AsyncCallback\): void + +Initiates a call. This function uses an asynchronous callback to return the execution result. + +Before using this API, you must declare the **ohos.permission.PLACE\_CALL** permission (a system permission). + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | -------- | -------- | -------- | + | phoneNumber | string | Yes|Phone number.| + | callback |AsyncCallback<boolean>|Yes|Callback used to return the result.
- **true**: success
-**false**: failure| + +- Example + + ``` + call.dial("138xxxxxxxx", (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## call.dial + +dial\(phoneNumber: string, options: DialOptions, callback: AsyncCallback\): void + +Initiates a call. You can set call options as needed. This function uses an asynchronous callback to return the execution result. + +Before using this API, you must declare the **ohos.permission.PLACE\_CALL** permission (a system permission). + +- Parameters + + | Parameter| Type| Mandatory| Description| + | ----------- | ---------------------------- | ---- | ------------------------------------------------- | + | phoneNumber | string | Yes| Phone number.| + | options | DialOptions | Yes| Call options. For details, see [DialOptions](#DialOptions).| + | callback | AsyncCallback<boolean> | Yes| Callback used to return the result.
- **true**: success
-**false**: failure| + + +- Example + + ``` + call.dial("138xxxxxxxx", { + extras: false + }, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## call.dial + +dial\(phoneNumber: string, options?: DialOptions\): Promise + +Initiates a call. You can set call options as needed. This function uses a promise to return the execution result. + +Before using this API, you must declare the **ohos.permission.PLACE\_CALL** permission (a system permission). + +- Parameters + + | Name| Type| Mandatory| Description| + | ----------- | ----------- | ---- | ------------------------------------------- | + | phoneNumber | string | Yes| Phone number.| + | options | DialOptions | Yes| Call options. For details, see [DialOptions](#DialOptions).| + +- Return values + + | Type| Description| + | ---------------------- | --------------------------------- | + | Promise<boolean> | Promise used to return the result.| + +- Example + + ``` + let promise = call.dial("138xxxxxxxx", { + extras: false + }); + promise.then(data => { + console.log(`dial success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`dial fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + +## call.hasCall + +hasCall\(callback: AsyncCallback\): void + +Checks whether a call is in progress. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ---------------------------- | ---- | ------------------------------------------------------------ | + | callback | AsyncCallback<boolean> | Yes| Callback used to return the result:
- **true**: A call is in progress.
- **false**: No call is in progress. | + +- Example + + ``` + call.hasCall((err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## call.hasCall + +hasCall\(\): Promise + +Checks whether a call is in progress. This function uses a promise to return the result. + +- Return values + + | Type| Description| + | ---------------------- | --------------------------------------- | + | Promise<boolean> | Promise used to return the result.| + +- Example + + ``` + let promise = call.hasCall(); + promise.then(data => { + console.log(`hasCall success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`hasCall fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## call.getCallState + +getCallState\(callback: AsyncCallback\): void + +Obtains the call status. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | -------------------------------------------- | ---- | ------------------------------------ | + | callback | AsyncCallback<[CallState](#CallState)> | Yes| Callback used to return the result.| + +- Example + + ``` + call.getCallState((err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## call.getCallState + +getCallState\(\): Promise + +Obtains the call status. This function uses a promise to return the result. + +- Return values + + | Type| Description| + | -------------------------------------- | ----------------------------------------- | + | Promise<[CallState](#CallState)> | Promise used to return the result.| + +- Example + + ``` + let promise = call.getCallState(); + promise.then(data => { + console.log(`getCallState success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`getCallState fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + +## call.isEmergencyPhoneNumber7+ + +isEmergencyPhoneNumber\(phoneNumber: string, callback: AsyncCallback\): void + +Checks whether the call number is an emergency number. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ----------- | ---------------------------- | ---- | ------------------------------------------------------------ | + | phoneNumber | string | Yes| Phone number.| + | callback | AsyncCallback<boolean> | Yes| Callback used to return the result.
- **true**: The called number is an emergency number.
- **false**: The called number is not an emergency number.| + +- Example + + ``` + call.isEmergencyPhoneNumber("138xxxxxxxx", (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## call.isEmergencyPhoneNumber7+ + +isEmergencyPhoneNumber\(phoneNumber: string, options: EmergencyNumberOptions, callback: AsyncCallback\): void + +Checks whether the call number is an emergency number. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ----------- | ---------------------------- | ---- | ------------------------------------------------------------ | + | phoneNumber | string | Yes| Phone number.| + | options | EmergencyNumberOptions | Yes| Emergency number options defined in [EmergencyNumberOptions](#EmergencyNumberOptions).| + | callback | AsyncCallback<boolean> | Yes| Callback used to return the result.
- **true**: The called number is an emergency number.
- **false**: The called number is not an emergency number.| + +- Example + + ``` + call.isEmergencyPhoneNumber("112", {slotId: 1}, (err, value) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## call.isEmergencyPhoneNumber7+ + +isEmergencyPhoneNumber\(phoneNumber: string, options?: EmergencyNumberOptions\): Promise + +Checks whether the call number is an emergency number. This function uses a promise to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ----------- | ---------------------- | ---- | ------------------------------------------------------------ | + | phoneNumber | string | Yes| Phone number.| + | options | EmergencyNumberOptions | Yes| Emergency number options defined in [EmergencyNumberOptions](#EmergencyNumberOptions).| + +- Return values + + | Type| Description| + | ---------------------- | --------------------------------------------------- | + | Promise<boolean> | Promise used to return the result.| + +- Example + + ``` + let promise = call.isEmergencyPhoneNumber("138xxxxxxxx", {slotId: 1}); + promise.then(data => { + console.log(`isEmergencyPhoneNumber success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`isEmergencyPhoneNumber fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + +## call.formatPhoneNumber7+ + +formatPhoneNumber\(phoneNumber: string, callback: AsyncCallback\): void + +Formats a phone number. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ----------- | --------------------------- | ---- | ------------------------------------ | + | phoneNumber | string | Yes| Phone number.| + | callback | AsyncCallback<string> | Yes| Callback used to return the result.| + +- Example + + ``` + call.formatPhoneNumber("138xxxxxxxx", (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## call.formatPhoneNumber7+ + +formatPhoneNumber\(phoneNumber: string, options: NumberFormatOptions, callback: AsyncCallback\): void + +Formats a phone number based on specified formatting options. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ----------- | --------------------------- | ---- | ------------------------------------------------------------ | + | phoneNumber | string | Yes| Phone number.| + | options | NumberFormatOptions | Yes| Number formatting options defined in [NumberFormatOptions](#NumberFormatOptions).| + | callback | AsyncCallback<string> | Yes| Callback used to return the result.| + +- Example + + ``` + call.formatPhoneNumber("138xxxxxxxx",{ + countryCode: "CN" + }, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## call.formatPhoneNumber7+ + +formatPhoneNumber\(phoneNumber: string, options?: NumberFormatOptions\): Promise + +Formats a phone number based on specified formatting options. This function uses a promise to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ----------- | ------------------- | ---- | ------------------------------------------------------------ | + | phoneNumber | string | Yes| Phone number.| + | options | NumberFormatOptions | Yes| Number formatting options defined in [NumberFormatOptions](#NumberFormatOptions).| + +- Return values + + | Type| Description| + | --------------------- | ------------------------------------------- | + | Promise<string> | Promise used to return the result.| + +- Example + + ``` + let promise = call.formatPhoneNumber("138xxxxxxxx", { + countryCode: "CN" + }); + promise.then(data => { + console.log(`formatPhoneNumber success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`formatPhoneNumber fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + +## call.formatPhoneNumberToE1647+ + +formatPhoneNumberToE164\(phoneNumber: string, countryCode: string, callback: AsyncCallback\): void + +Converts a phone number into the E.164 format. This function uses an asynchronous callback to return the result. + +The phone number must match the specified country code. For example, for a China phone number, the country code must be **CN**. Otherwise, **null** will be returned. + +All country codes are supported. + +- Parameters + + | Name| Type| Mandatory| Description| + | ----------- | --------------------------- | ---- | ----------------------------------------------------- | + | phoneNumber | string | Yes| Phone number.| + | countryCode | string | Yes| Country code, for example, **CN** (China). All country codes are supported.| + | callback | AsyncCallback<string> | Yes| Callback used to return the result.| + +- Example + + ``` + call.formatPhoneNumberToE164("138xxxxxxxx",{ + countryCode: "CN" + }, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## call.formatPhoneNumberToE1647+ + +formatPhoneNumberToE164\(phoneNumber: string, countryCode: string\): Promise + +Converts a phone number into the E.164 format. This function uses a promise to return the result. + +The phone number must match the specified country code. For example, for a China phone number, the country code must be **CN**. Otherwise, **null** will be returned. + +All country codes are supported. + +- Parameters + + | Name| Type| Mandatory| Description| + | ----------- | ------ | ---- | ---------------------------------------- | + | phoneNumber | string | Yes| Phone number.| + | countryCode | string | Yes| Country code, for example, **CN** (China). All country codes are supported.| + +- Return values + + | Type| Description| + | --------------------- | ------------------------------------------------------------ | + | Promise<string> | Promise used to return the result.| + +- Example + + ``` + let promise = call.formatPhoneNumberToE164("138xxxxxxxx", { + countryCode: "CN" + }); + promise.then(data => { + console.log(`formatPhoneNumberToE164 success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`formatPhoneNumberToE164 fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + +## DialOptions + +Provides an option for determining whether a call is a video call. +| Name| Type| Mandatory| Description| +| -------- | -------- | -------- | -------- | +| extras | boolean | No|Indication of a video call. The options are as follows:
- **true**: video call
- **false**: voice call| + +## CallState + +Enumerates call states. +| Variable| Value| Description| +| -------- | -------- | -------- | +| CALL_STATE_UNKNOWN | -1 | The call status fails to be obtained and is unknown.| +| CALL_STATE_IDLE | 0 | No call is in progress.| +| CALL_STATE_RINGING | 1 | The call is in the ringing or waiting state.| +| CALL_STATE_OFFHOOK | 2 | At least one call is in dialing, active, or on hold, and no new incoming call is ringing or waiting.| + +## EmergencyNumberOptions7+ + +Provides an option for determining whether a number is an emergency number for the SIM card in the specified slot. +| Name| Type| Mandatory| Description| +| -------- | -------- | -------- | -------- | +| slotId | number | No|SIM card slot ID.
- **0**: slot 1
- **1**: slot 2| + +## NumberFormatOptions7+ + +Provides an option for number formatting. +| Name| Type| Mandatory| Description| +| -------- | -------- | -------- | -------- | +| countryCode | string | No|Country code, for example, **CN** (China). All country codes are supported. The default value is **CN**.| diff --git a/en/application-dev/js-reference/apis/js-apis-radio.md b/en/application-dev/js-reference/apis/js-apis-radio.md new file mode 100644 index 0000000000000000000000000000000000000000..69cac33509d195b8a3160f72b127a8ea17ac448c --- /dev/null +++ b/en/application-dev/js-reference/apis/js-apis-radio.md @@ -0,0 +1,460 @@ +# Radio + +>**Note:** +> +>- The APIs of this module are supported since API version 6. +>- APIs marked with 7+ are supported since API version 7. + + +## Modules to Import + +``` +import radio from '@ohos.telephony.radio' +``` + +## radio.getRadioTech + +getRadioTech\(slotId: number, callback: AsyncCallback<\{psRadioTech: RadioTechnology, csRadioTech: RadioTechnology\}\>\): void + +Obtains the radio access technologies (RATs) used by the CS and PS domains. This function uses an asynchronous callback to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_NETWORK\_INFO** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ------------------------------------------------------------ | ---- | -------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback\<{psRadioTech: [RadioTechnology](#RadioTechnology), csRadioTech:[RadioTechnology](#RadioTechnology)}\> | Yes| Callback used to return the result.| + +- Example + + ``` + let slotId = 0; + radio.getRadioTech(slotId, (err, data) =>{ + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## radio.getRadioTech + +getRadioTech\(slotId: number\): Promise<\{psRadioTech: RadioTechnology, csRadioTech: RadioTechnology\}\> + +Obtains the RAT used by the CS and PS domains. This function uses a promise to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_NETWORK\_INFO** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | ------------------------------------------------------------ | ----------------------------------------------- | + | Promise<{psRadioTech: [RadioTechnology](#RadioTechnology), csRadioTech: [RadioTechnology](#RadioTechnology)}> | Promise used to return the result.| + +- Example + + ``` + let slotId = 0; + let promise = radio.getRadioTech(slotId); + promise.then(data => { + console.log(`getRadioTech success, data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getRadioTech fail, err->${JSON.stringify(err)}`); + }); + ``` + + +## radio.getNetworkState + +getNetworkState\(callback: AsyncCallback\): void + +Obtains the network status. This function uses an asynchronous callback to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_NETWORK\_INFO** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ---------------------------------------------- | ---- | ---------- | + | callback | AsyncCallback\<[NetworkState](#NetworkState)\> | Yes| Callback used to return the result.| + +- Example + + ``` + radio.getNetworkState((err, data) =>{ + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## radio.getNetworkState + +getNetworkState\(slotId: number, callback: AsyncCallback\): void + +Obtains the network status of the SIM card in the specified slot. This function uses an asynchronous callback to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_NETWORK\_INFO** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ---------------------------------------------- | ---- | -------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback\<[NetworkState](#NetworkState)\> | Yes| Callback used to return the result.| + +- Example + + ``` + let slotId = 0; + radio.getNetworkState(slotId, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## radio.getNetworkState + +getNetworkState\(slotId?: number\): Promise + +Obtains the network status of the SIM card in the specified slot. This function uses a promise to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_NETWORK\_INFO** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | No| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | ---------------------------------------- | --------------------------- | + | Promise\<[NetworkState](#NetworkState)\> | Promise used to return the result.| + +- Example + + ``` + let slotId = 0; + let promise = radio.getNetworkState(slotId); + promise.then(data => { + console.log(`getNetworkState success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getNetworkState fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## radio.getNetworkSelectionMode + +getNetworkSelectionMode\(slotId: number, callback: AsyncCallback\): void + +Obtains the network selection mode of the SIM card in the specified slot. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ------------------------------------------------------------ | ---- | -------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback\<[NetworkSelectionMode](#NetworkSelectionMode)\> | Yes| Callback used to return the result.| + +- Example + + ``` + let slotId = 0; + radio.getNetworkSelectionMode(slotId, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## radio.getNetworkSelectionMode + +getNetworkSelectionMode\(slotId: number\): Promise + +Obtains the network selection mode of the SIM card in the specified slot. This function uses a promise to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | -------------------------------------------------------- | ------------------------------- | + | Promise\<[NetworkSelectionMode](#NetworkSelectionMode)\> | Promise used to return the result.| + +- Example + + ``` + let slotId = 0; + let promise = radio.getNetworkSelectionMode(slotId); + promise.then(data => { + console.log(`getNetworkSelectionMode success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getNetworkSelectionMode fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## radio.getISOCountryCodeForNetwork7+ + +getISOCountryCodeForNetwork\(slotId: number, callback: AsyncCallback\): void + +Obtains the ISO country code of the network with which the SIM card in the specified slot is registered. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ----------------------- | ---- | ---------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback\ | Yes| Callback used to return the result, which is a country code, for example, **CN** (China).| + +- Example + + ``` + let slotId = 0; + radio.getISOCountryCodeForNetwork(slotId, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## radio.getISOCountryCodeForNetwork7+ + +getISOCountryCodeForNetwork\(slotId: number\): Promise + +Obtains the ISO country code of the network with which the SIM card in the specified slot is registered. This function uses a promise to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | ----------------- | ------------------------------------------------------------ | + | Promise\ | Promise used to return the result, which is an ISO country code, for example, **CN** (China).| + +- Example + + ``` + let slotId = 0; + let promise = radio.getISOCountryCodeForNetwork(slotId); + promise.then(data => { + console.log(`getISOCountryCodeForNetwork success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getISOCountryCodeForNetwork fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## radio.getSignalInformation + +getSignalInformation\(slotId: number, callback: AsyncCallback\>\): void + +Obtains a list of signal strengths of the network with which the SIM card in the specified slot is registered. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback\\> | Yes| Callback used to return the result, which is a list of [SignalInformation](#SignalInformation) objects.| + +- Example + + ``` + let slotId = 0; + radio.getSignalInformation(slotId, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## radio.getSignalInformation + +getSignalInformation\(slotId: number\): Promise\> + +Obtains a list of signal strengths of the network with which the SIM card in the specified slot is registered. This function uses a promise to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | ----------------------------------------------------------- | ------------------------------------------------------------ | + | Promise\\> | Promise used to return the result, which is a list of [SignalInformation](#SignalInformation) objects.| + +- Example + + ``` + let slotId = 0; + let promise = radio.getSignalInformation(slotId); + promise.then(data => { + console.log(`getSignalInformation success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`getSignalInformation fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## radio.isRadioOn7+ + +isRadioOn\(callback: AsyncCallback\): void + +Checks whether radio is turned on. This function uses an asynchronous callback to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_NETWORK\_INFO** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ------------------------ | ---- | ------------------------------------------------------- | + | callback | AsyncCallback\ | Yes| Callback used to return the result.
- **true**: Radio is turned on.
- **false**: Radio is turned off.| + +- Example + + ``` + radio.isRadioOn((err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## radio.isRadioOn7+ + +isRadioOn\(\): Promise + +Checks whether radio is turned on. This function uses a promise to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_NETWORK\_INFO** permission. + +- Return values + + | Type| Description| + | ------------------ | ------------------------------------------------------------ | + | Promise\ | Promise used to return the result.
- **true**: Radio is turned on.
- **false**: Radio is turned off.| + +- Example + + ``` + let promise = radio.isRadioOn(); + promise.then(data => { + console.log(`isRadioOn success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`isRadioOn fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## RadioTechnology + +Enumerates the RATs. + +| Variable| Value| Description| +| ------------------------- | ---- | ------------------------------------------------------------ | +| RADIO_TECHNOLOGY_UNKNOWN | 0 | Unknown| +| RADIO_TECHNOLOGY_GSM | 1 | Global System for Mobile Communication (GSM)| +| RADIO_TECHNOLOGY_1XRTT | 2 | Single-Carrier Radio Transmission Technology (1XRTT)| +| RADIO_TECHNOLOGY_WCDMA | 3 | Wideband Code Division Multiple Access (WCDMA)| +| RADIO_TECHNOLOGY_HSPA | 4 | High Speed Packet Access (HSPA)| +| RADIO_TECHNOLOGY_HSPAP | 5 | Evolved High Speed Packet Access (HSPA+)| +| RADIO_TECHNOLOGY_TD_SCDMA | 6 | Time Division Synchronous Code Division Multiple Access (TD-SCDMA)| +| RADIO_TECHNOLOGY_EVDO | 7 | Evolution-Data Optimized (EVDO)| +| RADIO_TECHNOLOGY_EHRPD | 8 | Evolved High Rate Package Data (EHRPD)| +| RADIO_TECHNOLOGY_LTE | 9 | Long Term Evolution (LTE)| +| RADIO_TECHNOLOGY_LTE_CA | 10 | Long Term Evolution_Carrier Aggregation (LTE_CA)| +| RADIO_TECHNOLOGY_IWLAN | 11 | Industrial Wireless LAN (IWLAN)| +| RADIO_TECHNOLOGY_NR | 12 | New Radio (NR)| + + +## SignalInformation + +Defines the signal strength. + +| Attribute| Type| Description| +| ----------- | --------------------------- | ------------------ | +| signalType | [NetworkType](#NetworkType) | Signal strength type.| +| signalLevel | number | Signal strength level.| + + +## NetworkType + +Enumerates network types. + +| Variable| Value| Description| +| -------------------- | ---- | ------------------------------------------------------------ | +| NETWORK_TYPE_UNKNOWN | 0 | Unknown| +| NETWORK_TYPE_GSM | 1 | GSM network| +| NETWORK_TYPE_CDMA | 2 | CDMA network| +| NETWORK_TYPE_WCDMA | 3 | WCDMA network| +| NETWORK_TYPE_TDSCDMA | 4 | TD-SCDMA network| +| NETWORK_TYPE_LTE | 5 | LTE network| +| NETWORK_TYPE_NR | 6 | 5G NR network| + +## NetworkState + +Defines the network registration status. + +| Variable| Type| Description| +| ----------------- | --------------------- | ------------------------------ | +| longOperatorName | string | Long carrier name of the registered network.| +| shortOperatorName | string | Short carrier name of the registered network.| +| plmnNumeric | string | PLMN code of the registered network.| +| isRoaming | boolean | Whether the user is roaming.| +| regState | [RegState](#RegState) | Network registration status of the device.| +| nsaState | [NsaState](#NsaState) | NSA network registration status of the device.| +| isCaActive | boolean | Whether carrier aggregation (CA) is supported.| +| isEmergency | boolean | Whether only emergency calls are allowed.| + + +## RegState + +Enumerates network registration states. + +| Variable| Value| Description| +| ----------------------------- | ---- | -------------------------- | +| REG_STATE_NO_SERVICE | 0 | The device cannot use any service.| +| REG_STATE_IN_SERVICE | 1 | The device can use services normally. | +| REG_STATE_EMERGENCY_CALL_ONLY | 2 | The device can use only the emergency call service.| +| REG_STATE_POWER_OFF | 3 | The cellular radio service is disabled.| + + +## NsaState + +Enumerates NSA network states. + +| Variable| Value| Description| +| -------------------------- | ---- | ---------------------------------------------------------- | +| NSA_STATE_NOT_SUPPORT | 1 | The device is in idle or connected state in an LTE cell that does not support NSA.| +| NSA_STATE_NO_DETECT | 2 | The device is in the idle state in an LTE cell that supports NSA but does not support NR coverage detection.| +| NSA_STATE_CONNECTED_DETECT | 3 | The device is connected to the LTE network in an LTE cell that supports NSA and NR coverage detection.| +| NSA_STATE_IDLE_DETECT | 4 | The device is in the idle state in an LTE cell that supports NSA and NR coverage detection.| +| NSA_STATE_DUAL_CONNECTED | 5 | The device is connected to the LTE/NR network in an LTE cell that supports NSA.| +| NSA_STATE_SA_ATTACHED | 6 | The device is idle or connected to the NG-RAN cell when being attached to the 5G Core.| + + +## NetworkSelectionMode + +Enumerates network selection modes. + +| Variable| Value| Description| +| --------------------------- | ---- | -------------- | +| NETWORK_SELECTION_UNKNOWN | 0 | Unknown network selection mode.| +| NETWORK_SELECTION_AUTOMATIC | 1 | Automatic network selection mode.| +| NETWORK_SELECTION_MANUAL | 2 | Manual network selection mode.| diff --git a/en/application-dev/js-reference/apis/js-apis-sim.md b/en/application-dev/js-reference/apis/js-apis-sim.md new file mode 100644 index 0000000000000000000000000000000000000000..9d27fea1ef66d7e3727e2b3cfcaf22175668ea6c --- /dev/null +++ b/en/application-dev/js-reference/apis/js-apis-sim.md @@ -0,0 +1,388 @@ +# SIM Management + +>**Note:** +> +>- The APIs of this module are supported since API version 6. +>- APIs marked with 7+ are supported since API version 7. + +## Modules to Import + +``` +import sim from '@ohos.telephony.sim'; +``` + +## sim.getSimIccId + +getSimIccId\(slotId: number, callback: AsyncCallback\): void + +Obtains the integrated circuit card identity (ICCID) of the SIM card in the specified slot. This function uses an asynchronous callback to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_TELEPHONY\_STATE** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | --------------------------- | ---- | -------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback<string> | Yes| Callback used to return the result.| + + +- Example + + ``` + sim.getSimIccId(0, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sim.getSimIccId + +getSimIccId\(slotId: number\): Promise + +Obtains the ICCID of the SIM card in the specified slot. This function uses a promise to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_TELEPHONY\_STATE** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | --------------------- | ---------------------------------- | + | Promise<string> | Promise used to return the result.| + +- Example + + ``` + let promise = sim.getSimIccId(0); + promise.then(data => { + console.log(`getSimIccId success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getSimIccId fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + +## sim.getDefaultVoiceSlotId7+ + +getDefaultVoiceSlotId\(callback: AsyncCallback\): void + +Obtains the default slot ID of the SIM card that provides voice services. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | --------------------------- | ---- | ---------- | + | callback | AsyncCallback<number> | Yes| Callback used to return the result.| + +- Example + + ``` + sim.getDefaultVoiceSlotId((err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sim.getDefaultVoiceSlotId7+ + +getDefaultVoiceSlotId\(\): Promise + +Obtains the default slot ID of the SIM card that provides voice services. This function uses a promise to return the result. + +- Return values + + | Type| Description| + | ----------------- | --------------------------------------- | + | Promise\ | Promise used to return the result.| + +- Example + + ``` + let promise = sim.getDefaultVoiceSlotId(); + promise.then(data => { + console.log(`getDefaultVoiceSlotId success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getDefaultVoiceSlotId fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + +## sim.getISOCountryCodeForSim + +getISOCountryCodeForSim\(slotId: number, callback: AsyncCallback\): void + +Obtains the ISO country code of the SIM card in the specified slot. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ----------------------- | ---- | ---------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback\ | Yes| Callback used to return the result, which is a country code, for example, **CN** (China).| + +- Example + + ``` + sim.getISOCountryCodeForSim(0, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sim.getISOCountryCodeForSim + +getISOCountryCodeForSim\(slotId: number\): Promise + +Obtains the ISO country code of the SIM card in the specified slot. This function uses a promise to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | ----------------- | ------------------------------------------------------------ | + | Promise\ | Promise used to return the result, which is a country code, for example, **CN** (China).| + +- Example + + ``` + let promise = sim.getISOCountryCodeForSim(0); + promise.then(data => { + console.log(`getISOCountryCodeForSim success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getISOCountryCodeForSim fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## sim.getSimOperatorNumeric + +getSimOperatorNumeric\(slotId: number, callback: AsyncCallback\): void + +Obtains the public land mobile network (PLMN) ID of the SIM card in the specified slot. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ----------------------- | ---- | -------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback\ | Yes| Callback used to return the result.| + +- Example + + ``` + sim.getSimOperatorNumeric(0, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sim.getSimOperatorNumeric + +getSimOperatorNumeric\(slotId: number\): Promise + +Obtains the PLMN ID of the SIM card in the specified slot. This function uses a promise to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | ----------------- | ------------------------------------------------ | + | Promise\ | Promise used to return the result.| + +- Example + + ``` + let promise = sim.getSimOperatorNumeric(0); + promise.then(data => { + console.log(`getSimOperatorNumeric success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getSimOperatorNumeric fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## sim.getSimSpn + +getSimSpn\(slotId: number, callback: AsyncCallback\): void + +Obtains the service provider name (SPN) of the SIM card in the specified slot. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ----------------------- | ---- | -------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback\ | Yes| Callback used to return the result.| + +- Example + + ``` + sim.getSimSpn(0, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sim.getSimSpn + +getSimSpn\(slotId: number\): Promise + +Obtains the SPN of the SIM card in the specified slot. This function uses a promise to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | ----------------- | ----------------------------------------- | + | Promise\ | Promise used to return the result.| + +- Example + + ``` + let promise = sim.getSimSpn(0); + promise.then(data => { + console.log(`getSimSpn success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getSimSpn fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## sim.getSimState + +getSimState\(slotId: number, callback: AsyncCallback\): void + +Obtains the status of the SIM card in the specified slot. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | -------------------------------------- | ---- | ----------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback\<[SimState](#SimState)\> | Yes| Callback used to return the result. For details, see [SimState](#SimState).| + +- Example + + ``` + sim.getSimState(0, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sim.getSimState + +getSimState\(slotId: number\): Promise + +Obtains the status of the SIM card in the specified slot. This function uses a promise to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | -------------------------------- | ------------------------------------------ | + | Promise\<[SimState](#SimState)\> | Promise used to return the result.| + +- Example + + ``` + let promise = sim.getSimState(0); + promise.then(data => { + console.log(`getSimState success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getSimState fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + +## sim.getSimGid1 + +getSimGid1\(slotId: number, callback: AsyncCallback\): void + +Obtains the group identifier level 1 (GID1) of the SIM card in the specified slot. This function uses an asynchronous callback to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_TELEPHONY\_STATE** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ----------------------- | ---- | -------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback\ | Yes| Callback used to return the result.| + +- Example + + ``` + sim.getSimGid1(0, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sim.getSimGid1 + +getSimGid1\(slotId: number\): Promise + +Obtains the GID1 of the SIM card in the specified slot. This function uses a promise to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_TELEPHONY\_STATE** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | -------------------------------------- | + | slotId | number | Yes| Card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | ----------------- | ------------------------------------------------------------ | + | Promise\ | Promise used to return the result.| + +- Example + + ``` + let promise = sim.getSimGid1(0); + promise.then(data => { + console.log(`getSimGid1 success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.log(`getSimGid1 fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## SimState + +Enumerates SIM card states. + +| Variable| Description| +| --------------------- | ---------------------------------------------------------- | +| SIM_STATE_UNKNOWN | The SIM card is in **unknown** state; that is, the SIM card status cannot be obtained.| +| SIM_STATE_NOT_PRESENT | The SIM card is in **not present** state; that is, no SIM card is inserted into the slot.| +| SIM_STATE_LOCKED | The SIM card is in **locked** state; that is, the SIM card is locked by the personal identification number (PIN), PIN unblocking key (PUK), or network.| +| SIM_STATE_NOT_READY | The SIM card is in **not ready** state; that is, the SIM card is present but cannot work properly.| +| SIM_STATE_READY | The SIM card is in **ready** state; that is, the SIM card is present and is working properly.| +| SIM_STATE_LOADED | The SIM card is in **loaded** state; that is, the SIM card is present and all its files have been loaded.| diff --git a/en/application-dev/js-reference/apis/js-apis-sms.md b/en/application-dev/js-reference/apis/js-apis-sms.md new file mode 100644 index 0000000000000000000000000000000000000000..a45f89399ee9e2c5d7cd71585d08f9fb6f9c4c1c --- /dev/null +++ b/en/application-dev/js-reference/apis/js-apis-sms.md @@ -0,0 +1,352 @@ +# SMS + +>**Note:** +> +>- The APIs of this module are supported since API version 6. +> +>- APIs marked with 7+ are supported since API version 7. + +## Modules to Import + +``` +import sms from '@ohos.telephony.sms'; +``` + +## sms.createMessage + +createMessage\(pdu: Array, specification: string, callback: AsyncCallback\): void + +Creates an SMS message instance based on the protocol data unit (PDU) and the specified SMS protocol. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------------- | -------------------------------------------------- | ---- | ------------------------------------------------------------ | + | pdu | Array<number> | Yes| Protocol data unit, which is obtained from the received SMS message.| + | specification | string | Yes| SMS protocol type. The options are as follows:
- **3gpp**: GSM/UMTS/LTE SMS
- **3gpp2**: CDMA SMS| + | callback | AsyncCallback<[ShortMessage](#ShortMessage)> | Yes| Callback used to return the result.| + +- Example + + ``` + let specification = '3gpp'; + let pdu = [0x08, 0x91, ...]; + sms.createMessage(pdu, specification, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sms.createMessage + +createMessage\(pdu: Array, specification: string\): Promise + +Creates an SMS message instance based on the PDU and the specified SMS protocol. This function uses a promise to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------------- | ------------------- | ---- | ------------------------------------------------------------ | + | pdu | Array<number> | Yes| Protocol data unit, which is obtained from the received SMS message.| + | specification | string | Yes| SMS protocol type. The options are as follows:
- **3gpp**: GSM/UMTS/LTE SMS
- **3gpp2**: CDMA SMS| + +- Return values + + | Type| Description| + | -------------------------------------------- | --------------------------------- | + | Promise<[ShortMessage](#ShortMessage)> | Promise used to return the result.| + +- Example + + ``` + let specification = '3gpp'; + let pdu = [0x08, 0x91, ...]; + let promise = sms.createMessage(pdu, specification); + promise.then(data => { + console.log(`createMessage success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`createMessage fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + +## sms.sendMessage + +sendMessage(options: SendMessageOptions): void + +Sends an SMS message. + +Before using this API, you must declare the **ohos.permission.SEND_MESSAGES** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------- | ----------------------------------------- | ---- | ------------------------------------------------------------ | + | options | [SendMessageOptions](#SendMessageOptions) | Yes| Options (including the callback) for sending an SMS message. For details, see [SendMessageOptions](#SendMessageOptions).| + +- Example + + ``` + let sendCallback = function (err, data) { + console.log(`sendCallback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + } + let deliveryCallback = function (err, data) { + console.log(`deliveryCallback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + } + let slotId = 0; + let content ='SMS message content'; + let destinationHost = '+861xxxxxxxxxx'; + let serviceCenter = '+861xxxxxxxxxx'; + let destinationPort = 1000; + let options = {slotId, content, destinationHost, serviceCenter, destinationPort, sendCallback, deliveryCallback}; + sms.sendMessage(options); + ``` + + +## sms.getDefaultSmsSlotId7+ + +getDefaultSmsSlotId\(callback: AsyncCallback\): void + +Obtains the default slot of the SIM card used to send SMS messages. This function uses an asynchronous callback to return the result. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | --------------------------- | ---- | ---------------------------------------- | + | callback | AsyncCallback<number> | Yes| Callback used to return the result.
- **0**: slot 1
- **1**: slot 2| + +- Example + + ``` + sms.getDefaultSmsSlotId((err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sms.getDefaultSmsSlotId7+ + +getDefaultSmsSlotId\(\): Promise + +Obtains the default slot of the SIM card used to send SMS messages. This function uses a promise to return the result. + +- Return values + + | Type| Description| + | --------------- | ------------------------------------------------------------ | + | Promise | Promise used to return the result.
- **0**: slot 1
- **1**: slot 2| + +- Example + + ``` + let promise = call.getDefaultSmsSlotId(); + promise.then(data => { + console.log(`getDefaultSmsSlotId success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`getDefaultSmsSlotId fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## sms.setSmscAddr7+ + +setSmscAddr\(slotId: number, smscAddr: string, callback: AsyncCallback\): void + +Sets the short message service center (SMSC) address. This function uses an asynchronous callback to return the result. + +Before using this API, you must declare the **ohos.permission.SET\_TELEPHONY\_STATE** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ------------------------- | ---- | ----------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | smscAddr | string | Yes| SMSC address. | + | callback | AsyncCallback<void> | Yes| Callback used to return the result.| + +- Example + + ``` + let slotId = 0; + let smscAddr = '+861xxxxxxxxxx'; + sms.setSmscAddr(slotId, smscAddr, (err,data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sms.setSmscAddr7+ + +setSmscAddr\(slotId: number, smscAddr: string\): Promise + +Sets the SMSC address. This function uses a promise to return the result. + +Before using this API, you must declare the **ohos.permission.SET\_TELEPHONY\_STATE** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | ------ | ---- | ----------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | smscAddr | string | Yes| SMSC address.| + +- Return values + + | Type| Description| + | ------------------- | ------------------------------- | + | Promise<void> | Promise used to return the result.| + +- Example + + ``` + let slotId = 0; + let smscAddr = '+861xxxxxxxxxx'; + let promise = sms.setSmscAddr(slotId, smscAddr); + promise.then(data => { + console.log(`setSmscAddr success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`setSmscAddr fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## sms.getSmscAddr7+ + +getSmscAddr\(slotId: number, callback: AsyncCallback\): void + +Obtains the SMSC address. This function uses an asynchronous callback to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_TELEPHONY\_STATE** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | -------- | --------------------------- | ---- | ----------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + | callback | AsyncCallback<string> | Yes| Callback used to return the result.| + +- Example + + ``` + let slotId = 0; + sms.getSmscAddr(slotId, (err, data) => { + console.log(`callback: err->${JSON.stringify(err)}, data->${JSON.stringify(data)}`); + }); + ``` + + +## sms.getSmscAddr7+ + +getSmscAddr\(slotId: number\): Promise + +Obtains the SMSC address. This function uses a promise to return the result. + +Before using this API, you must declare the **ohos.permission.GET\_TELEPHONY\_STATE** permission. + +- Parameters + + | Name| Type| Mandatory| Description| + | ------ | ------ | ---- | ----------------------------------------- | + | slotId | number | Yes| SIM card slot ID. The options are as follows:
- **0**: slot 1
- **1**: slot 2| + +- Return values + + | Type| Description| + | --------------------- | --------------------------------------------- | + | Promise<string> | Promise used to return the result.| + +- Example + + ``` + let slotId = 0; + let promise = sms.getSmscAddr(slotId); + promise.then(data => { + console.log(`getSmscAddr success, promise: data->${JSON.stringify(data)}`); + }).catch(err => { + console.error(`getSmscAddr fail, promise: err->${JSON.stringify(err)}`); + }); + ``` + + +## ShortMessage + +Defines an SMS message instance. + +| Variable| Type| Description| +| ------------------------ | --------------------------------------- | ------------------------------------------------------------ | +| emailAddress | string | Email address.| +| emailMessageBody | string | Email body.| +| hasReplyPath | boolean | Whether the received SMS contains **TP-Reply-Path**. The default value is **false**.
**TP-Reply-Path**: the path in which the mobile phone can reply to the SMS message through the originating SMSC.| +| isEmailMessage | boolean | Whether the received SMS message is an email.| +| isReplaceMessage | boolean | Whether the received SMS message is a **replace short message**. The default value is **false**.
For details, see section 9.2.3.9 in **3GPP TS 23.040**.| +| isSmsStatusReportMessage | boolean | Whether the received SMS message is an SMS delivery status report. The default value is **false**.
SMS delivery status report: a message sent from the SMSC to show the current status of the SMS message you delivered.| +| messageClass | [ShortMessageClass](#ShortMessageClass) | SMS message type.| +| pdu | Array<number> | PDU in the SMS message.| +|protocolId|number|Protocol identifier used for delivering the SMS message.| +|scAddress|string|SMSC address.| +|scTimestamp|number|SMSC timestamp.| +|status|number|SMS message status sent by the SMSC in the **SMS-STATUS-REPORT** message.| +|userRawData|Array<number>|User data excluding the data header.| +|visibleMessageBody|string|SMS message body.| +|visibleRawAddress|string|Sender address to be displayed on the UI.| + + +## ShortMessageClass + +Enumerates SMS message types. + +| Variable| Value| Description| +| ---------------- | ---- | ---------------------------------------- | +| UNKNOWN | 0 | Unknown type.| +| INSTANT_MESSAGE | 1 | Instant message, which is displayed immediately after being received.| +| OPTIONAL_MESSAGE | 2 | Message stored in the device or SIM card.| +| SIM_MESSAGE | 3 | Message containing SIM card information, which is to be stored in the SIM card.| +| FORWARD_MESSAGE | 4 | Message to be forwarded to another device.| + + +## SendMessageOptions + +Provides the options (including callbacks) for sending an SMS message. + +For example, you can specify the SMS message type by the optional parameter **content**. + +| Name| Type| Mandatory| Description| +| ---------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | +| slotId | number | Yes| Slot ID of the SIM card used for sending SMS messages:
- **0**: slot 1
- **1**: slot 2| +| destinationHost | string | Yes| Destination address of the SMS message.| +| content | string \| Array<number> | Yes| SMS message type. If the content is comprised of character strings, the SMS message is a text message. If the content is comprised of byte arrays, the SMS message is a data message.| +| serviceCenter | string | No| SMSC address. By default, the SMSC address in the SIM card is used.| +| destinationPort | number | No| Destination port of the SMS message. This parameter is mandatory only for a data message. | +| sendCallback | AsyncCallback<[ISendShortMessageCallback](#ISendShortMessageCallback)> | No| Callback used to return the SMS message sending result. For details, see [ISendShortMessageCallback](#ISendShortMessageCallback).| +| deliveryCallback | AsyncCallback<[IDeliveryShortMessageCallback](#IDeliveryShortMessageCallback)> | No| Callback used to return the SMS message delivery report. For details, see [IDeliveryShortMessageCallback](#IDeliveryShortMessageCallback).| + + +## ISendShortMessageCallback + +Provides the callback for the SMS message delivery report. It consists of three parts: SMS message sending result, URI for storing the sent SMS message, and whether the SMS message is the last part of a long SMS message. + +| Name| Type| Mandatory| Description| +| ---------- | ------------------------------- | ---- | ------------------------------------------------------------ | +| isLastPart | boolean | No| Whether this SMS message is the last part of a long SMS message. The value **true** indicates that this SMS message is the last part of a long SMS message, and value **false** indicates the opposite. The default value is **false**.| +| result | [SendSmsResult](#SendSmsResult) | Yes| SMS message sending result.| +| url | string | Yes| URI for storing sent SMS messages.| + + +## IDeliveryShortMessageCallback + +Provides the callback for the SMS message delivery report. + +| Name| Type| Mandatory| Description| +| ------ | ------------------- | ---- | -------------- | +| pdu | Array<number> | Yes| SMS message delivery report.| + + +## SendSmsResult + +Enumerates SMS message sending results. + +| Name| Value| Description| +| ------------------------------------ | ---- | ------------------------------------------------------ | +| SEND_SMS_SUCCESS | 0 | The SMS message is sent successfully.| +| SEND_SMS_FAILURE_UNKNOWN | 1 | Failed to send the SMS message due to unknown reasons.| +| SEND_SMS_FAILURE_RADIO_OFF | 2 | Failed to send the SMS message because the modem is shut down.| +| SEND_SMS_FAILURE_SERVICE_UNAVAILABLE | 3 | Failed to send the SMS message because the network is unavailable or SMS message sending or receiving is not supported.| diff --git a/en/application-dev/quick-start/start-overview.md b/en/application-dev/quick-start/start-overview.md index bc4d355ab04d5f9b667bb96de59e4355f4a14d58..9fb98e63170838cb93d871b89b2787cc82fe2d70 100644 --- a/en/application-dev/quick-start/start-overview.md +++ b/en/application-dev/quick-start/start-overview.md @@ -49,6 +49,7 @@ For best results, use the [latest version of DevEco Studio](https://developer.h + ## Before You Start 1. Install DevEco Studio and configure the development environment. For details, see [Configuring the OpenHarmony SDK](configuring-openharmony-sdk.md). diff --git a/en/device-dev/Readme-EN.md b/en/device-dev/Readme-EN.md index b99935770e4b2d55a87cf33f4d17da6e16c14fbb..bbe11a57349df5d98efb884316d9e1dea5171221 100644 --- a/en/device-dev/Readme-EN.md +++ b/en/device-dev/Readme-EN.md @@ -55,28 +55,28 @@ In addition, OpenHarmony provides a series of optional system components that ca

Preparing for your development

- +

Quick start

Getting started with setup, build, burning, debugging, and running of OpenHarmony

-

Getting Started for Mini and Small Systems

+

Mini and Small Systems

Basic capabilities

Using basic capabilities of OpenHarmony

- +

Advanced development

Developing smart devices based on system capabilities

- +

Porting and adaptation

@@ -97,7 +97,7 @@ In addition, OpenHarmony provides a series of optional system components that ca

Referring to development specifications

- + @@ -125,21 +125,21 @@ In addition, OpenHarmony provides a series of optional system components that ca

Preparing for your development

- +

Quick start

Getting started with setup, build, burning, debugging, and running of OpenHarmony

-

Getting Started for Standard System

+

Standard System

Basic capabilities

Using basic capabilities of OpenHarmony

- +

Advanced development

@@ -153,7 +153,7 @@ In addition, OpenHarmony provides a series of optional system components that ca

Porting and adapting the OpenHarmony to a third-party library

- +

Contributing components

@@ -167,7 +167,7 @@ In addition, OpenHarmony provides a series of optional system components that ca

Referring to development specifications

- + diff --git a/en/device-dev/driver/Readme-EN.md b/en/device-dev/driver/Readme-EN.md index eb21fdeec4025c5c4dd2dc67030249d72e7d3103..c2c3dea84dfb01310ae917c9d6c60dd2c5a1e672 100644 --- a/en/device-dev/driver/Readme-EN.md +++ b/en/device-dev/driver/Readme-EN.md @@ -33,4 +33,5 @@ - [LCD](driver-peripherals-lcd-des.md) - [TOUCHSCREEN](driver-peripherals-touch-des.md) - [Sensor](driver-peripherals-sensor-des.md) - - [WLAN](driver-peripherals-external-des.md) \ No newline at end of file + - [WLAN](driver-peripherals-external-des.md) + - [USB](driver-peripherals-usb-des.md) \ No newline at end of file diff --git a/en/device-dev/driver/driver-peripherals-usb-des.md b/en/device-dev/driver/driver-peripherals-usb-des.md new file mode 100644 index 0000000000000000000000000000000000000000..0dd421ec369c8ff8d4deaee0560608a2090d6fef --- /dev/null +++ b/en/device-dev/driver/driver-peripherals-usb-des.md @@ -0,0 +1,1571 @@ +# USB + +- [Overview](#section175431838101617) + - [Available APIs](#section17667171301711) + +- [Development Guidelines](#section65745222184) + - [Developing Driver Using Host DDK APIs](#section865734181916) + - [Developing Driver Using Host Raw APIs](#section865734181916) + - [Developing Driver Using Device DDK APIs](#section865734181916) + +- [Development Examples](#section263714411191) + - [Developing Driver Using Host DDK APIs](#section18249155619195) + - [Developing Driver Using Host Raw APIs](#section3571192072014) + - [Developing Driver Using Device DDK APIs](#section6356758162015) + + +## Overview + +USB host development aims to provide host-related functions, including protocol encapsulation, device management, and driver installation and uninstall. + +USB device development aims to provide device-related functions, including device management, configuration management, and I/O management. These functions implement creation, configuration, and data communication of USB devices. + +The following figures show the UBS host and device driver models. + +**Figure 1** USB host driver model +![](figures/USB_host_driver_model.png "USB host driver model") + +**Figure 2** USB device driver model +![](figures/USB_device_driver_model.png "USB device driver model") + +The USB driver model offers the following APIs: + +- The USB host Driver Development Kit (DDK) provides driver capability APIs that can be directly called in user mode. The APIs can be classified into the DDK initialization class, interface operation class, and request operation class by function. These APIs can be used to perform DDK initialization, bind/release and open/close an interface, allocate/release a request, and implement isochronous or non-isochronous transfer. +- The USB device DDK provides device management, I/O management, and configuration management APIs, which can be used to create and delete a device, obtain/open an interface, and perform isochronous or non-isochronous transfer. + +### Available APIs + +Table 1 describes the APIs provided by the USB host driver model. + +**Table 1** APIs provided by the USB host driver model + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Header File

+

API

+

Description

+

usb_ddk_interface.h

+

+

+

int32_t UsbInitHostSdk(struct UsbSession **session);

+

Initializes the USB host driver DDK.

+

int32_t UsbExitHostSdk(const struct UsbSession *session);

+

Exits the USB host driver DDK.

+

const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex);

+

Obtains a USB interface.

+

int UsbReleaseInterface(const struct UsbInterface *interfaceObj);

+

Releases a USB interface.

+

int UsbAddOrRemoveInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex, UsbInterfaceStatus status);

+

Adds or removes a USB interface.

+

UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);

+

Opens a USB interface.

+

int32_t UsbCloseInterface(const UsbInterfaceHandle *interfaceHandle);

+

Closes a USB interface.

+

int32_t UsbSelectInterfaceSetting(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, struct UsbInterface **interfaceObj);

+

Sets a USB interface.

+

int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);

+

Obtains USB pipe information.

+

int32_t UsbClearInterfaceHalt(const UsbInterfaceHandle *interfaceHandle, uint8_t pipeAddress);

+

Clears the state of the pipe with the specified index.

+

struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int isoPackets, int length);

+

Allocates a request object.

+

int UsbFreeRequest(const struct UsbRequest *request);

+

Releases a request object.

+

int UsbSubmitRequestAsync(const struct UsbRequest *request);

+

Sends a request asynchronously.

+

int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);

+

Fills in a request.

+

sint UsbCancelRequest(const struct UsbRequest *request);

+

Cancels an asynchronous request.

+

int UsbSubmitRequestSync(const struct UsbRequest *request);

+

Sends a synchronous request.

+

usb_raw_api.h

+

+

+

+

+

+

int UsbRawInit(struct UsbSession **session);

+

Initializes the USB raw APIs.

+

int UsbRawExit(const struct UsbSession *session);

+

Exits the USB raw APIs.

+

UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);

+

Opens a USB device.

+

int UsbRawCloseDevice(const UsbRawHandle *devHandle);

+

Closes a USB device.

+

int UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData);

+

Performs a control transfer synchronously.

+

int UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);

+

Performs a bulk transfer synchronously.

+

int UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);

+

Performs an interrupt transfer synchronously.

+

int UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);

+

Obtains the configuration descriptor of a device.

+

void UsbRawFreeConfigDescriptor(const struct UsbRawConfigDescriptor *config);

+

Releases the memory space of a configuration descriptor.

+

int UsbRawGetConfiguration(const UsbRawHandle *devHandle, int *config);

+

Obtains the configuration in use.

+

int UsbRawSetConfiguration(const UsbRawHandle *devHandle, int config);

+

Sets the configuration in use.

+

int UsbRawGetDescriptor(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawDescriptorParam *param, const unsigned char *data);

+

Obtains descriptor information.

+

UsbRawDevice *UsbRawGetDevice(const UsbRawHandle *devHandle);

+

Obtains the device pointer based on the device handle.

+

int UsbRawGetDeviceDescriptor(const UsbRawDevice *rawDev, struct UsbDeviceDescriptor *desc);

+

Obtains the device descriptor of the specified USB device.

+

int UsbRawClaimInterface(const UsbRawHandle *devHandle, int interfaceNumber);

+

Declares the interface on the specified device handle.

+

int UsbRawReleaseInterface(const UsbRawHandle *devHandle, int interfaceNumber);

+

Releases the previously declared interface.

+

int UsbRawResetDevice(const UsbRawHandle *devHandle);

+

Resets a device.

+

struct UsbRawRequest *UsbRawAllocRequest(const UsbRawHandle *devHandle, int isoPackets, int length);

+

Allocates a transfer request with the specified number of sync packet descriptors.

+

int UsbRawFreeRequest(const struct UsbRawRequest *request);

+

Releases the previously allocated transfer request.

+

int UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

Fills in the bulk transfer request.

+

int UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData);

+

Fills in the control setup packet.

+

int UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

Fills in the control transfer request.

+

int UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

Fills in the interrupt transfer request.

+

int UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

Fills in the isochronous transfer request.

+

int UsbRawSubmitRequest(const struct UsbRawRequest *request);

+

Submits a transfer request.

+

int UsbRawCancelRequest(const struct UsbRawRequest *request);

+

Cancels a transfer request.

+

int UsbRawHandleRequests(const UsbRawHandle *devHandle);

+

Handles a transfer request event.

+
+ +Table 2 describes the APIs provided by the USB device driver model. + +**Table 2** APIs provided by the USB device driver model + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Header File

+

API

+

Description

+

usbfn_device.h

+

+

+

const struct UsbFnDevice *UsbFnCreateDevice(const char *udcName, const struct UsbFnDescriptorData *descriptor);

+

Creates a USB device.

+

int UsbFnRemoveDevice(struct UsbFnDevice *fnDevice);

+

Deletes a USB device.

+

const struct UsbFnDevice *UsbFnGetDevice(const char *udcName);

+

Obtains a USB device.

+

usbfn_interface.h

+

+

+

+

+

+

int UsbFnStartRecvInterfaceEvent(struct UsbFnInterface *interface, uint32_t eventMask, UsbFnEventCallback callback, void *context);

+

Starts to receive events.

+

int UsbFnStopRecvInterfaceEvent(struct UsbFnInterface *interface);

+

Stops receiving events.

+

UsbFnInterfaceHandle UsbFnOpenInterface(struct UsbFnInterface *interface);

+

Opens an interface.

+

int UsbFnCloseInterface(UsbFnInterfaceHandle handle);

+

Closes an interface.

+

int UsbFnGetInterfacePipeInfo(struct UsbFnInterface *interface, uint8_t pipeId, struct UsbFnPipeInfo *info);

+

Obtains pipe information.

+

int UsbFnSetInterfaceProp(const struct UsbFnInterface *interface, const char *name, const char *value);

+

Sets custom properties.

+

usbfn_request.h

+

+

+

+

+

+

+

+

struct UsbFnRequest *UsbFnAllocCtrlRequest(UsbFnInterfaceHandle handle, uint32_t len);

+

Applies for a control transfer request.

+

struct UsbFnRequest *UsbFnAllocRequest(UsbFnInterfaceHandle handle, uint8_t pipe, uint32_t len);

+

Applies for a data request.

+

int UsbFnFreeRequest(struct UsbFnRequest *req);

+

Releases a request.

+

int UsbFnSubmitRequestAsync(struct UsbFnRequest *req);

+

Sends a request asynchronously.

+

int UsbFnSubmitRequestSync(struct UsbFnRequest *req, uint32_t timeout);

+

Sends a request synchronously.

+

int UsbFnCancelRequest(struct UsbFnRequest *req);

+

Cancels a request.

+
+ +## Development Guidelines + +The USB driver is developed based on the Hardware Driver Foundation (HDF), platform, and Operating System Abstraction Layer (OSAL) APIs. A unified driver model is provided for USB devices, irrespective of the operating system and chip architecture. This document uses a serial port as an example to describe how to develop drivers for the USB host and USB device. + +### How to Develop + +### Developing Driver Using Host DDK APIs + +1. Configure the driver mapping table. +2. Initialize the USB host DDK. +3. Obtain a **UsbInterface** object. +4. Open the **UsbInterface** object to obtain the **UsbInterfaceHandle** object. +5. Obtain pipe information of the specified **pipeIndex** based on the **UsbInterfaceHandle** object. +6. Allocate an I/O request for the **UsbInterfaceHandle** object. +7. Fill in the I/O request based on the input parameters. +8. Submit the I/O request in synchronous or asynchronous mode. + + +### Developing Driver Using Host Raw APIs + +1. Configure the driver mapping table. +2. Initialize the host raw data, open the USB device, obtain the descriptor, and then obtain interface and endpoint information based on the descriptor. +3. Allocate a request and fill in the request based on the transfer type. +4. Submit the I/O request object in synchronous or asynchronous mode. + +### Developing Driver Using Device DDK APIs + +1. Construct a descriptor. +2. Instantiate a USB device using the descriptor constructed. +3. Call **UsbFnDeviceGetInterface** to obtain an interface, call **UsbFnInterfaceGetPipeInfo** to obtain pipe information based on the interface, call **UsbFnInterfaceOpen** to open the interface to obtain the handle, and call **UsbFnRequestAlloc** to obtain the request based on the handle and pipe ID. +4. Call **UsbFnInterfaceStartRecvEvent** to receive events such as Enable and Setup, and respond to the events in **UsbFnEventCallback**. +5. Send and receive data in synchronous or asynchronous mode. + +## Development Examples + +The following example helps you better understand the development of the USB serial port driver. + +### Developing Driver Using Host DDK APIs + +``` +root { + module = "usb_pnp_device"; + usb_pnp_config { + match_attr = "usb_pnp_match"; + usb_pnp_device_id = "UsbPnpDeviceId"; + UsbPnpDeviceId { + idTableList = [ + "host_acm_table" + ]; + host_acm_table { + // Driver module name, which must be the same as the value of moduleName in the driver entry structure. + moduleName = "usbhost_acm"; + // Service name of the driver, which must be unique. + serviceName = "usbhost_acm_pnp_service"; + // Keyword for matching private driver data. + deviceMatchAttr = "usbhost_acm_pnp_matchAttr"; + // Data length starting from this field, in bytes. + length = 21; + // USB driver matching rule: vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber. + matchFlag = 0x0303; + // Vendor ID. + vendorId = 0x12D1; + // Product ID. + productId = 0x5000; + // The least significant 16 bits of the device sequence number. + bcdDeviceLow = 0x0000; + // The most significant 16 bits of the device sequence number. + bcdDeviceHigh = 0x0000; + // Device class code allocated by the USB. + deviceClass = 0; + // Child class code allocated by the USB. + deviceSubClass = 0; + // Device protocol code allocated by the USB. + deviceProtocol = 0; + // Interface type. You can enter multiple types as needed. + interfaceClass = [0]; + // Interface subtype. You can enter multiple subtypes as needed. + interfaceSubClass = [2, 0]; + // Protocol that the interface complies with. You can enter multiple protocols as needed. + interfaceProtocol = [1, 2]; + // Interface numer. You can enter multiple interface numbers as needed. + interfaceNumber = [2, 3]; + } + } + } +} + +#include "usb_serial.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "osal_time.h" +#include "securec.h" +#include "usb_ddk_interface.h" +#include "hdf_usb_pnp_manage.h" + +#define HDF_LOG_TAG USB_HOST_ACM +#define STR_LEN 512 + +static struct UsbRequest *g_syncRequest = NULL; +static struct UsbRequest *g_ctrlCmdRequest = NULL; +static bool g_acmReleaseFlag = false; +static uint8_t *g_acmReadBuffer = NULL; +... +static int SerialCtrlMsg(struct AcmDevice *acm, uint8_t request, + uint16_t value, void *buf, uint16_t len) +{ + int ret; + uint16_t index = acm->intPipe->interfaceId; + struct UsbControlParams controlParams = {}; + struct UsbRequestParams parmas = {}; + if (acm == NULL || buf == NULL) { + HDF_LOGE("%{public}s:invalid param", __func__); + return HDF_ERR_IO; + } + if (acm->ctrlReq == NULL) { + acm->ctrlReq = UsbAllocRequest(acm->ctrDevHandle, 0, len); + if (acm->ctrlReq == NULL) { + HDF_LOGE("%{public}s: UsbAllocRequest failed", __func__); + return HDF_ERR_IO; + } + } + + controlParams.request = request; + controlParams.target = USB_REQUEST_TARGET_INTERFACE; + controlParams.reqType = USB_REQUEST_TYPE_CLASS; + controlParams.directon = USB_REQUEST_DIR_TO_DEVICE; + controlParams.value = value; + controlParams.index = index; + controlParams.data = buf; + controlParams.size = len; + + parmas.interfaceId = USB_CTRL_INTERFACE_ID; + parmas.pipeAddress = acm->ctrPipe->pipeAddress; + parmas.pipeId = acm->ctrPipe->pipeId; + parmas.requestType = USB_REQUEST_PARAMS_CTRL_TYPE; + parmas.timeout = USB_CTRL_SET_TIMEOUT; + parmas.ctrlReq = UsbControlSetUp(&controlParams); + ret = UsbFillRequest(acm->ctrlReq, acm->ctrDevHandle, &parmas); + if (HDF_SUCCESS != ret) { + HDF_LOGE("%{public}s: failed, ret=%{public}d ", __func__, ret); + return ret; + } + ret = UsbSubmitRequestSync(acm->ctrlReq); // Send an I/O request synchronously. + if (HDF_SUCCESS != ret) { + HDF_LOGE("UsbSubmitRequestSync faile, ret=%{public}d ", ret); + return ret; + } + if (!acm->ctrlReq->compInfo.status) { + HDF_LOGE("%{public}s status=%{public}d ", __func__, acm->ctrlReq->compInfo.status); + } + return HDF_SUCCESS; +} +... +static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm, + uint8_t interfaceIndex) +{ + struct UsbInterface *tmpIf = NULL; + tmpIf = (struct UsbInterface *)UsbClaimInterface(acm->session, acm->busNum, \ + acm->devAddr, interfaceIndex); // Obtain the UsbInterface object. + return tmpIf; +} +... +static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm, + uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection) +{ + uint8_t i; + int ret; + struct UsbInterfaceInfo *info = NULL; + UsbInterfaceHandle *interfaceHandle = NULL; + if (pipeType == USB_PIPE_TYPE_CONTROL) + { + info = &acm->ctrIface->info; + interfaceHandle = acm->ctrDevHandle; + } + else + { + info = &acm->iface[interfaceIndex]->info; + interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex); + } + + for (i = 0; i <= info->pipeNum; i++) { + struct UsbPipeInfo p; + ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);// Obtain information about the pipe with index i. + if (ret < 0) { + continue; + } + if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) { + struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi)); + if (pi == NULL) { + HDF_LOGE("%{public}s: Alloc pipe failed", __func__); + return NULL; + } + p.interfaceId = info->interfaceIndex; + *pi = p; + return pi; + } + } + return NULL; +} + +static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm, + UsbPipeType pipeType, UsbPipeDirection pipeDirection) +{ + uint8_t i; + if (acm == NULL) { + HDF_LOGE("%{public}s: invalid parmas", __func__); + return NULL; + } + for (i = 0; i < acm->interfaceCnt; i++) { + struct UsbPipeInfo *p = NULL; + if (!acm->iface[i]) { + continue; + } + p = EnumePipe(acm, i, pipeType, pipeDirection); + if (p == NULL) { + continue; + } + return p; + } + return NULL; +} + +/* HdfDriverEntry implementations */ +static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) +{ + struct UsbPnpNotifyServiceInfo *info = NULL; + errno_t err; + struct AcmDevice *acm = NULL; + if (device == NULL) { + HDF_LOGE("%s: device is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm)); + if (acm == NULL) { + HDF_LOGE("%s: Alloc usb serial device failed", __func__); + return HDF_FAILURE; + } + if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { + HDF_LOGE("%s:%d OsalMutexInit fail", __func__, __LINE__); + goto error; + } + info = (struct UsbPnpNotifyServiceInfo *)device->priv; + if (info != NULL) { + HDF_LOGD("%s:%d busNum=%d,devAddr=%d,interfaceLength=%d", \ + __func__, __LINE__, info->busNum, info->devNum, info->interfaceLength); + acm->busNum = info->busNum; + acm->devAddr = info->devNum; + acm->interfaceCnt = info->interfaceLength; + err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, + (const void*)info->interfaceNumber, info->interfaceLength); + if (err != EOK) { + HDF_LOGE("%s:%d memcpy_s failed err=%d", \ + __func__, __LINE__, err); + goto lock_error; + } + } else { + HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__); + goto lock_error; + } + acm->device = device; + device->service = &(acm->service); + acm->device->service->Dispatch = UsbSerialDeviceDispatch; + HDF_LOGD("UsbSerialDriverBind=========================OK"); + return HDF_SUCCESS; + +lock_error: + if (OsalMutexDestroy(&acm->lock)) { + HDF_LOGE("%s:%d OsalMutexDestroy fail", __func__, __LINE__); + } +error: + OsalMemFree(acm); + acm = NULL; + return HDF_FAILURE; +} +... +static int AcmAllocReadRequests(struct AcmDevice *acm) +{ + int ret; + struct UsbRequestParams readParmas = {}; + for (int i = 0; i < ACM_NR; i++) { + acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize); // Allocate the readReq I/O request object to be sent. + if (!acm->readReq[i]) { + HDF_LOGE("readReq request failed\n"); + goto error; + } + readParmas.userData = (void *)acm; + readParmas.pipeAddress = acm->dataInPipe->pipeAddress; + readParmas.pipeId = acm->dataInPipe->pipeId; + readParmas.interfaceId = acm->dataInPipe->interfaceId; + readParmas.callback = AcmReadBulk; + readParmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE; + readParmas.timeout = USB_CTRL_SET_TIMEOUT; + readParmas.dataReq.numIsoPackets = 0; + readParmas.dataReq.directon = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1; + readParmas.dataReq.length = acm->readSize; + ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParmas); // Fill in the readReq object to be sent. + if (HDF_SUCCESS != ret) { + HDF_LOGE("%{public}s: UsbFillRequest faile, ret=%{public}d \n", __func__, ret); + goto error; + } + } + return HDF_SUCCESS; + +error: + AcmFreeReadRequests(acm); + return HDF_ERR_MALLOC_FAIL; +} + +static int AcmAllocNotifyRequest(struct AcmDevice *acm) +{ + int ret; + struct UsbRequestParams intParmas = {}; + acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize); // Allocate the interrupt I/O request object to be sent. + if (!acm->notifyReq) { + HDF_LOGE("notifyReq request fail\n"); + return HDF_ERR_MALLOC_FAIL; + } + intParmas.userData = (void *)acm; + intParmas.pipeAddress = acm->intPipe->pipeAddress; + intParmas.pipeId = acm->intPipe->pipeId; + intParmas.interfaceId = acm->intPipe->interfaceId; + intParmas.callback = AcmCtrlIrq; + intParmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE; + intParmas.timeout = USB_CTRL_SET_TIMEOUT; + intParmas.dataReq.numIsoPackets = 0; + intParmas.dataReq.directon = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK; + intParmas.dataReq.length = acm->intSize; + ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParmas); // Fill in the interrupt I/O request. + if (HDF_SUCCESS != ret) { + HDF_LOGE("%{public}s: UsbFillRequest faile, ret=%{public}d \n", __func__, ret); + goto error; + } + return HDF_SUCCESS; + +error: + AcmFreeNotifyReqeust(acm); + return ret; +} + +static void AcmReleaseInterfaces(struct AcmDevice *acm) +{ + for (int i = 0; i < acm->interfaceCnt; i++) { + if (acm->iface[i]) { + UsbReleaseInterface(acm->iface[i]); + acm->iface[i] = NULL; + } + } + if (acm->ctrIface) { + UsbReleaseInterface(acm->ctrIface); + acm->ctrIface = NULL; + } +} + +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]); // Obtain the UsbInterface object. + if (acm->iface[i] == NULL) { + HDF_LOGE("%{public}s: interface%{public}d is null", __func__, acm->interfaceIndex[i]); + goto error; + } + } + + acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID); // Obtain the UsbInterface object corresponding to the control interface. + if (acm->ctrIface == NULL) { + HDF_LOGE("%{public}s: GetUsbInterfaceById null", __func__); + goto error; + } + + return HDF_SUCCESS; + + error: + AcmReleaseInterfaces(acm); + return HDF_FAILURE; +} + +static void AcmCloseInterfaces(struct AcmDevice *acm) +{ + for (int i = 0; i < acm->interfaceCnt; i++) { + if (acm->devHandle[i]) { + UsbCloseInterface(acm->devHandle[i]); + acm->devHandle[i] = NULL; + } + } + if (acm->ctrDevHandle) { + UsbCloseInterface(acm->ctrDevHandle); + acm->ctrDevHandle = NULL; + } +} + +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]); // Open the UsbInterface object obtained. + if (acm->devHandle[i] == NULL) { + HDF_LOGE("%{public}s: UsbOpenInterface null", __func__); + goto error; + } + } + } + acm->ctrDevHandle = UsbOpenInterface(acm->ctrIface); + if (acm->ctrDevHandle == NULL) { + HDF_LOGE("%{public}s: ctrDevHandle UsbOpenInterface null", __func__); + goto error; + } + + return HDF_SUCCESS; + +error: + AcmCloseInterfaces(acm); + return HDF_FAILURE; +} + +static int32_t AcmGetPipes(struct AcmDevice *acm) +{ + acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN); // Obtain pipe information of dataInPipe. + if (acm->dataInPipe == NULL) { + HDF_LOGE("dataInPipe is NULL"); + goto error; + } + + acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT); // Obtain pipe information of dataOutPipe. + 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); // Obtain pipe information of the control pipe. + if (acm->ctrPipe == NULL) { + HDF_LOGE("ctrPipe is NULL"); + goto error; + } + + acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN); // Obtain pipe information of the interrupt pipe. + if (acm->intPipe == NULL) { + HDF_LOGE("intPipe is NULL"); + goto error; + } + + acm->readSize = acm->dataInPipe->maxPacketSize; + acm->writeSize = acm->dataOutPipe->maxPacketSize; + acm->ctrlSize = acm->ctrPipe->maxPacketSize; + acm->intSize = acm->intPipe->maxPacketSize; + + return HDF_SUCCESS; + +error: + AcmFreePipes(acm); + return HDF_FAILURE; +} + +static void AcmFreeRequests(struct AcmDevice *acm) +{ + if (g_syncRequest != NULL) { + UsbFreeRequest(g_syncRequest); + g_syncRequest = NULL; + } + AcmFreeReadRequests(acm); + AcmFreeNotifyReqeust(acm); + AcmFreeWriteRequests(acm); + AcmWriteBufFree(acm); +} + +static int32_t AcmAllocRequests(struct AcmDevice *acm) +{ + int32_t ret; + + if (AcmWriteBufAlloc(acm) < 0) { + HDF_LOGE("%{public}s: AcmWriteBufAlloc failed", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + for (int i = 0; i < ACM_NW; i++) { + struct AcmWb *snd = &(acm->wb[i]); + snd->request = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataOutPipe->interfaceId), 0, acm->writeSize); // Allocate the I/O request object to be sent. + snd->instance = acm; + if (snd->request == NULL) { + HDF_LOGE("%{public}s:%{public}d snd request fail", __func__, __LINE__); + goto error_alloc_write_req; + } + } + + ret = AcmAllocNotifyRequest(acm); // Allocate and fill in the interrupt I/O request object. + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s:%{public}d AcmAllocNotifyRequest fail", __func__, __LINE__); + goto error_alloc_int_req; + } + + ret = AcmAllocReadRequests(acm); // Allocate and fill in the readReq I/O request object. + if (ret) { + HDF_LOGE("%{public}s:%{public}d AcmAllocReadRequests fail", __func__, __LINE__); + goto error_alloc_read_req; + } + + return HDF_SUCCESS; + +error_alloc_read_req: + AcmFreeNotifyReqeust(acm); +error_alloc_int_req: + AcmFreeWriteRequests(acm); +error_alloc_write_req: + AcmWriteBufFree(acm); + return HDF_FAILURE; +} + +static int32_t AcmInit(struct AcmDevice *acm) +{ + int32_t ret; + struct UsbSession *session = NULL; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d: initFlag is true", __func__, __LINE__); + return HDF_SUCCESS; + } + + ret = UsbInitHostSdk(NULL); // Initialize the host DDK. + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: UsbInitHostSdk failed", __func__); + return HDF_ERR_IO; + } + acm->session = session; + + ret = AcmClaimInterfaces(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmClaimInterfaces failed", __func__); + goto error_claim_interfaces; + } + + ret = AcmOpenInterfaces(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmOpenInterfaces failed", __func__); + goto error_open_interfaces; + } + + ret = AcmGetPipes(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmGetPipes failed", __func__); + goto error_get_pipes; + } + + ret = AcmAllocRequests(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmAllocRequests failed", __func__); + goto error_alloc_reqs; + } + + acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); + acm->lineCoding.bCharFormat = CHARFORMAT; + acm->lineCoding.bParityType = USB_CDC_NO_PARITY; + acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; + acm->initFlag = true; + + HDF_LOGD("%{public}s:%{public}d========OK", __func__, __LINE__); + return HDF_SUCCESS; + +error_alloc_reqs: + AcmFreePipes(acm); +error_get_pipes: + AcmCloseInterfaces(acm); +error_open_interfaces: + AcmReleaseInterfaces(acm); +error_claim_interfaces: + UsbExitHostSdk(acm->session); + acm->session = NULL; + return ret; +} + +static void AcmRelease(struct AcmDevice *acm) +{ + if (acm->initFlag == false) { + HDF_LOGE("%{public}s:%{public}d: initFlag is false", __func__, __LINE__); + return; + } + + AcmFreeRequests(acm); + AcmFreePipes(acm); + AcmCloseInterfaces(acm); + AcmReleaseInterfaces(acm); + UsbExitHostSdk(acm->session); + acm->session = NULL; + + acm->initFlag = false; +} + +static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct AcmDevice *acm = NULL; + + if (device == NULL) { + HDF_LOGE("%{public}s: device is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + acm = (struct AcmDevice *)device->service; + OsalMutexInit(&acm->readLock); + OsalMutexInit(&acm->writeLock); + HDF_LOGD("%{public}s:%{public}d busNum=%{public}d,devAddr=%{public}d", \ + __func__, __LINE__, acm->busNum, acm->devAddr); + + ret = UsbSerialDeviceAlloc(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: Serial Device alloc failed", __func__); + } + + acm->initFlag = false; + g_acmReleaseFlag = false; + + HDF_LOGD("%{public}s:%{public}d init ok!", __func__, __LINE__); + + return ret; +} + +static void UsbSerialDriverRelease(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + + if (device == NULL) { + HDF_LOGE("%{public}s: device is NULL", __func__); + return; + } + acm = (struct AcmDevice *)device->service; + if (acm == NULL) { + HDF_LOGE("%{public}s: acm is null", __func__); + return; + } + + g_acmReleaseFlag = true; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d AcmRelease", __func__, __LINE__); + AcmRelease(acm); + } + UsbSeriaDevicelFree(acm); + OsalMutexDestroy(&acm->writeLock); + OsalMutexDestroy(&acm->readLock); + OsalMutexDestroy(&acm->lock); + OsalMemFree(acm); + acm = NULL; + HDF_LOGD("%{public}s:%{public}d exit", __func__, __LINE__); +} + +struct HdfDriverEntry g_usbSerialDriverEntry = { + .moduleVersion = 1, + .moduleName = "usbhost_acm", // Driver module name, which must be the same as that configured in the .hcs file. + .Bind = UsbSerialDriverBind, + .Init = UsbSerialDriverInit, + .Release = UsbSerialDriverRelease, +}; +HDF_INIT(g_usbSerialDriverEntry); +``` + +### Developing Driver Using Host Raw APIs + +``` +root { + module = "usb_pnp_device"; + usb_pnp_config { + match_attr = "usb_pnp_match"; + usb_pnp_device_id = "UsbPnpDeviceId"; + UsbPnpDeviceId { + idTableList = [ + "host_acm_rawapi_table" + ]; + host_acm_rawapi_table { // Driver mapping table information. + // Driver module name, which must be the same as the value of moduleName in the driver entry structure. + moduleName = "usbhost_acm_rawapi"; + // Service name of the driver, which must be unique. + serviceName = "usbhost_acm_rawapi_service"; + // Keyword for matching private driver data. + deviceMatchAttr = "usbhost_acm_rawapi_matchAttr"; + // Data length starting from this field, in bytes. + length = 21; + // USB driver matching rule: vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber. + matchFlag = 0x0303; + // Vendor ID. + vendorId = 0x12D1; + // Product ID. + productId = 0x5000; + // The least significant 16 bits of the device sequence number. + bcdDeviceLow = 0x0000; + // The most significant 16 bits of the device sequence number. + bcdDeviceHigh = 0x0000; + // Device class code allocated by the USB. + deviceClass = 0; + // Child class code allocated by the USB. + deviceSubClass = 0; + // Device protocol code allocated by the USB. + deviceProtocol = 0; + // Interface type. You can enter multiple types as needed. + interfaceClass = [0]; + // Interface subtype. You can enter multiple subtypes as needed. + interfaceSubClass = [2, 0]; + // Protocol that the interface complies with. You can enter multiple protocols as needed. + interfaceProtocol = [1, 2]; + // Interface numer. You can enter multiple interface numbers as needed. + interfaceNumber = [2, 3]; + } + } + } +} + +#include "usb_serial_rawapi.h" +#include +#include "osal_mem.h" +#include "osal_time.h" +#include "securec.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "hdf_usb_pnp_manage.h" + +#define HDF_LOG_TAG USB_HOST_ACM_RAW_API +#define USB_CTRL_REQ_SIZE 64 +#define USB_IO_THREAD_STACK_SIZE 8192 +#define USB_RAW_IO_SLEEP_MS_TIME 100 +#define USB_RAW_IO_STOP_WAIT_MAX_TIME 3 + +static struct UsbRawRequest *g_syncRequest = NULL; +static UsbRawIoProcessStatusType g_stopIoStatus = USB_RAW_IO_PROCESS_RUNNING; +struct OsalMutex g_stopIoLock; +static bool g_rawAcmReleaseFlag = false; +...... + +static int UsbGetConfigDescriptor(UsbRawHandle *devHandle, struct UsbRawConfigDescriptor **config) +{ + UsbRawDevice *dev = NULL; + int activeConfig; + int ret; + + if (devHandle == NULL) { + HDF_LOGE("%{public}s:%{public}d devHandle is NULL", + __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + + ret = UsbRawGetConfiguration(devHandle, &activeConfig); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbRawGetConfiguration failed, ret=%{public}d", + __func__, __LINE__, ret); + return HDF_FAILURE; + } + HDF_LOGE("%{public}s:%{public}d activeConfig=%{public}d", __func__, __LINE__, activeConfig); + dev = UsbRawGetDevice(devHandle); + if (dev == NULL) { + HDF_LOGE("%{public}s:%{public}d UsbRawGetDevice failed", + __func__, __LINE__); + return HDF_FAILURE; + } + + ret = UsbRawGetConfigDescriptor(dev, activeConfig, config); + if (ret) { + HDF_LOGE("UsbRawGetConfigDescriptor failed, ret=%{public}d\n", ret); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} +... +static int UsbAllocWriteRequests(struct AcmDevice *acm) +{ + int i; + + for (i = 0; i < ACM_NW; i++) { + struct AcmWb *snd = &acm->wb[i]; + snd->request = UsbRawAllocRequest(acm->devHandle, 0, acm->dataOutEp->maxPacketSize); + snd->instance = acm; + if (snd->request == NULL) { + HDF_LOGE("%{public}s: UsbRawAllocRequest failed", __func__); + return HDF_ERR_MALLOC_FAIL; + } + } + + return HDF_SUCCESS; +} +... +/* HdfDriverEntry implementations */ +static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + struct UsbPnpNotifyServiceInfo *info = NULL; + errno_t err; + + if (device == NULL) { + HDF_LOGE("%s: device is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm)); + if (acm == NULL) { + HDF_LOGE("%s: Alloc usb serial device failed", __func__); + return HDF_FAILURE; + } + if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { + HDF_LOGE("%s:%d OsalMutexInit fail", __func__, __LINE__); + goto error; + } + + info = (struct UsbPnpNotifyServiceInfo *)device->priv; + if (info != NULL) { + acm->busNum = info->busNum; + acm->devAddr = info->devNum; + acm->interfaceCnt = info->interfaceLength; + err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, + (const void*)info->interfaceNumber, info->interfaceLength); + if (err != EOK) { + HDF_LOGE("%s:%d memcpy_s failed err=%d", \ + __func__, __LINE__, err); + goto lock_error; + } + } else { + HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__); + goto lock_error; + } + + device->service = &(acm->service); + device->service->Dispatch = UsbSerialDeviceDispatch; + acm->device = device; + HDF_LOGD("UsbSerialDriverBind=========================OK"); + return HDF_SUCCESS; + +lock_error: + if (OsalMutexDestroy(&acm->lock)) { + HDF_LOGE("%s:%d OsalMutexDestroy fail", __func__, __LINE__); + } +error: + OsalMemFree(acm); + acm = NULL; + return HDF_FAILURE; +} +... +static int UsbAllocReadRequests(struct AcmDevice *acm) +{ + struct UsbRawFillRequestData reqData; + int size = acm->dataInEp->maxPacketSize; + int ret; + + for (int i = 0; i < ACM_NR; i++) { + acm->readReq[i] = UsbRawAllocRequest(acm->devHandle, 0, size); + if (!acm->readReq[i]) { + HDF_LOGE("readReq request failed\n"); + return HDF_ERR_MALLOC_FAIL; + } + + reqData.endPoint = acm->dataInEp->addr; + reqData.numIsoPackets = 0; + reqData.callback = AcmReadBulkCallback; + reqData.userData = (void *)acm; + reqData.timeout = USB_CTRL_SET_TIMEOUT; + reqData.length = size; + + ret = UsbRawFillBulkRequest(acm->readReq[i], acm->devHandle, &reqData); + if (ret) { + HDF_LOGE("%{public}s: FillBulkRequest faile, ret=%{public}d \n", + __func__, ret); + return HDF_FAILURE; + } + } + + return HDF_SUCCESS; +} +... +static int UsbAllocNotifyRequest(struct AcmDevice *acm) +{ + struct UsbRawFillRequestData fillRequestData; + int size = acm->notifyEp->maxPacketSize; + int ret; + + acm->notifyReq = UsbRawAllocRequest(acm->devHandle, 0, size); + if (!acm->notifyReq) { + HDF_LOGE("notifyReq request fail\n"); + return HDF_ERR_MALLOC_FAIL; + } + + fillRequestData.endPoint = acm->notifyEp->addr; + fillRequestData.length = size; + fillRequestData.numIsoPackets = 0; + fillRequestData.callback = AcmNotifyReqCallback; + fillRequestData.userData = (void *)acm; + fillRequestData.timeout = USB_CTRL_SET_TIMEOUT; + + ret = UsbRawFillInterruptRequest(acm->notifyReq, acm->devHandle, &fillRequestData); + if (ret) { + HDF_LOGE("%{public}s: FillInterruptRequest faile, ret=%{public}d", __func__, ret); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} +... +static int32_t UsbSerialInit(struct AcmDevice *acm) +{ + struct UsbSession *session = NULL; + UsbRawHandle *devHandle = NULL; + int32_t ret; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d: initFlag is true", __func__, __LINE__); + return HDF_SUCCESS; + } + + ret = UsbRawInit(NULL); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbRawInit failed", __func__, __LINE__); + return HDF_ERR_IO; + } + acm->session = session; + + devHandle = UsbRawOpenDevice(session, acm->busNum, acm->devAddr); + if (devHandle == NULL) { + HDF_LOGE("%{public}s:%{public}d UsbRawOpenDevice failed", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_open_device; + } + acm->devHandle = devHandle; + ret = UsbGetConfigDescriptor(devHandle, &acm->config); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbGetConfigDescriptor failed", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_get_desc; + } + ret = UsbParseConfigDescriptor(acm, acm->config); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s:%{public}d UsbParseConfigDescriptor failed", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_parse_desc; + } + + ret = AcmWriteBufAlloc(acm); + if (ret < 0) { + HDF_LOGE("%{public}s:%{public}d AcmWriteBufAlloc failed", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_alloc_write_buf; + } + ret = UsbAllocWriteRequests(acm); + if (ret < 0) { + HDF_LOGE("%{public}s:%{public}d UsbAllocWriteRequests failed", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_alloc_write_reqs; + } + ret = UsbAllocNotifyRequest(acm); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbAllocNotifyRequests failed", __func__, __LINE__); + goto err_alloc_notify_req; + } + ret = UsbAllocReadRequests(acm); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbAllocReadRequests failed", __func__, __LINE__); + goto err_alloc_read_reqs; + } + ret = UsbStartIo(acm); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbAllocReadRequests failed", __func__, __LINE__); + goto err_start_io; + } + + acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); + acm->lineCoding.bCharFormat = CHARFORMAT; + acm->lineCoding.bParityType = USB_CDC_NO_PARITY; + acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; + + ret = UsbRawSubmitRequest(acm->notifyReq); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbRawSubmitRequest failed", __func__, __LINE__); + goto err_submit_req; + } + + acm->initFlag = true; + + HDF_LOGD("%{public}s:%{public}d=========================OK", __func__, __LINE__); + + return HDF_SUCCESS; + +err_submit_req: + UsbStopIo(acm); +err_start_io: + UsbFreeReadRequests(acm); +err_alloc_read_reqs: + UsbFreeNotifyReqeust(acm); + err_alloc_notify_req: + UsbFreeWriteRequests(acm); +err_alloc_write_reqs: + AcmWriteBufFree(acm); +err_alloc_write_buf: + UsbReleaseInterfaces(acm); +err_parse_desc: + UsbRawFreeConfigDescriptor(acm->config); + acm->config = NULL; +err_get_desc: + (void)UsbRawCloseDevice(devHandle); +err_open_device: + UsbRawExit(acm->session); + + return ret; +} + +static void UsbSerialRelease(struct AcmDevice *acm) +{ + if (acm->initFlag == false) { + HDF_LOGE("%{public}s:%{public}d: initFlag is false", __func__, __LINE__); + return; + } + + /* stop io thread and release all resources */ + UsbStopIo(acm); + if (g_syncRequest != NULL) { + UsbRawFreeRequest(g_syncRequest); + g_syncRequest = NULL; + } + UsbFreeReadRequests(acm); + UsbFreeNotifyReqeust(acm); + UsbFreeWriteRequests(acm); + AcmWriteBufFree(acm); + (void)UsbRawCloseDevice(acm->devHandle); + UsbReleaseInterfaces(acm); + UsbRawFreeConfigDescriptor(acm->config); + acm->config = NULL; + UsbRawExit(acm->session); + + acm->initFlag = false; +} + +static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + int32_t ret; + + if (device == NULL) { + HDF_LOGE("%{public}s:%{public}d device is null", __func__, __LINE__); + return HDF_ERR_INVALID_OBJECT; + } + acm = (struct AcmDevice *)device->service; + OsalMutexInit(&acm->readLock); + OsalMutexInit(&acm->writeLock); + + ret = UsbSerialDeviceAlloc(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s:%{public}d UsbSerialDeviceAlloc failed", __func__, __LINE__); + } + + acm->initFlag = false; + g_rawAcmReleaseFlag = false; + + HDF_LOGD("%{public}s:%{public}d init ok!", __func__, __LINE__); + + return ret; +} + +static void UsbSerialDriverRelease(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + if (device == NULL) { + HDF_LOGE("%{public}s: device is NULL", __func__); + return; + } + + acm = (struct AcmDevice *)device->service; + if (acm == NULL) { + HDF_LOGE("%{public}s: acm is null", __func__); + return; + } + + g_rawAcmReleaseFlag = true; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d UsbSerialRelease", __func__, __LINE__); + UsbSerialRelease(acm); + } + UsbSeriaDevicelFree(acm); + OsalMutexDestroy(&acm->writeLock); + OsalMutexDestroy(&acm->readLock); + OsalMutexDestroy(&acm->lock); + OsalMemFree(acm); + acm = NULL; + HDF_LOGD("%{public}s:%{public}d exit", __func__, __LINE__); +} + +struct HdfDriverEntry g_usbSerialRawDriverEntry = { + .moduleVersion = 1, + .moduleName = "usbhost_acm_rawapi", // Driver module name, which must be the same as that configured in the .hcs file. + .Bind = UsbSerialDriverBind, + .Init = UsbSerialDriverInit, + .Release = UsbSerialDriverRelease, +}; +HDF_INIT(g_usbSerialRawDriverEntry); +``` + +### Developing Driver Using Device DDK APIs +The core code of the USB Abstract Control Model (ACM) device is available in **drivers\peripheral\usb\gadget\function\acm\cdcacm.c**. The following is an example. + +``` +1. Create a device. +static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, + struct DeviceResourceIface *iface) +{ + struct UsbFnDevice *fnDev = NULL; +struct UsbFnDescriptorData descData; +uint8_t useHcs; + ... +if (useHcs == 0) { + descData.type = USBFN_DESC_DATA_TYPE_DESC; + descData.descriptor = &g_masterFuncDevice; +} else { + descData.type = USBFN_DESC_DATA_TYPE_PROP; + descData.property = device->property; +} +/* Create a device. */ + fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData); + if (fnDev == NULL) { + HDF_LOGE("%{public}s: create usb function device failed", __func__); + return HDF_FAILURE; + } + ... +} +2. Obtain an interface and open the interface for pipe information. +static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface) +{ + ... + for (i = 0; i < fnIface->info.numPipes; i++) { + struct UsbFnPipeInfo pipeInfo; +/* Obtain pipe information. */ + ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo); + ... + } + return HDF_SUCCESS; +} +/* Obtain the interface and open the interface to obtain the handle. */ +static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev) +{ + ... + for (i = 0; i < fnDev->numInterfaces; i++) { + /* Obtain an interface.*/ + fnIface = (struct UsbFnInterface *)UsbFnDeviceGetInterface(fnDev, i); + ... + /* Open the interface. */ + handle = UsbFnInterfaceOpen(fnIface); + ... + } + return HDF_SUCCESS; +} +3. Receive events. +static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int num) +{ + ... + req = UsbFnCtrlRequestAlloc(acm->ctrlIface.handle, + sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding)); + ... +} +static int32_t AcmDriverInit(struct HdfDeviceObject *device) +{ +... +/* Start to receive events.*/ + ret = UsbFnInterfaceStartRecvEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm); + ... +} +4. Perform USB communication (read and write). +static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type, + uint16_t value, void *data, uint32_t length) +{ +... +/* Send a request asynchronously. */ + ret = UsbFnRequestSubmitAsync(req); + ... +} +5. Close the interface, stop receiving events, and remove the device. +static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm) +{ +int32_t ret; +/* Close the interface. */ + (void)UsbFnInterfaceClose(acm->ctrlIface.handle); +(void)UsbFnInterfaceClose(acm->dataIface.handle); +/* Stop receiving events. */ +(void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn); +/* Remove the device. */ + ret = UsbFnDeviceRemove(acm->fnDev); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: remove usb function device failed", __func__); + } + return ret; +} +``` diff --git a/en/device-dev/driver/figures/USB_device_driver_model.png b/en/device-dev/driver/figures/USB_device_driver_model.png new file mode 100644 index 0000000000000000000000000000000000000000..3766cf8117505a0d47720dcbccc1030536921bdb Binary files /dev/null and b/en/device-dev/driver/figures/USB_device_driver_model.png differ diff --git a/en/device-dev/driver/figures/USB_host_driver_model.png b/en/device-dev/driver/figures/USB_host_driver_model.png new file mode 100644 index 0000000000000000000000000000000000000000..6bea2992afd00b031176998278c0bcfce0f8e843 Binary files /dev/null and b/en/device-dev/driver/figures/USB_host_driver_model.png differ diff --git a/en/device-dev/get-code/gettools-acquire.md b/en/device-dev/get-code/gettools-acquire.md index ce5512e1a6459ba18560349b0b8b5379f6a5c90f..c2f9ba20abb9ef92bcdcb46d67968542ed9c7a8a 100644 --- a/en/device-dev/get-code/gettools-acquire.md +++ b/en/device-dev/get-code/gettools-acquire.md @@ -222,7 +222,7 @@ Run the following script to start building for standard-system devices \(referen **product\_name** indicates the platform supported by the current distribution, for example, Hi3516D V300. -Files generated during building are stored in the **out/ohos-arm-release/** directory, and the generated image is stored in the **out/ohos-arm-release/packages/phone/images/** directory. +Files generated during building are stored in the **out/{device_name}/** directory, and the generated image is stored in the **out/{device_name}/packages/phone/images/** directory. >![](../public_sys-resources/icon-note.gif) **NOTE:** diff --git a/en/device-dev/guide/Readme-EN.md b/en/device-dev/guide/Readme-EN.md index a21f8de99fe4e9973e63e6c08d5d1a5351b82e9e..6b1407770583714f4d47dedb7276220ab2def364 100644 --- a/en/device-dev/guide/Readme-EN.md +++ b/en/device-dev/guide/Readme-EN.md @@ -2,8 +2,7 @@ - [Mini- and Small-System Devices](device-lite.md) - [WLAN-connected Products](device-wlan.md) - - [LED Peripheral Control](device-wlan-led.md) - - [LED Peripheral Control](device-wlan-led-outcontrol.md) + - [LED Peripheral Control](device-wlan-led-outcontrol.md) - [Third-Party SDK Integration](device-wlan-sdk.md) - [Cameras Without a Screen](device-iotcamera.md) - [Camera Control](device-iotcamera-control.md) diff --git a/en/device-dev/guide/device-clock-guide.md b/en/device-dev/guide/device-clock-guide.md index c9d006e9c4ddf9fca5ad9cdf74bc524068e7ec11..44f9935927813af5aa67be0082694a91d2a54d36 100644 --- a/en/device-dev/guide/device-clock-guide.md +++ b/en/device-dev/guide/device-clock-guide.md @@ -274,11 +274,7 @@ Before you install the app and run it on the development board, install the DevE 2. Open the **cmd** window, and run the following commands to push the HAP file to the device directory, and install it: ``` - hdc smode - hdc target mount - hdc file send clock.hap /data/clock.hap - hdc shell chmod 666 /data/clock.hap - hdc shell bm install -p /data/clock.hap + hdc install clock.hap ``` 3. Run the following command to start the app. **ohos.samples.clock** indicates the app package name, and **MainAbility** indicates the ability started by the app. diff --git a/en/device-dev/guide/device-wlan-touch.md b/en/device-dev/guide/device-wlan-touch.md deleted file mode 100644 index 5ff4442e9710c245f56d5c303493ee3d5ad742d4..0000000000000000000000000000000000000000 --- a/en/device-dev/guide/device-wlan-touch.md +++ /dev/null @@ -1,19 +0,0 @@ -# OneHop - -- **[Overview](onehop-overview.md)** - -- **[Preparations](onehop-dev-prerequisites.md)** - -- **[Developing the Hi3861 Development Board](onehop-dev-hi3861.md)** - -- **[Developing Atomic Services](onehop-dev-atomic-service.md)** - -- **[Writing an NFC Tag](onehop-write-nfc-info.md)** - -- **[Configuring a Service Association Intent](onehop-configuration-device-tag.md)** - -- **[Tapping to Launch an Atomic Service](onehop-open-atomic-service.md)** - -- **[References](onehop-reference-info.md)** - - diff --git a/en/device-dev/guide/device-wlan.md b/en/device-dev/guide/device-wlan.md index e4618dfb06cc8140fa3072cad3c2a0ec484dceb4..dd1fb71a73aa1bef16a5d4a906a00fe1b709df4b 100644 --- a/en/device-dev/guide/device-wlan.md +++ b/en/device-dev/guide/device-wlan.md @@ -1,6 +1,5 @@ # WLAN-connected Products -- **[OneHop](device-wlan-touch.md)** - **[LED Peripheral Control](device-wlan-led.md)** diff --git a/en/device-dev/kernel/Readme-EN.md b/en/device-dev/kernel/Readme-EN.md index 01ff40387c6f6816aea29dc6941e7c7b660f2d85..ce9ce8eb85b8ade128161c6a0ce2464a3d635781 100644 --- a/en/device-dev/kernel/Readme-EN.md +++ b/en/device-dev/kernel/Readme-EN.md @@ -52,7 +52,7 @@ - [Memory Leak Check](kernel-mini-imemory-debug-det.md) - [Memory Corruption Check](kernel-mini-memory-debug-cet.md) - [Exception Debugging](kernel-mini-memory-exception.md) - - [Trace Debugging](kernel-mini-memory-trace.md) + - [Trace](kernel-mini-memory-trace.md) - [Appendix](kernel-mini-app.md) - [Kernel Coding Specification](kernel-mini-appx-code.md) - [Basic Data Structure](kernel-mini-appx-data.md) @@ -192,5 +192,5 @@ - [Standard Library](kernel-small-apx-library.md) - [Kernel for Standard Systems](kernel-standard.md) - [Linux Kernel Overview](kernel-standard-overview.md) - - [Guidelines for Using Patches on OpenHarmony Development Boards](kernel-standard-patch.md) - - [Guidelines for Compiling and Building the Linux Kernel](kernel-standard-build.md) \ No newline at end of file + - [Applying Patches on OpenHarmony Development Boards](kernel-standard-patch.md) + - [Guidelines for Building the Linux Kernel](kernel-standard-build.md) \ No newline at end of file diff --git a/en/device-dev/kernel/kernel-mini-extend-dynamic-loading-basic.md b/en/device-dev/kernel/kernel-mini-extend-dynamic-loading-basic.md index 591fb131ef2de3a000706860c15cceb8c633b51f..36fc1e438a431063b4593bb226c5220188313b98 100644 --- a/en/device-dev/kernel/kernel-mini-extend-dynamic-loading-basic.md +++ b/en/device-dev/kernel/kernel-mini-extend-dynamic-loading-basic.md @@ -10,7 +10,7 @@ - [Options for Linking](#section17292133274) -In small devices with limited hardware resources, dynamic algorithm deployment capability is required to solve the problem that multiple algorithms cannot be deployed at the same time. The LiteOS-M kernel uses the Executable and Linkable Format \(ELF\) because it is easy to use and compatible with a wide variety of platforms. The LiteOS-M provides APIs similar to **dlopen** and **dlsym**. Apps can load and unload required algorithm libraries by using the APIs provided by the dynamic loading module. As shown in the following figure, the app obtains the corresponding information output through the API required by the third-party algorithm library. The third-party algorithm library depends on the basic APIs provided by the kernel, such as **malloc**. After the app loads the API and relocates undefined symbols, it can call the API to complete the function. The dynamic loading component supports only the Arm architecture. +In small devices with limited hardware resources, dynamic algorithm deployment capability is required to solve the problem that multiple algorithms cannot be deployed at the same time. The LiteOS-M kernel uses the Executable and Linkable Format \(ELF\) because it is easy to use and compatible with a wide variety of platforms. The LiteOS-M provides APIs similar to **dlopen** and **dlsym**. Apps can load and unload required algorithm libraries by using the APIs provided by the dynamic loading module. As shown in the following figure, the app obtains the corresponding information output through the API required by the third-party algorithm library. The third-party algorithm library depends on the basic APIs provided by the kernel, such as **malloc**. After the app loads the API and relocates undefined symbols, it can call the API to complete the function. The dynamic loading component supports only the Arm architecture.In addition, the shared library to be loaded needs signature verification or source restriction to ensure the security of the system. **Figure 1** LiteOS-M kernel dynamic loading architecture ![](figure/liteos-m-kernel-dynamic-loading-architecture.png "liteos-m-kernel-dynamic-loading-architecture") diff --git a/en/device-dev/kernel/kernel-mini-overview.md b/en/device-dev/kernel/kernel-mini-overview.md index e727b225c1998e4a54df754987d8f3440b818d7b..0e58d09e7380c078cd61950b671427b5a7ab4399 100644 --- a/en/device-dev/kernel/kernel-mini-overview.md +++ b/en/device-dev/kernel/kernel-mini-overview.md @@ -33,9 +33,9 @@ The CPU architecture includes two layers: general architecture definition layer

Header file location

-

kernel/arch/include

+

arch/include

-

kernel/arch/<arch>/<arch>/<toolchain>/

+

arch/<arch>/<arch>/<toolchain>/

Header file name

diff --git a/en/device-dev/porting/porting-chip-kernel-overview.md b/en/device-dev/porting/porting-chip-kernel-overview.md index 8f6702a15194823d1cade17e9ead203896569ab9..9941b2bc5ce9d9faacf2b27f7bdc217971648551 100644 --- a/en/device-dev/porting/porting-chip-kernel-overview.md +++ b/en/device-dev/porting/porting-chip-kernel-overview.md @@ -6,7 +6,7 @@ ## Porting Scenario -The chip architecture adaptation process is optional. If the particular chip architecture is supported in the **liteos\_m/kernel/arch** directory, you can directly implement the board adaptation. Otherwise, chip architecture porting is required. +The chip architecture adaptation process is optional. If the particular chip architecture is supported in the **liteos\_m/arch** directory, you can directly implement the board adaptation. Otherwise, chip architecture porting is required. ## Directory Specifications @@ -27,22 +27,22 @@ The directory structure of the kernel is described as follows: ``` . +├── arch --- Code of the kernel instruction architecture layer +│ ├── arm --- Code of the ARM32 architecture +│ │ ├── cortex-m3 --- Code of the Cortex-M3 architecture +│ │ │ ├── iar --- Implementation of the IAR toolchain +│ │ │ ├── keil --- Implementation of the Keil toolchain +│ │ │ └── xxx --- Implementation of the particular toolchain +│ │ └── cortex-m4 --- Code of the Cortex-M4 architecture +│ │ ├── iar --- Implementation of the IAR toolchain +│ │ ├── keil --- Implementation of the Keil toolchain +│ │ └── xxx --- Implementation of the particular toolchain +│ ├── include --- Header files that declare the APIs required, kernel-independent +│ └── risc-v --- RISK_V architecture +│ └── gcc --- Implementation of the GCC toolchain ├── components --- Components available for porting and header files exposed externally ├── kal --- APIs exposed externally, including CMSIS APIs and part of POSIX APIs ├── kernel --- Code for defining the minimum kernel function set -│ ├── arch --- Code of the kernel instruction architecture layer -│ │ ├── arm --- Code of the ARM32 architecture -│ │ │ ├── cortex-m3 --- Code of the Cortex-M3 architecture -│ │ │ │ ├── iar --- Implementation of the IAR toolchain -│ │ │ │ ├── keil --- Implementation of the Keil toolchain -│ │ │ │ └── xxx --- Implementation of the particular toolchain -│ │ │ └── cortex-m4 --- Code of the Cortex-M4 architecture -│ │ │ ├── iar --- Implementation of the IAR toolchain -│ │ │ ├── keil --- Implementation of the Keil toolchain -│ │ │ └── xxx --- Implementation of the particular toolchain -│ │ ├── include --- Header files that declare the APIs required, kernel-independent -│ │ └── risc-v --- RISK_V architecture -│ │ └── gcc --- Implementation of the IAR toolchain │ ├── include --- Code for defining the minimum kernel function set │ └── src --- Code for implementing the minimum kernel function set └──utils --- Basic code diff --git a/en/device-dev/porting/porting-linux-kernel-overview.md b/en/device-dev/porting/porting-linux-kernel-overview.md index 9f9781702136237ad9f03f4360e4d090a152199d..0a83bbfe9dc956d27139653dc5f65ca8476798b2 100644 --- a/en/device-dev/porting/porting-linux-kernel-overview.md +++ b/en/device-dev/porting/porting-linux-kernel-overview.md @@ -243,11 +243,11 @@ The procedure is as follows: 2. Push the dependencies and test cases to Raspberry Pi. ``` - hdc file send XXX\out\ohos-arm-release\hdf\hdf\libhdf_test_common.z.so /system/lib - hdc file send XXX\out\ohos-arm-release\tests\unittest\hdf\config\hdf_adapter_uhdf_test_config /data/test - hdc file send XXX\out\ohos-arm-release\tests\unittest\hdf\devmgr\DevMgrTest /data/test - hdc file send XXX\out\ohos-arm-release\tests\unittest\hdf\osal\OsalTest /data/test - hdc file send XXX\out\ohos-arm-release\tests\unittest\hdf\sbuf\SbufTest /data/test + hdc file send XXX\out\{device_name}\hdf\hdf\libhdf_test_common.z.so /system/lib + hdc file send XXX\out\{device_name}\tests\unittest\hdf\config\hdf_adapter_uhdf_test_config /data/test + hdc file send XXX\out\{device_name}\tests\unittest\hdf\devmgr\DevMgrTest /data/test + hdc file send XXX\out\{device_name}\tests\unittest\hdf\osal\OsalTest /data/test + hdc file send XXX\out\{device_name}\tests\unittest\hdf\sbuf\SbufTest /data/test ``` Method 2: Copy the test files to Raspberry Pi using its memory card. diff --git a/en/device-dev/porting/standard-system-porting-guide.md b/en/device-dev/porting/standard-system-porting-guide.md index 82a715286714c05db212f6e2f43a536b3848de1d..44da08b0724c3dd8ea27158fc76982f2f13f8d23 100644 --- a/en/device-dev/porting/standard-system-porting-guide.md +++ b/en/device-dev/porting/standard-system-porting-guide.md @@ -81,7 +81,7 @@ Run the following command to start the build of your product: ./build.sh --product-name MyProduct ``` -After the build is complete, you can view the built OpenHarmony image file in **//out/ohos-arm-release/packages/phone/images**. +After the build is complete, you can view the built OpenHarmony image file in **//out/{device_name}/packages/phone/images**. ## Porting the Kernel diff --git a/en/device-dev/quick-start/quickstart-lite-steps-hi3516-program.md b/en/device-dev/quick-start/quickstart-lite-steps-hi3516-program.md index 38c5419e03d6b5b659cf2e9a1d269e86dd3e19d9..2e4cfcb2adf66accdb3bb130fc9a78d609d0001c 100644 --- a/en/device-dev/quick-start/quickstart-lite-steps-hi3516-program.md +++ b/en/device-dev/quick-start/quickstart-lite-steps-hi3516-program.md @@ -9,7 +9,7 @@ This section describes how to develop a driver on the board, including introduct ## Introduction to Driver -The following operations take a HDF-based UART driver as an example to show how to add configuration files, code the driver, and compile the code for interactions between the user-space applications and the driver. The driver source code is stored in the **vendor/huawei/hdf/sample** directory. +The following operations take a HDF-based UART driver as an example to show how to add configuration files, code the driver, and compile the code for interactions between the user-space applications and the driver. The driver source code is stored in the **drivers/framework/sample** directory. 1. Add Configurations. @@ -360,7 +360,7 @@ The following operations take a HDF-based UART driver as an example to show how ``` LITEOS_BASELIB += -lhdf_uart_sample - LIB_SUBDIRS += $(LITEOS_SOURCE_ROOT)/vendor/huawei/hdf/sample/platform/uart + LIB_SUBDIRS += $(LITEOS_SOURCE_ROOT)/drivers/framework/sample/platform/uart ``` 4. Implement the code for interaction between the user-space applications and driver. @@ -400,7 +400,7 @@ The following operations take a HDF-based UART driver as an example to show how } ``` - Add the **hello\_uart\_sample** component to **targets** of the **hdf\_hi3516dv300\_liteos\_a** component in the **build/lite/components/drivers.json** file. + Add the **hello\_uart\_sample** component to **targets** of the **hdf\_hi3516dv300\_liteos\_a** component in the **build/lite/components/hdf.json** file. ``` { @@ -409,7 +409,7 @@ The following operations take a HDF-based UART driver as an example to show how "component": "hdf_hi3516dv300_liteos_a", ... "targets": [ - "//vendor/huawei/hdf/sample/platform/uart:hello_uart_sample" + "//drivers/framework/sample/platform/uart:hello_uart_sample" ] } ] @@ -417,7 +417,7 @@ The following operations take a HDF-based UART driver as an example to show how ``` >![](../public_sys-resources/icon-note.gif) **NOTE:** - >Preceding code snippets are for reference only. You can view the complete sample code in **vendor/huawei/hdf/sample.** + >Preceding code snippets are for reference only. You can view the complete sample code in **drivers/framework/sample**. >The sample code is not automatically compiled by default. You can add it to the compilation script. diff --git a/en/device-dev/quick-start/quickstart-lite-steps-hi3861-running.md b/en/device-dev/quick-start/quickstart-lite-steps-hi3861-running.md index 2eab40b209aa314c811a32bb28d64422f9ff0688..e1c70aa53cf8b1cc8e3a120bdc3a16ca232e8bb3 100644 --- a/en/device-dev/quick-start/quickstart-lite-steps-hi3861-running.md +++ b/en/device-dev/quick-start/quickstart-lite-steps-hi3861-running.md @@ -153,5 +153,5 @@ wifi init success! ## Follow-up Learning -Congratulations! You have finished all steps! You are advised to go on learning how to develop [WLAN-connected products](../guide/device-wifi.md). +Congratulations! You have finished all steps! You are advised to go on learning how to develop [WLAN-connected products](../guide/device-wlan.md). diff --git a/en/device-dev/quick-start/quickstart-standard-docker-environment.md b/en/device-dev/quick-start/quickstart-standard-docker-environment.md index e96a662f9ccefdab9c56c67dacf59378671cef34..93f11715dc1ce148831f9c1afb7a3536a316faec 100644 --- a/en/device-dev/quick-start/quickstart-standard-docker-environment.md +++ b/en/device-dev/quick-start/quickstart-standard-docker-environment.md @@ -116,7 +116,7 @@ By default, the downloaded prebuilts binary file is stored in **OpenHarmony\_2. **product\_name** indicates the platform supported by the current distribution, for example, Hi3516D V300. - Files generated during building are stored in the **out/ohos-arm-release/** directory, and the generated image is stored in the **out/ohos-arm-release/packages/phone/images/** directory. + Files generated during building are stored in the **out/{device_name}/** directory, and the generated image is stored in the **out/{device_name}/packages/phone/images/** directory. 2. Burn the image. For details, see [Burning Images](quickstart-standard-burn.md). diff --git a/en/device-dev/quick-start/quickstart-standard-package-environment.md b/en/device-dev/quick-start/quickstart-standard-package-environment.md index 8e0b4e69770cd43df8eb390cb138eb98b618410b..8bfe22b959e3ac18e79c0856577611b13e2b975b 100644 --- a/en/device-dev/quick-start/quickstart-standard-package-environment.md +++ b/en/device-dev/quick-start/quickstart-standard-package-environment.md @@ -91,7 +91,7 @@ Perform the following operations in the Linux environment: =====build Hi3516DV300 successful. ``` - Files generated during the build are stored in the **out/ohos-arm-release/** directory, and the generated image is stored in the **out/ohos-arm-release/packages/phone/images/** directory. + Files generated during the build are stored in the **out/{device_name}/** directory, and the generated image is stored in the **out/{device_name}/packages/phone/images/** directory. >![](../public_sys-resources/icon-note.gif) **NOTE:** >For details about module-specific build operations, see [Building Guidelines](../subsystems/subsys-build-standard-large.md). diff --git a/en/device-dev/subsystems/development-guidelines.md b/en/device-dev/subsystems/development-guidelines.md index 1f930477fe690212dfe6107d353628da2ff5931e..a7ca323e96c9c4dcacbbd8aaee8ae370ad3a2b73 100644 --- a/en/device-dev/subsystems/development-guidelines.md +++ b/en/device-dev/subsystems/development-guidelines.md @@ -612,5 +612,5 @@ ohos_shared_library("ril_vendor") { // Modem vendor library ### Debugging and Verification 1. Compile the code. -2. Check whether **libril\_vendor.z.so** exists in the **/out/ohos-arm-release/telephony/ril\_adapter** directory. If yes, the integration is successful. Otherwise, correct the error and perform debugging and verification again. +2. Check whether **libril\_vendor.z.so** exists in the **/out/{device_name}/telephony/ril\_adapter** directory. If yes, the integration is successful. Otherwise, correct the error and perform debugging and verification again. diff --git a/en/device-dev/subsystems/figure/structure-of-a-signed-hap.png b/en/device-dev/subsystems/figure/structure-of-a-signed-hap.png new file mode 100644 index 0000000000000000000000000000000000000000..ef0b2154947c2fa3ea3624bf3a46233485a0e1a1 Binary files /dev/null and b/en/device-dev/subsystems/figure/structure-of-a-signed-hap.png differ diff --git a/en/device-dev/subsystems/subsys-build-standard-large.md b/en/device-dev/subsystems/subsys-build-standard-large.md index e1a47c1b1329e7efcf2947b9018ae202e3dd50f1..9abbb5345d13498d3f1f5b0fd4714a1287ceb091 100644 --- a/en/device-dev/subsystems/subsys-build-standard-large.md +++ b/en/device-dev/subsystems/subsys-build-standard-large.md @@ -100,7 +100,7 @@ The process to build OpenHarmony is as follows: **product\_name** indicates the product supported by the current distribution, for example, Hi3516D V300. - The image generated after build is stored in the **out/ohos-arm-release/packages/phone/images/** directory. + The image generated after build is stored in the **out/{device_name}/packages/phone/images/** directory. - The build command supports the following options: @@ -232,6 +232,6 @@ The process to build OpenHarmony is as follows: 4. Obtain the build result. - Files generated during the build process are stored in the **out/ohos-arm-release/** directory, and the generated image is stored in the **out/ohos-arm-release/packages/phone/images/** directory. + Files generated during the build process are stored in the **out/hi3516dv300/** directory, and the generated image is stored in the **out/hi3516dv300/packages/phone/images/** directory. diff --git a/en/device-dev/subsystems/subsys-security-communicationverify.md b/en/device-dev/subsystems/subsys-security-communicationverify.md index 2432b3991460f75c348de2a094e993a63abd4fc7..5d98f1429cc85c245bfcd3827ba92e71443e0bd7 100644 --- a/en/device-dev/subsystems/subsys-security-communicationverify.md +++ b/en/device-dev/subsystems/subsys-security-communicationverify.md @@ -9,13 +9,13 @@ System services registered with Samgr can be accessed by other processes through IPC APIs. When a process requests to access such an API, IPC authentication is triggered to check whether the process has the required permission. If the process does not have the required permission, the access request will be denied. -When developing a system service, you can use the IPC authentication component to configure access policies for APIs of the service. When other processes access these APIs through IPC, Samgr calls APIs of the IPC authentication component to check whether the processes have the access permission. +When developing a system service, you can use the IPC authentication component to configure access policies for APIs of the service. When other services access these APIs through IPC, Samgr calls APIs of the IPC authentication component to check whether the services have the access permission. ## Available APIs The following table lists the APIs provided by IPC authentication \(intended for Samgr only\). -**Table 1** APIs provided by IPC authentication +**Table 1** APIs provided by IPC authentication - @@ -39,15 +39,15 @@ The following table lists the APIs provided by IPC authentication \(intended for ## How to Develop -This section uses BMS as an example to describe how to configure access policies for APIs provided by the IPC authentication component. In this example, the service registered by BMS with Samgr is **bundlems**, and the feature registered for open APIs is **BmsFeature**. +This section uses BMS as an example to describe how to configure access policies for APIs provided by the IPC authentication component. In this example, the service registered by BMS with Samgr is **bundlems**, and the feature registered for open APIs is **BmsFeature**. -1. On the OpenHarmony side, configure access policies in the **base/security/permission/services/permission\_lite/ipc\_auth/include/policy\_preset.h** file. On the device side, configure access policies in the **vendor/hisilicon/product_name/hals/security/permission\_lite/ipc\_auth/include/policy\_preset\_product.h** file (replace product_name with the actual product name). After that, set **POLICY\_PRODUCT** in the header files to **1**. Access policies are classified into the following three types: +1. On the OpenHarmony side, configure access policies in the **base/security/permission/services/permission\_lite/ipc\_auth/include/policy\_preset.h** file. On the device side, configure access policies in the **vendor/hisilicon/_product name_/hals/security/permission\_lite/ipc\_auth/include/policy\_preset\_product.h** file. After that, set **POLICY\_PRODUCT** in the header files to **1**. Access policies are classified into the following three types: - 1. **RANGE**: Processes with a specified range of UIDs can access BMS APIs. **uidMin** and **uidMax** must be specified. + 1. **RANGE**: Processes with a specified range of UIDs can access BMS APIs. **uidMin** and **uidMax** must be specified. - 2. **FIXED**: Processes with specified UIDs can access BMS APIs. **fixedUid** must be specified, and a maximum of eight UIDs are allowed. + 2. **FIXED**: Processes with specified UIDs can access BMS APIs. **fixedUid** must be specified, and a maximum of eight UIDs are allowed. - 3. **BUNDLENAME**: An application with a specified **bundleName** can access BMS APIs. + 3. **BUNDLENAME**: An application with a specified **bundleName** can access BMS APIs. ``` FeaturePolicy bmsFeature[] = { @@ -59,7 +59,7 @@ This section uses BMS as an example to describe how to configure access policies .fixedUid={2, 3, 8} }, { - .type=RANGE, // Processes with a specified range of UIDs can access BMS APIs. + .type=RANGE, // Processes with a specified range of UIDs can access BMS APIs. .uidMin=100, .uidMax=__INT_MAX__, }, @@ -82,13 +82,13 @@ This section uses BMS as an example to describe how to configure access policies }; ``` -2. Add the policies configured for the features in [Step 1](#li15901515152517) to the global policy settings. You need to set the number of features. +2. Add the policies configured for the features in [Step 1](#li15901515152517) to the global policy settings. You need to set the number of features. ``` static PolicySetting g_presetPolicies[] = { {"permissionms", pmsFeature, 1}, {"abilityms", amsFeature, 2}, - {"bundlems", bmsFeature, 2}, // Add the policies configured for the two features in Step 1 to the global policy settings. + {"bundlems", bmsFeature, 2}, // Add the policies configured for the two features in [Step 1](#li15901515152517) to the global policy settings. {"dtbschedsrv", dmsFeature, 1}, {"samgr", samgrFeature, 1}, {"appspawn", appspawnFeature, 1}, @@ -97,7 +97,7 @@ This section uses BMS as an example to describe how to configure access policies }; ``` -3. Register the **BmsFeature** defined in [Step 1](#li15901515152517) with Samgr. +3. Register the **BmsFeature** defined in [Step 1](#li15901515152517) with Samgr. ``` const char BMS_SERVICE[] = "bundlems"; @@ -118,22 +118,22 @@ This section uses BMS as an example to describe how to configure access policies ``` -When you register a service with Samgr, Samgr calls the **GetCommunicationStrategy** function of the IPC authentication component to obtain access policies of the service. When other processes access this service through IPC, Samgr calls the **IsCommunicationAllowed** function of the IPC authentication component to check whether the processes have the access permission. +When you register a service with Samgr, Samgr calls the **GetCommunicationStrategy** function of the IPC authentication component to obtain access policies of the service. When other services or applications access this service through IPC, Samgr calls the **IsCommunicationAllowed** function of the IPC authentication component to check whether the services or applications have the access permission. ## FAQ -- Service registration failure +- Registering a service with Samgr failed - **Symptom** + **Problem** During the startup of a new service, a message is displayed indicating that the service fails to be registered with Samgr. - **Possible Causes** + **Cause** The service UID is not configured in the IPC authentication component. - **Solutions** + **Solution** - Configure the service UID in the **base/security/permission/services/permission\_lite/ipc\_auth/src/ipc\_auth\_impl.c** file. + Configure a valid UID for the service in the **base/security/permission/services/permission\_lite/ipc\_auth/src/ipc\_auth\_impl.c** file. diff --git a/en/device-dev/subsystems/subsys-security-overview.md b/en/device-dev/subsystems/subsys-security-overview.md index 6149a7ce057d16bf7106862a7448d6742cc78fc1..11159d39de4e69aade5326c7ba4b31705d460934 100644 --- a/en/device-dev/subsystems/subsys-security-overview.md +++ b/en/device-dev/subsystems/subsys-security-overview.md @@ -13,13 +13,9 @@ The OpenHarmony security subsystem provides security capabilities that make your Application permissions determine what system resources and capabilities an application can access. During application development, you need to declare the permissions that the application may require in the **profile.json** file. Static permissions need to be registered during application installation, while dynamic permissions usually involve sensitive information and need users' dynamic authorization. -- Inter-process communication \(IPC\) authentication - - APIs are provided for processes to access system services through IPC. Access policies are configured for these APIs. When a process requests to access an API, the IPC authentication mechanism is triggered to check whether the process has the required permission. If it is found that the process does not have the required permission, the access request will be denied. - - Trusted device group management - You can create and query a group of trusted devices that use the same HUAWEI ID or a peer-to-peer group created by scanning a QR code or using OneHop. With this capability, distributed applications can perform trusted authentication between devices and request from the distributed virtual bus for secure sessions between devices. + You can create and query a group of trusted devices that use the same ID or a peer-to-peer group created by scanning a QR code or using OneHop. With this capability, distributed applications can perform trusted authentication between devices and request from the distributed virtual bus for secure sessions between devices. ## Basic Concepts @@ -33,7 +29,7 @@ Before developing an application that depends on the signature verification comp - BMS - Bundle Manager Service \(BMS\) manages application installation, uninstallation, and data. + Bundle Manager Service \(BMS\) manages application installation, uninstallation, and data on OpenHarmony. - Profile @@ -41,19 +37,9 @@ Before developing an application that depends on the signature verification comp The profile in this document refers to HarmonyAppProvision \(profile for short\). HarmonyAppProvision is in JSON format. -- Leaf certificate - - A leaf certificate is used to sign a bundle or profile. It is the last certificate in a digital certificate chain. - - - Debugging application - A debugging application is a HarmonyOS Ability Package \(HAP\) that is signed with a debugging certificate and profile obtained from the application market. - - -- Application for release - - This application refers to a HAP that is signed with a distribution certificate and profile obtained from the application market, but has not been released in the application market. + A debugging application is a HAP that is signed with a debugging certificate and profile obtained from the application market. - Released application @@ -63,14 +49,11 @@ Before developing an application that depends on the signature verification comp - OpenHarmony self-signed application - This application refers to a HAP that is signed with the profile of the OpenHarmony application you have compiled, and a public/private key pair and certificate of OpenHarmony. + A self-signed application is one that has been signed with the signing certificate and profile issued by OpenHarmony's open-source root CA, which is comprised of a certificate and a key. ## Limitations and Constraints -- Only signatures of debugging, released, and self-signed applications can be verified. +- Only signatures of debugging, released, and OpenHarmony self-signed applications can be verified. - To verify the signature of a debugging application, the UDID of the device on which the debugging application is installed must be in the UDID list contained in the profile. -- Signatures of the applications for release cannot be verified. -- APIs provided by the signature verification component are stored in the [app\_verify\_pub.h](https://gitee.com/fork_ohos_wj/security_interfaces_innerkits_app_verify/blob/master/app_verify_pub.h) file of the **security\_interfaces\_innerkits\_app\_verify** repository and can be called only by system application developers. -- APIs for managing trusted device groups are only available for applications with the system signature permission. diff --git a/en/device-dev/subsystems/subsys-security-rightmanagement.md b/en/device-dev/subsystems/subsys-security-rightmanagement.md index 747ecce03eb0dfdeeda525206f398330dbd6f6c4..8b15372203c89016c5862f443303daa59cdefc67 100644 --- a/en/device-dev/subsystems/subsys-security-rightmanagement.md +++ b/en/device-dev/subsystems/subsys-security-rightmanagement.md @@ -7,7 +7,7 @@ ## How Application Permission Management Works -OpenHarmony allows users to install third-party applications and controls calls made by third-party applications to sensitive permissions. When developing an application, you need to declare the sensitive permissions that the application may require in the **profile.json** file. The permissions include static and dynamic ones. Static permissions need to be registered during application installation, and dynamic permissions can be obtained only upon user authorization. Authorization modes include system settings, manual authorization by applications, and others. In addition, application signature control is used to ensure that the application installation package has been confirmed by the device vendor. +OpenHarmony allows users to install third-party applications and controls calls made by third-party applications to sensitive permissions. When developing an application, you need to declare the sensitive permissions that the application may require in the **profile.json** file. The permissions can be static or dynamic. Static permissions need to be registered during application installation, and dynamic permissions can be obtained only upon user authorization. Authorization modes include system settings, manual authorization by applications, and others. In addition, application signature control is used to ensure that the application installation package has been confirmed by the device vendor. **Table 1** OpenHarmony permissions @@ -215,7 +215,7 @@ This section uses the BMS as an example to describe the application permission d HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to nullptr parameters"); return false; } - // Check whether the ohos.permission.INSTALL_BUNDLE permission has been granted. + // Check whether the ohos.permission.INSTALL_BUNDLE permission has been granted. if (CheckPermission(0, static_cast(PERMISSION_INSTALL_BUNDLE)) != GRANTED) { HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to permission denied"); return false; // Application installation fails. diff --git a/en/device-dev/subsystems/subsys-security-sigverify.md b/en/device-dev/subsystems/subsys-security-sigverify.md index 8436c859d8d7708e4fd34d08f786dc53a359db4f..dfc7051d811f6dfe7e7ad0926ae764eac76b5c17 100644 --- a/en/device-dev/subsystems/subsys-security-sigverify.md +++ b/en/device-dev/subsystems/subsys-security-sigverify.md @@ -3,60 +3,48 @@ - [When to Use](#section18502174174019) - [Signature Verification Process](#section554632717226) - [Available APIs](#section1633115419401) -- [Development Procedure \(Scenario 1\)](#section4207112818418) - - [Signature Verification](#section11470123816297) - - [OpenHarmony Self-signed Application Generation](#section167151429133312) - - [Development Examples](#section174318361353) +- [How to Develop](#section4207112818418) + - [OpenHarmony Self-signed Application](#section167151429133312) -- [Development Procedure \(Scenario 2\)](#section81272563427) - - [Signature Verification](#section07028210442) - - [Development Examples](#section1930711345445) - -- [Debugging and Verification](#section427316292411) ## When to Use -You can call the APIs provided by the signature verification component to check integrity of a debugging, released, or OpenHarmony self-signed application. You can also call APIs of the signature verification component to obtain some information in the profile, for example, **appid**. In addition, you can call APIs to check whether the UDID of a debugging application matches that of the device to ensure that the application is installed on the right device. +To ensure the integrity and trustworthiness of the applications to be installed in OpenHarmony, the applications must be signed and their signatures must be verified. + +- In application development: After developing an application, you need to sign its installation package to ensure that the installation package is not tampered with when it is released on devices. To sign the application package, you can use the signature tools and the public key certificates and follow the signing certificate generation specifications provided by the application integrity verification module. For your convenience, a public key certificate and a corresponding private key are preset in OpenHarmony. You need to replace the public key certificate and private key in your commercial version of OpenHarmony. +- In application installation: The Application Framework subsystem of OpenHarmony installs applications. Upon receiving an application installation package, the Application Framework subsystem parses the signature of the installation package, and verifies the signature using the application integrity verification APIs. The application can be installed only after the verification succeeds. During the verification, the application integrity verification module uses the preset public key certificate to verify the signature. ## Signature Verification Process An unsigned HAP is in **.zip** format and consists of a file block, central directory, and end of central directory \(EOCD\). -After the HAP is signed, a signature block is added between the file block and the central directory. The signature block consists of a file signature block, profile signature block, and signature header. The following figure shows the structure of a signed HAP. - -**Figure 1** Structure of a signed HAP - +After the HAP is signed, a signature block is added between the file block and the central directory. The integrated signature block consists of a profile signature block, HAP signature block, and signature header. The following figure shows the structure of a signed HAP. -![](figure/安全子系统.png) +**Figure 1** Structure of a signed HAP +![](figure/structure-of-a-signed-hap.png "structure-of-a-signed-hap") -The signature verification process consists of three steps: HAP signature verification, signature verification for the profile signature block, and profile content verification. +The signature verification process consists of three steps: HAP signature verification, profile signature verification, and profile content verification. **HAP signature verification** -Use the preset root certificate of the device and the certificate chain to prove that the leaf certificate is trusted. Then use the digest obtained by decrypting the public key of the leaf certificate to prove that the HAP is not tampered with. +The HAP signature block is a signed data block in PKCS7 format. The signature verification process includes PKSC7 signature verification, hash comparison, certificate chain verification, and matching between the certificate chain and the device's preset root certificate. -The process is as follows: +**Profile signature verification** -1. Use the preset root certificate of the device to verify the certificate chain in the file signature block and prove that the leaf certificate is trusted. -2. Use the public key in the leaf certificate to verify the file signature block and prove that this block is not tampered with. -3. Calculate and merge the digests of the file block, central directory, and EOCD. Merge the calculation result with the digest of the profile signature block in the signature block. Then compare the merge result with the digest of the file signature block. If they are the same, the HAP signature verification is successful. - -**Signature verification for the profile signature block** - -First of all, check who issued the signature of the profile signature block. If the signature was issued by the application market, the signature is trusted and does not need to be verified. Otherwise, the signature needs to be verified. Next, verify the certificate chain and then use the leaf certificate to verify the signature of the profile signature block to prove that it is not tampered with. +The profile signature block is a signed data block in PKCS7 format. The profile content is stored in **contentinfo** of the PKCS7 signature block. The signature verification process includes PKCS7 signature verification, hash comparison, certificate chain verification, and profile certificate validity verification. **Profile content verification** -Obtain the profile and check the validity of its content. If the HAP is a debugging application, check whether the UDID of the current device is contained in the UDID list in the profile. If yes, the verification is successful. Then compare the certificate in the profile with the leaf certificate used for HAP verification \(this is not required for a released or OpenHarmony self-signed application\). If they are the same, the entire signature verification process is complete. +The signature verification module checks the validity of the profile content. If the profile is of the debugging type, the module checks whether the UDID of the current device is contained in the UDID list in the profile. If yes, the module compares the certificate in the profile with the certificate used for HAP signature verification. If they are the same, the entire verification process is complete. ## Available APIs The following table lists the innerkits APIs provided by the signature verification component. These APIs are available only for system applications. -**Table 1** APIs provided by the signature verification component +**Table 1** APIs provided by the signature verification component for mini systems -

Function

@@ -31,7 +31,7 @@ The following table lists the APIs provided by IPC authentication \(intended for

int IsCommunicationAllowed(AuthParams params)

Checks whether a process has the permission to access an API of another service.

+

Checks whether a process has the permission to access an API of another process.

Function

+ @@ -81,192 +69,26 @@ The following table lists the innerkits APIs provided by the signature verificat

API

Description

-## Development Procedure \(Scenario 1\) - -### Signature Verification - -To verify applications released in the application market, debugging applications signed with debugging certificates of the application market, and OpenHarmony self-signed applications, perform the following steps: - -1. Construct the VerifyResult structure. - - ``` - VerifyResult verifyResult = {0}; - ``` - -2. Call the APPVERI\_AppVerify function by specifying the file path and VerifyResult to verify the application signature. - - ``` - int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); - ``` - -3. Check the returned result. If the verification is successful, obtain and process the data in VerifyResult. - - ``` - signatureInfo.appId = verifyResult.profile.appid; - signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; - ``` - -4. Call the APPVERI\_FreeVerifyRst function to release memory in VerifyResult. - - ``` - APPVERI_FreeVerifyRst(&verifyResult); - ``` - - -### OpenHarmony Self-signed Application Generation - -The procedure is as follows: - -1. Prepare required materials. - - Prepare the signature tool, system application HAP, system application profile \(\*.p7b\), signing certificate \(\*.cer\), and signing public/private key pair \(\*.jks\). - -2. Place all the materials in the same directory and start the shell. -3. Run the following command in the shell to sign the application: - - ``` - java -jar hapsigntoolv2.jar sign -mode localjks -privatekey "OpenHarmony Software Signature" -inputFile camera.hap -outputFile signed_camera.hap -signAlg SHA256withECDSA -keystore OpenHarmony.jks -keystorepasswd 123456 -keyaliaspasswd 123456 -profile camera_release.p7b -certpath OpenHarmony.cer -profileSigned 1 - ``` - - Key fields: - - **-jar**: signature tool, which is **[hapsigntool](https://repo.huaweicloud.com/harmonyos/develop_tools/hapsigntoolv2.jar)** - - **-mode**: local signature flag, which is fixed at **localjks** - - **-privatekey**: alias of the public/private key pair, which is **OpenHarmony Software Signature** - - **-inputFile**: application to be signed, which is generated through compilation - - **-outputFile**: signed application +**Table 2** APIs provided by the signature verification component for standard systems - **-signAlg**: signing algorithm, which is fixed at **SHA256withECDSA** - - **-keystore**: public/private key pair, which is [OpenHarmony.jks](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.jks) in the **OpenHarmonyCer** directory of the **security\_services\_app\_verify** repository. The default password is **123456**. You can use a tool \(such as keytool\) to change the password. - - **-keystorepasswd**: password of the public/private key pair, which is **123456** by default - - **-keyaliaspasswd**: password of the public/private key pair alias, which is **123456** by default - - **-profile**: application profile, which is stored in the code directory - - **-certpath**: signing certificate, which is [OpenHarmony.cer](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.cer) in the **OpenHarmonyCer** directory of the **security\_services\_app\_verify** repository. - - **-profileSigned**: whether the signature block contains the profile. The value is fixed at **1**, indicating that the signature block contains the profile. - - -### Development Examples - -The following example describes how the application management framework component verifies the signature of an application during its installation. - -``` -uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) -{ - bool mode = ManagerService::GetInstance().IsDebugMode(); - HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); - // Construct the VerifyResult structure. - VerifyResult verifyResult = {0}; - // Verify the signature by specifying the file path. - int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); - uint8_t errorCode = SwitchErrorCode(ret); - if (errorCode != ERR_OK) { - return errorCode; - } - // Obtain appid from the VerifyResult structure. - signatureInfo.appId = verifyResult.profile.appid; - // Obtain the application name written in the profile from the VerifyResult structure. - signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; - int32_t restricNum = verifyResult.profile.permission.restricNum; - for (int32_t i = 0; i < restricNum; i++) { - signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); - } - // Release memory in VerifyResult. - APPVERI_FreeVerifyRst(&verifyResult); - return ERR_OK; -} -``` - -## Development Procedure \(Scenario 2\) - -### Signature Verification - -To verify applications signed with certificates that are based on debugging root keys, perform the following steps: - -1. Call the APPVERI\_SetDebugMode\(true\) function to enable the debugging mode. - - ``` - ManagerService::SetDebugMode(true); - ... - uint8_t ManagerService::SetDebugMode(bool enable) - { - int32_t ret = APPVERI_SetDebugMode(enable); - if (ret < 0) { - HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); - return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; - } - isDebugMode_ = enable; - HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); - return ERR_OK; - } - ``` - -2. Construct the **VerifyResult** structure, verify the application signature, and release memory in **VerifyResult**. -3. Call the APPVERI\_SetDebugMode\(false\) function to disable the debugging mode. - - ``` - ManagerService::SetDebugMode(false); - ``` - - -### Development Examples - -The following is the example code \(supplemented based on the example code for scenario 1\): + + + + + + + + + +

API

+

Description

+

nt HapVerify(const std::string& filePath, HapVerifyResult& hapVerifyResult)

+

Verifies application integrity and identifies the application source.

+
-``` -uint8_t ManagerService::SetDebugMode(bool enable) -{ - int32_t ret = APPVERI_SetDebugMode(enable); - if (ret < 0) { - HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); - return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; - } - isDebugMode_ = enable; - HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); - return ERR_OK; -} -uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) -{ - // Enable debugging mode. - ManagerService::SetDebugMode(true); - bool mode = ManagerService::GetInstance().IsDebugMode(); - HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); - // Construct the VerifyResult structure. - VerifyResult verifyResult = {0}; - // Verify the signature by specifying the file path. - int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); - uint8_t errorCode = SwitchErrorCode(ret); - if (errorCode != ERR_OK) { - return errorCode; - } - // Obtain appid from the VerifyResult structure. - signatureInfo.appId = verifyResult.profile.appid; - // Obtain the application name written in the profile from the VerifyResult structure. - signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; - int32_t restricNum = verifyResult.profile.permission.restricNum; - for (int32_t i = 0; i < restricNum; i++) { - signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); - } - // Release memory in VerifyResult. - APPVERI_FreeVerifyRst(&verifyResult); - // Disable debugging mode. - ManagerService::SetDebugMode(false); - return ERR_OK; -} -``` +## How to Develop -## Debugging and Verification +### OpenHarmony Self-signed Application -1. Choose an application that can be properly installed on OpenHarmony. -2. Develop the application based on the development guidelines. -3. Use a self-developed program to verify the signature of the developed application. If the verification is successful and **appid** can be obtained, the development is successful. +To develop an OpenHarmony self-signed application, follow instructions provided in the guide of [_Configuring the OpenHarmony App Signature_](https://gitee.com/openharmony/docs/blob/master/en/application-dev/quick-start/configuring-openharmony-app-signature.md) : diff --git a/en/device-dev/subsystems/subsys-testguide-test.md b/en/device-dev/subsystems/subsys-testguide-test.md index c037ff22c314f5abf144fd5854efdf3b86f2b7b7..ac5aa3e746600805a78d7e7985bfb89354623a95 100644 --- a/en/device-dev/subsystems/subsys-testguide-test.md +++ b/en/device-dev/subsystems/subsys-testguide-test.md @@ -719,7 +719,7 @@ Test cases cannot be built on Windows. You need to run the following command to > - --**product-name**: specifies the name of the product to build, for example, **Hi3516DV300**. > - --**build-target**: specifies the target to build. It is optional. **make_test** indicates all test cases. You can set the build options based on requirements. -When the build is complete, the test cases are automatically saved in the **out/ohos-arm-release/packages/phone/tests** directory. +When the build is complete, the test cases are automatically saved in the **out/hi3516dv300/packages/phone/tests** directory. #### Setting Up the Execution Environment 1. On Windows, create the **Test** directory in the test framework and then create the **testcase** directory in the **Test** directory. diff --git a/en/readme.md b/en/readme.md index c3293c74dab84f93735326759ada19b32e475df2..7a3b845eda10d6478ea218cfda0b5508558d3373 100644 --- a/en/readme.md +++ b/en/readme.md @@ -17,7 +17,6 @@ This project stores OpenHarmony documentation, including the quick start guide, - **Subsystems**: [subsystems](device-dev/subsystems/Readme-EN.md) \(such as compilation and building, graphics, DFX, and XTS\) - **Security**: [privacy and security](device-dev/security/Readme-EN.md) - **guide**: - - [OneHop](device-dev/guide/device-wlan-touch.md) - [WLAN-connected products](device-dev/guide/device-wifi.md) \(LED peripheral control and third-party SDK integration\) - [Screenless cameras](device-dev/guide/device-iotcamera-control.md) \(camera control\) - [Cameras with a screen](device-dev/guide/device-camera.md) \(screen and camera control, visual application development\) diff --git a/en/readme/distributed-scheduler.md b/en/readme/distributed-scheduler.md index eef3ae0cc0f645ec4dd195d054fc572adf5560d2..ec46001bd381e1734384e13e8b2f7eb0d7536271 100755 --- a/en/readme/distributed-scheduler.md +++ b/en/readme/distributed-scheduler.md @@ -1,17 +1,25 @@ # Distributed Scheduler - [Introduction](#section11660541593) +- [System Architecture](#section13587185873516) - [Directory Structure](#section161941989596) - [Repositories Involved](#section1371113476307) ## Introduction -The Distributed Scheduler in OpenHarmony provides functions related to system abilities \(also called system services\), including system ability startup, registration, and query. +Distributed Scheduler is used for cross-device component management. It allows the local device to access or control remote components, and enables app collaboration in distributed scenarios. Its main functions are as follows: -**Figure 1** Distributed Scheduler subsystem architecture +- Remote ability startup: Starts an ability on a remote device. +- Remote ability migration: Migrates an ability to a remote device. +- Remote ability binding: Binds an ability on a remote device. +- System service management: Provides system service startup, registration, and query on the local device as well as system service query on a remote device. +## System Architecture -![](figures/en-us_image_0000001162500331.png) +**Figure 1** Distributed Scheduler architecture + + +![](figures/dms-architecture.png) ## Directory Structure diff --git a/en/readme/figures/dms-architecture.png b/en/readme/figures/dms-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..1b7001cc23104148d5e6ea6b43cc32506872dc89 Binary files /dev/null and b/en/readme/figures/dms-architecture.png differ diff --git a/en/readme/test_subsystem.md b/en/readme/test_subsystem.md index c548455b7471b4aae4d7ff81fb19ca4673f81f5d..41e56907b26ef35d2e06e660c57c8390fee52b49 100644 --- a/en/readme/test_subsystem.md +++ b/en/readme/test_subsystem.md @@ -721,7 +721,7 @@ Test cases cannot be built on Windows. You need to run the following command to ``` ./build.sh --product-name Hi3516DV300 --build-target make_test ``` -When the build is complete, the test cases are automatically saved in the **out/ohos-arm-release/packages/phone/images/tests** directory. +When the build is complete, the test cases are automatically saved in the **out/hi3516dv300/packages/phone/images/tests** directory. >**Note:** In the command, **Hi3516DV300** is the platform supported by the current version, and **make_test** indicates all test cases. You can set the build options based on requirements: > - --**product-name**: specifies the name of the product to build. It is mandatory. diff --git a/zh-cn/application-dev/Readme-CN.md b/zh-cn/application-dev/Readme-CN.md index 3dabd771aad9a52346bde57b8996ebc10c37ef9f..16e9eb71a3379856393da92ecb650a008b8f19d0 100644 --- a/zh-cn/application-dev/Readme-CN.md +++ b/zh-cn/application-dev/Readme-CN.md @@ -10,5 +10,6 @@ - [基于TS扩展的声明式开发范式](ui/ui-arkui-ts.md) - [音频](media/audio.md) - [IPC与RPC通信](connectivity/ipc-rpc.md) +- [应用事件打点](application-event-logging/hiappevent.md) - [JS 开发参考](js-reference/Readme-CN.md) diff --git a/zh-cn/application-dev/ability/service-ability.md b/zh-cn/application-dev/ability/service-ability.md index e0c861c6ae1952a883fb5c48f93b77ebaacc5e59..908875bb4216b7aadcf4cfd796a4a57680bb05ac 100644 --- a/zh-cn/application-dev/ability/service-ability.md +++ b/zh-cn/application-dev/ability/service-ability.md @@ -145,7 +145,7 @@ var connId = featureAbility.connectAbility( ); ``` -同时,Service侧也需要在onConnect()时返回IRemoteObject,从而定义与Service进行通信的接口。onConnect()需要返回一个IRemoteObject对象,HarmonyOS提供了IRemoteObject的默认实现,用户可以通过继承rpc.RemoteObject来创建自定义的实现类。 +同时,Service侧也需要在onConnect()时返回IRemoteObject,从而定义与Service进行通信的接口。onConnect()需要返回一个IRemoteObject对象,OpenHarmony提供了IRemoteObject的默认实现,用户可以通过继承rpc.RemoteObject来创建自定义的实现类。 Service侧把自身的实例返回给调用侧的代码示例如下: diff --git a/zh-cn/application-dev/application-event-logging/hiappevent-guidelines.md b/zh-cn/application-dev/application-event-logging/hiappevent-guidelines.md new file mode 100644 index 0000000000000000000000000000000000000000..c283e3a95e8fdab47041dc96fd536a3138776df5 --- /dev/null +++ b/zh-cn/application-dev/application-event-logging/hiappevent-guidelines.md @@ -0,0 +1,117 @@ +# 应用事件开发指导 + +## 场景介绍 + +应用事件打点的主要工作是在应用运行过程中,帮助应用记录在运行过程中发生的各种信息。 + +## 接口说明 + +应用事件JS打点接口由hiAppEvent模块提供。 + +**打点接口功能介绍:** + +| 接口名 | 返回值 | 描述 | +| ------------------------------------------------------------ | -------------- | ---------------------------------------------------- | +| write(string eventName, EventType type, object keyValues, AsyncCallback\ callback): void | void | 应用事件异步打点方法,使用callback方式作为异步回调。 | +| write(string eventName, EventType type, object keyValues): Promise\ | Promise\ | 应用事件异步打点方法,使用promise方式作为异步回调。 | + +- 参数eventName:开发者自定义事件名称。事件名称在48个字符以内,有效的字符是0-9、a-z、下划线,只能以字母开头。 + +- 参数type:事件所属的类型,取值为枚举EventType,具体值如下表。 + + | 类型 | 描述 | + | --------- | -------------- | + | FAULT | 故障类型事件。 | + | STATISTIC | 统计类型事件。 | + | SECURITY | 安全类型事件。 | + | BEHAVIOR | 行为类型事件。 | + +- 参数keyValues:事件参数键值对,如果是变长参数类型,则依次输入事件的参数名与参数值。如果是Json对象类型,则Json对象的key是事件的参数名,value是事件的参数值。 + - 参数名只支持string类型,参数值只支持boolean、number、string、Array(数组参数值为基本类型)。 + - 事件的参数个数必须小于等于32。 + - 参数名在16个字符以内,有效的字符是0-9、a-z、下划线,只能以字母开头,不能以下划线结尾。 + - string类型参数值在8*1024个字符内。 + - Array类型参数值的元素个数必须在100个以内,超出时会进行截断处理。 +- 参数callback:回调函数,可以在回调函数中处理接口返回值。返回值为0表示事件参数校验成功,事件正常异步写入事件文件;大于0表示事件存在异常参数,事件在忽略异常参数后再异步写入事件文件;小于0表示事件校验失败,不执行事件异步打点操作。 + +当采用callback作为异步回调时,可以在callback中进行下一步处理。当采用Promise对象返回时,可以在Promise对象中类似地处理接口返回值。具体结果码说明见[事件校验结果码](hiappevent-overview.md#事件校验结果码)。 + +**打点配置接口功能介绍:** + +| 接口名 | 返回值 | 描述 | +| ------------------------------ | ------- | ------------------------------------------------------------ | +| configure(ConfigOption config) | boolean | 应用事件打点配置方法,可以对打点功能进行自定义配置。返回true表示配置成功,false表示配置失败。 | + +- 参数config:应用事件打点配置项对象。应用打点配置选项ConfigOption如下表。 + + | 参数名 | 类型 | 必填 | 说明 | + | ---------- | ------- | ---- | ------------------------------------------------------------ | + | disable | boolean | 否 | 应用打点功能开关,例如配置值为true表示关闭打点功能。 | + | maxStorage | string | 否 | 打点落盘文件存放目录的配额大小,默认限额为“10M”,超出限额后会对存放目录进行清理。 | + + +**预定义事件名称常量接口Event:** +| 常量名 | 类型 | 描述 | +| ------------------------- | ------ | ------------------------ | +| USER_LOGIN | string | 用户登录事件名称。 | +| USER_LOGOUT | string | 用户登出事件名称。 | +| DISTRIBUTED_SERVICE_START | string | 分布式服务启动事件名称。 | + + +**预定义参数名称常量接口Param:** +| 常量名 | 类型 | 描述 | +| ------------------------------- | ------ | ------------------ | +| USER_ID | string | 用户自定义ID。 | +| DISTRIBUTED_SERVICE_NAME | string | 分布式服务名称。 | +| DISTRIBUTED_SERVICE_INSTANCE_ID | string | 分布式服务示例ID。 | + +## 开发步骤 + +在应用启动执行页面加载后,执行一个应用事件打点,用于记录应用的初始页面加载事件。 + +1. 新建一个JS应用工程,在“Project”窗口点击“entry > src > main > js > default > pages > index”,打开工程中的“index.js”文件,在页面执行加载后,执行一个应用事件打点,用于记录应用的初始页面加载事件,示例代码如下: + + ```js + import hiAppEvent from '@ohos.hiAppEvent' + + export default { + data: { + title: "" + }, + onInit() { + this.title = this.$t('strings.world'); + + // 1.callback方式 + hiAppEvent.write("start_event", hiAppEvent.EventType.BEHAVIOR, {"int_data":100, "str_data":"strValue"}, (err, value) => { + if (err) { + console.error(`failed to write event because ${err.code}`); + return; + } + console.log(`success to write event: ${value}`); + }); + + // 2.Promise方式 + hiAppEvent.write("start_event", hiAppEvent.EventType.BEHAVIOR, {"int_data":100, "str_data":"strValue"}) + .then((value) => { + console.log(`success to write event: ${value}`); + }).catch((err) => { + console.error(`failed to write event because ${err.code}`); + }); + }); + + // 3.配置应用打点开关 + hiAppEvent.configure({ + disable: true + }); + + // 4.配置事件文件目录限额(默认为10M) + hiAppEvent.configure({ + maxStorage: '100M' + }); + } + } + ``` + +2. 运行项目,点击应用界面上的运行按钮。 + + diff --git a/zh-cn/application-dev/application-event-logging/hiappevent-overview.md b/zh-cn/application-dev/application-event-logging/hiappevent-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..2075f94f3c37e3d2fe5619676dfc5eb472fb589a --- /dev/null +++ b/zh-cn/application-dev/application-event-logging/hiappevent-overview.md @@ -0,0 +1,28 @@ +# 应用事件打点概述 + +HiAppEvent提供了应用事件打点接口,为应用提供事件打点的功能,用于帮助应用记录在运行过程中发生的故障信息、统计信息、安全信息、用户行为信息,以支撑开发者分析应用的运行情况。 + +## 基本概念 + +OpenHarmony系统HiAppEvent模块支持应用事件业务的开发,提供应用事件相关的功能,主要包括应用事件落盘、查询历史应用事件数据等功能。 + +- **打点** + + 记录由用户操作引起的变化,提供业务数据信息,以供开发、产品、运维分析。 + +## 事件校验结果码 + +| 错误码 | 原因 | 校验规则 | 处理结果 | +| ------ | --------------------------- | ------------------------------------------------------------ | ----------------------------------------------------- | +| 0 | 无 | 事件校验成功 | 事件正常打点。 | +| -1 | 无效的事件名称 | 非空且长度在48个字符以内(含)。
只由以下字符组成:0-9、a-z、_。
非数字以及下划线开头。 | 忽略该事件,不执行打点。 | +| -2 | 无效的事件基本参数类型 | 事件名称参数必须为string。
事件类型参数必须为number类型。
keyValues参数必须为object类型。 | 忽略该事件,不执行打点。 | +| -99 | 应用打点功能被关闭 | 应用打点功能被关闭。 | 忽略该事件,不执行打点。 | +| -100 | 未知错误 | 无。 | 忽略该事件,不执行打点。 | +| 1 | 无效的key参数名称 | 非空且长度在16个字符以内(含)。
只由以下字符组成:0-9、a-z、_。
非数字以及下划线开头。
非下划线结尾。 | 忽略该键值对参数后,继续执行打点。 | +| 2 | 无效的key参数类型 | Key参数必须为字符串类型。 | 忽略该键值对参数后,继续执行打点。 | +| 3 | 无效的value参数类型 | value参数只支持以下类型:
boolean、number、string、Array[基本类型]。
| 忽略该键值对参数后,继续执行打点。 | +| 4 | value参数值过长 | 参数值长度必须在8*1024个字符以内(含)。 | 忽略该键值对参数后,继续执行打点。 | +| 5 | key-value参数对数过多 | key-value参数对数必须在32对以内(含)。 | 忽略后面多余的键值对参数后,继续执行打点。 | +| 6 | List类型的value参数容量过大 | List类型的value参数容量必须在100个以内(含)。 | 对List进行截断(只保留前100个元素)后,继续执行打点。 | +| 7 | 无效的List类型value参数 | List的泛型类型只能为基本类型。
List内的参数必须为同一类型。 | 忽略该键值对参数后,继续执行打点。 | \ No newline at end of file diff --git a/zh-cn/application-dev/application-event-logging/hiappevent.md b/zh-cn/application-dev/application-event-logging/hiappevent.md new file mode 100644 index 0000000000000000000000000000000000000000..e79ac250ded24889ab768c23a594a4b8ad4e258c --- /dev/null +++ b/zh-cn/application-dev/application-event-logging/hiappevent.md @@ -0,0 +1,5 @@ +# 应用事件打点 + +- [应用事件打点概述](hiappevent-overview.md) +- [应用事件打点开发指导](hiappevent-guidelines.md) + diff --git a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-animator.md b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-animator.md index 81e08630864c13e55f3f79c4add7fd28807b74cb..86b57fc066d2ba3aa7a244b3e4f8e78e818d96a2 100644 --- a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-animator.md +++ b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-animator.md @@ -439,7 +439,6 @@ createAnimator\(options\[...\]\): void ``` // js - import Animator from "@ohos.animator"; export default { data : { divWidth: 200, @@ -455,7 +454,7 @@ createAnimator\(options\[...\]\): void begin: 200.0, end: 400.0 }; - this.animator = Animator.createAnimator(options); + this.animator = animator.createAnimator(options); }, Show() { var options1 = { diff --git a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-app-context.md b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-app-context.md index 201556ce619453520e8fb4a15fbd48108c5d89fd..65a177cbc072f349b6395d11ae53a5fd7d4659b1 100644 --- a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-app-context.md +++ b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-app-context.md @@ -62,9 +62,12 @@ getInfo\(\): <[AppResponse](#t3e93239d9b134b80957bcdd4acb05291)\> - 示例 ``` - - var info = app.getInfo(); - console.log(JSON.stringify(info)); + export default { + getInfo(){ + var info = app.getInfo(); + console.log(JSON.stringify(info)); + } + } ``` @@ -77,8 +80,10 @@ terminate\(\): void - 示例 ``` - - app.terminate(); + export default { + terminate(){ + app.terminate(); + }} ``` diff --git a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-configuration.md b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-configuration.md index 6b0aa3826a59574a7d20fdb88958182797b5b6a8..8f590bf1a2ca171aa3080c3ce4fa7d2aaad72438 100644 --- a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-configuration.md +++ b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-configuration.md @@ -65,9 +65,12 @@ getLocale\(\): <[LocaleResponse](#table1544853546)\> - 示例 ``` - - const localeInfo = configuration.getLocale(); - console.info(localeInfo.language); + export default { + getLocale() { + const localeInfo = configuration.getLocale(); + console.info(localeInfo.language); + } + } ``` diff --git a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-logs.md b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-logs.md index 8b172bec109982ffc628e3bc37862f3691096b5a..1b26f76e3b16fe85acf4b609d7f69acd6dfcedcb 100644 --- a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-logs.md +++ b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-logs.md @@ -171,12 +171,15 @@ error\(message: string\): void ## 示例 ``` - -var versionCode = 1; -console.info('Hello World. The current version code is ' + versionCode); -console.log(`versionCode: ${versionCode}`) -// 以下写法从API Version 6开始支持 -console.log('versionCode:%d.', versionCode); +export default { + clickConsole(){ + var versionCode = 1; + console.info('Hello World. The current version code is ' + versionCode); + console.log(`versionCode: ${versionCode}`); + // 以下写法从API Version 6开始支持 + console.log('versionCode:%d.', versionCode); + } +} ``` 在DevEco Studio的底部,切换到“HiLog”窗口。选择当前的设备及进程,日志级别选择Info,搜索内容设置为“Hello World”。此时窗口仅显示符合条件的日志,效果如图所示: diff --git a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-pop-up.md b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-pop-up.md index 82706369ec346547864cc2200ff1a24616597c32..4ac34ca0b8a6348ba58752a14643f5bb8644751c 100644 --- a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-pop-up.md +++ b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-pop-up.md @@ -66,11 +66,14 @@ showToast\(Object\): void - 示例 ``` - - prompt.showToast({ - message: 'Message Info', - duration: 2000, - }); + export default { + showToast() { + prompt.showToast({ + message: 'Message Info', + duration: 2000, + }); + } + } ``` @@ -174,23 +177,26 @@ showDialog\(\): void - 示例 ``` - - prompt.showDialog({ - title: 'Title Info', - message: 'Message Info', - buttons: [ - { - text: 'button', - color: '#666666', - }, - ], - success: function(data) { - console.log('dialog success callback,click button : ' + data.index); - }, - cancel: function() { - console.log('dialog cancel callback'); - }, - }); + export default { + showDialog() { + prompt.showDialog({ + title: 'Title Info', + message: 'Message Info', + buttons: [ + { + text: 'button', + color: '#666666', + }, + ], + success: function(data) { + console.log('dialog success callback,click button : ' + data.index); + }, + cancel: function() { + console.log('dialog cancel callback'); + }, + }); + } + } ``` @@ -285,26 +291,29 @@ showActionMenu\(Object\): void - 示例 ``` - - prompt.showActionMenu({ - title: 'Title Info', - buttons: [ - { - text: 'item1', - color: '#666666', - }, - { - text: 'item2', - color: '#000000', - }, - ], - success: function(data) { - console.log('dialog success callback,click button : ' + data.tapIndex); - }, - fail: function(data) { - console.log('dialog fail callback' + data.errMsg); - }, - }); + export default { + showActionMenu() { + prompt.showActionMenu({ + title: 'Title Info', + buttons: [ + { + text: 'item1', + color: '#666666', + }, + { + text: 'item2', + color: '#000000', + }, + ], + success: function(data) { + console.log('dialog success callback,click button : ' + data.tapIndex); + }, + fail: function(data) { + console.log('dialog fail callback' + data.errMsg); + }, + }); + } + } ``` diff --git a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-routes.md b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-routes.md index 8c933dc7b27d3188053b540acca82943651b9177..bf73f7235583eba894a521780785cf98a7ef3f15 100644 --- a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-routes.md +++ b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-routes.md @@ -194,21 +194,41 @@ back\(Object\): void ``` // index页面 - router.push({ - uri: 'pages/detail/detail', - }); + export default { + indexPushPage() { + router.push({ + uri: 'pages/detail/detail', + }); + } + } // detail页面 - router.push({ - uri: 'pages/mall/mall', - }); + export default { + detailPushPage() { + router.push({ + uri: 'pages/mall/mall', + }); + } + } // mall页面通过back,将返回detail页面 - router.back(); + export default { + mallBackPage() { + router.back(); + } + } // detail页面通过back,将返回index页面 - router.back(); + export default { + defaultBack() { + router.back(); + } + } // 通过back,返回到detail页面 - router.back({uri:'pages/detail/detail'}); + export default { + backToDetail() { + router.back({uri:'pages/detail/detail'}); + } + } ``` >![](../../public_sys-resources/icon-note.gif) **说明:** @@ -224,8 +244,11 @@ clear\(\): void - 示例 ``` - - router.clear(); + export default { + clearPage() { + router.clear(); + } + } ``` @@ -255,9 +278,12 @@ getLength\(\): string - 示例 ``` - - var size = router.getLength(); - console.log('pages stack size = ' + size); + export default { + getLength() { + var size = router.getLength(); + console.log('pages stack size = ' + size); + } + } ``` @@ -309,11 +335,14 @@ getState\(\): <[RouterState](#tf9e3eb9ef0aa4d9880f996fe6afa6d1b)\> - 示例 ``` - - var page = router.getState(); - console.log('current index = ' + page.index); - console.log('current name = ' + page.name); - console.log('current path = ' + page.path); + export default { + getState() { + var page = router.getState(); + console.log('current index = ' + page.index); + console.log('current name = ' + page.name); + console.log('current path = ' + page.path); + } + } ``` @@ -378,16 +407,19 @@ enableAlertBeforeBackPage\(Object\): void - 示例 ``` - - router.enableAlertBeforeBackPage({ - message: 'Message Info', - success: function() { - console.log('success'); - }, - fail: function() { - console.log('fail'); - }, - }); + export default { + enableAlertBeforeBackPage() { + router.enableAlertBeforeBackPage({ + message: 'Message Info', + success: function() { + console.log('success'); + }, + fail: function() { + console.log('fail'); + }, + }); + } + } ``` @@ -443,15 +475,18 @@ disableAlertBeforeBackPage\(Object\): void - 示例 ``` - - router.disableAlertBeforeBackPage({ - success: function() { - console.log('success'); - }, - fail: function() { - console.log('fail'); - }, - }); + export default { + disableAlertBeforeBackPage() { + router.disableAlertBeforeBackPage({ + success: function() { + console.log('success'); + }, + fail: function() { + console.log('fail'); + }, + }); + } + } ``` diff --git a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-timer.md b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-timer.md index d81c74fcbee4d5fa935e3dadb79cbec638b6b495..9a1375fc02533067d50250c5db602a069c88afb8 100644 --- a/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-timer.md +++ b/zh-cn/application-dev/js-reference/apis/js-apis-basic-features-timer.md @@ -60,15 +60,15 @@ setTimeout\(handler\[,delay\[,…args\]\]\): number - 返回值 - - - - - - @@ -243,11 +243,11 @@ - - - @@ -256,11 +256,11 @@ - - - @@ -269,11 +269,11 @@ - - - - - - - - - @@ -937,17 +937,17 @@ 除支持[通用方法](js-components-common-methods.md)外,还支持如下方法: -

类型

+ - - - @@ -77,10 +77,13 @@ setTimeout\(handler\[,delay\[,…args\]\]\): number - 示例 ``` - - var timeoutID = setTimeout(function() { - console.log('delay 1s'); - }, 1000); + export default { + setTimeOut() { + var timeoutID = setTimeout(function() { + console.log('delay 1s'); + }, 1000); + } + } ``` @@ -118,12 +121,14 @@ clearTimeout\(timeoutID: number\): void - 示例 ``` - - var timeoutID = setTimeout(function() { - console.log('do after 1s delay.'); - }, 1000); - - clearTimeout(timeoutID); + export default { + clearTimeOut() { + var timeoutID = setTimeout(function() { + console.log('do after 1s delay.'); + }, 1000); + clearTimeout(timeoutID); + } + } ``` @@ -196,10 +201,13 @@ setInterval\(handler\[, delay\[, ...args\]\]\): number - 示例 ``` - - var intervalID = setInterval(function() { - console.log('do very 1s.'); - }, 1000); + export default { + setInterval() { + var intervalID = setInterval(function() { + console.log('do very 1s.'); + }, 1000); + } + } ``` @@ -237,12 +245,14 @@ clearInterval\(intervalID: number\): void - 示例 ``` - - var intervalID = setInterval(function() { - console.log('do very 1s.'); - }, 1000); - - clearInterval(intervalID); + export default { + clearInterval() { + var intervalID = setInterval(function() { + console.log('do very 1s.'); + }, 1000); + clearInterval(intervalID); + } + } ``` diff --git a/zh-cn/application-dev/js-reference/apis/js-apis-fileio.md b/zh-cn/application-dev/js-reference/apis/js-apis-fileio.md index b451a76cf11e81d56528ac08153a486b397025d2..f4e52b91d2019292d8210efd7682f1a7b592c30c 100644 --- a/zh-cn/application-dev/js-reference/apis/js-apis-fileio.md +++ b/zh-cn/application-dev/js-reference/apis/js-apis-fileio.md @@ -17,38 +17,13 @@ import fileio from '@ohos.fileio'; 使用该功能模块对文件/目录进行操作前,需要先获取其绝对路径,获取方式及其接口用法请参考:[Context模块的接口getOrCreateLocalDir](js-apis-Context.md)。 - -

类型

说明

+

说明

number

+

number

timeout定时器的ID。

+

timeout定时器的ID。

- - - - - - - - - - - - - -

目录类型

-

说明

-

相关接口

-

内部存储的缓存目录

-

可读写,随时可能清除,不保证持久性。一般用作下载临时目录或缓存目录。

-

getCacheDir

-

内部存储目录

-

随应用卸载删除。

-

getFilesDir

-
“文件/目录绝对路径”=“应用目录路径”+“文件/目录名” 通过上述接口获取到应用目录路径dir,文件名为“xxx.txt”,文件所在绝对路径为: ``` -let path = dir + "xxx.txt" +let path = dir + "/xxx.txt" ``` 文件描述符fd: diff --git a/zh-cn/application-dev/js-reference/apis/js-apis-sensor.md b/zh-cn/application-dev/js-reference/apis/js-apis-sensor.md index 54657bc27577b2cd75baaf20091a628bdc9b4efd..75d83aca39a4a0e442cbdbf19e57bc619f6c1802 100644 --- a/zh-cn/application-dev/js-reference/apis/js-apis-sensor.md +++ b/zh-cn/application-dev/js-reference/apis/js-apis-sensor.md @@ -1,7 +1,7 @@ # 传感器 >![](../../public_sys-resources/icon-note.gif) **说明:** ->从API Version 7 开始支持。 +>从API Version 8 开始支持。 ## 导入模块 diff --git a/zh-cn/application-dev/js-reference/apis/js-apis-update.md b/zh-cn/application-dev/js-reference/apis/js-apis-update.md deleted file mode 100644 index 65e4dd111d0bbf6d3dc0a80ec0010057644e4ce6..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/js-reference/apis/js-apis-update.md +++ /dev/null @@ -1,241 +0,0 @@ -# 系统恢复 - -- [导入模块](#zh-cn_topic_0000001163565327_section370mcpsimp) -- [权限列表](#zh-cn_topic_0000001163565327_section373mcpsimp) -- [方法](#zh-cn_topic_0000001163565327_section1319529172015) -- [verifyUpdatePackage\(upgradeFile: string, certsFile: string\): void](#zh-cn_topic_0000001163565327_section16874643181519) -- [rebootAndCleanUserData\(\): Promise](#zh-cn_topic_0000001163565327_section3242122116516) -- [rebootAndCleanUserData\(callback: AsyncCallback\): void](#zh-cn_topic_0000001163565327_section15242102114516) -- [applyNewVersion\(\): Promise](#zh-cn_topic_0000001163565327_section129661811195815) -- [applyNewVersion\(callback: AsyncCallback\): void](#zh-cn_topic_0000001163565327_section3381192816421) - -## 导入模块 - -``` -import update from '@ohos.update' -``` - -## 权限列表 - -无 - -## 方法 - -## verifyUpdatePackage\(upgradeFile: string, certsFile: string\): void - -升级前检查升级包是否有效。 - -**参数:** - - - - - - - - - - - - - - - - - - - -

参数名

-

类型

-

必填

-

说明

-

upgradeFile

-

string

-

-

待校验的升级包路径

-

certsFile

-

string

-

-

证书路径

-
- -**返回值:** - -无 - -**示例:** - -``` -var getVar = update.getUpdater(); -getVar.on("verifyProgress", function (callback){ - console.info('on verifyProgress ' + callback.percent); -}); -getVar.verifyUpdatePackage("XXX", "XXX"); -getVar.off("verifyProgress"); -``` - -## rebootAndCleanUserData\(\): Promise - -重启设备并清除用户分区数据。 - -**参数:** - -无 - -**返回值:** - - - - - - - - - - -

类型

-

说明

-

Promise<number>

-

Promise示例,用于异步获取结果。

-
- -**示例:** - -``` -var getVar = update.getUpdater(); -p = getVar.rebootAndCleanUserData(); -p.then(function (value) { - console.info("rebootAndCleanUserData promise success: " + value); -}).catch(function (err) { - console.info("rebootAndCleanUserData promise error: " + err.code); -}); -``` - -## rebootAndCleanUserData\(callback: AsyncCallback\): void - -重启设备并清除用户分区数据。 - -**参数:** - - - - - - - - - - - - - - -

参数名

-

类型

-

必填

-

说明

-

callback

-

Function

-

-

AsyncCallback<number>

-
- -**返回值:** - -无 - -**示例:** - -``` -var getVar = update.getUpdater(); -getVar.rebootAndCleanUserData(function (err, data) { - if (err.code == 0) { - console.info("rebootAndCleanUserData callback success:" + data) - } else { - console.info("rebootAndCleanUserData callback err:" + err.code) - } -}); -``` - -## applyNewVersion\(\): Promise - -重启设备后安装升级包。 - -**参数:** - -无 - -**返回值:** - - - - - - - - - - -

类型

-

说明

-

Promise<number>

-

Promise示例,用于异步获取结果。

-
- -**示例:** - -``` -var getVar = update.getUpdater(); -p.then(function (value) { - console.info("applyNewVersion promise success: " + value); -}).catch(function (err) { - console.info("applyNewVersion promise error: " + err.code); -}); -``` - -## applyNewVersion\(callback: AsyncCallback\): void - -重启设备后安装升级包。 - -**参数:** - - - - - - - - - - - - - - -

参数名

-

类型

-

必填

-

说明

-

callback

-

Function

-

-

AsyncCallback<number>

-
- -**返回值:** - -无 - -**示例:** - -``` -var getVar = update.getUpdater(); -getVar.applyNewVersion(function (err, data) { - if (err.code == 0) { - console.info("applyNewVersion callback success:" + data) - } else { - console.info("applyNewVersion callback err:" + err.code) - } -}); -``` - diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/000000-3.png b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/000000-5.png similarity index 100% rename from zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/000000-3.png rename to zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/000000-5.png diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001198530395.png b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/1-2.png similarity index 100% rename from zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001198530395.png rename to zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/1-2.png diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/1-1.gif b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/1-3.gif similarity index 100% rename from zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/1-1.gif rename to zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/1-3.gif diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/11-1.gif b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/11-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..7ca939d4de4d330dea962b991362b41ef0aacba9 Binary files /dev/null and b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/11-1.gif differ diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/12.gif b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/12.gif new file mode 100644 index 0000000000000000000000000000000000000000..561e823f7a9eb432e2aedbbf84637f8be40b0337 Binary files /dev/null and b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/12.gif differ diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/2-2.gif b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/2-4.gif similarity index 100% rename from zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/2-2.gif rename to zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/2-4.gif diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/44.gif b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/44.gif new file mode 100644 index 0000000000000000000000000000000000000000..483d53003cc3be451c2c2962d60256b293aee428 Binary files /dev/null and b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/44.gif differ diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/SVID_20210301_193525_1.gif b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/SVID_20210301_193525_1.gif deleted file mode 100644 index 9f4b3be2a876397f9d73f512e22d922fef20eff3..0000000000000000000000000000000000000000 Binary files a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/SVID_20210301_193525_1.gif and /dev/null differ diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001152773860.png b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/c3.png similarity index 100% rename from zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001152773860.png rename to zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/c3.png diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/slategray-4.png b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/slategray-6.png similarity index 100% rename from zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/slategray-4.png rename to zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/slategray-6.png diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001150368628.png b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001150368628.png deleted file mode 100644 index 80ea0c9b9a321e061224884976545e6a9fe04196..0000000000000000000000000000000000000000 Binary files a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001150368628.png and /dev/null differ diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001181458721.png b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001178875308.png similarity index 100% rename from zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001181458721.png rename to zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001178875308.png diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001135171488.png b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001179035242.png similarity index 100% rename from zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001135171488.png rename to zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001179035242.png diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001181449919.png b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001224354967.png similarity index 100% rename from zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001181449919.png rename to zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001224354967.png diff --git "a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/\346\215\225\350\216\267.png" "b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/\346\215\225\350\216\267.png" new file mode 100644 index 0000000000000000000000000000000000000000..2ed837e111c3ac1ba1eafb5b28da581ef4de5d22 Binary files /dev/null and "b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/\346\215\225\350\216\267.png" differ diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-appendix-types.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-appendix-types.md index d3bbd07fb3a78e8ce0570849c2719e1a73010151..7328c141b88f9c663459aaa9634d4e7c402ea67b 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-appendix-types.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-appendix-types.md @@ -118,7 +118,7 @@

#000000

+

blanchedalmond

@@ -993,7 +993,7 @@

#708090

+

snow

diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-button.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-button.md index 4eca5ccf03afc1e220a625687390efe9123c55c0..3a54e3a64126b6e99924089ef51d03048bde1419 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-button.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-button.md @@ -393,14 +393,14 @@ // xxx.js export default { data: { - progress: 5, + count: 5, downloadText: "Download" }, progress(e) { - this.progress += 10; - this.downloadText = this.progress + "%"; - this.$element('download-btn').setProgress({ progress: this.progress }); - if (this.progress >= 100) { + this.count+= 10; + this.downloadText = this.count+ "%"; + this.$element('download-btn').setProgress({ progress: this.count}); + if (this.count>= 100) { this.downloadText = "Done"; } } diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-chart.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-chart.md index 67c9c8e63a23fd878b0245f62454193e2488de20..60d22aeea225cfc661a2fe0af97bdd1b6e041bd2 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-chart.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-chart.md @@ -231,11 +231,11 @@

类型

默认值

+

默认值

必填

+

必填

描述

+

描述

number

0

+

0

+

轴的最小值。

+

轴的最小值。

说明:

仅线形图支持负数。

number

100

+

100

+

轴的最大值。

+

轴的最大值。

说明:

仅线形图支持负数。

number

10

+

10

+

轴显示的刻度数量。

+

轴显示的刻度数量。

说明:

仅支持1~20,且具体显示的效果与如下计算值有关(图的宽度所占的像素/(max-min))。

在柱状图中,每组数据显示的柱子数量与刻度数量一致,且柱子显示在刻度处。

@@ -283,22 +283,22 @@

boolean

false

+

false

+

是否显示轴。

+

是否显示轴。

color

<color>

#c0c0c0

+

#c0c0c0

+

轴颜色。

+

轴颜色。

方法

+ - - - - + + + + + + diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-common-events.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-common-events.md index 704c9f3b77df0241da2dd94d7f7734eebac14b23..10f52594e1d6290e65c522e7a08e5c5778933798 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-common-events.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-common-events.md @@ -388,7 +388,7 @@

方法

参数

+

参数

描述

append

+

append

{

+

{

serial: number, // 设置要更新的线形图数据下标

data: Array<number>, // 设置新增的数据

}

diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-image.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-image.md index 0c2e0d6189891f08cbe7fd4c13be53680ae53c19..2c6fc5216f99b44d18df2647567fa6a8382f1e1b 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-image.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-image.md @@ -202,7 +202,7 @@ ```
- + -
``` ``` diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-piece.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-piece.md index 5e597d4f8f420692b17ead24ea5389cd5da38703..fc9a08fe4a14c9653970b5ed28945881ec5fac83 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-piece.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-piece.md @@ -100,12 +100,22 @@ ``` -
- - +
+ +
``` +``` +/* xxx.css */ +.container { + width: 100%; + height: 100%; + align-items: center; + justify-content: center; +} +``` + ``` // xxx.js export default { @@ -119,5 +129,5 @@ export default { } ``` -![](figures/SVID_20210301_193525_1.gif) +![](figures/11-1.gif) diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-qrcode.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-qrcode.md index 5c33671af048ff6897278621e56950f1eec35fa6..2cc06af6065797af7377282a7854e0f95fdfdaf5 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-qrcode.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-basic-qrcode.md @@ -113,6 +113,71 @@ ## 示例 ``` - + +
+ + Type + + Color + + Background Color + +
``` +``` +/* xxx.css */ +.container { + width: 100%; + height: 100%; + flex-direction: column; + justify-content: center; + align-items: center; +} +.txt { + margin: 30px; + color: orangered; +} +select{ + margin-top: 40px; + margin-bottom: 40px; +} +``` + +``` +/* index.js */ +export default { + data: { + qr_type: 'rect', + qr_size: '300px', + qr_col: '#87ceeb', + col_list: ['#87ceeb','#fa8072','#da70d6','#80ff00ff','#00ff00ff'], + qr_bcol: '#f0ffff', + bcol_list: ['#f0ffff','#ffffe0','#d8bfd8'] + }, + settype(e) { + if (e.checked) { + this.qr_type = 'rect' + } else { + this.qr_type = 'circle' + } + }, + setvalue(e) { + this.qr_value = e.newValue + }, + setcol(e) { + this.qr_col = e.newValue + }, + setbcol(e) { + this.qr_bcol = e.newValue + } +} +``` + +![](figures/12.gif) + diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-canvas.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-canvas.md index e7924a562c6b3de89e51482b9f20bb405ff7b352..7a063a973f1d278383d2693f82285c96ece1d7b1 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-canvas.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-canvas.md @@ -26,38 +26,142 @@ 除支持[通用方法](js-components-common-methods.md)外,还支持如下方法: - - - - - - - - - - - - - - - -

名称

-

参数

-

描述

-

getContext

-

getContext ( type: '2d', attributes6+: { antialias: boolean } ) => CanvasRendering2dContext

-

获取canvas绘图上下文。调用方法如下两种6+

-

var ctx = canvas.getContext(contextType);

-

var ctx = canvas.getContext(contextType, contextAttributes);

-

其中contextType为必填项,当前支持"2d",contextAttributes为可选参数,当前仅支持配置是否开启抗锯齿功能,默认为关闭。

-

contextType对应的上下文对象如下:

-

"2d":返回值为2D绘制对象,该对象提供具体的2D绘制操作。详见CanvasRenderingContext2D对象章节。

-

不支持在onInit和onReady中进行调用。

-

toDataURL6+

-

string type, number encoderOptions

-

生成一个包含图片展示的URL。

-
  • type:可选参数,用于指定图像格式,默认格式为image/png。
  • encoderOptions:在指定图片格式为image/jpeg或image/webp的情况下,可以从0到1的区间内选择图片的质量。如果超出取值范围,将会使用默认值0.92。
-
+### getContext\(type: '2d', options?: ContextAttrOptions\) + +getContext \(type: '2d', options?: ContextAttrOptions\): CanvasRendering2dContext + +获取canvas绘图上下文。不支持在onInit和onReady中进行调用。 + +- 参数 + + + + + + + + + + + + + + + + + + + +

参数名

+

参数类型

+

必填

+

描述

+

type

+

string

+

+

可选值为'2d',返回值为2D绘制对象,该对象提供具体的2D绘制操作。

+

options6+

+

ContextAttrOptions

+

+

具体表现为当前仅支持配置是否开启抗锯齿功能,默认为关闭。

+
+ + **表 1** ContextAttrOptions + + + + + + + + + + + + +

参数名

+

类型

+

说明

+

antialias

+

boolean

+

是否开启抗锯齿功能,默认为false。

+
+ +- 返回值 + + + + + + + + + + +

类型

+

说明

+

CanvasRenderingContext2D

+

用于在画布组件上绘制矩形、文本、图片等

+
+ + +### toDataURL6+ + +toDataURL\(type?: string, quality?: number\): string + +生成一个包含图片展示的URL。 + +- 参数 + + + + + + + + + + + + + + + + + + + +

参数名

+

参数类型

+

必填

+

描述

+

type

+

string

+

+

可选参数,用于指定图像格式,默认格式为image/png。

+

quality

+

number

+

+

在指定图片格式为image/jpeg或image/webp的情况下,可以从0到1的区间内选择图片的质量。如果超出取值范围,将会使用默认值0.92。

+
+ +- 返回值 + + + + + + + + + + +

类型

+

说明

+

string

+

图像的URL地址。

+
+ ## 示例 diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-canvasrenderingcontext2d.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-canvasrenderingcontext2d.md index 90ef4151b83eca22df6e39043738e46b8dbec664..ab70e8675217afd2664686023193df33b40d4369 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-canvasrenderingcontext2d.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-canvasrenderingcontext2d.md @@ -513,7 +513,7 @@ ctx.fillRect(30, 30, 100, 100); ``` var img = new Image(); -img.src = 'common/image/huawei.jpg'; +img.src = 'common/image/example.jpg'; img.onload = function() { ctx.imageSmoothingEnabled = false; ctx.drawImage(img, 0, 0, 400, 200); diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-image.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-image.md index 57fcaecc1c7f0050c280f4df30dd395d359be0c4..283448a511b235f9a1437532d847135f5ac2f047 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-image.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-image.md @@ -80,7 +80,7 @@ ``` var ctx = this.$element('drawImage').getContext('2d'); var img = new Image(); -img.src = 'common/images/huawei.jpg'; +img.src = 'common/images/example.jpg'; img.onload = function() { console.log('Image load success'); ctx.drawImage(img, 0, 0, 360, 250); @@ -90,5 +90,5 @@ img.onerror = function() { }; ``` -![](figures/zh-cn_image_0000001198530395.png) +![](figures/1-2.png) diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-offscreencanvas.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-offscreencanvas.md index 0ea82bfafffc7fab634515abb98bd9c1d4ef0c00..4839d31b10459cfdf5299d80619ebec09b42fcfe 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-offscreencanvas.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-canvas-offscreencanvas.md @@ -35,43 +35,145 @@ ## 方法 - - - - - - - - - - - - - - - - - - - -

名称

-

参数

-

描述

-

getContext

-

contextId: "2d", options?: CanvasRenderingContext2DSettings

-

调用方法如下两种:

-

var ctx = canvas.getContext(contextId);

-

var ctx = canvas.getContext(contextId, options);

-

其中contextId为必填项,当前仅支持"2d",options为可选项,暂时不支持。

-

获取offscreen canvas绘图上下文,参数仅支持“2d”,返回值为2D绘制对象,该对象提供具体的2D绘制操作。详见OffscreenCanvasRenderingContext2D对象章节。

-

toDataURL

-

type?: string, quality?: number

-

生成一个包含图片展示的URL。

-
  • type:可选参数,用于指定图像格式,默认格式为image/png。
  • quality:在指定图片格式为image/jpeg或image/webp的情况下,可以从0到1的区间内选择图片的质量。如果超出取值范围,将会使用默认值0.92。
-

transferToImageBitmap

-

-

从OffscreenCanvas最近渲染的图像创建一个 ImageBitmap 对象

-
+### getContext + +getContext\(type: string, options?: CanvasRenderingContext2DSettings\): OffscreenCanvasRenderingContext2D + +获取offscreen canvas绘图上下文,返回值为2D绘制对象。 + +- 参数 + + + + + + + + + + + + + + + + + + + +

参数名

+

参数类型

+

必填

+

描述

+

contextId

+

string

+

+

仅支持"2d"。

+

options

+

CanvasRenderingContext2DSettings

+

+

用于在离屏画布上进行绘制矩形、文本、图片等

+
+ +- 返回值 + + + + + + + + + + +

类型

+

说明

+

OffscreenCanvasRenderingContext2D

+

用于在画布组件上绘制矩形、文本、图片等

+
+ + +### toDataURL + +toDataURL\(type?: string, quality?:number\): + +生成一个包含图片展示的URL。 + +- 参数 + + + + + + + + + + + + + + + + + + + +

参数名

+

参数类型

+

必填

+

描述

+

type

+

string

+

+

可选参数,用于指定图像格式,默认格式为image/png。

+

quality

+

number

+

+

在指定图片格式为image/jpeg或image/webp的情况下,可以从0到1的区间内选择图片的质量。如果超出取值范围,将会使用默认值0.92。

+
+ +- 返回值 + + + + + + + + + + +

类型

+

说明

+

string

+

图像的URL地址。

+
+ + +### transferToImageBitmap + +transferToImageBitmap\(\): ImageBitmap + +在离屏画布最近渲染的图像上创建一个ImageBitmap对象。 + +- 返回值 + + + + + + + + + + +

类型

+

说明

+

ImageBitmap

+

存储离屏画布上渲染的像素数据。

+
+ ## 示例 diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-common-attributes.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-common-attributes.md index 3f5927d0d93f09e1d418648f9790d67121db753a..3d73f5c0caaa18e1b307e1e0810da1f44cba3e15 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-common-attributes.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-common-attributes.md @@ -83,7 +83,21 @@

当前组件是否可以获取焦点。 当focusable设置为true时,组件可以响应焦点事件和按键事件。当组件额外设置了按键事件或者点击事件时,框架会设置该属性为true。

data-*6+

+

data

+

string

+

-

+

+

给当前组件设置data属性,进行相应的数据存储和读取。JS文件中:

+
  • 在事件回调中使用 e.target.attr.data 读取数据,e为事件回调函数入参。
  • 使用$element或者$refs获取DOM元素后,通过attr.data 进行访问。
+
说明:

从API Version 6 开始,建议使用data-*。

+
+

data-*6+

string

-**表 6** DragEvent对象属性列表\(继承BaseEvent\)7+\(Rich\) +**表 6** DragEvent对象属性列表\(继承BaseEvent\)7+ - @@ -143,7 +143,7 @@ on\(type: 'change', callback: Callback\): void - diff --git a/zh-cn/application-dev/media/audio-playback.md b/zh-cn/application-dev/media/audio-playback.md index d6a6b72cee39a7569cd0a5efe6ef532ee6e7412e..2afa827c57fc2cc9703c7c8c3ac8ffb6ad54b26d 100644 --- a/zh-cn/application-dev/media/audio-playback.md +++ b/zh-cn/application-dev/media/audio-playback.md @@ -34,7 +34,7 @@ | src:string | 音频播放的媒体URI。 | | state:AudioState | 播放的状态属性。 | | currentTime:number | 音频的当前播放位置。 | -| duration:number | 音频播放的时长。 | +| duration:number | 音频播放的时长(当数据源不支持改变播放位置时返回-1, 比如实时流媒体场景)。 | | loop:boolean | 音频的循环播放属性。 | | on('play', function callback) | 订阅音频播放开始事件。 | | on('pause', function callback) | 订阅音频播放暂停事件。 | diff --git a/zh-cn/application-dev/quick-start/installing-openharmony-app.md b/zh-cn/application-dev/quick-start/installing-openharmony-app.md index d7ece1e0766c046ab77b76938eef3153fcedc19f..175f7261e6553077222dc1ae363dedd210b279fc 100644 --- a/zh-cn/application-dev/quick-start/installing-openharmony-app.md +++ b/zh-cn/application-dev/quick-start/installing-openharmony-app.md @@ -37,5 +37,5 @@ hdc工具本身需要手动从开源仓中获取。然后使用工具将编译 ``` -完整的hdc工具使用指导及命令格式请参见开源仓”docs/zh-cn/device-dev/subsystems/hdc使用指导.md“。 +完整的hdc工具使用指导及命令格式请参见[hdc_std使用指导](../../device-dev/subsystems/subsys-toolchain-hdc-guide.md)。 diff --git a/zh-cn/contribute/template/js-template.md b/zh-cn/contribute/template/js-template.md index c86a6f192f1519771d566ab7fdbceef9630654ec..950e5b047546046e3ae3ff83fbd8b344b287b3b4 100644 --- a/zh-cn/contribute/template/js-template.md +++ b/zh-cn/contribute/template/js-template.md @@ -1,318 +1,232 @@ -# API模板 - -- [完成写作后删除](#完成写作后删除) - - [版本说明](#版本说明) -- [导入模块](#导入模块) -- [权限](#权限) -- [属性](#属性) -- [方法名称](#方法名称) -- [枚举名称](#枚举名称) -- [类名称](#类名称) - - [类属性](#类属性) - - [类方法名称](#类方法名称) -- [以k-v表示的interface](#以k-v表示的interface) -- [类似class的interface](#类似class的interface) - - [interface属性](#interface属性) - - [interface方法名称](#interface方法名称) -- [type名称](#type名称) -- [AbilityInfo](#abilityinfo) - -## 完成写作后删除 - -1. 每个章节(Topic)对应一个d.ts文件。 - -2. 章节(Topic)名称为接口提供的功能,优先选择动宾短语。如:打印日志 - -3. 模板中的说明和示例,均使用斜体和蓝色文字以做区分, **正式文档使用正常黑色字体**。 - -4. 参数类型的写法: - - *Object、Function、Array等引用数据类型统一大写首字母;* - - *string、number、boolean等基本数据类型统一小写首字母;* - - *<color>、<percentage>、<length>等尖括号内的枚举类型统一小写首字母。* - - -### 版本说明 - -- 新增内容 - - 新增整个组件/接口 - 在组件或API的概述下方,点击 **插入**,选择 **说明**“从 API Version 7 开始支持。” - - > **说明:** - > 从 API Version 7 开始支持。 - - 新增小部分内容 - 在新增部分后面添加“7+”,并使用“sup”标签设置为上标,示例:7+。 - - 1. 新增属性、样式等,在属性名后加7+,示例: - | 名称 | 类型 | 默认值 | 必填 | 描述 | - | -------- | -------- | -------- | -------- | -------- | - | selected7+ | string | - | 否 | 指定当前列表中被选中激活的项,可选值为list-item的section属性值。 | - 2. 新增属性值,在属性值后加7+,示例: - | 名称 | 类型 | 默认值 | 必填 | 描述 | - | -------- | -------- | -------- | -------- | -------- | - | type | string | horizontal | 否 | 设置进度条的类型,该属性不支持动态修改,可选值为:
- horizontal:线性进度条。
- arc:弧形进度条。
- eclipse7+:圆形进度条,展现类似月圆月缺的进度展示效果。 | - 3. 新增部分描述,在增加的部分描述后加7+,示例: - 仅父容器为<div>、<list-item>、<tabs>时生效。 - -- 废弃内容 - 不要直接在文档上删去,在废弃内容后面加括号标注deprecated,并说明建议使用的替代方式,加上对应的链接。 - - 并且按上述方式标注版本号。 - - | 名称 | 类型 | 默认值 | 必填 | 描述 | - | -------- | -------- | -------- | -------- | -------- | - | backgroundColor(deprecated) 7+ | <color> | \#ff6384 | 否 | 设置线或柱的颜色( 不推荐使用,建议使用 [AbilityInfo](#abilityinfo))。 | - - -> **说明:** -> 从API Version x 开始支持。 - +# API接口说明模板 + +> *写作说明* +> +> 0.1 - 所有的写作说明,在完成写作后,都要删除。 +> +> 0.2 - 上传路径:docs/zh-cn/application-dev/js-reference/apis,图片放到对应的figures文件夹中。上传后可通过提issue的方式,触发翻译。 +> +> 0.3 - 一个d.ts文件对应一个js api接口文档。**文件名称:js-apis-模块名.md**。示例: +> +> ​ 媒体@ohos.multimedia.audio,文件命名为:js-apis-audio.md +> +> ​ 电话@ohos.telephony.sms,文件命名为:js-apis-sms.md +> +> 0.4 - 新增文件,需要修改对应的Readme,即docs/zh-cn/application-dev/js-reference/apis/Readme-CN.md。 +> +> 0.5 - **文档标题**:使用中文短语概括本模块功能。但如果部分概念使用英文更便于开发者理解,不必强求,比方说,Ability、SIM卡等概念可以直接使用。 +> +> 0.6 - 文档标题为一级标题;namespace下的属性字段、function、class、interface、enum、type为二级标题;class下的属性、function为三级标题。 +> +> 0.7 - **对已有模块的新增接口标记起始版本:使用标签,标记对应的版本号。** +> +> ​ 示例:API 6已有的模块,在API 7新增了一个属性字段,则在属性后加标记,即newAttribute7+。 +> +> ​ 如果新增了一个方法,则在方法标题后增加标记,即 sim.getSimIccId7+,interface、class、枚举等同理。 +> +> 0.8 - **废弃内容**:不能直接在文档上删去,在废弃内容后面加上标标注deprecated,并使用“>”引用语法建议使用的替代方式,加上对应的链接。 +> +> ​ 示例:abandonmentMethod(deprecated) +> +> > 从API Version 7 开始废弃,建议使用[newMethod](#newMethod)替代。 +> +> 下面进入具体每个API的写作。 + +*** +> *写作说明* +> +> 1.1 - 使用markdown的引用语法“>”对接口的起始版本进行说明。 +> +> 1.2 - 一个模块只会有一个起始版本。 +> +> 1.3 - 如果是第一个版本,只写第一句“从 API Version **x** 开始支持。”,x修改为对应的版本号,比方说API Version 7 +> +> 1.4 - 如果涉及新版本的接口,需要在新增接口中进行说明。在版本说明这里,要加上第二句,不必做任何改动。 + +> **说明** +> +> 本模块首批接口从API version 8开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 + +模块说明。此处对该模块提供的功能、使用场景和使用建议进行简要描述。 ## 导入模块 - -必选,描述需导入的模块。如果有,则用import语句描述。如无,写“无需导入”。例如: - -```undefined -import app from '@system.app'; +> *写作说明* +> +> 2.1 - 根据实际情况填写导入模块。采用代码段的样式,给出import语句。 +> +> 2.2 - 如果没有导入模块,将“导入模块”修改为“使用说明”。 +> +> ​ 使用说明案例: +> +> ​ 在使用AbilityContext的功能前,需要通过[getContext()](链接到对应的接口说明文件中.md)先获取Context对象。 +> ```js +> import ability_featureAbility from '@ohos.ability.featureAbility'; +> var context = ability_featureAbility.getContext(); +> ``` + +```js +import call from '@ohos.telephony.call'; ``` - -## 权限 - -必选,表示运行该模块所需的权限。如无需权限,写“无”。 - -ohos.permission.INTERNET - - ## 属性 -可选,如果没有属性可删除此section。 - -| 名称 | 参数类型 | 可读 | 可写 | 说明 | -| -------- | -------- | -------- | -------- | -------- | -| 示例:deviceType | string | 是 | 否 | 设备类型。 | - - -## 方法名称 - -> **说明:** -> 方法名称的前缀为导入类的名称。如果有多个方法,则分多个section描写。 -> -> 示例:storage.get - - -此处给出该方法的具体调用形式,为:方法名称(参数1名称:参数1类型,参数2名称:参数2类型,……):返回值类型,与d.ts文件中的方法描述保持一致。 - - -示例:show(url:string, type:string):Promise<void> - - -如有使用限制,在此处进行详细描述说明。 - - -然后,按照参数、返回值、示例对API进行详细描述。格式如下: - - -- 参数: - 可选,若无参数,不写此项,并在方法的调用描述中设置参数为空。 - - 如果参数类型为一个自定义的引用数据类型,则在该章节的最后进行说明,并建立对应的超链接,如示例2所示 。 - | 参数名 | 类型 | 必填 | 说明 | - | -------- | -------- | -------- | -------- | - | * 示例1:*visible | boolean | 否 | 是否启动保活,默认值false。 如有默认值、合法值需要进行说明。 | - | * 示例2:*connection | [AbilityInfo](#abilityinfo) | 是 | 需要关闭的连接。 | - -- 返回值: - 可选,若无返回值,不写此项,并在方法的调用描述中添加返回值为void。 - - 若返回值无参数名,可删除第一列。 - - 若返回值类型为一个自定义的引用数据类型,则在该章节的最后进行说明,并建立对应的超链接,如示例2所示 。 - | 参数名 | 类型 | 说明 | - | -------- | -------- | -------- | - | 示例1:appName | string | 表示应用的名称。 | - | 示例2:versionName | [AbilityInfo](#abilityinfo) | 表示应用的版本名称。 | - -- 示例: - ```undefined - var info = app.getInfo(); - console.log(JSON.stringify(info)); - ``` - - -## 枚举名称 - ->**说明:** -> 如果有多个枚举,则分多个section描写。 - - -必选,在此给出该枚举类型的简要描述。如:用于表示电池充电状态。 - - -| 名称 | 默认值 | 说明 | -| -------- | -------- | -------- | -| 示例:NONE | 1 | 表示电池充电状态未知。 | - - -## 类名称 - -> **说明:** -> 如果有多个类,则分多个section描写。 - - -在此处给出类的简要描述。需要说明在使用该类的方法前,通过哪个方法构造实例。 - - -### 类属性 - ->**说明:** -> “类属性”是对不同属性的标识说明,在文档编写时直接以“属性”作为Section标题。 - -可选,如果该类里没有属性可删除此subsection。 - -| 名称 | 参数类型 | 可读 | 可写 | 说明 | -| -------- | -------- | -------- | -------- | -------- | -| 示例:src | string | 是 | 是 | 播放的音频媒体uri。 | - - -### 类方法名称 - -> **说明:** -> 如果有多个方法,则分多个subsection描写。 -> -> 示例:setPasteData - - -此处给出该方法的具体调用形式,为:(如果是静态方法需说明) 方法名称(参数1名称:参数1类型,参数2名称:参数2类型,……):返回值类型,与d.ts文件中的方法描述保持一致 - - -示例:setPasteData(pasteData:PasteData): Promise<void> - - -在此处给出该方法的简要描述。 - - -如有使用限制,在此处进行详细描述说明。 - - -然后,按照参数、返回值、示例对API进行详细描述。格式如下: - - -- 参数: - 可选,如无参数,不写此项,并在方法的调用描述中设置参数为空。。 - - 如果参数类型为一个自定义的引用数据类型,则在该章节的最后进行说明,并建立对应的超链接,如示例2所示 。 - | 参数名 | 类型 | 必填 | 说明 | - | -------- | -------- | -------- | -------- | - | 示例1:visible | boolean | 否 | 是否启动保活,默认值false。 如有默认值、合法值需要进行说明。 | - | 示例2:connection | [AbilityInfo](#abilityinfo) | 是 | 需要关闭的连接。 | - -- 返回值: - 可选,若无返回值,不写此项,并在方法的调用描述中添加返回值为void。 - - 若返回值无参数名,可删除第一列。 - - 若返回值类型为一个自定义的引用数据类型,则在该章节的最后进行说明,并建立对应的超链接,如示例2所示 。 - | 参数名 | 类型 | 说明 | - | -------- | -------- | -------- | - | 示例1:appName | string | 表示应用的名称。 | - | 示例2:versionName | [AbilityInfo](#abilityinfo) | 表示应用的版本名称。 | - -- 示例: - ```undefined - var info = app.getInfo(); - console.log(JSON.stringify(info)); - ``` - - -## 以k-v表示的interface - -> **说明:** -> 如果有多个以k-v表示的interface,则分多个section描写。 -> -> 示例:AbilityInfo - - -在此处给出interface的简要描述。 - - -| 名称 | 参数类型 | 必填 | 说明 | -| -------- | -------- | -------- | -------- | -| 示例:url | string | 否 | 拉起FA时,指定打开的页面的url。默认直接打开首页。 | - - -## 类似class的interface - -> **说明:** -> 如果有多个类似class的interface,则分多个section描写。 -> -> 示例:AbilityInfo - - -在此处给出interface的简要描述。 - - -### interface属性 - -> **说明:** -> “interface属性”是对不同属性的标识说明,在文档编写时直接以“属性”作为Section标题。 - -可选,如果该类里没有属性可删除此subsection。 +> *写作说明* +> +> 4.1 - 可选,如果没有属性可删除此二级标题。 +> +> 4.2 - 类型如果为自定义类型,需要建立链接到对应的interface或enum中。 +> +> 4.3 - 对于可读属性:如果取值为有特殊含义的有限值,需要进行枚举。 +> +> 4.4 - 对于可写属性:如果仅支持固定字段,需要进行说明。 + +| 名称 | 类型 | 可读 | 可写 | 说明 | +| ---------------- | ----------------------------------------- | ---- | ---- | ------------------------------------------ | +| pluggedType | [BatteryPluggedType](#BatteryPluggedType) | 是 | 否 | 表示当前设备连接的充电器类型。 | +| isBatteryPresent | boolean | 是 | 否 | 表示当前设备是否支持电池或者电池是否在位。 | + +## 枚举 + +> *写作说明* +> +> 5.1 - 可选,如果没有可删除。如果有多个枚举,请分多个二级内容描述,并使用“##”自行新建二级标题。 +> +> 5.2 - 二级标题名为实际枚举名,比方说 BatteryHealthState 。 + +在此处给出该枚举类型的简要描述。如:表示连接的充电器类型的枚举。 + +| 名称 | 值 | 说明 | +| ---- | ---- | -------------------------- | +| NONE | 1 | 表示连接的充电器类型未知。 | + +## 方法 + +> *写作说明* +> +> 6.1 - 可选,如果没有可删除。如果有多个方法,请分多个二级内容描述,并使用“##”自行新建二级标题。 +> +> 6.2 - 二级标题名为方法名,采用导入类.方法名,如果是订阅方法,需要在方法名加上对应的订阅事件。 +> +> ​ 示例: sim.getSimIccId +> +> ​ 订阅方法:sim.on('exampleEvent') +> +> 6.3 - **方法具体调用形式**:和d.ts保持一致,需要包括参数类型、参数名、返回值类型。 +> +> ​ 示例:getNetworkState(slotId: number, callback: AsyncCallback\): void +> +> ​ 注意:尖括号<>可能会被识别为标签,导致界面显示失效,可增加一个\,以保证界面正常显示,如“\<>”或使用转义字符< > 。 +> +> 6.4.1 - **方法描述**:对方法实现的功能进行描述,包括其使用的前提条件(*如:在xx方法调用后才能调用、需要确保网络已连接……*)、使用之后的影响(*如:调用该接口后再进行xx将不起效*)、权限限制等。 +> +> 6.4.2 - **异步方法描述**:存在大量异步方法,其返回方式需要在方法描述处进行说明。通过注册回调函数获取?还是通过Promise获取? +> +> 6.4.3 - **表格内换行**:markdown语法中,换行采用特殊标记
+ +在此处给出方法的具体调用形式:(如果是静态方法需说明) 方法名称(参数1名称:参数1类型,参数2名称:参数2类型,……):返回值类型 + +在此处给出方法描述。说明请参考6.4.1和6.4.2。 + +需要权限:ohos.permission.XXX(如不涉及可删除,如果是系统权限要说明) + +**参数:** (可选,如不涉及可删除) + +| 参数名 | 类型 | 必填 | 说明 | +| ------------ | --------------------------------------------- | ---- | ------------------------------------------------------------ | +| parameterOne | number \| string \| [CustomType](#CustomType) | 是 | 参数描述。给出取值范围、建议值。如果有固定格式,需要给出格式样例,尤其是URI。
自定义类型需要进行建链说明。 | +| callback | Callback\> | 否 | 参数描述。可选参数需要说明不填写该参数的后果。
如:不填该参数则取消该type对应的所有回调。 | + +**返回值**:(可选,如不涉及可删除) + +| 类型 | 说明 | +| ------------------------------------------ | -------------------------------------------- | +| string | 返回值描述。取到返回值之后,可以用来做什么。 | +| Promise\> | 返回值描述。通过Promise获取了什么。 | + +**示例:** + +```js +// 必选项。 +// 所有的示例代码需要进行自检。 +// 不能出现缺符号、变量前后不一致等低错。 +// 所有的使用到的变量要进行声明。 +// 不允许直接写参数名,必须是可使用、易替代的实际用例。 +// 如果非用户自定义填写,需通过注释进行说明。 +// 示例:var result = xxx.createExample(parameterOne); // parameterOne由扫描自动获取 +``` -| 名称 | 参数类型 | 可读 | 可写 | 说明 | -| -------- | -------- | -------- | -------- | -------- | -| 示例:src | string | 是 | 是 | 播放的音频媒体uri。 | +## Class/Interface +> *写作说明* +> +> 7.1 - 可选,如果没有可删除。如果有多个,请分多个二级内容描述,并使用“##”自行新建二级标题。 +> +> 7.2 - 二级标题名为class、interface的名称。 +> +> 7.3 - 如果该API中,既有属性,又有方法,需要先进行属性的写作,并使用“###”三级标题。 +> +> ​ 如果该API中,只有属性,那么不需要新建三级标题,直接使用表格陈列属性,具体示例参考[CustomType](#CustomType)。 -### interface方法名称 +类描述/interface描述。如果有使用限制,需要在这个地方说明。比方说,是否有前提条件,是否需要通过什么方法先构造一个实例。 -> **说明:** -> 如果该interface有多个方法,则分多个subsection描写。 +### 属性 +> *写作说明* +> +> 除标题使用三级标题外,其余要求同[属性](#属性)。 -在此处给出API的简要描述。需说明是什么方法(包括:构造方法、静态方法、实例方法),如有使用限制,一并在此说明。 +### Class/Interface中的方法 +> *写作说明* +> +> 7.4 - 标题名为方法名,使用三级标题,**没有前缀**。如果是订阅方法,需要在方法名加上对应的订阅事件。 +> +> ​ 示例: getSimIccId +> +> ​ 订阅方法:on('exampleEvent') +> +> 其余要求请参考[方法](#方法)中的说明。 -示例:构造方法,用于xxxxxx。 +在此处给出方法的具体调用形式。说明请参考6.3。 +在此处给出方法描述。说明请参考6.4.1和6.4.2。 -然后,按照参数、返回值、示例对API进行详细描述。格式如下: +需要权限:ohos.permission.XXX(如不涉及可删除,如果是系统权限要说明) +**参数:** (可选,如不涉及可删除) -- 参数: - | 参数名 | 类型 | 必填 | 说明 | - | -------- | -------- | -------- | -------- | - | 示例1:visible | boolean | 否 | 是否启动保活,默认值false。 如有默认值、合法值需要进行说明。 | - | 示例2:connection | [AbilityInfo](#abilityinfo) | 是 | 需要关闭的连接。 | +| 参数名 | 类型 | 必填 | 说明 | +| ------------ | --------------------------------------------- | ---- | ------------------------------------------------------------ | +| parameterOne | number \| string \| [CustomType](#CustomType) | 是 | 参数描述。给出取值范围、建议值。如果有固定格式,需要给出格式样例,尤其是URI。
自定义类型需要进行建链说明。 | +| callback | Callback\> | 否 | 参数描述。可选参数需要说明不填写该参数的后果。
如:不填该参数则取消该type对应的所有回调。 | -- 返回值: - | 参数名 | 类型 | 说明 | - | -------- | -------- | -------- | - | 示例1:appName | string | 表示应用的名称。 | - | 示例2:versionName | [AbilityInfo](#abilityinfo)| 表示应用的版本名称。 | +**返回值**:(可选,如不涉及可删除) -- 示例: - ```undefined - var info = app.getInfo(); - console.log(JSON.stringify(info)); - ``` +| 类型 | 说明 | +| ------------------------------------------ | -------------------------------------------- | +| string | 返回值描述。取到返回值之后,可以用来做什么。 | +| Promise\> | 返回值描述。通过Promise获取了什么。 | +**示例:** -## type名称 +```js +// 必选项。 +// 所有的示例代码需要进行自检。 +// 不能出现缺符号、变量前后不一致等低错。 +// 所有的使用到的变量要进行声明。 +// 不允许直接写参数名,必须是可使用、易替代的实际用例。 +// 如果非用户自定义填写,需通过注释进行说明。 +// 示例:var result = xxx.createExample(parameterOne); // parameterOne由扫描自动获取 +``` -> **说明:** -> 如果有多个type,则分多个section描写。 +## CustomType +仅有k-v键值对的自定义类型示例。 -| 名称 | 类型 | 描述 | -| -------- | -------- | -------- | -| | | | -| | | | +| 名称 | 类型 | 可读 |可写| 说明 | +| ------------ | ---- | ---- | ---- | ---- | +| parameterUrl | string | 是 | 是 |媒体输出URI。支持:
1. 协议类型为“internal”的相对路径,示例如下:
临时目录:internal://cache/test.mp4

2. 文件的绝对路径,示例如下:
file:///data/data/ohos.xxx.xxx/files/test.mp4| +| parameterOne | [CustomEnum](#枚举) | 是 | 是 |属性描述,要求与参数说明类似。| -## AbilityInfo -| 参数名 | 类型 | 必填 | 说明 | -| -------- | -------- | -------- | -------- | -| bundleName | string | 是 | Ability的包名称,需要与PA端匹配,区分大小写。 | -| abilityName | string | 是 | Ability名称,需要与PA端匹配,区分大小写。 | -| entities | Array<string> | 否 | 希望被调起的FA所归属的实体列表,如果不填,默认查找所有实体列表。需配合action使用。 预定义类型待补充。 | diff --git a/zh-cn/device-dev/Readme-CN.md b/zh-cn/device-dev/Readme-CN.md index 802a3928dcfbed62ccfd5c39d14a2c316e379069..992ec8d7ec53e5c9da385a1d46503b9d5992be80 100644 --- a/zh-cn/device-dev/Readme-CN.md +++ b/zh-cn/device-dev/Readme-CN.md @@ -76,7 +76,7 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按
- - -

属性

diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-container-badge.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-container-badge.md index 3b6adb4e57e3366fb7beb7f821464892320d7392..ad2e7f024dd439cd6f8e01db896a56094521cc10 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-container-badge.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-container-badge.md @@ -193,10 +193,10 @@
- huawei + example - huawei + example
``` @@ -234,5 +234,5 @@ export default { } ``` -![](figures/zh-cn_image_0000001150368628.png) +![](figures/捕获.png) diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-container-list-item.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-container-list-item.md index cb3dfc1504453711ec30e0127073b950264f43b9..8a46fbcb110f025cbfe80a0ddf6876e98a82d6b5 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-container-list-item.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-container-list-item.md @@ -11,7 +11,7 @@ ## 子组件 -支持。 +支持单个子组件。 ## 属性 diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-custom-slot.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-custom-slot.md index c06026e572ade470cbb8c6a3439a89f61c7e9adf..d4310dd129fdec030edb69675c13398376195e1e 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-custom-slot.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-custom-slot.md @@ -48,7 +48,7 @@
插入第二个插槽中 - 插入第一个插槽中 + 插入第一个插槽中
``` diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-grid-col.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-grid-col.md index 684c959120c3ae752d4680b181d3b79b798a64a8..11f862e5d95e8ed2492fdea16d6af5597646dfa8 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-grid-col.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-grid-col.md @@ -302,3 +302,5 @@ export default { } ``` +![](figures/44.gif) + diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-grid-container.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-grid-container.md index 0676cf588622003beecf62a9e8a4763e0bed0bae..cf008a31ce856b34085dfe85ff47b1c8a94cadfb 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-grid-container.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-grid-container.md @@ -1,6 +1,6 @@ # grid-container -栅格布局容器根节点,使用grid-row与gird-col进行栅格布局。 +栅格布局容器根节点,使用grid-row与grid-col进行栅格布局。 ## 权限列表 diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-media-video.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-media-video.md index ad219bdef770ba35888857396cea90db6959288b..932a679a158baa5a183a34fb125d4fc127f84120 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-media-video.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-media-video.md @@ -205,31 +205,31 @@ - - - - - - - - diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-svg-animate.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-svg-animate.md index 8cfd911e7f6ecfa1c6e23edf4a1837a1703a5414..687a36b170036531020910428e5fb7016ad0bf96 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-svg-animate.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-svg-animate.md @@ -221,7 +221,7 @@ ``` -![](figures/1-1.gif) +![](figures/1-3.gif) ``` diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-svg-animatemotion.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-svg-animatemotion.md index 2f134e3079d957584b9eabf9b5b04eb50a3dfdfd..d5d209d73694846ae56733bd558a9d1bcd479580 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-svg-animatemotion.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-components-svg-animatemotion.md @@ -90,5 +90,5 @@ ``` -![](figures/2-2.gif) +![](figures/2-4.gif) diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-framework-js-tag.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-framework-js-tag.md index 834f0a58f7231bb117b53e3c8f425684825cbc0e..822b3dabfe28418dc7d4b5ceed84887f106812da 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-framework-js-tag.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-framework-js-tag.md @@ -141,7 +141,7 @@ window用于定义与显示窗口相关的配置。对于屏幕适配问题, ``` { "app": { - "bundleName": "com.huawei.player", + "bundleName": "com.example.player", "version": { "code": 1, "name": "1.0" diff --git a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-offscreencanvasrenderingcontext2d.md b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-offscreencanvasrenderingcontext2d.md index a8a40172a2ff3657dcda34c85daf4ab41b7d1f94..6c30391ab3b7e1c35591a641fdc6c00c65f37d43 100644 --- a/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-offscreencanvasrenderingcontext2d.md +++ b/zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/js-offscreencanvasrenderingcontext2d.md @@ -72,139 +72,238 @@ var bitmap = offscreen.transferToImageBitmap(); ctx.transferFromImageBitmap(bitmap); ``` -![](figures/zh-cn_image_0000001152773860.png) +![](figures/c3.png) ## 方法 除支持与CanvasRenderingContext2D对象相同的方法外,还支持如下方法: - -

名称

参数

+

参数

描述

+

描述

start

-

+

-

请求播放视频。

+

请求播放视频。

pause

-

+

-

请求暂停播放视频。

+

请求暂停播放视频。

setCurrentTime

{ currenttime: value }

+

{ currenttime: value }

指定视频播放的进度位置,单位为s。

+

指定视频播放的进度位置,单位为s。

- - - - - - - - - - - - - - - - - -

名称

-

参数

-

描述

-

isPointInPath

-

-

path?: Path2D, x: number, y: number

-

判断指定点是否在路径的区域内。

-

path:可选对象,指定用来判断的路径。若没有设置,则使用当前路径

-

x:待判断点的x轴坐标

-

y:待判断点的y轴坐标

-

isPointInStroke

-

path?: Path2D, x: number, y: number

-

判断指定点是否在路径的边缘线上。

-

path:可选对象,指定用来判断的路径。若没有设置,则使用当前路径

-

x:待判断点的x轴坐标

-

y:待判断点的y轴坐标

-

resetTransform

-

-

将当前变换重置为单位矩阵。

-
- -- isPointInPath示例 - -![](figures/zh-cn_image_0000001181449919.png) - -``` - -
- In path:{{textValue}} -
- -``` +### isPointInPath + +isPointInPath\(path?: Path2D, x: number, y: number\): boolean + +判断指定点是否在路径的区域内。 + +- 参数 + + + + + + + + + + + + + + + + + + + + + + + + +

参数名

+

参数类型

+

必填

+

描述

+

path

+

Path2D

+

+

可选对象,指定用来判断的路径。若没有设置,则使用当前路径。

+

x

+

number

+

+

待判断点的x轴坐标。

+

y

+

number

+

+

待判断点的y轴坐标。

+
+ +- 返回值 + + + + + + + + + + +

类型

+

说明

+

boolean

+

指定点是否在路径的区域内。

+
-``` -// xxx.js -export default { - data: { - textValue: 0 - }, - onShow(){ - var canvas = this.$refs.canvas.getContext('2d'); - var offscreen = new OffscreenCanvas(500,500); - var offscreenCanvasCtx = offscreen.getContext("2d"); - - offscreenCanvasCtx.rect(10, 10, 100, 100); - offscreenCanvasCtx.fill(); - this.textValue = offscreenCanvasCtx.isPointInPath(30, 70); +- 示例 - var bitmap = offscreen.transferToImageBitmap(); - canvas.transferFromImageBitmap(bitmap); - } -} -``` + ``` + +
+ In path:{{textValue}} +
+ + ``` + + ``` + // xxx.js + export default { + data: { + textValue: 0 + }, + onShow(){ + var canvas = this.$refs.canvas.getContext('2d'); + var offscreen = new OffscreenCanvas(500,500); + var offscreenCanvasCtx = offscreen.getContext("2d"); + + offscreenCanvasCtx.rect(10, 10, 100, 100); + offscreenCanvasCtx.fill(); + this.textValue = offscreenCanvasCtx.isPointInPath(30, 70); + + var bitmap = offscreen.transferToImageBitmap(); + canvas.transferFromImageBitmap(bitmap); + } + } + ``` + + ![](figures/zh-cn_image_0000001224354967.png) + + +### isPointInStroke + +isPointInStroke\(path?: Path2D, x: number, y: number\): boolean + +判断指定点是否在路径的边缘线上。 + +- 参数 + + + + + + + + + + + + + + + + + + + + + + + + +

参数名

+

参数类型

+

必填

+

描述

+

path

+

Path2D

+

+

可选对象,指定用来判断的路径。若没有设置,则使用当前路径。

+

x

+

number

+

+

待判断点的x轴坐标。

+

y

+

number

+

+

待判断点的y轴坐标。

+
+ +- 返回值 + + + + + + + + + + +

类型

+

说明

+

boolean

+

指定点是否在路径的区域内。

+
-- isPointInStroke示例 +- 示例 -![](figures/zh-cn_image_0000001181458721.png) + ``` + +
+ In path:{{textValue}} +
+ + ``` + + ``` + // xxx.js + export default { + data: { + textValue: 0 + }, + onShow(){ + var canvas = this.$refs.canvas.getContext('2d'); + var offscreen = new OffscreenCanvas(500,500); + var offscreenCanvasCtx = offscreen.getContext("2d"); + + offscreenCanvasCtx.rect(10, 10, 100, 100); + offscreenCanvasCtx.stroke(); + this.textValue = offscreenCanvasCtx.isPointInStroke(50, 10); + + var bitmap = offscreen.transferToImageBitmap(); + canvas.transferFromImageBitmap(bitmap); + } + } + ``` + + ![](figures/zh-cn_image_0000001178875308.png) + + +### resetTransform + +resetTransform\(\): void -``` - -
- In path:{{textValue}} -
- -``` +- 示例 -``` -// xxx.js -export default { - data: { - textValue: 0 - }, - onShow(){ + ``` var canvas = this.$refs.canvas.getContext('2d'); var offscreen = new OffscreenCanvas(500,500); var offscreenCanvasCtx = offscreen.getContext("2d"); - - offscreenCanvasCtx.rect(10, 10, 100, 100); - offscreenCanvasCtx.stroke(); - this.textValue = offscreenCanvasCtx.isPointInStroke(50, 10); - + + offscreenCanvasCtx.transform(1, 0, 1.7, 1, 0, 0); + offscreenCanvasCtx.fillStyle = 'gray'; + offscreenCanvasCtx.fillRect(40, 40, 50, 20); + offscreenCanvasCtx.fillRect(40, 90, 50, 20); + + // Non-skewed rectangles + offscreenCanvasCtx.resetTransform(); + offscreenCanvasCtx.fillStyle = 'red'; + offscreenCanvasCtx.fillRect(40, 40, 50, 20); + offscreenCanvasCtx.fillRect(40, 90, 50, 20); + var bitmap = offscreen.transferToImageBitmap(); canvas.transferFromImageBitmap(bitmap); - } -} -``` - -- resetTransform示例 + ``` -![](figures/zh-cn_image_0000001135171488.png) + ![](figures/zh-cn_image_0000001179035242.png) -``` -var canvas = this.$refs.canvas.getContext('2d'); -var offscreen = new OffscreenCanvas(500,500); -var offscreenCanvasCtx = offscreen.getContext("2d"); - -offscreenCanvasCtx.transform(1, 0, 1.7, 1, 0, 0); -offscreenCanvasCtx.fillStyle = 'gray'; -offscreenCanvasCtx.fillRect(40, 40, 50, 20); -offscreenCanvasCtx.fillRect(40, 90, 50, 20); - -// Non-skewed rectangles -offscreenCanvasCtx.resetTransform(); -offscreenCanvasCtx.fillStyle = 'red'; -offscreenCanvasCtx.fillRect(40, 40, 50, 20); -offscreenCanvasCtx.fillRect(40, 90, 50, 20); - -var bitmap = offscreen.transferToImageBitmap(); -canvas.transferFromImageBitmap(bitmap); -``` diff --git a/zh-cn/application-dev/js-reference/ts-based-declarative-development-paradigm/ts-methods-media-query.md b/zh-cn/application-dev/js-reference/ts-based-declarative-development-paradigm/ts-methods-media-query.md index 803445fddfcda98be942581830e324a217e90221..9c0a408adefacb210f8e604352c2bf42c860c2f2 100644 --- a/zh-cn/application-dev/js-reference/ts-based-declarative-development-paradigm/ts-methods-media-query.md +++ b/zh-cn/application-dev/js-reference/ts-based-declarative-development-paradigm/ts-methods-media-query.md @@ -35,7 +35,7 @@ matchMediaSync\(condition: string\): MediaQueryListener

媒体事件的匹配条件。条件字符串格式: 参考媒体查询

+

媒体事件的匹配条件。

向媒体查询注册的回调

+

向媒体查询注册的回调。

结合系统能力开发智能设备

+

移植适配

diff --git a/zh-cn/device-dev/driver/Readme-CN.md b/zh-cn/device-dev/driver/Readme-CN.md index 17116f4e45cb37b89953e10d828a63f229c8c7a1..d3ed210b8068969885c91f3ca23c1afac100f3c5 100755 --- a/zh-cn/device-dev/driver/Readme-CN.md +++ b/zh-cn/device-dev/driver/Readme-CN.md @@ -10,7 +10,9 @@ - [平台驱动开发](driver-develop.md) - [ADC](driver-platform-adc-develop.md) - [GPIO](driver-platform-gpio-develop.md) + - [HDMI](driver-platform-hdmi-develop.md) - [I2C](driver-platform-i2c-develop.md) + - [I3C](driver-platform-i3c-develop.md) - [MIPI-DSI](driver-platform-mipidsi-develop.md) - [MMC](driver-platform-mmc-develop.md) - [PWM](driver-platform-pwm-develop.md) @@ -20,8 +22,11 @@ - [UART](driver-platform-uart-develop.md) - [WatchDog](driver-platform-watchdog-develop.md) - [平台驱动使用](driver-platform.md) + - [ADC](driver-platform-adc-des.md) - [GPIO](driver-platform-gpio-des.md) + - [HDMI](driver-platform-hdmi-des.md) - [I2C](driver-platform-i2c-des.md) + - [I3C](driver-platform-i3c-des.md) - [RTC](driver-platform-rtc-des.md) - [SDIO](driver-platform-sdio-des.md) - [SPI](driver-platform-spi-des.md) @@ -33,4 +38,5 @@ - [LCD](driver-peripherals-lcd-des.md) - [TOUCHSCREEN](driver-peripherals-touch-des.md) - [SENSOR](driver-peripherals-sensor-des.md) - - [WLAN](driver-peripherals-external-des.md) \ No newline at end of file + - [WLAN](driver-peripherals-external-des.md) + - [USB](driver-peripherals-usb-des.md) diff --git a/zh-cn/device-dev/driver/driver-hdf-sample.md b/zh-cn/device-dev/driver/driver-hdf-sample.md index 0cc2f0686ff32618900012839c2800fdb8724962..93cb1965a5ad017d7053e6e165bebf71f9db76f8 100644 --- a/zh-cn/device-dev/driver/driver-hdf-sample.md +++ b/zh-cn/device-dev/driver/driver-hdf-sample.md @@ -8,7 +8,7 @@ ## 添加配置 -在HDF框架的配置文件(例如vendor/hisilicon/xxx/config/device\_info)中添加该驱动的配置信息,如下所示: +在HDF框架的配置文件(例如vendor/hisilicon/xxx/hdf_config/device\_info)中添加该驱动的配置信息,如下所示: ``` root { @@ -232,7 +232,7 @@ int main() >![](../public_sys-resources/icon-note.gif) **说明:** >用户态应用程序使用了HDF框架中的消息发送接口,因此在编译用户态程序的过程中需要依赖HDF框架对外提供的hdf\_core和osal的动态库,在gn编译文件中添加如下依赖项: >deps = \[ ->"//drivers/adapter/lite/uhdf/manager:hdf\_core", ->"//drivers/adapter/lite/uhdf/posix:hdf\_posix\_osal", +>"//drivers/adapter/uhdf/manager:hdf\_core", +>"//drivers/adapter/uhdf/posix:hdf\_posix\_osal", >\] diff --git a/zh-cn/device-dev/driver/driver-peripherals-usb-des.md b/zh-cn/device-dev/driver/driver-peripherals-usb-des.md new file mode 100644 index 0000000000000000000000000000000000000000..cb0f0ef8a5a0c714ea93ae7a161bc4fe4151dc7c --- /dev/null +++ b/zh-cn/device-dev/driver/driver-peripherals-usb-des.md @@ -0,0 +1,1551 @@ +# USB + +- [概述](#section127mcpsimp) + - [接口说明](#section141mcpsimp) + +- [开发指导](#section581mcpsimp) + - [Host DDK API驱动开发步骤](#section584mcpsimp) + - [Host RAW API驱动开发步骤](#section594mcpsimp) + - [Device DDK API驱动开发步骤](#section600mcpsimp) + +- [开发实例](#section607mcpsimp) + - [Host DDK API驱动开发](#section609mcpsimp) + - [Host RAW API驱动开发](#section612mcpsimp) + - [Device DDK API驱动开发](#section615mcpsimp) + + +## 概述 + +USB Host部分,主要包括协议封装、设备管理、驱动安装与卸载等。 + +USB Device部分,支持USB功能设备的开发,提供USB设备相关功能,主要包括设备管理、配置管理、IO管理,实现USB功能设备创建、配置、数据通信等。 + +USB Host驱动模型如下图1所示: + +**图 1** USB Host驱动模型图 +![](figures/USB-Host驱动模型图.png "USB-Host驱动模型图") + +**图 2** USB Device驱动模型图 +![](figures/USB-Device驱动模型图.png "USB-Device驱动模型图") + +USB驱动模型对外开放的API接口能力如下: + +- Usb Host DDK提供给用户态可直接调用的驱动能力接口,按照功能分类三大类:DDK初始化类、对interface对象操作类、对request对象操作类,可以提供DDK初始化、interface绑定和释放,打开和关闭操作,request的申请和释放,同步和异步传输等。 +- Usb Deivce DDK提供设备管理、IO管理、配置管理,主要功能有:创建和删除设备、获取和打开接口、同步和异步传输等。 + +### 接口说明 + +USB驱动模型Host侧开放的API接口功能,参考[图1](#fig1649563542917)。 + +**表 1** USB驱动模型Host侧开放的API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

头文件

+

接口名称

+

功能描述

+

usb_ddk_interface.h

+

int32_t UsbInitHostSdk(struct UsbSession **session);

+

USB主机端驱动开发工具包初始化

+

int32_t UsbExitHostSdk(const struct UsbSession *session);

+

USB主机端驱动开发工具包退出

+

const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex);

+

获取USB接口对象

+

int UsbReleaseInterface(const struct UsbInterface *interfaceObj);

+

释放USB接口对象

+

int UsbAddOrRemoveInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex, UsbInterfaceStatus status);

+

增加移除接口

+

UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);

+

打开USB对象接口

+

int32_t UsbCloseInterface(const UsbInterfaceHandle *interfaceHandle);

+

关闭USB接口对象

+

int32_t UsbSelectInterfaceSetting(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, struct UsbInterface **interfaceObj);

+

设置可选配置

+

int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);

+

获取指定可选设置的管道信息

+

int32_t UsbClearInterfaceHalt(const UsbInterfaceHandle *interfaceHandle, uint8_t pipeAddress);

+

清除指定索引的管道状态

+

struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int isoPackets, int length);

+

分配请求对象

+

int UsbFreeRequest(const struct UsbRequest *request);

+

释放请求对象

+

int UsbSubmitRequestAsync(const struct UsbRequest *request);

+

发送异步请求

+

int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);

+

填充请求

+

sint UsbCancelRequest(const struct UsbRequest *request);

+

取消异步请求

+

int UsbSubmitRequestSync(const struct UsbRequest *request);

+

发送同步请求

+

usb_raw_api.h

+

int UsbRawInit(struct UsbSession **session);

+

USB驱动开发工具包专家模式初始化

+

int UsbRawExit(const struct UsbSession *session);

+

USB驱动开发工具包专家模式退出

+

UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);

+

打开USB设备对象

+

int UsbRawCloseDevice(const UsbRawHandle *devHandle);

+

关闭USB设备对象

+

int UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData);

+

执行同步控制传输

+

int UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);

+

执行同步批量传输

+

int UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);

+

执行同步中断传输

+

int UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);

+

获取给定设备指定ID的设备配置描述符

+

void UsbRawFreeConfigDescriptor(const struct UsbRawConfigDescriptor *config);

+

释放配置描述符内存空间

+

int UsbRawGetConfiguration(const UsbRawHandle *devHandle, int *config);

+

获取当前激活配置

+

int UsbRawSetConfiguration(const UsbRawHandle *devHandle, int config);

+

设置当前激活配置

+

int UsbRawGetDescriptor(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawDescriptorParam *param, const unsigned char *data);

+

获取描述符信息

+

UsbRawDevice *UsbRawGetDevice(const UsbRawHandle *devHandle);

+

由设备句柄获取设备指针

+

int UsbRawGetDeviceDescriptor(const UsbRawDevice *rawDev, struct UsbDeviceDescriptor *desc);

+

获取给定设备的USB设备描述符

+

int UsbRawClaimInterface(const UsbRawHandle *devHandle, int interfaceNumber);

+

声明给定设备句柄上的接口

+

int UsbRawReleaseInterface(const UsbRawHandle *devHandle, int interfaceNumber);

+

释放之前声明的接口

+

int UsbRawResetDevice(const UsbRawHandle *devHandle);

+

复位设备

+

struct UsbRawRequest *UsbRawAllocRequest(const UsbRawHandle *devHandle, int isoPackets, int length);

+

分配一个带有指定数量的同步包描述符的传输请求

+

int UsbRawFreeRequest(const struct UsbRawRequest *request);

+

释放之前分配的传输请求

+

int UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

填充批量传输请求所需信息

+

int UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData);

+

填充控制传输设置包所需信息

+

int UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

填充控制传输请求所需信息

+

int UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

填充中断传输请求所需信息

+

int UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

+

填充同步传输(Isochronous Transfers)请求所需信息

+

int UsbRawSubmitRequest(const struct UsbRawRequest *request);

+

提交一个传输请求

+

int UsbRawCancelRequest(const struct UsbRawRequest *request);

+

取消一个传输请求

+

int UsbRawHandleRequests(const UsbRawHandle *devHandle);

+

传输请求事件完成处理

+
+ +USB驱动模型Device侧开放的API接口功能,参考[图2](#fig8847615103013)。 + +**表 2** USB驱动模型Device侧开放的API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

头文件

+

头文件

+

功能描述

+

usbfn_device.h

+

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设备

+

usbfn_interface.h

+

int UsbFnStartRecvInterfaceEvent(struct UsbFnInterface *interface, uint32_t eventMask, UsbFnEventCallback callback, void *context);

+

开始接受Event事件

+

int UsbFnStopRecvInterfaceEvent(struct UsbFnInterface *interface);

+

停止接受Event事件

+

UsbFnInterfaceHandle UsbFnOpenInterface(struct UsbFnInterface *interface);

+

打开一个接口

+

int UsbFnCloseInterface(UsbFnInterfaceHandle handle);

+

关闭一个接口

+

int UsbFnGetInterfacePipeInfo(struct UsbFnInterface *interface, uint8_t pipeId, struct UsbFnPipeInfo *info);

+

获取管道信息

+

int UsbFnSetInterfaceProp(const struct UsbFnInterface *interface, const char *name, const char *value);

+

设置自定义属性

+

usbfn_request.h

+

struct UsbFnRequest *UsbFnAllocCtrlRequest(UsbFnInterfaceHandle handle, uint32_t len);

+

申请一个控制请求

+

struct UsbFnRequest *UsbFnAllocRequest(UsbFnInterfaceHandle handle, uint8_t pipe, uint32_t len);

+

申请一个数据请求

+

int UsbFnFreeRequest(struct UsbFnRequest *req);

+

释放一个请求

+

int UsbFnSubmitRequestAsync(struct UsbFnRequest *req);

+

发送异步请求

+

int UsbFnSubmitRequestSync(struct UsbFnRequest *req, uint32_t timeout);

+

发送同步请求

+

int UsbFnCancelRequest(struct UsbFnRequest *req);

+

取消请求

+
+ +## 开发指导 + +USB驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同USB器件提供统一的驱动模型。本篇开发指导以串口为例,分别介绍USB Host和USB Device驱动开发。 + +### 开发步骤 + +### Host DDK API驱动开发步骤 + +1. 驱动匹配表配置。 +2. 初始化Host DDK。 +3. 待步骤2初始化完后获取UsbInterface接口对象。 +4. 打开步骤3获取到的UsbInterface接口对象,获取对应接口的UsbInterfaceHandle对象。 +5. 根据步骤4获取到的UsbInterfaceHandle对象,获取指定索引为pinpeIndex的pipeInfo信息。 +6. 为步骤4获取到的UsbInterfaceHandle预先分配待发送的IO Request对象。 +7. 根据输入参数params填充步骤6预先分配的IO Request。 +8. 提交IO Request对象,可以选择同步或异步两种模式。 + +### Host RAW API驱动开发步骤 + +1. 驱动匹配表配置。 +2. 初始化Host RAW,并打开USB设备,然后获取描述符,通过描述符获取接口、端点信息。 +3. 分配Request,并根据传输类型使用如下接口对Request进行填充。 +4. 提交IO Request对象,可以选择同步或异步两种模式。 + +### Device DDK API驱动开发步骤 + +1. 构造描述符。 +2. 创建设备,使用步骤1构造的描述符实例化一个USB设备。 +3. 根据创建的设备获取接口(UsbFnDeviceGetInterface),获取Pipe信息(UsbFnInterfaceGetPipeInfo),打开接口获取Handle(UsbFnInterfaceOpen),根据Handle和Pipe号获取Request(UsbFnRequestAlloc)。 +4. 接收Event事件(UsbFnInterfaceStartRecvEvent)如Enable、Setup等事件,回调函数(UsbFnEventCallback)中对Event事件做出响应。 +5. 收发数据,可以选择同步异步发送模式。 + +## 开发实例 + +本实例提供USB串口驱动开发示例,并简要对具体关键点进行开发说明。 + +### Host DDK API驱动开发 + +``` +root { + module = "usb_pnp_device"; + usb_pnp_config { + match_attr = "usb_pnp_match"; + usb_pnp_device_id = "UsbPnpDeviceId"; + UsbPnpDeviceId { + idTableList = [ + "host_acm_table" + ]; + host_acm_table { + //驱动模块名,该字段的值必须和驱动入口结构的moduleName一致 + moduleName = "usbhost_acm"; + //驱动对外发布服务的名称,必须唯一 + serviceName = "usbhost_acm_pnp_service"; + //驱动私有数据匹配关键字 + deviceMatchAttr = "usbhost_acm_pnp_matchAttr"; + //从该字段开始(包含该字段)之后数据长度,以byte为单位 + length = 21; + //USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber + matchFlag = 0x0303; + //厂商编号 + vendorId = 0x12D1; + //产品编号 + productId = 0x5000; + //设备出厂编号,低16位 + bcdDeviceLow = 0x0000; + //设备出厂编号,高16位 + bcdDeviceHigh = 0x0000; + //USB分配的设备类代码 + deviceClass = 0; + //USB分配的子类代码 + deviceSubClass = 0; + //USB分配的设备协议代码 + deviceProtocol = 0; + //接口类型,根据实际需要可填写多个 + interfaceClass = [0]; + //接口子类型,根据实际需要可填写多个 + interfaceSubClass = [2, 0]; + //接口所遵循的协议,根据实际需要可填写多个 + interfaceProtocol = [1, 2]; + //接口的编号,根据实际需要可填写多个 + interfaceNumber = [2, 3]; + } + } + } +} + +#include "usb_serial.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "osal_time.h" +#include "securec.h" +#include "usb_ddk_interface.h" +#include "hdf_usb_pnp_manage.h" + +#define HDF_LOG_TAG USB_HOST_ACM +#define STR_LEN 512 + +static struct UsbRequest *g_syncRequest = NULL; +static struct UsbRequest *g_ctrlCmdRequest = NULL; +static bool g_acmReleaseFlag = false; +static uint8_t *g_acmReadBuffer = NULL; +... +static int SerialCtrlMsg(struct AcmDevice *acm, uint8_t request, + uint16_t value, void *buf, uint16_t len) +{ + int ret; + uint16_t index = acm->intPipe->interfaceId; + struct UsbControlParams controlParams = {}; + struct UsbRequestParams parmas = {}; + if (acm == NULL || buf == NULL) { + HDF_LOGE("%{public}s:invalid param", __func__); + return HDF_ERR_IO; + } + if (acm->ctrlReq == NULL) { + acm->ctrlReq = UsbAllocRequest(acm->ctrDevHandle, 0, len); + if (acm->ctrlReq == NULL) { + HDF_LOGE("%{public}s: UsbAllocRequest faild", __func__); + return HDF_ERR_IO; + } + } + + controlParams.request = request; + controlParams.target = USB_REQUEST_TARGET_INTERFACE; + controlParams.reqType = USB_REQUEST_TYPE_CLASS; + controlParams.directon = USB_REQUEST_DIR_TO_DEVICE; + controlParams.value = value; + controlParams.index = index; + controlParams.data = buf; + controlParams.size = len; + + parmas.interfaceId = USB_CTRL_INTERFACE_ID; + parmas.pipeAddress = acm->ctrPipe->pipeAddress; + parmas.pipeId = acm->ctrPipe->pipeId; + parmas.requestType = USB_REQUEST_PARAMS_CTRL_TYPE; + parmas.timeout = USB_CTRL_SET_TIMEOUT; + parmas.ctrlReq = UsbControlSetUp(&controlParams); + ret = UsbFillRequest(acm->ctrlReq, acm->ctrDevHandle, &parmas); + if (HDF_SUCCESS != ret) { + HDF_LOGE("%{public}s: faile, ret=%{public}d ", __func__, ret); + return ret; + } + ret = UsbSubmitRequestSync(acm->ctrlReq); //发送同步IO Request + if (HDF_SUCCESS != ret) { + HDF_LOGE("UsbSubmitRequestSync faile, ret=%{public}d ", ret); + return ret; + } + if (!acm->ctrlReq->compInfo.status) { + HDF_LOGE("%{public}s status=%{public}d ", __func__, acm->ctrlReq->compInfo.status); + } + return HDF_SUCCESS; +} +... +static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm, + uint8_t interfaceIndex) +{ + struct UsbInterface *tmpIf = NULL; + tmpIf = (struct UsbInterface *)UsbClaimInterface(acm->session, acm->busNum, + acm->devAddr, interfaceIndex); //获取UsbInterface接口对象 + return tmpIf; +} +... +static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm, + uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection) +{ + uint8_t i; + int ret; + struct UsbInterfaceInfo *info = NULL; + UsbInterfaceHandle *interfaceHandle = NULL; + if (pipeType == USB_PIPE_TYPE_CONTROL) + { + info = &acm->ctrIface->info; + interfaceHandle = acm->ctrDevHandle; + } + else + { + info = &acm->iface[interfaceIndex]->info; + interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex); + } + + for (i = 0; i <= info->pipeNum; i++) { + struct UsbPipeInfo p; + ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);//获取指定索引为i的pipeInfo信息 + if (ret < 0) { + continue; + } + if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) { + struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi)); + if (pi == NULL) { + HDF_LOGE("%{public}s: Alloc pipe failed", __func__); + return NULL; + } + p.interfaceId = info->interfaceIndex; + *pi = p; + return pi; + } + } + return NULL; +} + +static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm, + UsbPipeType pipeType, UsbPipeDirection pipeDirection) +{ + uint8_t i; + if (acm == NULL) { + HDF_LOGE("%{public}s: invalid parmas", __func__); + return NULL; + } + for (i = 0; i < acm->interfaceCnt; i++) { + struct UsbPipeInfo *p = NULL; + if (!acm->iface[i]) { + continue; + } + p = EnumePipe(acm, i, pipeType, pipeDirection); + if (p == NULL) { + continue; + } + return p; + } + return NULL; +} + +/* HdfDriverEntry implementations */ +static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) +{ + struct UsbPnpNotifyServiceInfo *info = NULL; + errno_t err; + struct AcmDevice *acm = NULL; + if (device == NULL) { + HDF_LOGE("%s: device is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm)); + if (acm == NULL) { + HDF_LOGE("%s: Alloc usb serial device failed", __func__); + return HDF_FAILURE; + } + if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { + HDF_LOGE("%s:%d OsalMutexInit fail", __func__, __LINE__); + goto error; + } + info = (struct UsbPnpNotifyServiceInfo *)device->priv; + if (info != NULL) { + HDF_LOGD("%s:%d busNum=%d,devAddr=%d,interfaceLength=%d", + __func__, __LINE__, info->busNum, info->devNum, info->interfaceLength); + acm->busNum = info->busNum; + acm->devAddr = info->devNum; + acm->interfaceCnt = info->interfaceLength; + err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, + (const void*)info->interfaceNumber, info->interfaceLength); + if (err != EOK) { + HDF_LOGE("%s:%d memcpy_s faile err=%d", + __func__, __LINE__, err); + goto lock_error; + } + } else { + HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__); + goto lock_error; + } + acm->device = device; + device->service = &(acm->service); + acm->device->service->Dispatch = UsbSerialDeviceDispatch; + HDF_LOGD("UsbSerialDriverBind=========================OK"); + return HDF_SUCCESS; + +lock_error: + if (OsalMutexDestroy(&acm->lock)) { + HDF_LOGE("%s:%d OsalMutexDestroy fail", __func__, __LINE__); + } +error: + OsalMemFree(acm); + acm = NULL; + return HDF_FAILURE; +} +... +static int AcmAllocReadRequests(struct AcmDevice *acm) +{ + int ret; + struct UsbRequestParams readParmas = {}; + for (int i = 0; i < ACM_NR; i++) { + acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize); //分配待发送的readReq IO Request对象 + if (!acm->readReq[i]) { + HDF_LOGE("readReq request faildn"); + goto error; + } + readParmas.userData = (void *)acm; + readParmas.pipeAddress = acm->dataInPipe->pipeAddress; + readParmas.pipeId = acm->dataInPipe->pipeId; + readParmas.interfaceId = acm->dataInPipe->interfaceId; + readParmas.callback = AcmReadBulk; + readParmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE; + readParmas.timeout = USB_CTRL_SET_TIMEOUT; + readParmas.dataReq.numIsoPackets = 0; + readParmas.dataReq.directon = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1; + readParmas.dataReq.length = acm->readSize; + ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParmas); //填充待发送的readReq对象 + if (HDF_SUCCESS != ret) { + HDF_LOGE("%{public}s: UsbFillRequest faile, ret=%{public}d n", __func__, ret); + goto error; + } + } + return HDF_SUCCESS; + +error: + AcmFreeReadRequests(acm); + return HDF_ERR_MALLOC_FAIL; +} + +static int AcmAllocNotifyRequest(struct AcmDevice *acm) +{ + int ret; + struct UsbRequestParams intParmas = {}; + acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize); //分配待发送的中断IO Request对象 + if (!acm->notifyReq) { + HDF_LOGE("notifyReq request failn"); + return HDF_ERR_MALLOC_FAIL; + } + intParmas.userData = (void *)acm; + intParmas.pipeAddress = acm->intPipe->pipeAddress; + intParmas.pipeId = acm->intPipe->pipeId; + intParmas.interfaceId = acm->intPipe->interfaceId; + intParmas.callback = AcmCtrlIrq; + intParmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE; + intParmas.timeout = USB_CTRL_SET_TIMEOUT; + intParmas.dataReq.numIsoPackets = 0; + intParmas.dataReq.directon = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK; + intParmas.dataReq.length = acm->intSize; + ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParmas); //填充预先分配的中断IO Request + if (HDF_SUCCESS != ret) { + HDF_LOGE("%{public}s: UsbFillRequest faile, ret=%{public}d n", __func__, ret); + goto error; + } + return HDF_SUCCESS; + +error: + AcmFreeNotifyReqeust(acm); + return ret; +} + +static void AcmReleaseInterfaces(struct AcmDevice *acm) +{ + for (int i = 0; i < acm->interfaceCnt; i++) { + if (acm->iface[i]) { + UsbReleaseInterface(acm->iface[i]); + acm->iface[i] = NULL; + } + } + if (acm->ctrIface) { + UsbReleaseInterface(acm->ctrIface); + acm->ctrIface = NULL; + } +} + +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接口对象 + if (acm->iface[i] == NULL) { + HDF_LOGE("%{public}s: interface%{public}d is null", __func__, acm->interfaceIndex[i]); + goto error; + } + } + + acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID); //获取控制接口对应的UsbInterface接口对象 + if (acm->ctrIface == NULL) { + HDF_LOGE("%{public}s: GetUsbInterfaceById null", __func__); + goto error; + } + + return HDF_SUCCESS; + + error: + AcmReleaseInterfaces(acm); + return HDF_FAILURE; +} + +static void AcmCloseInterfaces(struct AcmDevice *acm) +{ + for (int i = 0; i < acm->interfaceCnt; i++) { + if (acm->devHandle[i]) { + UsbCloseInterface(acm->devHandle[i]); + acm->devHandle[i] = NULL; + } + } + if (acm->ctrDevHandle) { + UsbCloseInterface(acm->ctrDevHandle); + acm->ctrDevHandle = NULL; + } +} + +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接口对象 + if (acm->devHandle[i] == NULL) { + HDF_LOGE("%{public}s: UsbOpenInterface null", __func__); + goto error; + } + } + } + acm->ctrDevHandle = UsbOpenInterface(acm->ctrIface); + if (acm->ctrDevHandle == NULL) { + HDF_LOGE("%{public}s: ctrDevHandle UsbOpenInterface null", __func__); + goto error; + } + + return HDF_SUCCESS; + +error: + AcmCloseInterfaces(acm); + return HDF_FAILURE; +} + +static int32_t AcmGetPipes(struct AcmDevice *acm) +{ + 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信息 + 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信息 + 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信息 + if (acm->intPipe == NULL) { + HDF_LOGE("intPipe is NULL"); + goto error; + } + + acm->readSize = acm->dataInPipe->maxPacketSize; + acm->writeSize = acm->dataOutPipe->maxPacketSize; + acm->ctrlSize = acm->ctrPipe->maxPacketSize; + acm->intSize = acm->intPipe->maxPacketSize; + + return HDF_SUCCESS; + +error: + AcmFreePipes(acm); + return HDF_FAILURE; +} + +static void AcmFreeRequests(struct AcmDevice *acm) +{ + if (g_syncRequest != NULL) { + UsbFreeRequest(g_syncRequest); + g_syncRequest = NULL; + } + AcmFreeReadRequests(acm); + AcmFreeNotifyReqeust(acm); + AcmFreeWriteRequests(acm); + AcmWriteBufFree(acm); +} + +static int32_t AcmAllocRequests(struct AcmDevice *acm) +{ + int32_t ret; + + if (AcmWriteBufAlloc(acm) < 0) { + HDF_LOGE("%{public}s: AcmWriteBufAlloc failed", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + for (int i = 0; i < ACM_NW; i++) { + struct AcmWb *snd = &(acm->wb[i]); + snd->request = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataOutPipe->interfaceId), 0, acm->writeSize); //分配待发送的IO Request对象 + snd->instance = acm; + if (snd->request == NULL) { + HDF_LOGE("%{public}s:%{public}d snd request fail", __func__, __LINE__); + goto error_alloc_write_req; + } + } + + ret = AcmAllocNotifyRequest(acm); //分配并填充中断IO Request对象 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s:%{public}d AcmAllocNotifyRequest fail", __func__, __LINE__); + goto error_alloc_int_req; + } + + ret = AcmAllocReadRequests(acm); //分配并填充readReq IO Request对象 + if (ret) { + HDF_LOGE("%{public}s:%{public}d AcmAllocReadRequests fail", __func__, __LINE__); + goto error_alloc_read_req; + } + + return HDF_SUCCESS; + +error_alloc_read_req: + AcmFreeNotifyReqeust(acm); +error_alloc_int_req: + AcmFreeWriteRequests(acm); +error_alloc_write_req: + AcmWriteBufFree(acm); + return HDF_FAILURE; +} + +static int32_t AcmInit(struct AcmDevice *acm) +{ + int32_t ret; + struct UsbSession *session = NULL; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d: initFlag is true", __func__, __LINE__); + return HDF_SUCCESS; + } + + ret = UsbInitHostSdk(NULL); //初始化Host DDK + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: UsbInitHostSdk faild", __func__); + return HDF_ERR_IO; + } + acm->session = session; + + ret = AcmClaimInterfaces(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmClaimInterfaces faild", __func__); + goto error_claim_interfaces; + } + + ret = AcmOpenInterfaces(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmOpenInterfaces faild", __func__); + goto error_open_interfaces; + } + + ret = AcmGetPipes(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmGetPipes failed", __func__); + goto error_get_pipes; + } + + ret = AcmAllocRequests(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: AcmAllocRequests failed", __func__); + goto error_alloc_reqs; + } + + acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); + acm->lineCoding.bCharFormat = CHARFORMAT; + acm->lineCoding.bParityType = USB_CDC_NO_PARITY; + acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; + acm->initFlag = true; + + HDF_LOGD("%{public}s:%{public}d========OK", __func__, __LINE__); + return HDF_SUCCESS; + +error_alloc_reqs: + AcmFreePipes(acm); +error_get_pipes: + AcmCloseInterfaces(acm); +error_open_interfaces: + AcmReleaseInterfaces(acm); +error_claim_interfaces: + UsbExitHostSdk(acm->session); + acm->session = NULL; + return ret; +} + +static void AcmRelease(struct AcmDevice *acm) +{ + if (acm->initFlag == false) { + HDF_LOGE("%{public}s:%{public}d: initFlag is false", __func__, __LINE__); + return; + } + + AcmFreeRequests(acm); + AcmFreePipes(acm); + AcmCloseInterfaces(acm); + AcmReleaseInterfaces(acm); + UsbExitHostSdk(acm->session); + acm->session = NULL; + + acm->initFlag = false; +} + +static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct AcmDevice *acm = NULL; + + if (device == NULL) { + HDF_LOGE("%{public}s: device is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + acm = (struct AcmDevice *)device->service; + OsalMutexInit(&acm->readLock); + OsalMutexInit(&acm->writeLock); + HDF_LOGD("%{public}s:%{public}d busNum=%{public}d,devAddr=%{public}d", + __func__, __LINE__, acm->busNum, acm->devAddr); + + ret = UsbSerialDeviceAlloc(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: Serial Device alloc faild", __func__); + } + + acm->initFlag = false; + g_acmReleaseFlag = false; + + HDF_LOGD("%{public}s:%{public}d init ok!", __func__, __LINE__); + + return ret; +} + +static void UsbSerialDriverRelease(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + + if (device == NULL) { + HDF_LOGE("%{public}s: device is NULL", __func__); + return; + } + acm = (struct AcmDevice *)device->service; + if (acm == NULL) { + HDF_LOGE("%{public}s: acm is null", __func__); + return; + } + + g_acmReleaseFlag = true; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d AcmRelease", __func__, __LINE__); + AcmRelease(acm); + } + UsbSeriaDevicelFree(acm); + OsalMutexDestroy(&acm->writeLock); + OsalMutexDestroy(&acm->readLock); + OsalMutexDestroy(&acm->lock); + OsalMemFree(acm); + acm = NULL; + HDF_LOGD("%{public}s:%{public}d exit", __func__, __LINE__); +} + +struct HdfDriverEntry g_usbSerialDriverEntry = { + .moduleVersion = 1, + .moduleName = "usbhost_acm", //驱动模块名称,必须与hcs文件中配置的名称一致 + .Bind = UsbSerialDriverBind, + .Init = UsbSerialDriverInit, + .Release = UsbSerialDriverRelease, +}; +HDF_INIT(g_usbSerialDriverEntry); +``` + +### Host RAW API驱动开发 + +``` +root { + module = "usb_pnp_device"; + usb_pnp_config { + match_attr = "usb_pnp_match"; + usb_pnp_device_id = "UsbPnpDeviceId"; + UsbPnpDeviceId { + idTableList = [ + "host_acm_rawapi_table" + ]; + host_acm_rawapi_table { //驱动配置匹配表信息 + //驱动模块名,该字段的值必须和驱动入口结构的moduleName一致 + moduleName = "usbhost_acm_rawapi"; + //驱动对外发布服务的名称,必须唯一 + serviceName = "usbhost_acm_rawapi_service"; + //驱动私有数据匹配关键字 + deviceMatchAttr = "usbhost_acm_rawapi_matchAttr"; + //从该字段开始(包含该字段)之后数据长度,以byte为单位 + length = 21; + //USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber + matchFlag = 0x0303; + //厂商编号 + vendorId = 0x12D1; + //产品编号 + productId = 0x5000; + //设备出厂编号,低16位 + bcdDeviceLow = 0x0000; + //设备出厂编号,高16位 + bcdDeviceHigh = 0x0000; + //USB分配的设备类代码 + deviceClass = 0; + //USB分配的子类代码 + deviceSubClass = 0; + //USB分配的设备协议代码 + deviceProtocol = 0; + //接口类型,根据实际需要可填写多个 + interfaceClass = [0]; + //接口子类型,根据实际需要可填写多个 + interfaceSubClass = [2, 0]; + //接口所遵循的协议,根据实际需要可填写多个 + interfaceProtocol = [1, 2]; + //接口的编号,根据实际需要可填写多个 + interfaceNumber = [2, 3]; + } + } + } +} + +#include "usb_serial_rawapi.h" +#include +#include "osal_mem.h" +#include "osal_time.h" +#include "securec.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "hdf_usb_pnp_manage.h" + +#define HDF_LOG_TAG USB_HOST_ACM_RAW_API +#define USB_CTRL_REQ_SIZE 64 +#define USB_IO_THREAD_STACK_SIZE 8192 +#define USB_RAW_IO_SLEEP_MS_TIME 100 +#define USB_RAW_IO_STOP_WAIT_MAX_TIME 3 + +static struct UsbRawRequest *g_syncRequest = NULL; +static UsbRawIoProcessStatusType g_stopIoStatus = USB_RAW_IO_PROCESS_RUNNING; +struct OsalMutex g_stopIoLock; +static bool g_rawAcmReleaseFlag = false; +...... + +static int UsbGetConfigDescriptor(UsbRawHandle *devHandle, struct UsbRawConfigDescriptor **config) +{ + UsbRawDevice *dev = NULL; + int activeConfig; + int ret; + + if (devHandle == NULL) { + HDF_LOGE("%{public}s:%{public}d devHandle is NULL", + __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + + ret = UsbRawGetConfiguration(devHandle, &activeConfig); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbRawGetConfiguration failed, ret=%{public}d", + __func__, __LINE__, ret); + return HDF_FAILURE; + } + HDF_LOGE("%{public}s:%{public}d activeConfig=%{public}d", __func__, __LINE__, activeConfig); + dev = UsbRawGetDevice(devHandle); + if (dev == NULL) { + HDF_LOGE("%{public}s:%{public}d UsbRawGetDevice failed", + __func__, __LINE__); + return HDF_FAILURE; + } + + ret = UsbRawGetConfigDescriptor(dev, activeConfig, config); + if (ret) { + HDF_LOGE("UsbRawGetConfigDescriptor failed, ret=%{public}dn", ret); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} +... +static int UsbAllocWriteRequests(struct AcmDevice *acm) +{ + int i; + + for (i = 0; i < ACM_NW; i++) { + struct AcmWb *snd = &acm->wb[i]; + snd->request = UsbRawAllocRequest(acm->devHandle, 0, acm->dataOutEp->maxPacketSize); + snd->instance = acm; + if (snd->request == NULL) { + HDF_LOGE("%{public}s: UsbRawAllocRequest faild", __func__); + return HDF_ERR_MALLOC_FAIL; + } + } + + return HDF_SUCCESS; +} +... +/* HdfDriverEntry implementations */ +static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + struct UsbPnpNotifyServiceInfo *info = NULL; + errno_t err; + + if (device == NULL) { + HDF_LOGE("%s: device is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm)); + if (acm == NULL) { + HDF_LOGE("%s: Alloc usb serial device failed", __func__); + return HDF_FAILURE; + } + if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { + HDF_LOGE("%s:%d OsalMutexInit fail", __func__, __LINE__); + goto error; + } + + info = (struct UsbPnpNotifyServiceInfo *)device->priv; + if (info != NULL) { + acm->busNum = info->busNum; + acm->devAddr = info->devNum; + acm->interfaceCnt = info->interfaceLength; + err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, + (const void*)info->interfaceNumber, info->interfaceLength); + if (err != EOK) { + HDF_LOGE("%s:%d memcpy_s faile err=%d", + __func__, __LINE__, err); + goto lock_error; + } + } else { + HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__); + goto lock_error; + } + + device->service = &(acm->service); + device->service->Dispatch = UsbSerialDeviceDispatch; + acm->device = device; + HDF_LOGD("UsbSerialDriverBind=========================OK"); + return HDF_SUCCESS; + +lock_error: + if (OsalMutexDestroy(&acm->lock)) { + HDF_LOGE("%s:%d OsalMutexDestroy fail", __func__, __LINE__); + } +error: + OsalMemFree(acm); + acm = NULL; + return HDF_FAILURE; +} +... +static int UsbAllocReadRequests(struct AcmDevice *acm) +{ + struct UsbRawFillRequestData reqData; + int size = acm->dataInEp->maxPacketSize; + int ret; + + for (int i = 0; i < ACM_NR; i++) { + acm->readReq[i] = UsbRawAllocRequest(acm->devHandle, 0, size); + if (!acm->readReq[i]) { + HDF_LOGE("readReq request faildn"); + return HDF_ERR_MALLOC_FAIL; + } + + reqData.endPoint = acm->dataInEp->addr; + reqData.numIsoPackets = 0; + reqData.callback = AcmReadBulkCallback; + reqData.userData = (void *)acm; + reqData.timeout = USB_CTRL_SET_TIMEOUT; + reqData.length = size; + + ret = UsbRawFillBulkRequest(acm->readReq[i], acm->devHandle, &reqData); + if (ret) { + HDF_LOGE("%{public}s: FillBulkRequest faile, ret=%{public}d n", + __func__, ret); + return HDF_FAILURE; + } + } + + return HDF_SUCCESS; +} +... +static int UsbAllocNotifyRequest(struct AcmDevice *acm) +{ + struct UsbRawFillRequestData fillRequestData; + int size = acm->notifyEp->maxPacketSize; + int ret; + + acm->notifyReq = UsbRawAllocRequest(acm->devHandle, 0, size); + if (!acm->notifyReq) { + HDF_LOGE("notifyReq request failn"); + return HDF_ERR_MALLOC_FAIL; + } + + fillRequestData.endPoint = acm->notifyEp->addr; + fillRequestData.length = size; + fillRequestData.numIsoPackets = 0; + fillRequestData.callback = AcmNotifyReqCallback; + fillRequestData.userData = (void *)acm; + fillRequestData.timeout = USB_CTRL_SET_TIMEOUT; + + ret = UsbRawFillInterruptRequest(acm->notifyReq, acm->devHandle, &fillRequestData); + if (ret) { + HDF_LOGE("%{public}s: FillInterruptRequest faile, ret=%{public}d", __func__, ret); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} +... +static int32_t UsbSerialInit(struct AcmDevice *acm) +{ + struct UsbSession *session = NULL; + UsbRawHandle *devHandle = NULL; + int32_t ret; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d: initFlag is true", __func__, __LINE__); + return HDF_SUCCESS; + } + + ret = UsbRawInit(NULL); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbRawInit faild", __func__, __LINE__); + return HDF_ERR_IO; + } + acm->session = session; + + devHandle = UsbRawOpenDevice(session, acm->busNum, acm->devAddr); + if (devHandle == NULL) { + HDF_LOGE("%{public}s:%{public}d UsbRawOpenDevice faild", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_open_device; + } + acm->devHandle = devHandle; + ret = UsbGetConfigDescriptor(devHandle, &acm->config); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbGetConfigDescriptor faild", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_get_desc; + } + ret = UsbParseConfigDescriptor(acm, acm->config); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s:%{public}d UsbParseConfigDescriptor faild", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_parse_desc; + } + + ret = AcmWriteBufAlloc(acm); + if (ret < 0) { + HDF_LOGE("%{public}s:%{public}d AcmWriteBufAlloc faild", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_alloc_write_buf; + } + ret = UsbAllocWriteRequests(acm); + if (ret < 0) { + HDF_LOGE("%{public}s:%{public}d UsbAllocWriteRequests faild", __func__, __LINE__); + ret = HDF_FAILURE; + goto err_alloc_write_reqs; + } + ret = UsbAllocNotifyRequest(acm); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbAllocNotifyRequests faild", __func__, __LINE__); + goto err_alloc_notify_req; + } + ret = UsbAllocReadRequests(acm); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbAllocReadRequests faild", __func__, __LINE__); + goto err_alloc_read_reqs; + } + ret = UsbStartIo(acm); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbAllocReadRequests faild", __func__, __LINE__); + goto err_start_io; + } + + acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); + acm->lineCoding.bCharFormat = CHARFORMAT; + acm->lineCoding.bParityType = USB_CDC_NO_PARITY; + acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; + + ret = UsbRawSubmitRequest(acm->notifyReq); + if (ret) { + HDF_LOGE("%{public}s:%{public}d UsbRawSubmitRequest failed", __func__, __LINE__); + goto err_submit_req; + } + + acm->initFlag = true; + + HDF_LOGD("%{public}s:%{public}d=========================OK", __func__, __LINE__); + + return HDF_SUCCESS; + +err_submit_req: + UsbStopIo(acm); +err_start_io: + UsbFreeReadRequests(acm); +err_alloc_read_reqs: + UsbFreeNotifyReqeust(acm); + err_alloc_notify_req: + UsbFreeWriteRequests(acm); +err_alloc_write_reqs: + AcmWriteBufFree(acm); +err_alloc_write_buf: + UsbReleaseInterfaces(acm); +err_parse_desc: + UsbRawFreeConfigDescriptor(acm->config); + acm->config = NULL; +err_get_desc: + (void)UsbRawCloseDevice(devHandle); +err_open_device: + UsbRawExit(acm->session); + + return ret; +} + +static void UsbSerialRelease(struct AcmDevice *acm) +{ + if (acm->initFlag == false) { + HDF_LOGE("%{public}s:%{public}d: initFlag is false", __func__, __LINE__); + return; + } + + /* stop io thread and release all resources */ + UsbStopIo(acm); + if (g_syncRequest != NULL) { + UsbRawFreeRequest(g_syncRequest); + g_syncRequest = NULL; + } + UsbFreeReadRequests(acm); + UsbFreeNotifyReqeust(acm); + UsbFreeWriteRequests(acm); + AcmWriteBufFree(acm); + (void)UsbRawCloseDevice(acm->devHandle); + UsbReleaseInterfaces(acm); + UsbRawFreeConfigDescriptor(acm->config); + acm->config = NULL; + UsbRawExit(acm->session); + + acm->initFlag = false; +} + +static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + int32_t ret; + + if (device == NULL) { + HDF_LOGE("%{public}s:%{public}d device is null", __func__, __LINE__); + return HDF_ERR_INVALID_OBJECT; + } + acm = (struct AcmDevice *)device->service; + OsalMutexInit(&acm->readLock); + OsalMutexInit(&acm->writeLock); + + ret = UsbSerialDeviceAlloc(acm); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s:%{public}d UsbSerialDeviceAlloc faild", __func__, __LINE__); + } + + acm->initFlag = false; + g_rawAcmReleaseFlag = false; + + HDF_LOGD("%{public}s:%{public}d init ok!", __func__, __LINE__); + + return ret; +} + +static void UsbSerialDriverRelease(struct HdfDeviceObject *device) +{ + struct AcmDevice *acm = NULL; + if (device == NULL) { + HDF_LOGE("%{public}s: device is NULL", __func__); + return; + } + + acm = (struct AcmDevice *)device->service; + if (acm == NULL) { + HDF_LOGE("%{public}s: acm is null", __func__); + return; + } + + g_rawAcmReleaseFlag = true; + + if (acm->initFlag == true) { + HDF_LOGE("%{public}s:%{public}d UsbSerialRelease", __func__, __LINE__); + UsbSerialRelease(acm); + } + UsbSeriaDevicelFree(acm); + OsalMutexDestroy(&acm->writeLock); + OsalMutexDestroy(&acm->readLock); + OsalMutexDestroy(&acm->lock); + OsalMemFree(acm); + acm = NULL; + HDF_LOGD("%{public}s:%{public}d exit", __func__, __LINE__); +} + +struct HdfDriverEntry g_usbSerialRawDriverEntry = { + .moduleVersion = 1, + .moduleName = "usbhost_acm_rawapi", //驱动模块名称,必须与hcs文件中配置的名称一致 + .Bind = UsbSerialDriverBind, + .Init = UsbSerialDriverInit, + .Release = UsbSerialDriverRelease, +}; +HDF_INIT(g_usbSerialRawDriverEntry); +``` + +### Device DDK API驱动开发 + +USB ACM设备核心代码路径为driversperipheralusbgadgetfunctionacmcdcacm.c,其使用示例如下所示,首先根据描述符创建设备,然后获取接口,打开接口,获取Pipe信息,接收Event事件,接着进行USB通信(读写等),设备卸载时候,关闭接口,停止Event接收,删除设备。 + +``` +1、创建设备 +static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, + struct DeviceResourceIface *iface) +{ + struct UsbFnDevice *fnDev = NULL; +struct UsbFnDescriptorData descData; +uint8_t useHcs; + ... +if (useHcs == 0) { + descData.type = USBFN_DESC_DATA_TYPE_DESC; + descData.descriptor = &g_masterFuncDevice; +} else { + descData.type = USBFN_DESC_DATA_TYPE_PROP; + descData.property = device->property; +} +/* 创建设备 */ + fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData); + if (fnDev == NULL) { + HDF_LOGE("%{public}s: create usb function device failed", __func__); + return HDF_FAILURE; + } + ... +} +2、获取接口,打开接口,获取Pipe信息 +static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface) +{ + ... + for (i = 0; i < fnIface->info.numPipes; i++) { + struct UsbFnPipeInfo pipeInfo; +/* 获取pipe信息 */ + ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo); + ... + } + return HDF_SUCCESS; +} +/* 获取接口,打开接口获取handle */ +static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev) +{ + ... + for (i = 0; i < fnDev->numInterfaces; i++) { + /* 获取接口 */ + fnIface = (struct UsbFnInterface *)UsbFnDeviceGetInterface(fnDev, i); + ... + /* 打开接口 */ + handle = UsbFnInterfaceOpen(fnIface); + ... + } + return HDF_SUCCESS; +} +3、接收Event事件 +static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int num) +{ + ... + req = UsbFnCtrlRequestAlloc(acm->ctrlIface.handle, + sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding)); + ... +} +static int32_t AcmDriverInit(struct HdfDeviceObject *device) +{ +... +/* 开始接收Event */ + ret = UsbFnInterfaceStartRecvEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm); + ... +} +4、进行USB通信(读写等) +static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type, + uint16_t value, void *data, uint32_t length) +{ +... +/* 异步发送 */ + ret = UsbFnRequestSubmitAsync(req); + ... +} +5、关闭接口,停止Event接收,删除设备 +static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm) +{ +int32_t ret; +/* 关闭接口 */ + (void)UsbFnInterfaceClose(acm->ctrlIface.handle); +(void)UsbFnInterfaceClose(acm->dataIface.handle); +/* 停止接收Event */ +(void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn); +/* 删除设备 */ + ret = UsbFnDeviceRemove(acm->fnDev); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: remove usb function device failed", __func__); + } + return ret; +} +``` + diff --git a/zh-cn/device-dev/driver/driver-platform-adc-des.md b/zh-cn/device-dev/driver/driver-platform-adc-des.md new file mode 100755 index 0000000000000000000000000000000000000000..1a9702a722fd88151575a7adfe35cfb6dd831fdb --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-adc-des.md @@ -0,0 +1,254 @@ +# ADC + +- [概述](#section1) +- [接口说明](#section2) +- [使用指导](#section3) + - [使用流程](#section4) + - [打开ADC设备](#section5) + - [读取AD转换结果](#section6) + - [关闭ADC设备](#section7) + +- [使用实例](#section8) + +## 概述 + +- ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备。 + +- ADC接口定义了完成ADC传输的通用方法集合,包括: + - ADC设备管理: 打开或关闭ADC设备。 + - ADC读取转换结果:读取AD转换结果。 + + **图 1** ADC物理连线示意图 + ![](figures/ADC物理连线示意图.png "ADC物理连线示意图") + +## 接口说明 + +**表 1** ADC驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

ADC设备管理接口

+

AdcOpen

+
打开ADC设备

+

AdcClose

+

关闭ADC设备

+

ADC读取转换结果接口

+

AdcRead

+

读取AD转换结果值

+
+ +## 使用指导 + +### 使用流程 + +使用ADC设备的一般流程如[图2](#fig2)所示。 + + **图 2** ADC使用流程图 +![](figures/ADC使用流程图.png "ADC使用流程图") + +### 打开ADC设备 + +在进行AD转换之前,首先要调用AdcOpen打开ADC设备。 + +```c +DevHandle AdcOpen(int16_t number); +``` + +**表 2** AdcOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

number

+

ADC设备号

+

返回值

+

返回值描述

+

NULL

+

打开ADC设备失败

+

设备句柄

+

打开的ADC设备句柄

+
+ +假设系统中存在2个ADC设备,编号从0到1,那么我们现在获取1号设备。 + +```c +DevHandle adcHandle = NULL; /* ADC设备句柄 / + +/* 打开ADC设备 */ +adcHandle = AdcOpen(1); +if (adcHandle == NULL) { + HDF_LOGE("AdcOpen: failed\n"); + return; +} +``` + +### 读取AD转换结果 + +```c +int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t *val); +``` + +**表 3** AdcRead参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

ADC设备句柄

+

channel

+

ADC设备通道号

+

val

+

AD转换结果

+

返回值

+

返回值描述

+

0

+

读取成功

+

负数

+

读取失败

+
+ +### 关闭ADC设备 + +ADC通信完成之后,需要关闭ADC设备,关闭函数如下所示: +```c +void AdcClose(DevHandle handle); +``` +**表 4** AdcClose参数和返回值描述 + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

ADC设备句柄

+
+关闭ADC设备示例: + +```c +AdcClose(adcHandle); /* 关闭ADC设备 */ +``` + +## 使用实例 + +本例程以操作开发板上的ADC设备为例,详细展示ADC接口的完整使用流程。 + +本例拟对Hi3516DV300某开发板上ADC设备进行简单的读取操作,基本硬件信息如下: + +- SOC:hi3516dv300。 + +- 原理图信息:电位器挂接在0号ADC设备1通道下。 + +本例程对测试ADC进行连续读取操作,测试ADC功能是否正常。 + +示例如下: + +```c +#include "adc_if.h" /* ADC标准接口头文件 */ +#include "hdf_log.h" /* 标准日志打印头文件 */ + +/* 设备号0,通道号1 */ +#define ADC_DEVICE_NUM 0 +#define ADC_CHANNEL_NUM 1 + +/* ADC例程总入口 */ +static int32_t TestCaseAdc(void) +{ + int32_t i; + int32_t ret; + DevHandle adcHandle; + uint32_t Readbuf[30] = {0}; + + /* 打开ADC设备 */ + adcHandle = AdcOpen(ADC_DEVICE_NUM); + if (adcHandle == NULL) { + HDF_LOGE("%s: Open ADC%u fail!", __func__, ADC_DEVICE_NUM); + return -1; + } + + /* 连续进行30次AD转换并读取转换结果 */ + for (i = 0; i < 30; i++) { + ret = AdcRead(adcHandle, ADC_CHANNEL_NUM, &Readbuf[i]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: tp ADC write reg fail!:%d", __func__, ret); + AdcClose(adcHandle); + return -1; + } + } + HDF_LOGI("%s: ADC read successful!", __func__); + + /* 访问完毕关闭ADC设备 */ + AdcClose(adcHandle); + + return 0; +} +``` + diff --git a/zh-cn/device-dev/driver/driver-platform-hdmi-des.md b/zh-cn/device-dev/driver/driver-platform-hdmi-des.md new file mode 100755 index 0000000000000000000000000000000000000000..8b606fcc9919e4a9c08033e651436eb8136d3356 --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-hdmi-des.md @@ -0,0 +1,1003 @@ +# HDMI + +- [概述](#section1) +- [接口说明](#section2) +- [使用指导](#section3) + - [使用流程](#section4) + - [打开HDMI控制器](#section5) + - [注册热插拔回调函数](#section6) + - [读取EDID](#section7) + - [设置属性](#section8) + - [启动HDMI传输](#section10) + - [停止HDMI传输](#section11) + - [注销热插拔回调函数](#section12) + - [关闭HDMI控制器](#section13) + +- [使用实例](#section14) + +## 概述 + +- HDMI(High-Definition Multiface Interface)是Hitachi, Panasonic, Philips, SiliconImage, Sony, Thomson, Toshiba几家公司共同发布的一款音视频传输协议。 +- HDMI以主从方式工作,通常有一个Source端和一个Sink端。 +- HDMI接口定义了完成HDMI传输的通用方法集合,包括: + + - HDMI控制器管理: 打开或关闭HDMI控制器 + - HDMI启动/停止传输:启动或停止HDMI传输 + - HDMI控制器设置:设置音频、视频及HDR属性,设置色彩深度、声音图像消隐等 + - HDMI读取EDID:读取sink端原始的EDID数据 + - HDMI热插拔:注册/注销热插拔回调函数 +- HDMI物理连接如[图1](#fig1)所示: + **图 1** HDMI物理连线示意图 + ![](figures/HDMI物理连线示意图.png "HDMI物理连线示意图") + +## 接口说明 + +**表 1** HDMI驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

HDMI控制器管理接口

+

HdmiOpen

+
打开HDMI控制器

+

HdmiClose

+

关闭HDMI控制器

+

启动/停止HDMI传输接口

+

HdmiStart

+
启动HDMI传输

+

HdmiStop

+

停止HDMI传输

+

HDMI控制器设置接口

+

HdmiAvmuteSet

+
HDMI声音图像消隐设置

+

HdmiDeepColorSet

+

设置色彩深度

+

HdmiDeepColorGet

+

获取色彩深度

+

HdmiSetVideoAttribute

+

设置视频属性

+

HdmiSetAudioAttribute

+

设置音频属性

+

HdmiSetHdrAttribute

+

设置HDR属性

+

EDID获取接口

+

HdmiReadSinkEdid

+
HDMI读取Sink端原始EDID数据

+

HDMI热插拔相关接口

+

HdmiRegisterHpdCallbackFunc

+
注册HDMI热插拔检测回调函数

+

HdmiUnregisterHpdCallbackFunc

+

注销HDMI热插拔回调函数

+
+ +## 使用指导 + +### 使用流程 + +使用HDMI设备的一般流程如[图2](#fig2)所示。 + +**图 2** HDMI设备使用流程图 +![](figures/HDMI使用流程图.png "HDMI使用流程图") + +### 打开HDMI控制器 + +在进行HDMI通信前,首先要调用HdmiOpen打开HDMI控制器。 + +```c +DevHandle HdmiOpen(int16_t number); +``` + +**表 2** HdmiOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

number

+

HDMI控制器号

+

返回值

+

返回值描述

+

NULL

+

打开HDMI控制器失败

+

控制器句柄

+

打开的HDMI控制器句柄

+
+ +假设系统中存在2个HDMI控制器,编号从0到1,那么我们现在获取0号控制器: + +```c +DevHandle hdmiHandle = NULL; /* HDMI控制器句柄 / + +/* 打开HDMI控制器 */ +hdmiHandle = HdmiOpen(0); +if (hdmiHandle == NULL) { + HDF_LOGE("HdmiOpen: failed\n"); + return; +} +``` + +### 注册热插拔回调函数 + +```c +int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo *callback); +``` + +**表 3** HdmiRegisterHpdCallbackFunc参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

callback

+

热插拔回调函数信息

+

返回值

+

返回值描述

+

0

+

注册成功

+

负数

+

注册失败

+
+ +注册热插拔回调函数示例: + +```c +/* 热插拔回调函数定义 */ +static void HdmiHpdHandle(void *data, bool hpd) +{ + if (data == NULL) { + HDF_LOGE("priv data is NULL"); + return; +} + + if (hpd == true) { + HDF_LOGD("HdmiHpdHandle: hot plug"); + /* 调用者添加相关处理 */ + } else { + HDF_LOGD("HdmiHpdHandle: hot unplog"); + /* 调用者添加相关处理 */ + } +} + + /* 热插拔回调函数注册示例 */ + struct HdmiHpdCallbackInfo info = {0}; + info.data = handle; + info.callbackFunc = HdmiHpdHandle; + ret = HdmiRegisterHpdCallbackFunc(hdmiHandle, info); + if (ret != 0) { + HDF_LOGE("HdmiRegisterHpdCallbackFunc: Register failed!"); + } +``` + +### 读取EDID + +```c +int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len); +``` + +**表 4** HdmiReadSinkEdid参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

buffer

+

数据缓冲区

+

len

+

数据长度

+

返回值

+

返回值描述

+

正整数

+

成功读取的原始EDID数据

+

负数或0

+

读取失败

+
+ +读取Sink端的原始EDID数据示例: + +```c +int32_t len; +uint8_t edid[HDMI_EDID_MAX_LEN] = {0}; + +len = HdmiReadSinkEdid(hdmiHandle, edid, HDMI_EDID_MAX_LEN); +if (len <= 0) { + HDF_LOGE("%s: HdmiReadSinkEdid failed len = %d.", __func__, len); +} +``` + +### 设置音频、视频及HDR属性 + +#### 设置音频属性 + +```c +int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr); +``` + +**表 5** HdmiSetAudioAttribute参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

attr

+

音频属性

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +设置音频属性示例: + +```c +struct HdmiAudioAttr audioAttr = {0}; +int32_t ret; + +audioAttr.codingType = HDMI_AUDIO_CODING_TYPE_MP3; +audioAttr.ifType = HDMI_AUDIO_IF_TYPE_I2S; +audioAttr.bitDepth = HDMI_ADIO_BIT_DEPTH_16; +audioAttr.sampleRate = HDMI_SAMPLE_RATE_8K; +audioAttr.channels = HDMI_AUDIO_FORMAT_CHANNEL_3; +ret = HdmiSetAudioAttribute(handle, &audioAttr); +if (ret != 0) { + HDF_LOGE("HdmiSetAudioAttribute failed."); +} +``` + +#### 设置视频属性 + +```c +int32_t HdmiSetVideoAttribute(DevHandle handle, struct HdmiVideoAttr *attr); +``` + +**表 6** HdmiSetVideoAttribute参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

attr

+

视频属性

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +设置音频属性示例: + +```c +struct HdmiVideoAttr videoAttr = {0}; +int32_t ret; + +videoAttr.colorSpace = HDMI_COLOR_SPACE_YCBCR444; +videoAttr.colorimetry = HDMI_COLORIMETRY_EXTENDED; +videoAttr.extColorimetry = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM; +videoAttr.quantization = HDMI_QUANTIZATION_RANGE_FULL; +ret = HdmiSetVideoAttribute(handle, &videoAttr); +if (ret != 0) { + HDF_LOGE("HdmiSetVideoAttribute failed."); +} +``` + +#### 设置HDR属性 + +```c +int32_t HdmiSetHdrAttribute(DevHandle handle, struct HdmiHdrAttr *attr); +``` + +**表 7** HdmiSetHdrAttribute参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

attr

+

HDR属性

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +设置HDR属性示例: + +```c +struct HdmiHdrAttr hdrAttr = {0}; +int32_t ret; + +hdrAttr.mode = HDMI_HDR_MODE_CEA_861_3; +hdrAttr.userMode = HDMI_HDR_USERMODE_DOLBY; +hdrAttr.eotfType = HDMI_EOTF_SMPTE_ST_2048; +hdrAttr.metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1; +hdrAttr.colorimetry = HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709; +ret = HdmiSetHdrAttribute(handle, &hdrAttr); +if (ret != 0) { + HDF_LOGE("HdmiSetHdrAttribute failed."); +} +``` + +### 其他可选设置 + +#### 设置HDMI声音图像消隐 + +```c +int32_t HdmiAvmuteSet(DevHandle handle, bool enable); +``` + +**表 8** HdmiAvmuteSet参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

enable

+

使能/去使能avmute

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +设置声音图像消隐示例: + +```c +int32_t ret; + +ret = HdmiAvmuteSet(hdmiHandle, true); +if (ret != 0) { + HDF_LOGE("HdmiAvmuteSet failed."); +} +``` + +#### 设置色彩深度 + +```c +int32_t HdmiDeepColorSet(DevHandle handle, enum HdmiDeepColor color); +``` + +**表 9** HdmiDeepColorSet参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

attr

+

色彩深度

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +设置色彩深度示例: + +```c +int32_t ret; + +ret = HdmiDeepColorSet(handle, HDMI_DEEP_COLOR_48BITS); +if (ret != 0) { + HDF_LOGE("HdmiDeepColorSet failed."); +} +``` + +#### 获取色彩深度 + +```c +int32_t HdmiDeepColorGet(DevHandle handle, enum HdmiDeepColor *color); +``` + +**表 10** HdmiDeepColorGet参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

color

+

色彩深度

+

返回值

+

返回值描述

+

0

+

获取成功

+

负数

+

获取失败

+
+ +获取色彩深度示例: + +```c +enum HdmiDeepColor color; +int32_t ret; + +ret = HdmiDeepColorGet(handle, &color); +if (ret != 0) { + HDF_LOGE("HdmiDeepColorGet failed."); +} +``` + +### 启动HDMI传输 + +```c +int32_t HdmiStart(DevHandle handle); +``` + +**表 11** HdmiStart参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

返回值

+

返回值描述

+

0

+

启动成功

+

负数

+

启动失败

+
+ +启动HDMI传输示例: + +```c +int32_t ret; + +ret = HdmiStart(hdmiHandle); +if (ret != 0) { + HDF_LOGE("start transmission failed!"); +} +``` + +### 停止HDMI传输 + +```c +int32_t HdmiStop(DevHandle handle); +``` + +**表 12** HdmiStop参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

返回值

+

返回值描述

+

0

+

停止成功

+

负数

+

停止失败

+
+ +停止HDMI传输示例: + +```c +int32_t ret; + +ret = HdmiStop(hdmiHandle); +if (ret != 0) { + HDF_LOGE("stop transmission failed!"); +} +``` + +### 注销热插拔回调函数 + +```c +int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle); +``` + +**表 13** HdmiUnregisterHpdCallbackFunc参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

返回值

+

返回值描述

+

0

+

注销成功

+

负数

+

注销失败

+
+ +注销热插拔回调函数示例: + +```c +int32_t ret; + +ret = HdmiUnregisterHpdCallbackFunc(hdmiHandle); +if (ret != 0) { + HDF_LOGE("unregister failed!"); +} +``` + +### 关闭HDMI控制器 + +```c +void HdmiClose(DevHandle handle); +``` + +**表 14** HdmiClose参数和返回值描述 + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+
+ +关闭HDMI控制器示例: + +```c +HdmiClose(hdmiHandle); +``` + +## 使用实例 + +本例程以操作开发板上的HDMI设备为例,详细展示HDMI接口的完整使用流程。 + +本例拟在Hi3516DV300某开发板上对虚拟驱动进行简单的传输操作: + +- SOC:hi3516dv300。 + +- HDMI控制器:使用0号HDMI控制器。 + + +示例如下: + +```c +#include "hdmi_if.h" /* HDMI标准接口头文件 */ +#include "hdf_log.h" /* 标准日志打印头文件 */ +#include "osal_time.h" /* 标准延迟&睡眠接口头文件 */ + +/* 热插拔回调函数 */ +static void HdmiHpdHandle(void *data, bool hpd) +{ + if (data == NULL) { + HDF_LOGE("priv data is NULL"); + return; + } + + if (hpd == true) { + HDF_LOGD("HdmiHpdHandle: hot plug"); + /* 调用者添加相关处理 */ + } else { + HDF_LOGD("HdmiHpdHandle: hot unplog"); + /* 调用者添加相关处理 */ + } +} + +/* 设置HDMI相关属性 */ +static int32_t TestHdmiSetAttr(DevHandle handle) +{ + enum HdmiDeepColor color; + struct HdmiVideoAttr videoAttr = {0}; + struct HdmiAudioAttr audioAttr = {0}; + struct HdmiHdrAttr hdrAttr = {0}; + int32_t ret; + + ret = HdmiDeepColorSet(handle, HDMI_DEEP_COLOR_48BITS); + + if (ret != 0) { + HDF_LOGE("HdmiDeepColorSet failed."); + return ret; + } + ret = HdmiDeepColorGet(handle, &color); + if (ret != 0) { + HDF_LOGE("HdmiDeepColorGet failed."); + return ret; + } + HDF_LOGE("HdmiDeepColorGet successful, color = %d.", color); + videoAttr.colorSpace = HDMI_COLOR_SPACE_YCBCR444; + videoAttr.colorimetry = HDMI_COLORIMETRY_EXTENDED; + videoAttr.extColorimetry = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM; + videoAttr.quantization = HDMI_QUANTIZATION_RANGE_FULL; + ret = HdmiSetVideoAttribute(handle, &videoAttr); + if (ret != 0) { + HDF_LOGE("HdmiSetVideoAttribute failed."); + return ret; + } + audioAttr.codingType = HDMI_AUDIO_CODING_TYPE_MP3; + audioAttr.ifType = HDMI_AUDIO_IF_TYPE_I2S; + audioAttr.bitDepth = HDMI_ADIO_BIT_DEPTH_16; + audioAttr.sampleRate = HDMI_SAMPLE_RATE_8K; + audioAttr.channels = HDMI_AUDIO_FORMAT_CHANNEL_3; + ret = HdmiSetAudioAttribute(handle, &audioAttr); + if (ret != 0) { + HDF_LOGE("HdmiSetAudioAttribute failed."); + return ret; + } + hdrAttr.mode = HDMI_HDR_MODE_CEA_861_3; + hdrAttr.userMode = HDMI_HDR_USERMODE_DOLBY; + hdrAttr.eotfType = HDMI_EOTF_SMPTE_ST_2048; + hdrAttr.metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1; + hdrAttr.colorimetry = HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709; + ret = HdmiSetHdrAttribute(handle, &hdrAttr); + if (ret != 0) { + HDF_LOGE("HdmiSetHdrAttribute failed."); + return ret; + } + + return 0; +} + +/* HDMI例程总入口 */ +static int32_t TestCaseHdmi(void) +{ + DevHandle handle = NULL; + int32_t ret; + + struct HdmiHpdCallbackInfo info = {0}; + uint8_t data[128] = {0}; + + HDF_LOGD("HdmiAdapterInit: successful."); + handle = HdmiOpen(0); + if (handle == NULL) { + HDF_LOGE("HdmiOpen failed."); + return ret; + } + info.data = handle; + info.callbackFunc = HdmiHpdHandle; + ret = HdmiRegisterHpdCallbackFunc(handle, &info); + if (ret != 0) { + HDF_LOGE("HdmiRegisterHpdCallbackFunc failed."); + return ret; + } + + ret = HdmiReadSinkEdid(handle, data, 128); + if (ret <= 0) { + HDF_LOGE("HdmiReadSinkEdid failed."); + return ret; + } + HDF_LOGE("HdmiReadSinkEdid successful, data[6] = %d, data[8] = %d.", data[6], data[8]); + + ret = TestHdmiSetAttr(handle); + if (ret != 0) { + HDF_LOGE("TestHdmiSetAttr failed."); + return ret; + } + + ret = HdmiStart(handle); + if (ret != 0) { + HDF_LOGE("HdmiStart failed."); + return ret; + } + + OsalMSleep(1000); + + ret = HdmiStop(handle); + if (ret != 0) { + HDF_LOGE("HdmiStop failed."); + return ret; + } + + ret = HdmiUnregisterHpdCallbackFunc(handle); + if (ret != 0) { + HDF_LOGE("HdmiUnregisterHpdCallbackFunc failed."); + return ret; + } + HdmiClose(handle); + return 0; +} + +``` \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-hdmi-develop.md b/zh-cn/device-dev/driver/driver-platform-hdmi-develop.md new file mode 100755 index 0000000000000000000000000000000000000000..9f4f0bb802c0bb87dde4f26a48a30a2b7107f138 --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-hdmi-develop.md @@ -0,0 +1,384 @@ +# HDMI + +- [概述](#1) +- [开发步骤](#2) +- [开发实例](#3) + +## 概述 + +HDMI(High-Definition Multiface Interface)是Hitachi, Panasonic, Philips, SiliconImage, Sony, Thomson, Toshiba几家公司共同发布的一款音视频传输协议,主要用于DVD, 机顶盒等音视频source到TV,显示器等sink设备的传输。传输基于的是TMDS(Transition Minimized Differential Signaling)协议。此外,使用TMDS也是DVI标准的主要特点 。 + +在HDF框架中,HDMI的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 + +![image1](figures/HDMI独立服务模式结构图.png) + +## 开发步骤 + +HDMI模块适配的三个环节是配置属性文件,实例化驱动入口以及实例化HDMI控制器对象。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device_info.hcs文件中添加deviceNode描述。 + - 【可选】添加hdmi_config.hcs器件属性文件。 + +3. **实例化HDMI控制器对象:** + - 初始化HdmiCntlr成员。 + - 实例化HdmiCntlr成员HdmiCntlrOps方法集合,其定义和成员函数说明见下文。 + +HdmiCntlrOps定义: +```c +struct HdmiCntlrOps { +void (*hardWareInit)(struct HdmiCntlr *cntlr); +void (*hardWareStatusGet)(struct HdmiCntlr *cntlr, struct HdmiHardwareStatus *status); +void (*controllerReset)(struct HdmiCntlr *cntlr); +bool (*hotPlugStateGet)(struct HdmiCntlr *cntlr); +bool (*hotPlugInterruptStateGet)(struct HdmiCntlr *cntlr); +void (*lowPowerSet)(struct HdmiCntlr *cntlr, bool enable); +void (*tmdsModeSet)(struct HdmiCntlr *cntlr, enum HdmiTmdsModeType mode); +int32_t (*tmdsConfigSet)(struct HdmiCntlr *cntlr, struct HdmiTmdsConfig mode); +void (*infoFrameEnable)(struct HdmiCntlr *cntlr, enum HdmiPacketType infoFrameType, bool enable); +int32_t (*infoFrameSend)(struct HdmiCntlr *cntlr, enum HdmiPacketType infoFrameType, uint8_t *data, uint32_t len); +int32_t (*infoFrameDataSet)(struct HdmiCntlr *cntlr, uint32_t type, uint8_t *data, uint32_t len); +int32_t (*cecMsgSend)(struct HdmiCntlr *cntlr, struct HdmiCecMsg *msg); +void (*audioPathEnable)(struct HdmiCntlr *cntlr, bool enable); +void (*audioPathSet)(struct HdmiCntlr *cntlr, struct HdmiAudioConfigInfo *config); +void (*phyOutputEnable)(struct HdmiCntlr *cntlr, bool enable); +void (*phyOutputSet)(struct HdmiCntlr *cntlr, struct HdmiPhyCfg *cfg); +void (*blackDataSet)(struct HdmiCntlr *cntlr, bool enable); +void (*videoMuteEnable)(struct HdmiCntlr *cntlr, bool enable); +void (*videoPathSet)(struct HdmiCntlr *cntlr, struct HdmiVideoAttr *attr); +void (*audioMuteEnable)(struct HdmiCntlr *cntlr, bool enable); +void (*avmuteSet)(struct HdmiCntlr *cntlr, bool enable); +int32_t (*ddcTransfer)(struct HdmiCntlr *cntlr, struct HdmiDdcCfg *ddcCfg); +bool (*scdcSourceScrambleGet)(struct HdmiCntlr *cntlr); +int32_t (*scdcSourceScrambleSet)(struct HdmiCntlr *cntlr, bool enable); +void (*frlSet)(struct HdmiCntlr *cntlr); +int32_t (*frlEnable)(struct HdmiCntlr *cntlr, bool enable); +int32_t (*audioNctsSet)(struct HdmiCntlr *cntlr, struct HdmiFrlAudioNctsConfig *cfg); +void (*frlTrainingConfigSet)(struct HdmiCntlr *cntlr, struct HdmiFrlTrainConfig *cfg); +void (*frlTrainingStart)(struct HdmiCntlr *cntlr); +void (*frlGetTriningRslt)(struct HdmiCntlr *cntlr, struct HdmiFrlTrainRslt *rslt); +void (*hdcpRegInit)(struct HdmiCntlr *cntlr); +int32_t (*hdcpGenerateAksvAndAn)(struct HdmiCntlr *cntlr); +int32_t (*hdcpOptReg)(struct HdmiCntlr *cntlr, enum HdmiHdcpRegOptType type, uint8_t *data, uint32_t len); +void (*hdrTimerSet)(struct HdmiCntlr *cntlr, struct HdmiHdrTimerConfig *config); +}; +``` + +表1 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相关状态|发送inforFrame| +|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配置信息| + +## 开发实例 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + +HDMI驱动入口参考: + +```c +struct HdfDriverEntry g_hdmiDriverEntry = { + .moduleVersion = 1, + .Bind = HdmiAdapterBind, + .Init = HdmiAdapterInit, + .Release = HdmiAdapterRelease, + .moduleName = "adapter_hdmi_driver",//【必要且与 HCS 里面的名字匹配】 +}; +HDF_INIT(g_hdmiDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 +``` + +2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在hdmi_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层HdmiCntlr相关成员的默认值或限制范围有密切关系。 + + **从第一个节点开始配置具体HDMI控制器信息**,此节点并不表示某一路HDMI控制器,而是代表一个资源性质设备,用于描述一类HDMI控制器的信息。**本例只有一个HDMI控制器,如有多个控制器,则需要在device_info文件增加deviceNode信息,以及在hdmi_config文件中增加对应的器件属性**。 + +- device_info.hcs 配置参考 + + ```c + root { + platform :: host { + device_hdmi :: device { + device0 :: deviceNode { + policy = 2; // 等于2,需要发布服务 + priority = 20; // 驱动启动优先级 + permission = 0644; // 驱动创建设备节点权限 + serviceName = "HDF_PLATFORM_HDMI_0"; //【必要】驱动对外发布服务的名称,必须唯一 + moduleName = "hdmi_driver"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; + deviceMatchAttr = "adapter_hdmi_driver"; //【必要】用于配置控制器私有数据,要与hdmi_config.hcs中对应控制器保持一致 + } // 具体的控制器信息在 hdmi_config.hcs 中 + } + } + } + ``` + +- hdmi_config.hcs 配置参考 + + ```c + root { + platform { + hdmi_config { + + template hdmi_controller { // 模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 + match_attr = ""; //【必要】需要和device_info.hcs中的deviceMatchAttr值一致 + index = 0; //【必要】hdmi控制器编号 + regBasePhy = 0x10100000; //【必要】寄存器物理基地址 + regSize = 0xd1; //【必要】寄存器位宽 + irqNum = 100; //【必要】中断号 + maxTmdsClock = 300; + videoTiming = 10; + quantization = 1; + colorSpace = 0; + colorimetry = 0; + audioIfType = 0; + audioBitDepth = 1; + audioSampleRate = 2; + audioChannels = 1; + hdrColorimetry = 4; + hdrUserMode = 1; + cap = 0xd001e045; + } + controller_0x10100000 :: hdmi_controller { + match_attr = "adapter_hdmi_driver"; + index = 0; + regBasePhy = 0x10100000; + irqNum = 100; + maxTmdsClock = 400; + defTmdsClock = 300; + maxFrlRate = 600; + videoTiming = 10; + quantization = 1; + colorSpace = 0; + colorimetry = 0; + audioIfType = 0; + audioSampleRate = 2; + audioChannels = 1; + hdrColorimetry = 4; + hdrUserMode = 1; + cap = 0xd001e045; + } + } + } + } + ``` + +3. 最后一步,完成驱动入口注册之后,要以核心层HdmiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化HdmiCntlr成员HdmiCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release) + + +- 自定义结构体参考 + + > ![](../public_sys-resources/icon-note.gif) **说明:** + > 从驱动的角度看,自定义结构体是参数和数据的载体,而且hdmi_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层HdmiCntlr对象,例如设备号、总线号等。 + + ```c + struct HdmiAdapterHost { + struct HdmiCntlr *cntlr; //【必要】是核心层控制对象,具体描述如下 + volatile unsigned char *regBase;//【必要】寄存器基地址 + uint32_t regBasePhy; //【必要】寄存器物理基地址 + uint32_t regSize; //【必要】寄存器位宽 + uint32_t irqNum; //【必要】中断号 + }; + + /* HdmiCntlr是核心层控制器结构体,其中的成员在Init函数中被赋值 */ + struct HdmiCntlr { + struct IDeviceIoService service; + struct HdfDeviceObject *hdfDevObj; + struct PlatformDevice device; + struct OsalMutex mutex; + struct PlatformQueue *msgQueue; + struct HdmiCntlrCap cap; + struct HdmiAttr attr; + struct HdmiCntlrOps *ops; + uint32_t deviceIndex; + uint32_t state; // 控制器状态 + enum HdmiTmdsModeType tmdsMode; + struct HdmiDevice *hdmi; + struct HdmiInfoframe infoframe; + struct HdmiScdc *scdc; + struct HdmiDdc ddc; + struct HdmiFrl *frl; + struct HdmiHdcp *hdcp; + struct HdmiCec *cec; + struct HdmiEvent event; + struct HdmiHdr *hdr; + void *priv; + }; + ``` + + +- **【重要】** HdmiCntlr成员回调函数结构体HdmiCntlrOps的实例化 + + ```c + + + static struct HdmiCntlrOps g_hdmiAdapterHostOps = { + .hardWareInit = HdmiAdapterHardWareInit, + .hardWareStatusGet = HdmiAdapterHardWareStatusGet, + .controllerReset = HdmiAdapterControllerReset, + .hotPlugStateGet = HdmiAdapterHotPlugStateGet, + .hotPlugInterruptStateGet = HdmiAdapterHotPlugInterruptStateGet, + .lowPowerSet = HdmiAdapterLowPowerSet, + .tmdsModeSet = HdmiAdapterTmdsModeSet, + .tmdsConfigSet = HdmiAdapterTmdsConfigSet, + .infoframeEnable = HdmiAdapterInfoframeEnable, + .infoframeSend = HdmiAdapterInfoframeSend, + .infoframeDataSet = HdmiAdapterInfoframeDataSet, + .cecMsgSend = HdmiAdapterCecMsgSend, + .audioPathEnable = HdmiAdapterAudioPathEnable, + .audioPathSet = HdmiAdapterAudioPathSet, + .phyOutputEnable = HdmiAdapterPhyOutputEnable, + .phyOutputSet = HdmiAdapterPhyOutputSet, + .blackDataSet = HdmiAdapterBlackDataSet, + .videoMuteEnable = HdmiAdapterVideoMuteEnable, + .videoPathSet = HdmiAdapterVideoPathSet, + .audioMuteEnable = HdmiAdapterAudioMuteEnable, + .avmuteSet = HdmiAdapterAvmuteSet, + .ddcTransfer = HdmiAdapterDdcTransfer, + .scdcSourceScrambleGet = HdmiAdapterScdcSourceScrambleGet, + .scdcSourceScrambleSet = HdmiAdapterScdcSourceScrambleSet, + .frlSet = HdmiAdapterFrlSet, + .frlEnable = HdmiAdapterFrlEnable, + .audioNctsSet = HdmiAdapterAudioNctsSet, + .frlTrainingConfigSet = HdmiAdapterFrlTrainingConfigSet, + .frlTrainingStart = HdmiAdapterFrlTrainingStart, + .frlGetTriningRslt = HdmiAdapterFrlGetTriningRslt, + .hdcpRegInit = HdmiAdapterHdcpRegInit, + .hdcpGenerateAksvAndAn = HdmiAdapterHdcpGenerateAksvAndAn, + .hdcpOptReg = HdmiAdapterHdcpOptReg, + .hdrTimerSet = HdmiAdapterHdrTimerSet, + }; + ``` + +- **Bind函数参考** + + > **入参:** + > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + > + > **返回值:** + > 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_SUCCESS |传输成功| + |HDF_FAILURE |传输失败| + + > ![](../public_sys-resources/icon-note.gif) **函数说明:** + > HdmiCntlr,HdmiAdapterHost,HdfDeviceObject之间互相赋值,方便其他函数可以相互转化,初始化自定义结构体对象HdmiAdapterHost,初始化HdmiCntlr成员,调用核心层HdmiCntlrAdd函数。 + + ```c + static int32_t HdmiAdapterBind(struct HdfDeviceObject *obj) + { + struct HdmiCntlr *cntlr = NULL; + struct HimciAdapterHost *host = NULL; + int32_t ret; + cntlr = (struct HdmiCntlr *)OsalMemCalloc(sizeof(struct HdmiCntlr)); + if (cntlr == NULL) { + HDF_LOGE("%s: malloc cntlr failed!", __func__); + return HDF_ERR_MALLOC_FAIL; + } + host = (struct HimciAdapterHost *)OsalMemCalloc(sizeof(struct HimciAdapterHost)); + if (host == NULL) { + HDF_LOGE("%s: malloc host failed!", __func__); + return HDF_ERR_MALLOC_FAIL; + } + cntlr->priv = (void *)host; //【必要】将host存放至cntlr的私有数据 + cntlr->ops = &g_hdmiHostOps; //【必要】HdmiCntlrOps的实例化对象的挂载 + cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提 + obj->service = &cntlr->service; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提 + ret = HdmiAdapterCntlrParse(cntlr, obj); //【必要】 初始化 cntlr. 失败则 goto __ERR; + ... + ret = HdmiAdapterHostParse(host, obj); //【必要】 初始化 host对象的相关属性,失败则 goto __ERR; + ... + ret = HdmiAdapterHostInit(host, cntlr);//厂商自定义的初始化,失败则 goto __ERR; + ... + ret = HdmiCntlrAdd(cntlr); //调用核心层函数 失败则 goto __ERR; + ... + HDF_LOGD("HdmiAdapterBind: success."); + return HDF_SUCCESS; + __ERR: + HdmiAdapterDeleteHost(host); + HDF_LOGD("HdmiAdapterBind: fail, err = %d.", ret); + return ret; + } + ``` + +- **init函数参考** + + >**入参:** + >HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + + >**返回值:** + >HDF_STATUS相关状态 + > + >函数说明: + > + >实现HdmiAdapterInit。 + + ```c + static int32_t HdmiAdapterInit(struct HdfDeviceObject *obj) + { + return HDF_SUCCESS; + } + ``` + +- **Release 函数参考** + + > **入参:** + > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + + > **返回值:** + > 无 + > + > **函数说明:** + > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + + ```c + static void HdmiAdapterRelease(struct HdfDeviceObject *obj) + { + struct HdmiCntlr *cntlr = NULL; + ... + cntlr = (struct HdmiCntlr *)obj->service;//这里有HdfDeviceObject到HdmiCntlr的强制转化,通过service成员,赋值见Bind函数 + ... + HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);//厂商自定义的内存释放函数,这里有HdmiCntlr到HimciAdapterHost的强制转化 + } + ``` + diff --git a/zh-cn/device-dev/driver/driver-platform-i3c-des.md b/zh-cn/device-dev/driver/driver-platform-i3c-des.md new file mode 100755 index 0000000000000000000000000000000000000000..2c65adfc71c2efb448d49b27878832158f44a4a0 --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-i3c-des.md @@ -0,0 +1,620 @@ +# I3C + +- [概述](#section1) +- [接口说明](#section2) +- [使用指导](#section3) + - [使用流程](#section4) + - [打开I3C控制器](#section5) + - [进行I3C通信](#section6) + - [获取I3C控制器配置](#section7) + - [配置I3C控制器](#section8) + - [请求IBI(带内中断)](#section9) + - [释放IBI(带内中断)](#section10) + - [关闭I3C控制器](#section11) + +- [使用实例](#section12) + +## 概述 + +- I3C(Improved Inter Integrated Circuit)总线是由MIPI Alliance开发的一种简单、低成本的双向二线制同步串行总线。 +- I3C总线向下兼容传统的I2C设备,同时增加了带内中断(In-Bind Interrupt)功能,支持I3C设备进行热接入操作,弥补了I2C总线需要额外增加中断线来完成中断的不足。 +- I3C总线上允许同时存在I2C设备、I3C从设备和I3C次级主设备。 +- I3C接口定义了完成I3C传输的通用方法集合,包括: + + - I3C控制器管理:打开或关闭I3C控制器。 + - I3C控制器配置:获取或配置I3C控制器参数。 + - I3C消息传输:通过消息传输结构体数组进行自定义传输。 + - I3C带内中断:请求或释放带内中断。 + - I3C的物理连接如[图1](#fig1)所示: + **图 1** I3C物理连线示意图 + ![](figures/I3C物理连线示意图.png "I3C物理连线示意图") + +## 接口说明 + +**表 1** I3C驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

I3C控制器管理接口

+

I3cOpen

+
打开I3C控制器

+

I3cClose

+

关闭I3C控制器

+

I3c消息传输接口

+

I3cTransfer

+

自定义传输

+

I3C控制器配置接口

+

I3cSetConfig

+
配置I3C控制器

+

I3cGetConfig

+

获取I3C控制器配置

+

I3C带内中断接口

+

I3cRequestIbi

+
请求带内中断

+

I3cFreeIbi

+

释放带内中断

+
+ + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用I3C设备的一般流程如[图2](#fig2)所示。 + +**图 2** I3C设备使用流程图 +![](figures/I3C使用流程图.png "I3C使用流程图") + +### 打开I3C控制器 + +在进行I3C通信前,首先要调用I3cOpen打开I3C控制器。 +```c +DevHandle I3cOpen(int16_t number); +``` + +**表 2** I3cOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

number

+

I3C控制器号

+

返回值

+

返回值描述

+

NULL

+

打开I3C控制器失败

+

控制器句柄

+

打开的I3C控制器句柄

+
+ +假设系统中存在8个I3C控制器,编号从0到7,那么我们现在获取1号控制器: + +```c +DevHandle i3cHandle = NULL; /* I3C控制器句柄 / + +/* 打开I3C控制器 */ +i3cHandle = I3cOpen(1); +if (i3cHandle == NULL) { + HDF_LOGE("I3cOpen: failed\n"); + return; +} +``` + +### 进行I3C通信 + +消息传输 +```c +int32_t I3cTransfer(DevHandle handle, struct I3cMsg *msgs, int16_t count, enum TransMode mode); +``` + +**表 3** I3cTransfer参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器句柄

+

msgs

+

待传输数据的消息结构体数组

+

count

+

消息数组长度

+

mode

+

传输模式,0:I2C模式;1:I3C模式;2:发送CCC(Common Command Code)

+

返回值

+

返回值描述

+

正整数

+

成功传输的消息结构体数目

+

负数

+

执行失败

+
+ +I3C传输消息类型为I3cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。 + +```c +int32_t ret; +uint8_t wbuff[2] = { 0x12, 0x13 }; +uint8_t rbuff[2] = { 0 }; +struct I3cMsg msgs[2]; /* 自定义传输的消息结构体数组 */ +msgs[0].buf = wbuff; /* 写入的数据 */ +msgs[0].len = 2; /* 写入数据长度为2 */ +msgs[0].addr = 0x3F; /* 写入设备地址为0x3F */ +msgs[0].flags = 0; /* 传输标记为0,默认为写 */ +msgs[1].buf = rbuff; /* 要读取的数据 */ +msgs[1].len = 2; /* 读取数据长度为2 */ +msgs[1].addr = 0x3F; /* 读取设备地址为0x3F */ +msgs[1].flags = I3C_FLAG_READ /* I3C_FLAG_READ置位 */ +/* 进行一次I2C模式自定义传输,传输的消息个数为2 */ +ret = I3cTransfer(i3cHandle, msgs, 2, I2C_MODE); +if (ret != 2) { + HDF_LOGE("I3cTransfer: failed, ret %d\n", ret); + return; +} +``` + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>- I3cMsg结构体中的设备地址不包含读写标志位,读写信息由flags成员变量的读写控制位传递。 +>- 本函数不对消息结构体个数count做限制,其最大个数度由具体I3C控制器决定。 +>- 本函数也不对每个消息结构体中的数据长度做限制,同样由具体I3C控制器决定。 +>- 本函数可能会引起系统休眠,不允许在中断上下文调用 + +### 获取I3C控制器配置 + +```c +int32_t I3cGetConfig(DevHandle handle, struct I3cConfig *config); +``` + +**表 4** I3cGetConfig参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器句柄

+

config

+

I3C控制器配置

+

返回值

+

返回值描述

+

0

+

获取成功

+

负数

+

获取失败

+
+ +### 配置I3C控制器 + +```c +int32_t I3cSetConfig(DevHandle handle, struct I3cConfig *config); +``` + +**表 5** I3cSetConfig参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器句柄

+

config

+

I3C控制器配置

+

返回值

+

返回值描述

+

0

+

配置成功

+

负数

+

配置失败

+
+ +### 请求IBI(带内中断) + +```c +int32_t I3cRequestIbi(DevHandle handle, uint16_t addr, I3cIbiFunc func, uint32_t payload); +``` + +**表 6** I3cRequestIbi参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器设备句柄

+

addr

+

I3C设备地址

+

func

+

IBI回调函数

+

payload

+

IBI有效载荷

+

返回值

+

返回值描述

+

0

+

请求成功

+

负数

+

请求失败

+
+ +```c +static int32_t TestI3cIbiFunc(DevHandle handle, uint16_t addr, struct I3cIbiData data) +{ + (void)handle; + (void)addr; + HDF_LOGD("%s: %.16s", __func__, (char *)data.buf); + + return 0; +} + +int32_t I3cTestRequestIbi(void) +{ + DevHandle i3cHandle = NULL; + int32_t ret; + + /* 打开I3C控制器 */ + i3cHandle = I3cOpen(1); + if (i3cHandle == NULL) { + HDF_LOGE("I3cOpen: failed\n"); + return; +} + ret = I3cRequestIbi(i3cHandle, 0x3F, TestI3cIbiFunc, 16); + if (ret != 0) { + HDF_LOGE("%s: Requset IBI failed!", __func__); + return -1; + } + + I3cClose(i3cHandle); + HDF_LOGD("%s: Done", __func__); + + return 0; +} +``` + +### 释放IBI(带内中断) + +```c +int32_t I3cFreeIbi(DevHandle handle, uint16_t addr); +``` + +**表 7** I3cFreeIbi参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器设备句柄

+

addr

+

I3C设备地址

+

返回值

+

返回值描述

+

0

+

释放成功

+

负数

+

释放失败

+
+ +```c +I3cFreeIbi(i3cHandle, 0x3F); /* 释放带内中断 */ +``` + +### 关闭I3C控制器 + +I3C通信完成之后,需要关闭I3C控制器,关闭函数如下所示: +```c +void I3cClose(DevHandle handle); +``` + +**表 4** I3cClose参数和返回值描述 + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器设备句柄

+
+ + +```c +I3cClose(i3cHandle); /* 关闭I3C控制器 */ +``` + +## 使用实例 + +本例程以操作开发板上的I3C设备为例,详细展示I3C接口的完整使用流程。 + +由于Hi3516DV300系列SOC没有I3C控制器,本例拟在Hi3516DV300某开发板上对虚拟驱动进行简单的传输操作,基本硬件信息如下: + +- SOC:hi3516dv300。 + +- 虚拟:I3C地址为0x3f, 寄存器位宽为1字节。 + +- 原理图信息:虚拟I3C设备挂接在18号和19号I3C控制器下。 + +本例程进行简单的I3C传输,测试I3C通路是否正常。 + +示例如下: + +```c +#include "i3c_if.h" /* I3C标准接口头文件 */ +#include "i3c_ccc.h" /* I3C通用命令代码头文件 */ +#include "hdf_log.h" /* 标准日志打印头文件 */ +#include "osal_io.h" /* 标准IO读写接口头文件 */ +#include "osal_time.h" /* 标准延迟&睡眠接口头文件 */ + +/* 定义一个表示设备的结构体,存储信息 */ +struct TestI3cDevice { + uint16_t busNum; /* I3C总线号 */ + uint16_t addr; /* I3C设备地址 */ + uint16_t regLen; /* 寄存器字节宽度 */ + DevHandle i3cHandle; /* I3C控制器句柄 */ +}; + +/* 基于I3cTransfer方法封装一个寄存器读写的辅助函数, 通过flag表示读或写 */ +static int TestI3cReadWrite(struct TestI3cDevice *testDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen, uint8_t flag) +{ + int index = 0; + unsigned char regBuf[4] = {0}; + struct I3cMsg msgs[2] = {0}; + + /* 单双字节寄存器长度适配 */ + if (testDevice->regLen == 1) { + regBuf[index++] = regAddr & 0xFF; + } else { + regBuf[index++] = (regAddr >> 8) & 0xFF; + regBuf[index++] = regAddr & 0xFF; + } + + /* 填充I3cMsg消息结构 */ + msgs[0].addr = testDevice->addr; + msgs[0].flags = 0; /* 标记为0,表示写入 */ + msgs[0].len = testDevice->regLen; + msgs[0].buf = regBuf; + + msgs[1].addr = testDevice->addr; + msgs[1].flags = (flag == 1) ? I3C_FLAG_READ : 0; /* 添加读标记位,表示读取 */ + msgs[1].len = dataLen; + msgs[1].buf = regData; + + if (I3cTransfer(testDevice->i3cHandle, msgs, 2, I2C_MODE) != 2) { + HDF_LOGE("%s: i3c read err", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +/* 寄存器读函数 */ +static inline int TestI3cReadReg(struct TestI3cDevice *testDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen) +{ + return TestI3cReadWrite(testDevice, regAddr, regData, dataLen, 1); +} + +/* 寄存器写函数 */ +static inline int TestI3cWriteReg(struct TestI3cDevice *testDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen) +{ + return TestI3cReadWrite(testDevice, regAddr, regData, dataLen, 0); +} + +/* I3C例程总入口 */ +static int32_t TestCaseI3c(void) +{ + int32_t i; + int32_t ret; + unsigned char bufWrite[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xA, 0xB, 0xC }; + unsigned char bufRead[7] = {0}; + static struct TestI3cDevice testDevice; + + /* 设备信息初始化 */ + testDevice.busNum = 18; + testDevice.addr = 0x3F; + testDevice.regLen = 1; + testDevice.i3cHandle = NULL; + + /* 打开I3C控制器 */ + testDevice.i3cHandle = I3cOpen(testDevice.busNum); + if (testDevice.i3cHandle == NULL) { + HDF_LOGE("%s: Open I3c:%u fail!", __func__, testDevice.busNum); + return -1; + } + + /* 向地址为0x3F的设备连续写7字节数据 */ + ret = TestI3cWriteReg(&testDevice, 0x3F, bufWrite, 7); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: test i3c write reg fail!:%d", __func__, ret); + I3cClose(testDevice.i3cHandle); + return -1; + } + OsalMSleep(10); + + /* 从地址为0x3F的设备连续读7字节数据 */ + ret = TestI3cReadReg(&testDevice, 0x3F, bufRead, 7); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: test i3c read reg fail!:%d", __func__, ret); + I3cClose(testDevice.i3cHandle); + return -1; + } + HDF_LOGI("%s: test i3c write&read reg success!", __func__); + + /* 访问完毕关闭I3C控制器 */ + I3cClose(testDevice.i3cHandle); + + return 0; +} +``` \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-i3c-develop.md b/zh-cn/device-dev/driver/driver-platform-i3c-develop.md new file mode 100755 index 0000000000000000000000000000000000000000..ba621631c0eb31c2b1d2714c57dbe5a1de43ba3b --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-i3c-develop.md @@ -0,0 +1,417 @@ +# I3C + +- [概述](#1) +- [开发步骤](#2) +- [开发实例](#3) + +## 概述 + +I3C(Improved Inter Integrated Circuit)总线是由MIPI Alliance开发的一种简单、低成本的双向二线制同步串行总线。在HDF框架中,I3C模块接口适配模式采用统一服务模式,这需要一个设备服务来作为I3C模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如I3C可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 + +![image1](figures/I3C统一服务模式结构图.png) + +## 开发步骤 + +I3C模块适配的四个环节是配置属性文件,实例化驱动入口,实例化I3C控制器对象,以及注册中断处理子程序。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device_info.hcs文件中添加deviceNode描述。 + - 【可选】添加i3c_config.hcs器件属性文件。 + +3. **实例化I3C控制器对象:** + - 初始化I3cCntlr成员。 + - 实例化I3cCntlr成员I3cMethod方法集合,其定义和成员函数说明见下文。 + +4. **注册中断处理子程序:** + - 为控制器注册中断处理程序,实现设备热接入和IBI(带内中断)功能。 + +I3cMethod定义: +```c +struct I3cMethod { + int32_t (*sendCccCmd)(struct I3cCntlr *cntlr, struct I3cCccCmd *ccc); + int32_t (*transfer)(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count); + int32_t (*i2cTransfer)(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count); + int32_t (*setConfig)(struct I3cCntlr *cntlr, struct I3cConfig *config); + int32_t (*getConfig)(struct I3cCntlr *cntlr, struct I3cConfig *config); + int32_t (*requestIbi)(struct I3cDevice *dev); + void (*freeIbi)(struct I3cDevice *dev); +}; +``` + +表1 I3cMethod结构体成员的回调函数功能说明 + +|函数成员|入参|出参|返回值|功能| +|-|-|-|-|-| +|sendCccCmd|**cntlr**: 结构体指针,核心层I3C控制器;
**ccc**:传入的通用命令代码结构体指针;|**ccc**:传出的通用命令代码结构体指针;|HDF_STATUS相关状态|发送CCC(Common command Code,即通用命令代码)| +|Transfer |**cntlr: 结构体指针,核心层I3C控制器;
msgs:结构体指针,用户消息 ;
count**:uint16_t,消息数量|**msgs**:结构体指针,用户消息 ;|HDF_STATUS相关状态|使用I3C模式传递用户消息| +|i2cTransfer |**cntlr**: 结构体指针,核心层I3C控制器;
**msgs**:结构体指针,用户消息 ;
**count**:uint16_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| + + +## 开发实例 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + +一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + +I3C驱动入口参考: + +> I3C模块这种类型的控制器会出现很多个控制器挂接的情况,因而在HDF框架中首先会为这类型的控制器创建一个管理器对象,并同时对外发布一个管理器服务来统一处理外部访问。这样,用户需要打开某个控制器时,会先获取到管理器服务,然后管理器服务根据用户指定参数查找到指定控制器。 +> +> I3C管理器服务的驱动由核心层实现,**厂商不需要关注这部分内容的实现,这个但在实现Init函数的时候需要调用核心层的I3cCntlrAdd函数,它会实现相应功能。** + +```c + static struct HdfDriverEntry g_virtualI3cDriverEntry = { + .moduleVersion = 1, + .Init = VirtualI3cInit, + .Release = VirtualI3cRelease, + .moduleName = "virtual_i3c_driver",//【必要且与 HCS 里面的名字匹配】 + }; + 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对应 + }; + HDF_INIT(g_i3cManagerEntry); +``` + +2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在i3c_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层I3cCntlr相关成员的默认值或限制范围有密切关系。 + + **统一服务模式**的特点是device_info文件中第一个设备节点必须为I3C管理器,其各项参数必须如下设置: + + |成员名|值| + |-|-| + |moduleName | 固定为 HDF_PLATFORM_I3C_MANAGER| + |serviceName| 无| + |policy| 具体配置为0,不发布服务| + |cntlrMatchAttr| 没有使用,可忽略| + + **从第二个节点开始配置具体I3C控制器信息**,此节点并不表示某一路I3C控制器,而是代表一个资源性质设备,用于描述一类I3C控制器的信息。**本例只有一个I3C控制器,如有多个控制器,则需要在device_info文件增加deviceNode信息,以及在i3c_config文件中增加对应的器件属性**。 + +- device_info.hcs 配置参考 + + ```c + root { + device_i3c :: device { + device0 :: deviceNode { + policy = 0; + priority = 52; + permission = 0644; + serviceName = "HDF_PLATFORM_I3C_MANAGER"; + moduleName = "HDF_PLATFORM_I3C_MANAGER"; + } + } + i3c_virtual :: deviceNode { + policy = 0; // 等于0,不需要发布服务 + priority = 56; // 驱动启动优先级 + permission = 0644; // 驱动创建设备节点权限 + moduleName = "virtual_i3c_driver"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; + serviceName = "VIRTUAL_I3C_DRIVER"; //【必要】驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "virtual_i3c"; //【必要】用于配置控制器私有数据,要与i3c_config.hcs中对应控制器保持一致 + } // 具体的控制器信息在 i3c_config.hcs 中 + } + ``` + +- i3c_config.hcs 配置参考 + + ```c + root { + platform { + i3c_config { + match_attr = "virtual_i3c"; //【必要】需要和device_info.hcs中的deviceMatchAttr值一致 + template i3c_controller { // 模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 + 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+模式时钟速率 + } + controller_0 :: i3c_controller { + busId = 18; + IrqNum = 20; + } + } + } + } + ``` + +3. 完成驱动入口注册之后,要以核心层I3cCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化I3cCntlr成员I3cMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release) + + +- 自定义结构体参考 + + > 从驱动的角度看,自定义结构体是参数和数据的载体,而且i3c_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层I3cCntlr对象,例如设备号、总线号等。 + + ```c + struct VirtualI3cCntlr { + 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; + uint32_t i3cRate; + uint32_t i2cFmRate; + uint32_t i2cFmPlusRate; + }; + + /* I3cCntlr是核心层控制器结构体,其中的成员在Init函数中被赋值 */ + struct I3cCntlr { + OsalSpinlock lock; + void *owner; + int16_t busId; + struct I3cConfig config; + uint16_t addrSlot[(I3C_ADDR_MAX + 1) / ADDRS_PER_UINT16]; + struct I3cIbiInfo *ibiSlot[I3C_IBI_MAX]; + const struct I3cMethod *ops; + const struct I3cLockMethod *lockOps; + void *priv; + }; + ``` + + +- **【重要】** I3cCntlr成员回调函数结构体I3cMethod的实例化,I3cLockMethod回调函数结构体本例未实现,若要实例化,可参考I2C驱动开发,其他成员在Init函数中初始化 + + ```c + struct I3cMethod { + int32_t (*sendCccCmd)(struct I3cCntlr *cntlr, struct I3cCccCmd *ccc); + int32_t (*transfer)(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count); + int32_t (*i2cTransfer)(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count); + int32_t (*setConfig)(struct I3cCntlr *cntlr, struct I3cConfig *config); + int32_t (*getConfig)(struct I3cCntlr *cntlr, struct I3cConfig *config); + int32_t (*requestIbi)(struct I3cDevice *dev); + void (*freeIbi)(struct I3cDevice *dev); + }; + ``` + +- **init函数参考** + + > **入参:** + > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + > + > **返回值:** + > 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_SUCCESS |传输成功| + |HDF_FAILURE |传输失败| + + > **函数说明:** + > 初始化自定义结构体对象,初始化I3cCntlr成员,调用核心层I3cCntlrAdd函数。 + +```c + static int32_t VirtualI3cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) + { + int32_t ret; + struct VirtualI3cCntlr *virtual = NULL; //【必要】自定义结构体对象 + (void)device; + + 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文件的默认值填充到结构体中 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret); + goto __ERR__; + } + ... + 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的实例化对象的挂载 + (void)OsalSpinInit(&virtual->spin); + ret = I3cCntlrAdd(&virtual->cntlr); //【必要且重要】调用此函数将控制器添加至核心,返回成功信号后驱动才完全接入平台核心层 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: add i3c controller failed! ret = %d", __func__, ret); + (void)OsalSpinDestroy(&virtual->spin); + goto __ERR__; + } + + return HDF_SUCCESS; + __ERR__: //若控制器添加失败,需要执行去初始化相关函数 + if (virtual != NULL) { + OsalMemFree(virtual); + virtual = NULL; + } + + return ret; + } + + static int32_t VirtualI3cInit(struct HdfDeviceObject *device) + { + int32_t ret; + const struct DeviceResourceNode *childNode = NULL; + + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: device or property is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + ret = VirtualI3cParseAndInit(device, childNode); + if (ret != HDF_SUCCESS) { + break; + } + } + + return ret; + } +``` + +- **Release 函数参考** + + > **入参:** + > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 。 + > + > **返回值:** + > 无。 + > + > **函数说明:** + > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + +```c + static void VirtualI3cRemoveByNode(const struct DeviceResourceNode *node) + { + int32_t ret; + int16_t busId; + struct I3cCntlr *cntlr = NULL; + struct VirtualI3cCntlr *virtual = NULL; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s: invalid drs ops fail!", __func__); + return; + } + + ret = drsOps->GetUint16(node, "busId", (uint16_t *)&busId, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read busId fail!", __func__); + return; + } + ... + /* 可以调用I3cCntlrGet函数通过设备的cntlrNum获取I3cCntlr对象, 以及调用I3cCntlrRemove函数来释放I3cCntlr对象的内容 */ + cntlr = I3cCntlrGet(busId); + if (cntlr != NULL && cntlr->priv == node) { + I3cCntlrPut(cntlr); + I3cCntlrRemove(cntlr); //【必要】主要是从管理器驱动那边移除I3cCntlr对象 + virtual = (struct VirtualI3cCntlr *)cntlr;//【必要】通过强制转换获取自定义的对象并进行release操作 + (void)OsalSpinDestroy(&virtual->spin); + OsalMemFree(virtual); + } + return; + } + + static void VirtualI3cRelease(struct HdfDeviceObject *device) + { + const struct DeviceResourceNode *childNode = NULL; + + HDF_LOGI("%s: enter", __func__); + + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: device or property is NULL", __func__); + return; + } + ... + //遍历、解析i3c_config.hcs中的所有配置节点,并分别进行release操作 + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + VirtualI3cRemoveByNode(childNode); //函数定义如上 + } + } +``` +4. 最后一步,实现中断处理程序,在中断处理程序中通过判断中断产生的地址,实现热接入、IBI等操作。 + +```c +static int32_t VirtualI3cReservedAddrWorker(struct VirtualI3cCntlr *virtual, uint16_t addr) +{ + (void)virtual; + switch (addr) { + case I3C_HOT_JOIN_ADDR: + VirtualI3cHotJoin(virtual); + break; + case I3C_RESERVED_ADDR_7H3E: + case I3C_RESERVED_ADDR_7H5E: + case I3C_RESERVED_ADDR_7H6E: + case I3C_RESERVED_ADDR_7H76: + case I3C_RESERVED_ADDR_7H7A: + case I3C_RESERVED_ADDR_7H7C: + case I3C_RESERVED_ADDR_7H7F: + /* 广播地址单比特错误的所有情形 */ + HDF_LOGW("%s: broadcast Address single bit error!", __func__); + break; + default: + HDF_LOGD("%s: Reserved address which is not supported!", __func__); + break; + } + + return HDF_SUCCESS; +} + +static int32_t I3cIbiHandle(uint32_t irq, void *data) +{ + struct VirtualI3cCntlr *virtual = NULL; + struct I3cDevice *device = NULL; + uint16_t ibiAddr; + char *testStr = "Hello I3C!"; + + (void)irq; + if (data == NULL) { + HDF_LOGW("%s: data is NULL!", __func__); + return HDF_ERR_INVALID_PARAM; + } + virtual = (struct VirtualI3cCntlr *)data; + /* 【必要】获取产生中断的地址,使用CHECK_RESERVED_ADDR宏判断该地址是否为I3C保留地址 */ + ibiAddr = VirtualI3cGetIbiAddr(); + if (CHECK_RESERVED_ADDR(ibiAddr) == I3C_ADDR_RESERVED) { + HDF_LOGD("%s: Calling VirtualI3cResAddrWorker...", __func__); + return VirtualI3cReservedAddrWorker(virtual, ibiAddr); + } else { + HDF_LOGD("%s: Calling I3cCntlrIbiCallback...", __func__); + device = GetDeviceByAddr(&virtual->cntlr, ibiAddr); + if (device == NULL) { + HDF_LOGE("func:%s device is NULL!",__func__); + return HDF_ERR_MALLOC_FAIL; + } + if (device->ibi->payload > VIRTUAL_I3C_TEST_STR_LEN) { + /* 将字符串"Hello I3C!"放入IBI缓冲区内 */ + *device->ibi->data = *testStr; + } + /* 根据产生IBI的I3C设备调用IBI回调函数 */ + return I3cCntlrIbiCallback(device); + } + + return HDF_SUCCESS; +} +``` \ No newline at end of file diff --git "a/zh-cn/device-dev/driver/figures/ADC\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/ADC\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..9b140042ffdfff77a76cc69814a0217af2ddc5df Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/ADC\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/ADC\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/driver/figures/ADC\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..da94f3b486edb6b269ef341b12b1816f23036c32 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/ADC\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/HDMI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/HDMI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..fa578f83d99f47e868312dad99d6b38fa960e794 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/HDMI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/HDMI\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/driver/figures/HDMI\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..9c1618562e33dd6fd08d2ec7f48454a43c1e1541 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/HDMI\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/HDMI\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/HDMI\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..23324872566e5affac8baa186a30b64b3257f673 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/HDMI\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..40c7088de596e771921861c727d4813f686eda40 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/I3C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/driver/figures/I3C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..08942f92cdc1c9fa6c0442537525cfcba90254a7 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/I3C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/I3C\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/I3C\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..838f9a4416d901eb29b5d203b559b3dcfe29fed9 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/I3C\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/USB-Device\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/USB-Device\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..3766cf8117505a0d47720dcbccc1030536921bdb Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/USB-Device\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/USB-Host\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/USB-Host\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..6bea2992afd00b031176998278c0bcfce0f8e843 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/USB-Host\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" differ diff --git a/zh-cn/device-dev/get-code/gettools-acquire.md b/zh-cn/device-dev/get-code/gettools-acquire.md index 5381dd4199cbbbf6a6c962dea25050e4bbb1d4d3..0179cc9eb4186dfd04e5391fea7920d120eaea57 100644 --- a/zh-cn/device-dev/get-code/gettools-acquire.md +++ b/zh-cn/device-dev/get-code/gettools-acquire.md @@ -222,7 +222,7 @@ hb set \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 -编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 +编译所生成的文件都归档在out/{device_name}/目录下,结果镜像输出在 out/{device_name}/packages/phone/images/ 目录下。 >![](../public_sys-resources/icon-note.gif) **说明:** diff --git a/zh-cn/device-dev/guide/Readme-CN.md b/zh-cn/device-dev/guide/Readme-CN.md index 29da041335cb35e904727db70752dcf564d4ad1e..ce9d01e0c1e707e51ead27f2c25026118818f59e 100755 --- a/zh-cn/device-dev/guide/Readme-CN.md +++ b/zh-cn/device-dev/guide/Readme-CN.md @@ -2,8 +2,7 @@ - [轻量和小型系统设备](device-lite.md) - [WLAN连接类产品](device-wlan.md) - - [LED外设控制](device-wlan-led.md) - - [LED外设控制](oem_wifi_sdk_des.md) + - [LED外设控制](oem_wifi_sdk_des.md) - [集成三方SDK](device-wlan-sdk.md) - [无屏摄像头类产品](device-iotcamera.md) - [摄像头控制](device-iotcamera-control.md) diff --git a/zh-cn/device-dev/guide/device-clock-guide.md b/zh-cn/device-dev/guide/device-clock-guide.md index a29494b1407d890eb135708eef3cba271565608e..d42e3f024bf38c9acd8fb6788152ecc410d8cf67 100644 --- a/zh-cn/device-dev/guide/device-clock-guide.md +++ b/zh-cn/device-dev/guide/device-clock-guide.md @@ -272,11 +272,7 @@ 2. 启动cmd命令窗口,执行以下命令,推送hap应用包到设备目录下并安装。 ``` - hdc smode - hdc target mount - hdc file send clock.hap /data/clock.hap - hdc shell chmod 666 /data/clock.hap - hdc shell bm install -p /data/clock.hap + hdc install clock.hap ``` 3. 启动应用。执行以下命令,其中ohos.samples.clock为应用包名,MainAbility为应用启动的Ability。 diff --git a/zh-cn/device-dev/guide/device-wlan-touch.md b/zh-cn/device-dev/guide/device-wlan-touch.md deleted file mode 100644 index 2736daf4e21899d4fdc083b852d1869a70e57343..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/guide/device-wlan-touch.md +++ /dev/null @@ -1,19 +0,0 @@ -# 碰一碰 - -- **[碰一碰概述](onehop-overview.md)** - -- **[准备工作](onehop-dev-prerequisites.md)** - -- **[开发Hi3861设备侧功能](onehop-dev-hi3861.md)** - -- **[开发原子化服务](onehop-dev-atomic-service.md)** - -- **[写入NFC标签信息](onehop-write-nfc-info.md)** - -- **[配置服务关联意图](onehop-configuration-device-tag.md)** - -- **[碰一碰拉起原子化服务](onehop-open-atomic-service.md)** - -- **[参考信息](onehop-reference-info.md)** - - diff --git a/zh-cn/device-dev/guide/device-wlan.md b/zh-cn/device-dev/guide/device-wlan.md index 026cb3d7e593b8578addb252afe33907c223e1a0..53dd5ce855be9e98b1fba15f1aadceec8f42d76b 100644 --- a/zh-cn/device-dev/guide/device-wlan.md +++ b/zh-cn/device-dev/guide/device-wlan.md @@ -1,6 +1,5 @@ # WLAN连接类产品 - -- **[碰一碰](device-wlan-touch.md)** + - **[LED外设控制](device-wlan-led.md)** diff --git a/zh-cn/device-dev/kernel/Readme-CN.md b/zh-cn/device-dev/kernel/Readme-CN.md index b63423d773efc9efdb195e0bd5a5bf548736e90f..3197acaa99c845171e4ebb7670c71e58458a3130 100755 --- a/zh-cn/device-dev/kernel/Readme-CN.md +++ b/zh-cn/device-dev/kernel/Readme-CN.md @@ -51,6 +51,7 @@ - [踩内存检测](kernel-mini-memory-debug-cet.md) - [异常调测](kernel-mini-memory-exception.md) - [Trace调测](kernel-mini-memory-trace.md) + - [LMS调测](kernel-mini-debug-lms.md) - [附录](kernel-mini-app.md) - [内核编码规范](kernel-mini-appx-code.md) - [基本数据结构](kernel-mini-appx-data.md) @@ -165,6 +166,8 @@ - [魔法键使用方法](kernel-small-debug-shell-magickey.md) - [用户态异常信息说明](kernel-small-debug-shell-error.md) - [Trace调测](kernel-small-debug-trace.md) + - [Perf调测](kernel-small-debug-perf.md) + - [LMS调测](kernel-small-debug-lms.md) - [进程调测](kernel-small-debug-process.md) - [CPU占用率](kernel-small-debug-process-cpu.md) - [内存调测](kernel-small-debug-memory.md) diff --git "a/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" deleted file mode 100755 index b69b5289481953570adc99ff0d8e33f3b61ff3f7..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" and /dev/null differ diff --git a/zh-cn/device-dev/kernel/kernel-mini-debug-lms.md b/zh-cn/device-dev/kernel/kernel-mini-debug-lms.md new file mode 100644 index 0000000000000000000000000000000000000000..faf8e495fd9f0de91b148f8da073bce7ded81c44 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-mini-debug-lms.md @@ -0,0 +1,293 @@ +# LMS调测 + +- [基本概念](#section1) + +- [运行机制](#section2) + +- [接口说明](#section3) + +- [开发指导](#section4) + + - [开发流程](#section4.1.1) + + - [编程实例](#section4.1.2) + + - [实例代码](#section4.1.3) + + - [结果验证](#section4.1.4) + + +## 基本概念 +LMS全称为Lite Memory Sanitizer,是一种实时检测内存操作合法性的调测工具。LMS能够实时检测缓冲区溢出(buffer overflow),释放后使用(use after free) 和重复释放(double Free), 在异常发生的第一时间通知操作系统,结合backtrace等定位手段,能准确定位到产生内存问题的代码行,极大提升内存问题定位效率。 + +## 运行机制 +LMS使用影子内存映射标记系统内存的状态,一共可标记为三个状态:可读写,不可读写,已释放。影子内存存放在内存池的尾部。 + +- 内存从堆上申请后,会将数据区的影子内存设置为“可读写”状态,并将头结点区的影子内存设置为“不可读写”状态。 + +- 内存在堆上被释放时,会将被释放内存的影子内存设置为“已释放”状态。 + +- 编译代码时,会在代码中的读写指令前插入检测函数,对地址的合法性进行检验。主要是检测访问内存的影子内存的状态值,若检测到影子内存为不可读写,则会报溢出错误;若检测到影子内存为已释放,则会报释放后使用错误。 + +- 在内存释放时,会检测被释放地址的影子内存状态值,若检测到影子内存非可读写,则会报重复释放错误。 + +## 接口说明 + +OpenHarmony LiteOS-M内核的LMS模块提供下面几种功能,接口详细信息可以查看[API](https://gitee.com/openharmony/kernel_liteos_m/blob/master/components/lms/los_lms.h)参考。 + + +1. 支持多内存池检测; + +2. 支持LOS_MemAlloc、LOS_MemAllocAlign、LOS_MemRealloc申请出的内存检测; + +3. 支持安全函数的访问检测(默认开启); + +4. 支持libc 高频函数的访问检测,包括:memset、memcpy、memmove、strcat、strcpy、strncat、strncpy。 + +5. 可动态设置的功能如下: + +**表 1** LMS模块接口说明 + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

添加指定内存池被检测

+

LOS_LmsCheckPoolAdd

+

将指定内存池的地址范围添加到LMS的内存检测链表上,当访问的地址在链表范围内时,LMS才进行合法性校验;且LOS_MemInit接口会调用该接口,默认将初始化的内存池挂入到检测链表中。

+

删除指定内存池不被检测

+

LOS_LmsCheckPoolDel

+

不检测指定内存池地址范围内的合法性校验。

+

使能指定内存段锁保护

+

LOS_LmsAddrProtect

+

为某段内存地址上锁,设置为不可读写,一旦访问则报错。

+

去能指定内存段锁保护

+

LOS_LmsAddrDisableProtect

+

为某段内存地址解锁,设置为可读写。

+
+ + +## 开发指导 + +### 开发流程 + +开启LMS调测的典型流程如下: + +1. 配置LMS模块相关宏。 + + 配置LMS控制宏LOSCFG_KERNEL_LMS,默认关,在kernel/liteos_a目录下执行 make update_config命令配置"Kernel->Enable Lite Memory Sanitizer"中打开: + + | 配置项 | menuconfig选项 | 含义 | 设置值 | + | ------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------ | + | LOSCFG_KERNEL_LMS | Enable Lms Feature | Lms模块的裁剪开关 | YES/NO | + | LOSCFG_LMS_MAX_RECORD_POOL_NUM | Lms check pool max num | LMS支持的检测内存池最大个数 | INT | + | LOSCFG_LMS_LOAD_CHECK | Enable lms read check | LMS内存读检测的裁剪开关 | YES/NO | + | LOSCFG_LMS_STORE_CHECK | Enable lms write check | LMS内存写检测的裁剪开关 | YES/NO | + | LOSCFG_LMS_CHECK_STRICT | Enable lms strict check, byte-by-byte | LMS内存逐字节严格检测的裁剪开关 | YES/NO | + +2. 在被检测模块的编译脚本中,增加LMS检测编译选项-fsanitize=kernel-address。 + +3. 为避免编译器优化,增加-O0编译选项。 + +4. gcc与clang编译选项存在差异,参照如下示例: + + ``` + if ("$ohos_build_compiler_specified" == "gcc") { + cflags_c = [ + "-O0", + "-fsanitize=kernel-address", + ] + } else { + cflags_c = [ + "-O0", + "-fsanitize=kernel-address", + "-mllvm", + "-asan-instrumentation-with-call-threshold=0", + "-mllvm", + "-asan-stack=0", + "-mllvm", + "-asan-globals=0", + ] + } + ``` + +5. 重新编译,查看串口输出。如果检测到内存问题,会输出检测结果。 + +### 编程实例 + + 本实例实现如下功能: + + 1. 创建一个用于Lms测试的任务。 + + 2. 构造内存溢出错误和释放后使用错误。 + + 3. 添加-fsanitize=kernel-address后编译执行,观察输出结果 + +### 示例代码 + +实例代码如下: + +```C +#define PAGE_SIZE (0x1000U) +#define INDEX_MAX 20 + +UINT32 g_lmsTestTaskId; +char g_testLmsPool[2 * PAGE_SIZE]; + +STATIC VOID testPoolInit(void) +{ + UINT32 ret = LOS_MemInit(g_testLmsPool, 2 * PAGE_SIZE); + if (ret != 0) { + PRINT_ERR("%s failed, ret = 0x%x\n", __FUNCTION__, ret); + return; + } +} + +static VOID LmsTestOsmallocOverflow(VOID) +{ + PRINTK("\n######%s start ######\n", __FUNCTION__); + UINT32 i; + CHAR *str = (CHAR *)LOS_MemAlloc(g_testLmsPool, INDEX_MAX); + PRINTK("str[%2d]=0x%2x ", INDEX_MAX, str[INDEX_MAX]); /* trigger heap overflow at str[INDEX_MAX] */ + PRINTK("\n######%s stop ######\n", __FUNCTION__); +} + +static VOID LmsTestUseAfterFree(VOID) +{ + PRINTK("\n######%s start ######\n", __FUNCTION__); + UINT32 i; + CHAR *str = (CHAR *)LOS_MemAlloc(g_testLmsPool, INDEX_MAX); + LOS_MemFree(g_testLmsPool, str); + PRINTK("str[%2d]=0x%2x ", 0, str[0]); /* trigger use after free at str[0] */ + PRINTK("\n######%s stop ######\n", __FUNCTION__); +} + +VOID LmsTestCaseTask(VOID) +{ + testPoolInit(); + LmsTestOsmallocOverflow(); + LmsTestUseAfterFree(); +} + +UINT32 Example_Lms_test(VOID){ + UINT32 ret; + TSK_INIT_PARAM_S lmsTestTask; + /* 创建用于lms测试的任务 */ + memset(&lmsTestTask, 0, sizeof(TSK_INIT_PARAM_S)); + lmsTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)LmsTestCaseTask; + lmsTestTask.pcName = "TestLmsTsk"; /* 测试任务名称 */ + lmsTestTask.uwStackSize = 0x800; + lmsTestTask.usTaskPrio = 5; + lmsTestTask.uwResved = LOS_TASK_STATUS_DETACHED; + ret = LOS_TaskCreate(&g_lmsTestTaskId, &lmsTestTask); + if(ret != LOS_OK){ + PRINT_ERR("LmsTestTask create failed .\n"); + return LOS_NOK; + } + return LOS_OK; +} +``` + +### 结果验证 + +输出结果如下: + +```c +######LmsTestOsmallocOverflow start ###### +[ERR]***** Kernel Address Sanitizer Error Detected Start ***** +[ERR]Heap buffer overflow error detected +[ERR]Illegal READ address at: [0x4157a3c8] +[ERR]Shadow memory address: [0x4157be3c : 4] Shadow memory value: [2] +OsBackTrace fp = 0x402c0f88 +runTask->taskName = LmsTestCaseTask +runTask->taskID = 2 +*******backtrace begin******* +traceback fp fixed, trace using fp = 0x402c0fd0 +traceback 0 -- lr = 0x400655a4 fp = 0x402c0ff8 +traceback 1 -- lr = 0x40065754 fp = 0x402c1010 +traceback 2 -- lr = 0x40044bd0 fp = 0x402c1038 +traceback 3 -- lr = 0x40004e14 fp = 0xcacacaca + +[LMS] Dump info around address [0x4157a3c8]: + + [0x4157a3a0]: 00 00 00 00 00 00 00 00 | [0x4157be3a | 0]: 1 1 + [0x4157a3a8]: ba dc cd ab 00 00 00 00 | [0x4157be3a | 4]: 2 2 + [0x4157a3b0]: 20 00 00 80 00 00 00 00 | [0x4157be3b | 0]: 2 0 + [0x4157a3b8]: 00 00 00 00 00 00 00 00 | [0x4157be3b | 4]: 0 0 + [0x4157a3c0]: 00 00 00 00 00 00 00 00 | [0x4157be3c | 0]: 0 0 + [0x4157a3c8]: [ba] dc cd ab a8 a3 57 41 | [0x4157be3c | 4]: [2] 2 + [0x4157a3d0]: 2c 1a 00 00 00 00 00 00 | [0x4157be3d | 0]: 2 3 + [0x4157a3d8]: 00 00 00 00 00 00 00 00 | [0x4157be3d | 4]: 3 3 + [0x4157a3e0]: 00 00 00 00 00 00 00 00 | [0x4157be3e | 0]: 3 3 + [0x4157a3e8]: 00 00 00 00 00 00 00 00 | [0x4157be3e | 4]: 3 3 + [0x4157a3f0]: 00 00 00 00 00 00 00 00 | [0x4157be3f | 0]: 3 3 +[ERR]***** Kernel Address Sanitizer Error Detected End ***** +str[20]=0xffffffba +######LmsTestOsmallocOverflow stop ###### + +###### LmsTestUseAfterFree start ###### +[ERR]***** Kernel Address Sanitizer Error Detected Start ***** +[ERR]Use after free error detected +[ERR]Illegal READ address at: [0x4157a3d4] +[ERR]Shadow memory address: [0x4157be3d : 2] Shadow memory value: [3] +OsBackTrace fp = 0x402c0f90 +runTask->taskName = LmsTestCaseTask +runTask->taskID = 2 +*******backtrace begin******* +traceback fp fixed, trace using fp = 0x402c0fd8 +traceback 0 -- lr = 0x40065680 fp = 0x402c0ff8 +traceback 1 -- lr = 0x40065758 fp = 0x402c1010 +traceback 2 -- lr = 0x40044bd0 fp = 0x402c1038 +traceback 3 -- lr = 0x40004e14 fp = 0xcacacaca + +[LMS] Dump info around address [0x4157a3d4]: + + [0x4157a3a8]: ba dc cd ab 00 00 00 00 | [0x4157be3a | 4]: 2 2 + [0x4157a3b0]: 20 00 00 80 00 00 00 00 | [0x4157be3b | 0]: 2 0 + [0x4157a3b8]: 00 00 00 00 00 00 00 00 | [0x4157be3b | 4]: 0 0 + [0x4157a3c0]: 00 00 00 00 00 00 00 00 | [0x4157be3c | 0]: 0 0 + [0x4157a3c8]: ba dc cd ab a8 a3 57 41 | [0x4157be3c | 4]: 2 2 + [0x4157a3d0]: 2c 1a 00 00 [00] 00 00 00 | [0x4157be3d | 0]: 2 [3] + [0x4157a3d8]: 00 00 00 00 00 00 00 00 | [0x4157be3d | 4]: 3 3 + [0x4157a3e0]: 00 00 00 00 00 00 00 00 | [0x4157be3e | 0]: 3 3 + [0x4157a3e8]: ba dc cd ab c8 a3 57 41 | [0x4157be3e | 4]: 2 2 + [0x4157a3f0]: 0c 1a 00 00 00 00 00 00 | [0x4157be3f | 0]: 2 3 + [0x4157a3f8]: 00 00 00 00 00 00 00 00 | [0x4157be3f | 4]: 3 3 +[ERR]***** Kernel Address Sanitizer Error Detected End ***** +str[ 0]=0x 0 +######LmsTestUseAfterFree stop ###### +``` +输出的关键信息包括: +- 错误类型: + - Heap buffer overflow堆内存越界 + - Use after free 释放后使用 +- 错误操作: + - Illegal Read非法读 + - Illegal Write非法写 + - Illegal Double free重复释放 +- 上下文: + - 当前任务信息(taskName, taskId) + - 回溯栈(backtrace) +- 出错地址的内存信息: + - 内存的值、及对应影子内存的值 + - 内存地址:内存值| [影子内存地址 | 影子内存字节内偏移]:影子内存值 + - 影子内存值:0(可读可写)、3(已释放)、2(红区)、1(填充值)。 diff --git a/zh-cn/device-dev/kernel/kernel-mini-extend-dynamic-loading-basic.md b/zh-cn/device-dev/kernel/kernel-mini-extend-dynamic-loading-basic.md index d18b1cfc921423cd995b056d91972c0eda393639..49d9521d2095410914faee84d869b06b577265bf 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-extend-dynamic-loading-basic.md +++ b/zh-cn/device-dev/kernel/kernel-mini-extend-dynamic-loading-basic.md @@ -10,7 +10,7 @@ - [ELF共享库编译链接选项](#section17292133274) -在硬件资源有限的小设备中,需要通过算法的动态部署能力来解决无法同时部署多种算法的问题。以开发者易用为主要考虑因素,同时考虑到多平台的通用性,LiteOS-M选择业界标准的ELF方案,方便拓展算法生态。LiteOS-M提供类似于dlopen、dlsym等接口,APP通过动态加载模块提供的接口可以加载、卸载相应算法库。如图1所示,APP需要通过三方算法库所需接口获取对应信息输出,三方算法库又依赖内核提供的基本接口,如malloc等。APP加载所需接口,并对相关的未定义符号完成重定位后,APP即可调用该接口完成功能调用。目前动态加载组件只支持arm架构。 +在硬件资源有限的小设备中,需要通过算法的动态部署能力来解决无法同时部署多种算法的问题。以开发者易用为主要考虑因素,同时考虑到多平台的通用性,LiteOS-M选择业界标准的ELF方案,方便拓展算法生态。LiteOS-M提供类似于dlopen、dlsym等接口,APP通过动态加载模块提供的接口可以加载、卸载相应算法库。如图1所示,APP需要通过三方算法库所需接口获取对应信息输出,三方算法库又依赖内核提供的基本接口,如malloc等。APP加载所需接口,并对相关的未定义符号完成重定位后,APP即可调用该接口完成功能调用。目前动态加载组件只支持arm架构。此外,待加载的共享库需要验签或者限制来源,确保系统的安全性。 **图 1** LiteOS-M内核动态加载架构图 ![](figure/LiteOS-M内核动态加载架构图.png "LiteOS-M内核动态加载架构图") diff --git a/zh-cn/device-dev/kernel/kernel-mini-overview.md b/zh-cn/device-dev/kernel/kernel-mini-overview.md index 0966779d95cab06335077285e069b53793abbbc1..cb0c2d42c1efd2b137d9c9358fd247f6b9d3cbcc 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-overview.md +++ b/zh-cn/device-dev/kernel/kernel-mini-overview.md @@ -29,9 +29,9 @@ CPU体系架构分为通用架构定义和特定架构定义两层,通用架

头文件位置

kernel/arch/include

+

arch/include

kernel/arch/<arch>/<arch>/<toolchain>/

+

arch/<arch>/<arch>/<toolchain>/

头文件命名

diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-lms.md b/zh-cn/device-dev/kernel/kernel-small-debug-lms.md new file mode 100644 index 0000000000000000000000000000000000000000..708a386da7455abb49651e1950331667ca0ca467 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-lms.md @@ -0,0 +1,477 @@ +# LMS调测 + +- [基本概念](#section1) + +- [运行机制](#section2) + +- [接口说明](#section3) + + - [内核态](#section3.1) + + - [用户态](#section3.2) + +- [开发指导](#section4) + + - [内核态开发流程](#section4.1.1) + + - [内核态编程实例](#section4.1.2) + + - [内核态实例代码](#section4.1.3) + + - [内核态结果验证](#section4.1.4) + + - [用户态开发流程](#section4.2.1) + + - [用户态编程实例](#section4.2.2) + + - [用户态实例代码](#section4.2.3) + + - [用户态结果验证](#section4.2.4) + +## 基本概念 +LMS全称为Lite Memory Sanitizer,是一种实时检测内存操作合法性的调测工具。LMS能够实时检测缓冲区溢出(buffer overflow),释放后使用(use after free) 和重复释放(double Free), 在异常发生的第一时间通知操作系统,结合backtrace等定位手段,能准确定位到产生内存问题的代码行,极大提升内存问题定位效率。 + +## 运行机制 +LMS使用影子内存映射标记系统内存的状态,一共可标记为三个状态:可读写,不可读写,已释放。影子内存存放在内存池的尾部。 + +- 内存从堆上申请后,会将数据区的影子内存设置为“可读写”状态,并将头结点区的影子内存设置为“不可读写”状态。 + +- 内存在堆上被释放时,会将被释放内存的影子内存设置为“已释放”状态。 + +- 编译代码时,会在代码中的读写指令前插入检测函数,对地址的合法性进行检验。主要是检测访问内存的影子内存的状态值,若检测到影子内存为不可读写,则会报溢出错误;若检测到影子内存为已释放,则会报释放后使用错误。 + +- 在内存释放时,会检测被释放地址的影子内存状态值,若检测到影子内存非可读写,则会报重复释放错误。 + +## 接口说明 + +### 内核态 + +OpenHarmony LiteOS-A内核的LMS模块提供下面几种功能,接口详细信息可以查看[API](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_lms.h)参考。 + + +1. 支持多内存池检测; + +2. 支持LOS_MemAlloc、LOS_MemAllocAlign、LOS_MemRealloc申请出的内存检测; + +3. 支持安全函数的访问检测(默认开启); + +4. 支持libc 高频函数的访问检测,包括:memset、memcpy、memmove、strcat、strcpy、strncat、strncpy。 + +5. 可动态设置的功能如下: + +**表 1** LMS模块接口说明 + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

添加指定内存池被检测

+

LOS_LmsCheckPoolAdd

+

将指定内存池的地址范围添加到LMS的内存检测链表上,当访问的地址在链表范围内时,LMS才进行合法性校验;且LOS_MemInit接口会调用该接口,默认将初始化的内存池挂入到检测链表中。

+

删除指定内存池不被检测

+

LOS_LmsCheckPoolDel

+

不检测指定内存池地址范围内的合法性校验。

+

使能指定内存段锁保护

+

LOS_LmsAddrProtect

+

为某段内存地址上锁,设置为不可读写,一旦访问则报错。

+

去能指定内存段锁保护

+

LOS_LmsAddrDisableProtect

+

为某段内存地址解锁,设置为可读写。

+
+ + +### 用户态 + +用户态仅提供LMS检测库,不提供对外接口。 + +## 开发指导 + +### 内核态开发流程 + +开启LMS调测的典型流程如下: + +1. 配置LMS模块相关宏。 + + 配置LMS控制宏LOSCFG_KERNEL_LMS,默认关,在kernel/liteos_a目录下执行 make update_config命令配置"Kernel->Enable Lite Memory Sanitizer"中打开: + + | 配置项 | menuconfig选项 | 含义 | 设置值 | + | ------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------ | + | LOSCFG_KERNEL_LMS | Enable Lms Feature | Lms模块的裁剪开关 | YES/NO | + | LOSCFG_LMS_MAX_RECORD_POOL_NUM | Lms check pool max num | LMS支持的检测内存池最大个数 | INT | + | LOSCFG_LMS_LOAD_CHECK | Enable lms read check | LMS内存读检测的裁剪开关 | YES/NO | + | LOSCFG_LMS_STORE_CHECK | Enable lms write check | LMS内存写检测的裁剪开关 | YES/NO | + | LOSCFG_LMS_CHECK_STRICT | Enable lms strict check, byte-by-byte | LMS内存逐字节严格检测的裁剪开关 | YES/NO | + +2. 在被检测模块的编译脚本中,增加LMS检测编译选项-fsanitize=kernel-address。 + +3. 为避免编译器优化,增加-O0编译选项。 + +4. gcc与clang编译选项存在差异,参照如下示例: + + ``` + if ("$ohos_build_compiler_specified" == "gcc") { + cflags_c = [ + "-O0", + "-fsanitize=kernel-address", + ] + } else { + cflags_c = [ + "-O0", + "-fsanitize=kernel-address", + "-mllvm", + "-asan-instrumentation-with-call-threshold=0", + "-mllvm", + "-asan-stack=0", + "-mllvm", + "-asan-globals=0", + ] + } + ``` + +5. 重新编译,查看串口输出。如果检测到内存问题,会输出检测结果。 + +### 内核态编程实例 + + 本实例实现如下功能: + + 1. 创建一个用于Lms测试的任务。 + + 2. 构造内存溢出错误和释放后使用错误。 + + 3. 添加-fsanitize=kernel-address后编译执行,观察输出结果 + +### 内核态示例代码 + +实例代码如下: + +```C +#define PAGE_SIZE (0x1000U) +#define INDEX_MAX 20 + +UINT32 g_lmsTestTaskId; +char g_testLmsPool[2 * PAGE_SIZE]; + +STATIC VOID testPoolInit(void) +{ + UINT32 ret = LOS_MemInit(g_testLmsPool, 2 * PAGE_SIZE); + if (ret != 0) { + PRINT_ERR("%s failed, ret = 0x%x\n", __FUNCTION__, ret); + return; + } +} + +static VOID LmsTestOsmallocOverflow(VOID) +{ + PRINTK("\n######%s start ######\n", __FUNCTION__); + UINT32 i; + CHAR *str = (CHAR *)LOS_MemAlloc(g_testLmsPool, INDEX_MAX); + PRINTK("str[%2d]=0x%2x ", INDEX_MAX, str[INDEX_MAX]); /* trigger heap overflow at str[INDEX_MAX] */ + PRINTK("\n######%s stop ######\n", __FUNCTION__); +} + +static VOID LmsTestUseAfterFree(VOID) +{ + PRINTK("\n######%s start ######\n", __FUNCTION__); + UINT32 i; + CHAR *str = (CHAR *)LOS_MemAlloc(g_testLmsPool, INDEX_MAX); + LOS_MemFree(g_testLmsPool, str); + PRINTK("str[%2d]=0x%2x ", 0, str[0]); /* trigger use after free at str[0] */ + PRINTK("\n######%s stop ######\n", __FUNCTION__); +} + +VOID LmsTestCaseTask(VOID) +{ + testPoolInit(); + LmsTestOsmallocOverflow(); + LmsTestUseAfterFree(); +} + +UINT32 Example_Lms_test(VOID){ + UINT32 ret; + TSK_INIT_PARAM_S lmsTestTask; + /* 创建用于lms测试的任务 */ + memset(&lmsTestTask, 0, sizeof(TSK_INIT_PARAM_S)); + lmsTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)LmsTestCaseTask; + lmsTestTask.pcName = "TestLmsTsk"; /* 测试任务名称 */ + lmsTestTask.uwStackSize = 0x800; + lmsTestTask.usTaskPrio = 5; + lmsTestTask.uwResved = LOS_TASK_STATUS_DETACHED; + ret = LOS_TaskCreate(&g_lmsTestTaskId, &lmsTestTask); + if(ret != LOS_OK){ + PRINT_ERR("LmsTestTask create failed .\n"); + return LOS_NOK; + } + return LOS_OK; +} +LOS_MODULE_INIT(Example_Lms_test, LOS_INIT_LEVEL_KMOD_EXTENDED); +``` + +### 内核态结果验证 + +输出结果如下: + +```c +######LmsTestOsmallocOverflow start ###### +[ERR][KProcess:LmsTestCaseTask]***** Kernel Address Sanitizer Error Detected Start ***** +[ERR][KProcess:LmsTestCaseTask]Heap buffer overflow error detected +[ERR][KProcess:LmsTestCaseTask]Illegal READ address at: [0x4157a3c8] +[ERR][KProcess:LmsTestCaseTask]Shadow memory address: [0x4157be3c : 4] Shadow memory value: [2] +OsBackTrace fp = 0x402c0f88 +runTask->taskName = LmsTestCaseTask +runTask->taskID = 2 +*******backtrace begin******* +traceback fp fixed, trace using fp = 0x402c0fd0 +traceback 0 -- lr = 0x400655a4 fp = 0x402c0ff8 +traceback 1 -- lr = 0x40065754 fp = 0x402c1010 +traceback 2 -- lr = 0x40044bd0 fp = 0x402c1038 +traceback 3 -- lr = 0x40004e14 fp = 0xcacacaca + +[LMS] Dump info around address [0x4157a3c8]: + + [0x4157a3a0]: 00 00 00 00 00 00 00 00 | [0x4157be3a | 0]: 1 1 + [0x4157a3a8]: ba dc cd ab 00 00 00 00 | [0x4157be3a | 4]: 2 2 + [0x4157a3b0]: 20 00 00 80 00 00 00 00 | [0x4157be3b | 0]: 2 0 + [0x4157a3b8]: 00 00 00 00 00 00 00 00 | [0x4157be3b | 4]: 0 0 + [0x4157a3c0]: 00 00 00 00 00 00 00 00 | [0x4157be3c | 0]: 0 0 + [0x4157a3c8]: [ba] dc cd ab a8 a3 57 41 | [0x4157be3c | 4]: [2] 2 + [0x4157a3d0]: 2c 1a 00 00 00 00 00 00 | [0x4157be3d | 0]: 2 3 + [0x4157a3d8]: 00 00 00 00 00 00 00 00 | [0x4157be3d | 4]: 3 3 + [0x4157a3e0]: 00 00 00 00 00 00 00 00 | [0x4157be3e | 0]: 3 3 + [0x4157a3e8]: 00 00 00 00 00 00 00 00 | [0x4157be3e | 4]: 3 3 + [0x4157a3f0]: 00 00 00 00 00 00 00 00 | [0x4157be3f | 0]: 3 3 +[ERR][KProcess:LmsTestCaseTask]***** Kernel Address Sanitizer Error Detected End ***** +str[20]=0xffffffba +######LmsTestOsmallocOverflow stop ###### + +###### LmsTestUseAfterFree start ###### +[ERR][KProcess:LmsTestCaseTask]***** Kernel Address Sanitizer Error Detected Start ***** +[ERR][KProcess:LmsTestCaseTask]Use after free error detected +[ERR][KProcess:LmsTestCaseTask]Illegal READ address at: [0x4157a3d4] +[ERR][KProcess:LmsTestCaseTask]Shadow memory address: [0x4157be3d : 2] Shadow memory value: [3] +OsBackTrace fp = 0x402c0f90 +runTask->taskName = LmsTestCaseTask +runTask->taskID = 2 +*******backtrace begin******* +traceback fp fixed, trace using fp = 0x402c0fd8 +traceback 0 -- lr = 0x40065680 fp = 0x402c0ff8 +traceback 1 -- lr = 0x40065758 fp = 0x402c1010 +traceback 2 -- lr = 0x40044bd0 fp = 0x402c1038 +traceback 3 -- lr = 0x40004e14 fp = 0xcacacaca + +[LMS] Dump info around address [0x4157a3d4]: + + [0x4157a3a8]: ba dc cd ab 00 00 00 00 | [0x4157be3a | 4]: 2 2 + [0x4157a3b0]: 20 00 00 80 00 00 00 00 | [0x4157be3b | 0]: 2 0 + [0x4157a3b8]: 00 00 00 00 00 00 00 00 | [0x4157be3b | 4]: 0 0 + [0x4157a3c0]: 00 00 00 00 00 00 00 00 | [0x4157be3c | 0]: 0 0 + [0x4157a3c8]: ba dc cd ab a8 a3 57 41 | [0x4157be3c | 4]: 2 2 + [0x4157a3d0]: 2c 1a 00 00 [00] 00 00 00 | [0x4157be3d | 0]: 2 [3] + [0x4157a3d8]: 00 00 00 00 00 00 00 00 | [0x4157be3d | 4]: 3 3 + [0x4157a3e0]: 00 00 00 00 00 00 00 00 | [0x4157be3e | 0]: 3 3 + [0x4157a3e8]: ba dc cd ab c8 a3 57 41 | [0x4157be3e | 4]: 2 2 + [0x4157a3f0]: 0c 1a 00 00 00 00 00 00 | [0x4157be3f | 0]: 2 3 + [0x4157a3f8]: 00 00 00 00 00 00 00 00 | [0x4157be3f | 4]: 3 3 +[ERR][KProcess:LmsTestCaseTask]***** Kernel Address Sanitizer Error Detected End ***** +str[ 0]=0x 0 +######LmsTestUseAfterFree stop ###### +``` +输出的关键信息包括: +- 错误类型: + - Heap buffer overflow堆内存越界 + - Use after free 释放后使用 +- 错误操作: + - Illegal Read非法读 + - Illegal Write非法写 + - Illegal Double free重复释放 +- 上下文: + - 当前任务信息(taskName, taskId) + - 回溯栈(backtrace) +- 出错地址的内存信息: + - 内存的值、及对应影子内存的值 + - 内存地址:内存值| [影子内存地址 | 影子内存字节内偏移]:影子内存值 + - 影子内存值:0(可读可写)、3(已释放)、2(红区)、1(填充值)。 + + +### 用户态开发流程 +在待检测的app编译脚本中,添加如下参数即可, 完整示例可参见/kernel/liteos_a/apps/lms/BUILD.gn +``` +if ("$ohos_build_compiler_specified" == "gcc") { + cflags_c = [ + "-O0", + "-fsanitize=kernel-address", + "-funwind-tables", + "-fasynchronous-unwind-tables", + ] + } else { + cflags_c = [ + "-O0", + "-fsanitize=kernel-address", + "-mllvm", + "-asan-instrumentation-with-call-threshold=0", + "-mllvm", + "-asan-stack=0", + "-mllvm", + "-asan-globals=0", + "-funwind-tables", + "-fasynchronous-unwind-tables", + ] + } + ldflags = [ + "-rdynamic", + "-lunwind", + "-lusrlms", + "-Wl,--wrap=realloc", + "-Wl,--wrap=calloc", + "-Wl,--wrap=malloc", + "-Wl,--wrap=free", + "-Wl,--wrap=valloc", + "-Wl,--wrap=aligned_alloc", + "-Wl,--wrap=memset", + "-Wl,--wrap=memcpy", + "-Wl,--wrap=memmove", + "-Wl,--wrap=strcpy", + "-Wl,--wrap=strcat", + ] + deps = [ "//kernel/liteos_a/kernel/extended/lms/usr:usrlmslib" ] + ``` + +### 用户态编程实例 + + 本实例实现如下功能: + + 1. 构造内存溢出错误和释放后使用错误。 + + 2. 添加对应编译选项后,重新编译执行 + +### 用户态示例代码 +实例代码如下 +```c +static void BufWriteTest(void *buf, int start, int end) +{ + for (int i = start; i <= end; i++) { + ((char *)buf)[i] = 'a'; + } +} + +static void BufReadTest(void *buf, int start, int end) +{ + char tmp; + for (int i = start; i <= end; i++) { + tmp = ((char *)buf)[i]; + } +} + +static void LmsMallocTest(void) +{ + printf("\n-------- LmsMallocTest Start --------\n"); + char *buf = (char *)malloc(16); + BufReadTest(buf, -1, 16); + free(buf); + printf("\n-------- LmsMallocTest End --------\n"); +} + +static void LmsFreeTest(void) +{ + printf("\n-------- LmsFreeTest Start --------\n"); + char *buf = (char *)malloc(16); + free(buf); + BufReadTest(buf, 1, 1); + free(buf); + printf("\n-------- LmsFreeTest End --------\n"); +} + +int main(int argc, char * const * argv) +{ + printf("\n############### Lms Test start ###############\n"); + char *tmp = (char *)malloc(5000); + LmsMallocTest(); + LmsFreeTest(); + printf("\n############### Lms Test End ###############\n"); +} +``` +### 用户态结果验证 +输出结果如下: + +```c +***** Lite Memory Sanitizer Error Detected ***** +Heap buffer overflow error detected! +Illegal READ address at: [0x1f8b3edf] +Shadow memory address: [0x3d34d3ed : 6] Shadow memory value: [2] + +Accessable heap addr 0 +Heap red zone 2 +Heap freed buffer 3 + +Dump info around address [0x1f8b3edf]: + + [0x1f8b3eb8]: 74 55 8b 1f 74 55 8b 1f | [0x3d34d3eb | 4]: 0 0 + [0x1f8b3ec0]: f8 9c 8b 1f 00 00 00 00 | [0x3d34d3ec | 0]: 0 0 + [0x1f8b3ec8]: 00 00 00 00 9c fc fc fc | [0x3d34d3ec | 4]: 0 0 + [0x1f8b3ed0]: 21 00 00 00 41 00 00 00 | [0x3d34d3ed | 0]: 0 0 + [0x1f8b3ed8]: 60 55 8b 1f 60 55 8b [1f]| [0x3d34d3ed | 4]: 2 [2] + [0x1f8b3ee0]: 50 4e 0b 00 00 00 00 00 | [0x3d34d3ee | 0]: 0 0 + [0x1f8b3ee8]: 09 00 00 00 00 00 00 00 | [0x3d34d3ee | 4]: 0 0 + [0x1f8b3ef0]: 00 00 00 00 08 03 09 00 | [0x3d34d3ef | 0]: 2 2 + [0x1f8b3ef8]: 00 00 00 00 00 00 00 00 | [0x3d34d3ef | 4]: 2 2 +***** Lite Memory Sanitizer Error Detected End ***** + +Backtrace() returned 5 addresses + #01: [0x4d6c] -> ./sample_usr_lms + #02: <(null)+0x2004074>[0x4074] -> ./sample_usr_lms + #03: <(null)+0x2003714>[0x3714] -> ./sample_usr_lms + #04: [0x363c] -> ./sample_usr_lms + #05: <(null)+0x1f856f30>[0x56f30] -> /lib/libc.so +-------- LMS_malloc_test End -------- + +***** Lite Memory Sanitizer Error Detected ***** +Use after free error detected! +Illegal Double free address at: [0x1f8b3ee0] +Shadow memory address: [0x3d34d3ee : 0] Shadow memory value: [3] + +Accessable heap addr 0 +Heap red zone 2 +Heap freed buffer 3 + + +Dump info around address [0x1f8b3ee0]: + + [0x1f8b3ec0]: f8 9c 8b 1f 00 00 00 00 | [0x3d34d3ec | 0]: 0 0 + [0x1f8b3ec8]: 00 00 00 00 fc fd fc fc | [0x3d34d3ec | 4]: 0 0 + [0x1f8b3ed0]: 21 00 00 00 20 01 00 00 | [0x3d34d3ed | 0]: 0 0 + [0x1f8b3ed8]: 60 55 8b 1f 60 55 8b 1f | [0x3d34d3ed | 4]: 2 2 + [0x1f8b3ee0]: [20] 60 9a 1f 40 61 9a 1f | [0x3d34d3ee | 0]: [3] 3 + [0x1f8b3ee8]: 60 62 9a 1f 80 63 9a 1f | [0x3d34d3ee | 4]: 3 3 + [0x1f8b3ef0]: 20 40 8b 1f 20 20 8b 1f | [0x3d34d3ef | 0]: 3 3 + [0x1f8b3ef8]: 00 00 00 00 00 00 00 00 | [0x3d34d3ef | 4]: 3 3 + [0x1f8b3f00]: 00 00 00 00 00 00 00 00 | [0x3d34d3f0 | 0]: 3 3 +***** Lite Memory Sanitizer Error Detected End ***** + +Backtrace() returned 5 addresses + #01: [0x4d6c] -> ./sample_usr_lms + #02: [0x5548] -> ./sample_usr_lms + #03: <(null)+0x2003fc4>[0x3fc4] -> ./sample_usr_lms + #04: [0x3664] -> ./sample_usr_lms + #05: <(null)+0x1f856f30>[0x56f30] -> /lib/libc.so + +-------- LMS_free_test End -------- +``` +输出的Backtrace中包含地址所在的文件名,用户需查找对应文件中地址对应的代码行号。 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-perf.md b/zh-cn/device-dev/kernel/kernel-small-debug-perf.md new file mode 100644 index 0000000000000000000000000000000000000000..6fa440f4f729f9b6ec94022148b1028ba5ee35f1 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-perf.md @@ -0,0 +1,506 @@ +# Perf调测 + +- [基本概念](#section1) + +- [运行机制](#section2) + +- [接口说明](#section3) + + - [内核态](#section3.1) + + - [用户态](#section3.2) + +- [开发指导](#section4) + + - [内核态开发流程](#section4.1.1) + + - [内核态编程实例](#section4.1.2) + + - [内核态实例代码](#section4.1.3) + + - [内核态结果验证](#section4.1.4) + + - [用户态开发流程](#section4.2.1) + + - [用户态编程实例](#section4.2.2) + + - [用户态实例代码](#section4.2.3) + + - [用户态结果验证](#section4.2.4) + +## 基本概念 +Perf为性能分析工具,依赖PMU(Performance Monitoring Unit)对采样事件进行计数和上下文采集,统计出热点分布(hot spot)和热路径(hot path)。 + +## 运行机制 +基于事件采样原理,以性能事件为基础,当事件发生时,相应的事件计数器溢出发生中断,在中断处理函数中记录事件信息,包括当前的pc、当前运行的任务ID以及调用栈等信息。 + +Perf提供2种工作模式,计数模式和采样模式。 + +计数模式仅统计事件发生的次数和耗时,采样模式会收集上下文数据到环形buffer中,需要IDE进行数据解析生成热点函数与热点路径。 + +## 接口说明 + +### 内核态 + +OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细信息可以查看[API](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_perf.h)参考。 + +**表 1** Perf模块接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

开启/停止Perf采样

+

LOS_PerfStart

+

开启采样

+

LOS_PerfStop

+

停止采样

+

配置Perf采样事件

+

LOS_PerfConfig

+

配置采样事件的类型、周期等

+

读取采样数据

+

LOS_PerfDataRead

+

读取采样数据到指定地址

+

注册采样数据缓冲区的钩子函数

+

LOS_PerfNotifyHookReg

+

注册缓冲区水线到达的处理钩子

+

LOS_PerfFlushHookReg

+

注册缓冲区刷cache的钩子

+
+ +1. Perf采样事件的结构体为PerfConfigAttr,详细字段含义及取值详见kernel\include\los_perf.h。 + +2. 采样数据缓冲区为环形buffer,buffer中读过的区域可以覆盖写,未被读过的区域不能被覆盖写。 + +3. 缓冲区有限,用户可通过注册水线到达的钩子进行buffer溢出提醒或buffer读操作。默认水线值为buffer总大小的1/2。 + 示例如下: + ```c + VOID Example_PerfNotifyHook(VOID) + { + CHAR buf[LOSCFG_PERF_BUFFER_SIZE] = {0}; + UINT32 len; + PRINT_DEBUG("perf buffer reach the waterline!\n"); + len = LOS_PerfDataRead(buf, LOSCFG_PERF_BUFFER_SIZE); + OsPrintBuff(buf, len); /* print data */ + } + LOS_PerfNotifyHookReg(Example_PerfNotifyHook); + ``` + +4. 若perf采样的buffer涉及到cpu 跨cache,则用户可通过注册刷cache的钩子,进行cache同步。 + 示例如下: + ```c + VOID Example_PerfFlushHook(VOID *addr, UINT32 size) + { + OsCacheFlush(addr, size); /* platform interface */ + } + LOS_PerfNotifyHookReg(Example_PerfFlushHook); + ``` + 刷cache接口视具体的平台自行配置。 + +### 用户态 + +新增perf字符设备,位于"/dev/perf",通过对设备节点的read\write\ioctl,实现用户态perf的读写和控制: + +- read: 用户态读取perf记录数据 + +- write: 用户态采样事件配置 + +- ioctl: 用户态Perf控制操作,包括 + ```C + #define PERF_IOC_MAGIC 'T' + #define PERF_START _IO(PERF_IOC_MAGIC, 1) + #define PERF_STOP _IO(PERF_IOC_MAGIC, 2) + ``` + 分别对应Perf启动(LOS_PerfStart)、停止(LOS_PerfStop) + +具体的使用方法参见[用户态编程实例](#section4.2.2) + + + +## 开发指导 + +### 内核态开发流程 + +开启Perf调测的典型流程如下: + +1. 配置Perf模块相关宏。 + + 配置Perf控制宏LOSCFG_KERNEL_PERF,默认关,在kernel/liteos_a目录下执行 make update_config命令配置"Kernel->Enable Perf Feature"中打开: + + | 配置项 | menuconfig选项 | 含义 | 设置值 | + | ------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------ | + | LOSCFG_KERNEL_PERF | Enable Perf Feature | Perf模块的裁剪开关 | YES/NO | + | LOSCFG_PERF_CALC_TIME_BY_TICK | Time-consuming Calc Methods->By Tick | Perf计时单位为tick | YES/NO | + | LOSCFG_PERF_CALC_TIME_BY_CYCLE | Time-consuming Calc Methods->By Cpu Cycle | Perf计时单位为cycle | YES/NO | + | LOSCFG_PERF_BUFFER_SIZE | Perf Sampling Buffer Size | Perf采样buffer的大小 | INT | + | LOSCFG_PERF_HW_PMU | Enable Hardware Pmu Events for Sampling | 使能硬件PMU事件,需要目标平台支持硬件PMU | YES/NO | + | LOSCFG_PERF_TIMED_PMU | Enable Hrtimer Period Events for Sampling | 使能高精度周期事件,需要目标平台支持高精度定时器 | YES/NO | + | LOSCFG_PERF_SW_PMU | Enable Software Events for Sampling | 使能软件事件,需要开启LOSCFG_KERNEL_HOOK | INT | + +2. 调用LOS_PerfConfig配置需要采样的事件。 + + Perf提供2种模式的配置,及3大类型的事件配置: + + 2种模式:计数模式(仅统计事件发生次数)、采样模式(收集上下文如任务ID、pc、backtrace等)。 + + 3种事件类型:CPU硬件事件(cycle、branch、icache、dcache等)、高精度周期事件(cpu clock)、OS软件事件(task switch、mux pend、irq等)。 + +3. 在需要采样的代码起始点调用LOS_PerfStart(UINT32 sectionId), 入参sectionId标记不同的采样回话id。 + +4. 在需要采样的代码结束点调用LOS_PerfStop。 + +5. 调用输出缓冲区数据的接口LOS_PerfDataRead读取采样数据,并使用IDE工具进行解析。 + + +### 内核态编程实例 + + 本实例实现如下功能: + + 1. 创建perf测试任务。 + + 2. 配置采样事件。 + + 3. 启动perf。 + + 4. 执行需要统计的算法。 + + 5. 停止perf。 + + 6. 输出统计结果。 + +### 内核态示例代码 + +前提条件:在menuconfig菜单中完成perf模块的配置。 + +实例代码如下: + +```C +#include "los_perf.h" +STATIC VOID OsPrintBuff(const CHAR *buf, UINT32 num) +{ + UINT32 i = 0; + PRINTK("num: "); + for (i = 0; i < num; i++) { + PRINTK(" %02d", i); + } + PRINTK("\n"); + PRINTK("hex: "); + for (i = 0; i < num; i++) { + PRINTK(" %02x", buf[i]); + } + PRINTK("\n"); +} + +STATIC VOID perfTestHwEvent(VOID) +{ + UINT32 ret; + CHAR *buf = NULL; + UINT32 len; + + PerfConfigAttr attr = { + .eventsCfg = { + .type = PERF_EVENT_TYPE_HW, + .events = { + [0] = {PERF_COUNT_HW_CPU_CYCLES, 0xFFFF}, + [1] = {PERF_COUNT_HW_BRANCH_INSTRUCTIONS, 0xFFFFFF00}, + }, + .eventsNr = 2, + .predivided = 1, /* cycle counter increase every 64 cycles */ + }, + .taskIds = {0}, + .taskIdsNr = 0, + .needSample = 0, + .sampleType = PERF_RECORD_IP | PERF_RECORD_CALLCHAIN, + }; + + ret = LOS_PerfConfig(&attr); + if (ret != LOS_OK) { + PRINT_ERR("perf config error %u\n", ret); + return; + } + + PRINTK("------count mode------\n"); + LOS_PerfStart(0); + test(); /* this is any test function*/ + LOS_PerfStop(); + + PRINTK("--------sample mode------ \n"); + attr.needSample = 1; + LOS_PerfConfig(&attr); + LOS_PerfStart(2); + test(); /* this is any test function*/ + LOS_PerfStop(); + + buf = LOS_MemAlloc(m_aucSysMem1, LOSCFG_PERF_BUFFER_SIZE); + if (buf == NULL) { + PRINT_ERR("buffer alloc failed\n"); + return; + } + + /* get sample data */ + len = LOS_PerfDataRead(buf, LOSCFG_PERF_BUFFER_SIZE); + OsPrintBuff(buf, len); /* print data */ + + (VOID)LOS_MemFree(m_aucSysMem1, buf); +} + +UINT32 Example_Perf_test(VOID){ + UINT32 ret; + TSK_INIT_PARAM_S perfTestTask; + /* 创建用于perf测试的任务 */ + memset(&perfTestTask, 0, sizeof(TSK_INIT_PARAM_S)); + perfTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)perfTestHwEvent; + perfTestTask.pcName = "TestPerfTsk"; /* 测试任务名称 */ + perfTestTask.uwStackSize = 0x800; + perfTestTask.usTaskPrio = 5; + perfTestTask.uwResved = LOS_TASK_STATUS_DETACHED; + ret = LOS_TaskCreate(&g_perfTestTaskId, &perfTestTask); + if(ret != LOS_OK){ + PRINT_ERR("PerfTestTask create failed.\n"); + return LOS_NOK; + } + return LOS_OK; +} +LOS_MODULE_INIT(perfTestHwEvent, LOS_INIT_LEVEL_KMOD_EXTENDED); +``` + +### 内核态结果验证 + +输出结果如下: + +```c +--------count mode---------- +[EMG] [cycles] eventType: 0xff: 5466989440 +[EMG] [branches] eventType: 0xc: 602166445 +------- sample mode---------- +[EMG] dump section data, addr: 0x8000000 length: 0x800000 +num: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 ... +hex: 00 ef ef ef 00 00 00 00 14 00 00 00 60 00 00 00 00 00 00 00 70 88 36 40 08 00 00 00 6b 65 72 6e 65 6c 00 00 01 00 00 00 cc 55 30 40 08 00 00 00 6b 65 72 6e 65 6c 00 00 +``` + +- 针对计数模式,系统在perf stop后会打印: + + 事件名称(cycles)、事件类型(0xff)、事件发生的次数(5466989440)。 + + 当采样事件为硬件PMU事件时,打印的事件类型为实际的硬件事件id,非enum PmuHWId中定义的抽象类型。 + +- 针对采样模式,系统在perf stop后会打印采样数据的地址和长度: + + dump section data, addr: (0x8000000) length: (0x5000) + + 用户可以通过JTAG口导出该片内存,再使用IDE线下工具解析。 + + 或者通过LOS_PerfDataRead将数据读到指定地址,进行查看或进一步处理。示例中OsPrintBuff为测试接口,其按字节打印Read到的采样数据,num表示第几个字节,hex表示该字节中的数值。 + +### 用户态开发流程 +通过在menuconfig配置"Driver->Enable PERF DRIVER",开启Perf驱动。该配置仅在内核Enable Perf Feature后,才可在Driver的选项中可见。 +1. 打开“/dev/perf”字符文件,进行读写和IOCTL操作; +2. 系统提供用户态的perf命令,该命令位于/bin目录下,cd bin 后可执行如下命令: +- ./perf start [id] 启动perf采样, id 为可选项,默认值为0 + +- ./perf stop 停止perf采样 + +- ./perf read \ 从采样缓冲区中读取nBytes数据并打印内容 + +- ./perf list 罗列-e支持的具体事件 + +- ./perf stat/record [option] \ 计数/采样模式命令 + +option可选如下: + +- -e,配置采样事件。可使用./perf list 中罗列的同类型事件。 + +- -p,配置事件采样周期。 + +- -o, 指定perf采样数据结果保存的文件路径。 + +- -t,任务Id过滤(白名单),只采取指定任务中的上下文。如果不指定改参数,则默认采集所有的任务。 + +- -s, 配置采样的具体上下文类型,可查阅los_perf.h中定义的PerfSampleType。 + +- -P, 进程Id过滤(白名单),只采取指定进程中的上下文。如果不指定改参数,则默认采集所有进程。 + +- -d, 是否进行分频(事件每发生64次累计+1),该选项仅在硬件cycle事件上生效。 + +command 为待统计的子程序。 + +用户态命令行的典型使用方法如下: + +./perf list 查看可使用的事件列表, 输出如下: + +```c +cycles [Hardware event] +instruction [Hardware event] +dcache [Hardware event] +dcache-miss [Hardware event] +icache [Hardware event] +icache-miss [Hardware event] +branch [Hardware event] +branch-miss [Hardware event] +clock [Timed event] +task-switch [Software event] +irq-in [Software event] +mem-alloc [Software event] +mux-pend [Software event] +``` +./perf stat -e cycles os_dump, 输出如下: + +```c +type: 0 +events[0]: 255, 0xffff +predivided: 0 +sampleType: 0x0 +needSample: 0 +usage os_dump [--help | -l | SERVICE] + --help: shows this help + -l: only list services, do not dump them + SERVICE: dumps only service SERVICE +time used: 0.058000(s) +[cycles] eventType: 0xff [core 0]: 21720647 +[cycles] eventType: 0xff [core 1]: 13583830 +``` + +./perf record -e cycles os_dump, 输出如下: + +```c +type: 0 +events[0]: 255, 0xffff +predivided: 0 +sampleType: 0x60 +needSample: 1 +usage os_dump [--help | -l | SERVICE] + --help: shows this help + -l: only list services, do not dump them + SERVICE: dumps only service SERVICE +dump perf data, addr: 0x408643d8 length: 0x5000 +time used: 0.059000(s) +save perf data success at /storage/data/perf.data +``` +> ![](../public_sys-resources/icon-note.gif)**说明** + + > 在进行./perf stat/record命令后,用户可多次执行./perf start 和 ./perf stop进行采样, 采样的事件配置为最近一次执行./perf stat/record 中设置的参数。 + +### 用户态编程实例 + + 本实例实现如下功能: + + 1. 打开perf字符设备。 + + 4. 写perf配置事件。 + + 3. 启动perf。 + + 5. 停止perf。 + + 6. 读取perf采样数据。 + +### 用户态示例代码 +实例代码如下 +```c +#include "fcntl.h" +#include "user_copy.h" +#include "sys/ioctl.h" +#include "fs/driver.h" +#include "los_dev_perf.h" +#include "los_perf.h" +#include "los_init.h" + +/* perf ioctl */ +#define PERF_IOC_MAGIC 'T' +#define PERF_START _IO(PERF_IOC_MAGIC, 1) +#define PERF_STOP _IO(PERF_IOC_MAGIC, 2) + +int main(int argc, char **argv) +{ + char *buf = NULL; + ssize_t len; + + int fd = open("/dev/perf", O_RDWR); + if (fd == -1) { + printf("Perf open failed.\n"); + exit(EXIT_FAILURE); + } + + PerfConfigAttr attr = { + .eventsCfg = { +#ifdef LOSCFG_PERF_HW_PMU + .type = PERF_EVENT_TYPE_HW, + .events = { + [0] = {PERF_COUNT_HW_CPU_CYCLES, 0xFFFF}, + }, +#elif defined LOSCFG_PERF_TIMED_PMU + .type = PERF_EVENT_TYPE_TIMED, + .events = { + [0] = {PERF_COUNT_CPU_CLOCK, 100}, + }, +#elif defined LOSCFG_PERF_SW_PMU + .type = PERF_EVENT_TYPE_SW, + .events = { + [0] = {PERF_COUNT_SW_TASK_SWITCH, 1}, + }, +#endif + .eventsNr = 1, /* 1 event */ + .predivided = 0, + }, + .taskIds = {0}, + .taskIdsNr = 0, + .processIds = {0}, + .processIdsNr = 0, + .needSample = 1, + .sampleType = PERF_RECORD_IP | PERF_RECORD_CALLCHAIN, + }; + (void)write(fd, &attr, sizeof(PerfConfigAttr)); /* perf config */ + + ioctl(fd, PERF_START, NULL); /* perf start */ + test(); + ioctl(fd, PERF_STOP, NULL); /* perf stop */ + + buf = (char *)malloc(LOSCFG_PERF_BUFFER_SIZE); + if (buf == NULL) { + printf("no memory for read perf 0x%x\n", LOSCFG_PERF_BUFFER_SIZE); + return -1; + } + + len = read(fd, buf, LOSCFG_PERF_BUFFER_SIZE); + OsPrintBuff(buf, len); /* print data */ + + free(buf); + close(fd); + return 0; +} +``` +### 用户态结果验证 +输出结果如下: + +```c +[EMG] dump section data, addr: 0x8000000 length: 0x800000 +num: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 ... +hex: 00 ef ef ef 00 00 00 00 14 00 00 00 60 00 00 00 00 00 00 00 70 88 36 40 08 00 00 00 6b 65 72 6e 65 6c 00 00 01 00 00 00 cc 55 30 40 08 00 00 00 6b 65 72 6e 65 6c 00 00 +``` diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-cpup.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-cpup.md index be52d26dcbed8f3d72027b75371ee8e352727ef3..73dc510cc0a1fe0c2c55aeb49f4b761c179517b5 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-cpup.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-cpup.md @@ -57,7 +57,7 @@ cpup \[_mode_\] \[_taskID_\] ## 输出说明 -**示例 1** 指令输出结果 +**示例** 指令输出结果 ```shell OHOS # cpup 1 5 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-date.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-date.md index a7359f79e99f11111345c789a85fcef71deefe56..dbe354520768fb7d9ca5535507032029b5454188 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-date.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-date.md @@ -13,13 +13,14 @@ date命令用于查询系统日期和时间。 ## 命令格式 -date +- date -date --help +- date --help -date +\[_Format_\] +- date +\[_Format_\] + +- date -u -date -u ## 参数说明 @@ -67,13 +68,11 @@ date -u ## 使用实例 -举例: - -输入 date +%Y--%m--%d +举例:输入 date +%Y--%m--%d ## 输出说明 -**示例 1** 按指定格式打印系统日期 +**示例** 按指定格式打印系统日期 ```shell OHOS:/$ date +%Y--%m--%d diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-dmesg.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-dmesg.md index a64be9d945594ab112b91eea54243501e4c321b1..285837cbed1de2b7e3f5ce151af70a1e1e0e176c 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-dmesg.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-dmesg.md @@ -13,15 +13,16 @@ dmesg命令用于控制内核dmesg缓存区。 ## 命令格式 -dmesg +- dmesg -dmesg \[_-c/-C/-D/-E/-L/-U_\] +- dmesg \[_-c/-C/-D/-E/-L/-U_\] -dmesg -s \[_size_\] +- dmesg -s \[_size_\] -dmesg -l \[_level_\] +- dmesg -l \[_level_\] + +- dmesg \> \[_fileA_\] -dmesg \> \[_fileA_\] ## 参数说明 @@ -102,13 +103,11 @@ dmesg \> \[_fileA_\] ## 使用实例 -举例: - -输入dmesg \> dmesg.log。 +举例:输入dmesg \> dmesg.log。 ## 输出说明 -**示例 1** dmesg重定向到文件。 +**示例** dmesg重定向到文件。 ```shell OHOS # dmesg > dmesg.log diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-free.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-free.md index d37eb4f96c804d4e083dee34cafed0bf3feeb23d..3ef00f87b00ad57c8872ce098fb4d654053735e1 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-free.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-free.md @@ -90,7 +90,7 @@ free \[_-b | -k | -m | -g | -t_\] ## 输出说明 -**示例 1** 以三种方式显示内存使用情况 +**示例** 以三种方式显示内存使用情况 ```shell OHOS:/$ free diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-help.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-help.md index 5a1b32501a81508183a6c15bf87426333a100e6e..a5e1a75b0fb8fe2ff3f0255b82acc92e3d39df63 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-help.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-help.md @@ -29,36 +29,35 @@ help用于显示当前操作系统内所有操作指令。 ## 输出说明 -**示例1** 查看系统内所有操作指令 +**示例** 查看系统内所有操作指令 ```shell OHOS:/$ help +OHOS:/$ help *******************shell commands:************************* -arp cat cat_logmpp cd chgrp chmod chown cp -cpup date dhclient dmesg dns format free help -hi3881 hwi ifconfig ipdebug kill log ls lsfd -memcheck mkdir mount netstat oom panicreset partinfo partition -ping ping6 pmm pwd reset rm rmdir sem -shm stack statfs su swtmr sync systeminfo task -telnet touch umount uname v2p vmm watch writeproc -usage: help [command] - -Show usage information for toybox commands. -Run "toybox" with no arguments for a list of available commands. -``` - -**内容声明:** +arp cat cat_logmpp cd chgrp chmod +chown cp cpup date dhclient dmesg +dns format free help hi3881 hwi +ifconfig ipdebug kill log ls lsfd +memcheck mkdir mount netstat oom panicreset +partinfo partition ping ping6 pmm pwd +reset rm rmdir sem shm stack +statfs su swtmr sync systeminfo task +telnet touch umount uname v2p vmm +watch writeproc -展示toybox指令请使用toybox。 +After shell prompt "OHOS # ": +Use ` [args ...]` to run built-in shell commands listed above. +Use `exec [args ...]` or `./ [args ...]` to run external commands. -**示例2** toybox指令集 +*******************toybox commands:************************ -```shell -OHOS:/$ toybox chgrp chmod chown cp date du free help ifconfig kill ls mkdir mount mv ping ps reboot rm rmdir top touch umount uname -``` - +Use `toybox help [command]` to show usage information for a specific command. +Use `shell` to enter interactive legacy shell. +Use `alias` to display command aliases. +``` diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-kill.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-kill.md index 2326ebaa81fb70d01eba365f4253566754aa2fe2..dbcead042ddc3af6cb2c0dacb9855c2d62c60aa7 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-kill.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-kill.md @@ -71,13 +71,14 @@ kill \[-l \[_signo_\] | _-s signo_ | _-signo_\] _pid..._ ## 使用指南 -必须指定发送的信号编号及进程号。 +- 必须指定发送的信号编号及进程号。 + +- 进程编号取值范围根据系统配置变化,例如系统最大支持pid为256,则取值范围缩小为\[1-256\]。 -进程编号取值范围根据系统配置变化,例如系统最大支持pid为256,则取值范围缩小为\[1-256\]。 ## 使用实例 -1. 查看当前进程列表,查看需要杀死的进程PID(42)。 +- 查看当前进程列表,查看需要杀死的进程PID(42)。 ``` OHOS:/$ ps @@ -102,7 +103,7 @@ OHOS:/$ ps 43 8 43 2 Running 0x1d7000 0x3a000 0x1e577 0.0 toybox ``` -2. 发送信号9(SIGKILL默认行为为立即终止进程)给42号进程**test\_demo**(用户态进程):**kill -s 9 42**(kill -9 42效果相同),并查看当前进程列表,42号进程已终止。 +发送信号9(SIGKILL默认行为为立即终止进程)给42号进程**test\_demo**(用户态进程):**kill -s 9 42**(kill -9 42效果相同),并查看当前进程列表,42号进程已终止。 ``` OHOS:/$ kill -s 9 42 @@ -129,6 +130,8 @@ OHOS:/$ ps 45 8 45 2 Running 0x1d7000 0x3a000 0x1e9f5 0.0 toybox ``` +- 发送不存在的信号值 kill -100 31 + ## 输出说明 发送成功或失败输出结果如下。 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-log.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-log.md index d143978cd0d7c1846f14f694d779a1c87dd97500..8edb4bcf120e9d081d217cc698bb8d9a9bfbfe05 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-log.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-log.md @@ -66,12 +66,12 @@ log level \[_levelNum_\] ## 使用实例 -举例: - -输入log level 3 +举例:输入log level 3 ## 输出说明 +**示例** 设置当前日志打印级别为3 + ```shell OHOS # log level 3 Set current log level WARN diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-memcheck.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-memcheck.md index 1b6d0f6369d5ff78e816158f3602bd08a6934c16..989f35f97a1b9a35ba8bc2999f57b67cea8a88ed 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-memcheck.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-memcheck.md @@ -26,7 +26,10 @@ memcheck ## 使用实例 -举例:输入memcheck +举例: + +- 输入memcheck +- 输入memcheck出现内存越界 ## 输出说明 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-oom.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-oom.md index 1e947e576b9db558a8024552f1bbe401809bb9db..dc61c380e0008659bb020afe7dd0e239819cabf3 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-oom.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-oom.md @@ -12,15 +12,16 @@ ## 命令格式 -oom +- oom -oom -i \[_interval_\] +- oom -i \[_interval_\] -oom -m \[_mem byte_\] +- oom -m \[_mem byte_\] -oom -r \[_mem byte_\] +- oom -r \[_mem byte_\] + +- oom -h | --help -oom -h | --help ## 参数说明 @@ -73,11 +74,25 @@ oom -h | --help >![](../public_sys-resources/icon-note.gif) **说明:** >当系统内存不足时,会打印出内存不足的提示信息。 +- oom -i 100 + ## 输出说明 +**示例 1** oom缺省打印配置信息 + +```shell +OHOS:/$ oom +[oom] oom loop task status: enabled + oom low memory threshold: 0x80000(byte) + oom reclaim memory threshold: 0x500000(byte) + oom check interval: 100(microsecond) +``` + +系统内存不足时打印提示信息 + ```shell T:20 Enter:IT MEM 00M 001 -[oom] 0S is in low memory state +[oom] OS is in low memory state total physical memory: 0x1bcf000(byte), used: 0x1b50000(byte) ,free: 0x7f000(byte), low memory threshold: 0x80000(byte) [oom] candidate victim process init pid: 1, actual phy mem byte:82602 [oom] candidate victim process shell pid: 3, actual phy mem byte:14950e @@ -120,6 +135,13 @@ traceback 4 -- lr = 0x92427d4 fp = 0x20e20d44 lr in /usr/bin/testsuits app --> 0 traceback 5 -- 1r = 0x20c4df50 fp = 0хb0b0b0b 1r in /1ib/libc.so - -> 0x62f50 ``` +**示例 2** 设置 oom 线程任务检查的时间间隔 + +```shell +OHOS:/$ oom -i 100 +[oom] set oom check interval (100)ms successful +``` + **表 2** 输出说明 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-pmm.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-pmm.md index fca464be3deb316592cc0ac4fdbcb8e3ee4a57a0..16627c7f06ed6b5834d8441dafc4351bfd283aad 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-pmm.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-pmm.md @@ -25,11 +25,11 @@ Debug版本才具备的命令。 ## 使用实例 -输入pmm +举例:输入pmm ## 输出说明 -**示例 1** 查看物理页使用情况 +**示例** 查看物理页使用情况 ```shell OHOS # pmm diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sem.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sem.md index 0419b1128bbba319841ed402166d7cab8227ff96..3b8d57161af14e93b2bad6d6ba85a7dad07d23b1 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sem.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sem.md @@ -56,11 +56,11 @@ sem \[_ID__ / fulldata_\] ## 使用实例 -举例1:输入 sem fulldata +举例:输入 sem fulldata ## 输出说明 -**示例 1** 查询所有在用的信号量信息 +**示例** 查询所有在用的信号量信息 ```shell OHOS # sem diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-stack.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-stack.md index 73e950e6b90607dea1434d2be6de3954588dd4ca..22c5d2578131296d40c68af3aac713c210e54fc7 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-stack.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-stack.md @@ -25,11 +25,11 @@ stack ## 使用实例 -输入:stack +举例:输入stack ## 输出说明 -**示例 1** 系统堆栈使用情况 +**示例** 系统堆栈使用情况 ```shell OHOS # stack diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-su.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-su.md index 184b1fe6bdfc4b300bf6494b9c9cfe122c019210..3c84c74d27349d5bf97d9628e5f7e2a64df6a597 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-su.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-su.md @@ -57,7 +57,7 @@ su \[_uid_\] \[_gid_\] ## 输出说明 -**示例 1** **切换到**为uid为1000,gid为1000的用户 +**示例** 从当前用户切换至uid为1000,gid为1000的用户 ```shell OHOS # ls diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-swtmr.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-swtmr.md index d8c1b45ec5cf9ce87e3b3173e255df1373a5f036..48e4f83a588d8d14d269e1fcadfbaa8da07bc46d 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-swtmr.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-swtmr.md @@ -45,7 +45,10 @@ swtmr \[_ID_\] ## 使用实例 -举例:输入swtmr和swtmr 1 +举例: + +- swtmr +- swtmr 1 ## 输出说明 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sysinfo.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sysinfo.md index 4306973436785f8da283766bacb4e0c30c898b60..6daeaee0accf7da620fa6b27f27e0a1eccc71eac 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sysinfo.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sysinfo.md @@ -29,8 +29,18 @@ systeminfo ## 输出说明 -**图 1** 查看系统资源使用情况 -![](figure/查看系统资源使用情况.png "查看系统资源使用情况") +**示例** 查看系统资源使用情况 + +```shell +OHOS:/$ systeminfo + + Module Used Total Enabled +-------------------------------------------- + Task 96 256 YES + Sem 435 1024 YES + Queue 13 1024 YES + SwTmr 20 1024 YES +``` **表 1** 输出说明 @@ -88,4 +98,3 @@ systeminfo
- diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-task.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-task.md index ea62b034cbc341e60679548e686ca3f69ad40b90..a6a6fee99c929c453d4a498f967aaf9c6c671b0f 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-task.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-task.md @@ -40,7 +40,7 @@ task/task -a ## 使用指南 -- 参数缺省时默认打印部分任务信息。 +参数缺省时默认打印部分任务信息。 ## 使用实例 @@ -48,7 +48,7 @@ task/task -a ## 输出说明 -**示例 1** 查询任务部分信息 +**示例** 查询任务部分信息 ```shell OHOS # task diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-top.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-top.md index 514f1594cfad74af7002e691e40aaa350295c509..b6126ec614dacc4753906e5fb4dbf232f8220cd3 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-top.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-top.md @@ -47,7 +47,7 @@ top \[_-a_\] ## 使用指南 -- 参数缺省时默认打印部分任务信息。 +参数缺省时默认打印部分任务信息。 ## 使用实例 @@ -55,7 +55,7 @@ top \[_-a_\] ## 输出说明 -**示例 1** top 命令显示详情 +**示例** top 命令显示详情 ```shell OHOS:/$ top diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-uname.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-uname.md index da30027e1a1eb76e9e749552d164240953f39c2e..913f54dd166113f8a6310c848b51203b982156af 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-uname.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-uname.md @@ -12,7 +12,7 @@ uname命令用于显示当前操作系统的名称,版本创建时间,系统 ## 命令格式 -uname \[_-a | -s | -r | -m | -n | -v --help_\] +uname \[_-a | -s | -r | -m | -n | -v | --help_\] **表 1** 参数说明 @@ -68,15 +68,21 @@ uname \[_-a | -s | -r | -m | -n | -v --help_\] ## 使用指南 -uname用于显示当前操作系统名称。语法uname -a | -s | -r | -m | -n | -v 描述uname 命令将正在使用的操作系统名写到标准输出中。 +- uname用于显示当前操作系统名称。 + +- 除参数--help和-a以外,其他参数可以相互搭配使用;uname -a 等价于 uname -srmnv。 + ## 使用实例 -举例:输入uname -a 、uname -ms +举例: + +- uname -a +- uname -ms ## 输出说明 -**示例 1** 查看系统信息 +**示例 1** 查看系统详细信息 ```shell OHOS:/$ uname -a diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-vmm.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-vmm.md index 3cdef6ee4ea7394ebf74842cdc1426bcbc09408e..3a4581381821161ea3cf208edfc1f906edf6169f 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-vmm.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-vmm.md @@ -13,9 +13,10 @@ ## 命令格式 -vmm \[_-a / -h / --help_\] +- vmm \[_-a / -h / --help_\] + +- vmm \[_pid_\] -vmm \[_pid_\] ## 参数说明 @@ -60,11 +61,11 @@ vmm \[_pid_\] ## 使用实例 -输入vmm 3 +举例:输入vmm 3 ## 输出说明 -**示例 1** PID为3的进程虚拟内存使用信息 +**示例** PID为3的进程虚拟内存使用信息 ```shell OHOS # vmm 3 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-watch.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-watch.md index 4ba183c88ddd1459a282f42ce1221a934caf45c0..7a7bb9c45609e74dabdeab7290ab7df63bc6af62 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-watch.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-watch.md @@ -13,9 +13,10 @@ watch命令用于周期性的监视一个命令的运行结果。 ## 命令格式 -watch +- watch + +- watch \[_-c/-n/-t/--count/--interval/-no-title/--over_\] \[_command_\] -watch \[_-c/-n/-t/--count/--interval/-no-title/--over_\] \[_command_\] ## 参数说明 @@ -86,13 +87,11 @@ watch运行过程中可以执行**watch --over**结束本次watch命令。 ## 使用实例 -输入举例: - -watch -n 2 -c 6 task +举例:watch -n 2 -c 6 task ## 输出说明 -**示例 1** watch task 结果 +**示例** watch task 结果 ```shell OHOS # watch -n 2 -c 6 task diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cat.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cat.md index a5142c76fa9df65142bd10276fbf9b350e0e8d5a..9e04dbf213ceb3df90c773dc435d1978f05ce592 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cat.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cat.md @@ -48,7 +48,7 @@ cat用于显示文本文件的内容。 ## 输出说明 -**示例 1** 查看 hello-harmony.txt 文件的信息 +**示例** 查看 hello-harmony.txt 文件的信息 ```shell OHOS # cat hello-harmony.txt diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cd.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cd.md index 3396a5f6bee14cbe7af9adbb9ce261ce3a0aa851..ccaa2af58e6612c8838e87115069505bf6857484 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cd.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cd.md @@ -53,7 +53,7 @@ cd \[_path_\] ## 输出说明 -**示例 1** 显示结果如下 +**示例** 显示结果如下 ```shell OHOS:/nfs$ cd ../ diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chgrp.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chgrp.md index 22aafd1c9d20d14dffb05806d608798fc18678b0..0d12a471cf0dbe6501182a0958eca0d3dd69425b 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chgrp.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chgrp.md @@ -57,7 +57,7 @@ chgrp \[_group_\] \[_pathname_\] ## 输出说明 -**示例 1** 修改 dev/目录下testfile 文件的群组为100 +**示例** 修改 /dev目录下testfile 文件的群组为100 ```shell OHOS:/dev$ ll testfile diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chmod.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chmod.md index d3cc5ebd5a39448fa4a6be81ed4f39f190d436a6..8dec87d6b6eb4714987b89574d15bb0976765aa3 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chmod.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chmod.md @@ -52,11 +52,11 @@ chmod \[_mode_\] \[_filename_\] ## 使用实例 -举例:chmod 644 hello-harmony.txt ; chmod 777 hello-harmony.txt +举例:修改hello-harmony.txt 文件权限为644和777。 ## 输出说明 -**示例 1** 修改/dev目录下 hello-harmony.txt 文件的权限 +**示例** 修改/dev目录下 hello-harmony.txt 文件的权限 ```shell OHOS:/dev$ chmod 644 hello-harmony.txt diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cp.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cp.md index dd3cb63667b9b7066d8354487d91343058966718..13718a5a578ee3ecfb12ea4d653d6dc41ce84c04 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cp.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cp.md @@ -13,8 +13,6 @@ ## 命令格式 -cp --help - cp \[_SOURCEFILE_\] \[_DESTFILE_\] ## 参数说明 @@ -73,7 +71,7 @@ cp \[_SOURCEFILE_\] \[_DESTFILE_\] ## 输出说明 -**示例 1** 显示结果如下 +**示例** 同时拷贝两个文件至指定目录 ```shell OHOS:/$ ls diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-du.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-du.md index 57e9708b44923c587a219905085b25c16a8be4be..1ba75a22e2381d889700ea021ce80bb4dbe30457 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-du.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-du.md @@ -84,7 +84,7 @@ du \[_-kKmh_\] \[_file..._\] ## 输出说明 -**示例 1** 显示结果如下 +**示例** 显示结果如下 ```shell OHOS:/$ du -h testfile diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-format.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-format.md index 586fa16f70751981d4a6c356aab50c0c3976087f..e1631934f03b55e1e4d71d0f080e3c0620cf1d48 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-format.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-format.md @@ -63,7 +63,7 @@ format <_dev\_inodename_\> <_sectors_\> <_option_\> \[_label_\] ## 输出说明 -结果如下: +**示例** 格式化mmc卡 ```shell OHOS # format /dev/mmcblk1 128 2 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-ls.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-ls.md index a1fb4a932fdad4d230e664bd0f25a1fdf20e50d7..5dee2d60e826aba076c9a07f71544ef36c0d75bb 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-ls.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-ls.md @@ -286,7 +286,10 @@ ls \[_-ACHLSZacdfhiklmnopqrstux1_\] \[_--color_\[_=auto_\]\] \[_directory..._\] ## 使用实例 -举例:输入ls、ll +举例: + +- ls +- ll ## 输出说明 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-lsfd.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-lsfd.md index 685e878c4aef1d5c81ab3f246756caaf58d307ad..bf08c2222209f7cf03dd9c5084ffe53413a23de3 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-lsfd.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-lsfd.md @@ -24,7 +24,7 @@ lsfd命令显示当前已经打开文件的fd号以及文件的名字。 ## 输出说明 -**示例 1** lsfd输出说明 +**示例** lsfd输出说明 ```shell OHOS # lsfd diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mount.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mount.md index 43551e38c86887ec41fe25413626ffbeebafe999..1ff71d655efa93af59cfc0c409ccd820122d9e1d 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mount.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mount.md @@ -84,7 +84,7 @@ mount后加需要挂载的设备信息、指定目录以及设备文件格式, ## 输出说明 -**示例 1** 将服务器端nfs目录192.168.1.3:/nfs挂载到当前系统下新建的/nfs目录: +**示例** 将服务器端nfs目录192.168.1.3:/nfs挂载到当前系统下新建的/nfs目录: ```shell OHOS:/$ mkdir nfs diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mv.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mv.md index 2c0dfaad23e1364e495fa55d7afd65c530e6ec6a..1c57edf36c0ed45c8337036c10fc9ce1ed5eeb6f 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mv.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mv.md @@ -91,9 +91,10 @@ mv \[_-fivn_\] _SOURCE... DEST_ 举例: -mv -i test.txt testpath/ +- mv -i test.txt testpath/ + +- mv test?.txt testpath/ (移动 test3.txt testA.txt test_.txt) -mv test?.txt testpath/ (移动 test3.txt testA.txt test_.txt) ## 输出说明 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partinfo.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partinfo.md index 7620a18cf87cc68a2856f72951a02d674746b1e4..8c768cff95f1acadd5fdb74c015d56e5e882b8fd 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partinfo.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partinfo.md @@ -40,14 +40,16 @@ partinfo <_dev\_inodename_\> ## 使用指南 -无 +无。 ## 使用实例 -partinfo /dev/mmcblk0p0 +举例:partinfo /dev/mmcblk0p0 ## 输出说明 +**示例** 查看系统分区信息 + ```shell OHOS # partinfo /dev/mmcblk0p0 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-pwd.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-pwd.md index dbb092db964384fdfb387ac3d23f4d93221672ca..108f538119c7c2768767885b9acfbf565b0bf588 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-pwd.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-pwd.md @@ -29,7 +29,7 @@ pwd 命令将当前目录的全路径名称(从根目录)写入标准输出 ## 输出说明 -**示例 1** 查看当前路径 +**示例** 查看当前路径 ```shell OHOS:/sdcard/nfs$ pwd diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rm.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rm.md index 121a2b16f4631c36ede78c1bac07132a05e4bb83..d9c59e6ffbe0ed0410b03148fbe84dbb0e8699a4 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rm.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rm.md @@ -69,8 +69,8 @@ rm \[_-fv_\] _FILE or rm_ \[_-rv_\] \[_PATH_ | _filename_\]... 举例: -1. 输入rm testfile -2. 输入rm -r testpath/ +- 输入rm testfile +- 输入rm -r testpath/ ## 输出说明 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rmdir.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rmdir.md index 5d568e398b5b3465301f7cc182069fcc43d23d02..c73affdd12d64b7934e820c857300b6b469a4d90 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rmdir.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rmdir.md @@ -71,7 +71,7 @@ rmdir \[_-p_\] \[_dirname..._\] ## 输出说明 -**示例 1** 删除一个名为 dir 的目录 +**示例** 删除一个名为 dir 的目录 ```shell OHOS:/test$ mkdir dir diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-statfs.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-statfs.md index 58d3d624c6511994f1b874f656c39738f5466866..628c69d67437a6a6fe0cd0cb3cdf466a632f6f81 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-statfs.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-statfs.md @@ -45,9 +45,9 @@ statfs \[_directory_\] 以nfs文件系统为例: -statfs /nfs +输入statfs /nfs -**示例 1** statfs输出说明 +**示例** 但因nfs文件系统信息 ```shell OHOS # statfs ./nfs diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-touch.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-touch.md index 7a10c652a076fe063d8ca4c5f90320b10c105cec..a22e0cd45381d89996d731ae2aeeb73f08f548aa 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-touch.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-touch.md @@ -57,7 +57,10 @@ touch \[_filename_\] ## 使用实例 -举例:输入touch file.c 输出说明 +举例: + +- touch file.c +- touch testfile1 testfile2 testfile3 ## 输出说明 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-umount.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-umount.md index 4356532dc2c3a3ed02298e36ed5d1400e712559d..46beb6e133a543afd13b54b1d136aa54f80ffa9f 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-umount.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-umount.md @@ -66,11 +66,14 @@ umount后加上需要卸载的指定文件系统的目录,即将指定文件 ## 使用实例 -举例:umount ./nfs 、umount -a -t nfs ./nfs +举例: + +- umount ./nfs +- umount -a -t nfs ./nfs ## 输出说明 -将已在./nfs挂载的文件系统卸载 +将已在./nfs挂载的文件系统卸载掉。 **示例 1** umount输出示例 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-arp.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-arp.md index b1a4b7ef3ea7264f765f953ca72f6eb2dfaca7be..34c657e197ef4f2429a53bd64fee3b5762944999 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-arp.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-arp.md @@ -12,11 +12,12 @@ ## 命令格式 -arp +- arp -arp \[_-i IF_\] -s _IPADDR HWADDR_ +- arp \[_-i IF_\] -s _IPADDR HWADDR_ + +- arp \[_-i IF_\] -d _IPADDR_ -arp \[_-i IF_\] -d _IPADDR_ ## 参数说明 @@ -72,45 +73,45 @@ arp \[_-i IF_\] -d _IPADDR_ 举例: -1. 输入arp - - **示例 1** 打印整个 ARP 缓存表 - - ```shell - OHOS # arp - Address HWaddress Iface Type - 192.168.1.10 E6:2B:99:2C:4B:20 eth0 static - ``` - - **表 2** 参数说明 - - - - - - - - - - - - - - - - - - - -

参数

-

说明

-

Address

-

表示网络设备的IPv4地址。

-

HWaddress

-

表示网络设备的MAC地址。

-

Iface

-

表示该ARP表项使用的接口名。

-

Type

-

表示该ARP表项是动态的还是静态的,动态是指ARP表项由协议栈自动创建,静态是指ARP表项是由用户增加的。

-
+输入arp + +**示例** 打印整个 ARP 缓存表 + +```shell +OHOS # arp +Address HWaddress Iface Type +192.168.1.10 E6:2B:99:2C:4B:20 eth0 static +``` + +**表 2** 参数说明 + + + + + + + + + + + + + + + + + + + +

参数

+

说明

+

Address

+

表示网络设备的IPv4地址。

+

HWaddress

+

表示网络设备的MAC地址。

+

Iface

+

表示该ARP表项使用的接口名。

+

Type

+

表示该ARP表项是动态的还是静态的,动态是指ARP表项由协议栈自动创建,静态是指ARP表项是由用户增加的。

+
diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-dhclient.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-dhclient.md index 0afc2536a824f4d9441ed83f5d3c28fd2a303297..01be24bbbb990099c46be109ad1d4b266f0a31fd 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-dhclient.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-dhclient.md @@ -13,9 +13,9 @@ ## 命令格式 -dhclient <_netif name_\> +- dhclient <_netif name_\> -dhclient -x <_netif name_\> +- dhclient -x <_netif name_\> ## 参数说明 @@ -56,12 +56,20 @@ dhclient -x <_netif name_\> ## 使用指南 -dhclient eth0 - -dhclient -x eth0 +无。 ## 使用实例 +举例: + +- dhclient eth0 +- dhclient -x eth0 + + +## 输出说明 + +**示例 1** 启动网卡eth0的dhcp请求 + ```shell OHOS:/$ dhclient eth0 OHOS:/$ ifconfig @@ -71,6 +79,11 @@ lo ip:127.0.0.1 netmask:255.0.0.0 gateway:127.0.0.1 eth0 ip:192.168.1.10 netmask:255.255.255.0 gateway:192.168.1.1 HWaddr 42:da:81:bc:58:94 MTU:1500 Running Default Link UP OHOS:/$ +``` + +**示例 2** 关闭网卡eth0的dhcp请求 + +```shell OHOS:/$ dhclient -x eth0 NetifStatusCallback(eth0): nsc event: 0xf0 OHOS:/$ ifconfig @@ -81,6 +94,3 @@ eth0 ip:0.0.0.0 netmask:0.0.0.0 gateway:0.0.0.0 HWaddr 42:da:81:bc:58:94 MTU:1500 Running Default Link UP ``` -## 输出说明 - -无。 \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ifconfig.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ifconfig.md index e6e68c7c605d609d6b89047f20f441f3dafeda7b..75aa986e55d066bd552f9dc9234d84a8419b1d9e 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ifconfig.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ifconfig.md @@ -13,19 +13,21 @@ ifconfig命令用来查询和设置网卡的IP地址、网络掩码、网关、 ## 命令格式 -ifconfig +ifconfig [option] -\[_-a_\] +option: -<_interface_\> <_address_\> \[_netmask _\] \[_gateway _\] +- \[_-a_\] -\[_hw ether _\] \[_mtu _\] +- <_interface_\> <_address_\> \[_netmask _\] \[_gateway _\] +- \[_hw ether _\] \[_mtu _\] -\[_inet6 add _\] +- \[_inet6 add _\] -\[_inet6 del _\] +- \[_inet6 del _\] + +- \[_up|down_\] -\[_up|down_\] ## 参数说明 @@ -136,182 +138,183 @@ ifconfig ## 使用实例 -1. ifconfig eth0 192.168.100.31 netmask 255.255.255.0 gateway 192.168.100.1 hw ether 00:49:cb:6c:a1:31 -2. ifconfig -a -3. ifconfig eth0 inet6 add 2001:a:b:c:d:e:f:d -4. ifconfig eth0 inet6 del 2001:a:b:c:d:e:f:d +- ifconfig eth0 192.168.100.31 netmask 255.255.255.0 gateway 192.168.100.1 hw ether 00:49:cb:6c:a1:31 +- ifconfig -a +- ifconfig eth0 inet6 add 2001:a:b:c:d:e:f:d +- ifconfig eth0 inet6 del 2001:a:b:c:d:e:f:d ## 输出说明 -1. 设置网络参数 - - ```shell - OHOS:/$ ifconfig eth0 192.168.100.31 netmask 255.255.255.0 gateway 192.168.100.1 hw ether 00:49:cb:6c:a1:31 - OHOS:/$ ifconfig - lo ip:127.0.0.1 netmask:255.0.0.0 gateway:127.0.0.1 - ip6: ::1/64 - HWaddr 00 MTU:0 Running Link UP - eth0 ip:192.168.100.31 netmask:255.255.255.0 gateway:192.168.100.1 - HWaddr 00:49:cb:6c:a1:31 MTU:1500 Running Default Link UP - ``` - - 输出的各参数说明如下表所示: - - **表 2** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

说明

-

ip

-

板子IP地址。

-

netmask

-

网络掩码。

-

gateway

-

网关。

-

HWaddr

-

板子硬件mac地址。

-

MTU

-

网络最大传输单元。

-

Running/Stop

-

网卡是否正在运行。

-

Default

-

有这项说明此网卡连接到默认网关。

-

Link UP/Down

-

网卡连接状态。

-
- -2. 获取协议栈统计信息 - - ```shell - OHOS # ifconfig -a - RX packets:6922 errors:0 ip dropped:4312 link dropped:67 overrun:0 bytes:0 (0.0 B) - RX packets(ip6):3 errors:0 dropped:0 overrun:0 bytes:0 (0.0 B) - TX packets:1394 errors:0 link dropped:67 overrun:0 bytes:0(0.0 B) - TX packets(ip6):3 errors:0 overrun:0 bytes:0(0.0 B) - ``` - - 输出的各参数说明如下表所示: - - **表 3** ifconfig -a 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

说明

-

RX packets

-

IP层已接收的正常数据包的个数。

-

RX error

-

IP层已接收的错误数据包的个数,错误类型包括长度错误,校验错误,IP option错误,IP首部protocol错误等。

-

RX dropped

-

IP层已丢弃的数据包的个数,丢弃原因包括数据包错误,封包无法转发,本地网卡处于关闭状态等。

-

RX overrun

-

MAC层向上层协议栈投递封包失败的个数,失败原因主要是协议栈资源不足。

-

RX bytes

-

IP层已接收的正常数据包的总长度,不包括重组未完成的分片的长度。

-

TX packets

-

IP层已正常发送或转发的数据包的个数。

-

TX error

-

IP层发送失败的数据包的个数,失败原因包括封包无法路由,封包在协议栈内处理失败等。

-

TX dropped

-

MAC层由于发送失败而丢弃的数据包个数,失败原因包括网卡驱动处理封包失败等。

-

TX overrun

-

暂未使用。

-

TX bytes

-

IP层已正常发送或者转发的数据包的总长度。

-
- -3. 设置IPv6的地址信息 - - ```shell - OHOS:/$ ifconfig eth0 inet6 add 2001:a:b:c:d:e:f:d - NetifStatusCallback(eth0): nsc event: 0x8 - NetifStatusCallback(eth0): nsc status changed: 0 - NetifStatusCallback(eth0): nsc event: 0x200 - NetifStatusCallback(eth0): nsc event: 0x8 - NetifStatusCallback(eth0): nsc status changed: 1 - NetifStatusCallback(eth0): nsc event: 0x200 - NetifStatusCallback(eth0): nsc event: 0x200 - OHOS:/$ ifconfig - lo ip:127.0.0.1 netmask:255.0.0.0 gateway:127.0.0.1 - ip6: ::1/64 - HWaddr 00 MTU:0 Running Link UP - eth0 ip:192.168.1.10 netmask:255.255.255.0 gateway:192.168.1.1 - ip6: 2001:A:B:C:D:E:F:D/64 - HWaddr 66:2f:e5:bd:24:e6 MTU:1500 Running Default Link UP - ``` - -4. 删除IPv6的地址信息 - - ```shell - OHOS:/$ ifconfig eth0 inet6 del 2001:a:b:c:d:e:f:d - NetifStatusCallback(eth0): nsc event: 0x200 - OHOS:/$ ifconfig - lo ip:127.0.0.1 netmask:255.0.0.0 gateway:127.0.0.1 - ip6: ::1/64 - HWaddr 00 MTU:0 Running Link UP - eth0 ip:192.168.1.10 netmask:255.255.255.0 gateway:192.168.1.1 - HWaddr 66:2f:e5:bd:24:e6 MTU:1500 Running Default Link UP - ``` +**示例 1** 设置网络参数 + +```shell +OHOS:/$ ifconfig eth0 192.168.100.31 netmask 255.255.255.0 gateway 192.168.100.1 hw ether 00:49:cb:6c:a1:31 +OHOS:/$ ifconfig +lo ip:127.0.0.1 netmask:255.0.0.0 gateway:127.0.0.1 + ip6: ::1/64 + HWaddr 00 MTU:0 Running Link UP +eth0 ip:192.168.100.31 netmask:255.255.255.0 gateway:192.168.100.1 + HWaddr 00:49:cb:6c:a1:31 MTU:1500 Running Default Link UP +``` + +输出的各参数说明如下表所示: + +**表 2** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

说明

+

ip

+

板子IP地址。

+

netmask

+

网络掩码。

+

gateway

+

网关。

+

HWaddr

+

板子硬件mac地址。

+

MTU

+

网络最大传输单元。

+

Running/Stop

+

网卡是否正在运行。

+

Default

+

有这项说明此网卡连接到默认网关。

+

Link UP/Down

+

网卡连接状态。

+
+ +**示例 2** 获取协议栈统计信息 + +```shell +OHOS # ifconfig -a +RX packets:6922 errors:0 ip dropped:4312 link dropped:67 overrun:0 bytes:0 (0.0 B) +RX packets(ip6):3 errors:0 dropped:0 overrun:0 bytes:0 (0.0 B) +TX packets:1394 errors:0 link dropped:67 overrun:0 bytes:0(0.0 B) +TX packets(ip6):3 errors:0 overrun:0 bytes:0(0.0 B) +``` + +输出的各参数说明如下表所示: + +**表 3** ifconfig -a 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

说明

+

RX packets

+

IP层已接收的正常数据包的个数。

+

RX error

+

IP层已接收的错误数据包的个数,错误类型包括长度错误,校验错误,IP option错误,IP首部protocol错误等。

+

RX dropped

+

IP层已丢弃的数据包的个数,丢弃原因包括数据包错误,封包无法转发,本地网卡处于关闭状态等。

+

RX overrun

+

MAC层向上层协议栈投递封包失败的个数,失败原因主要是协议栈资源不足。

+

RX bytes

+

IP层已接收的正常数据包的总长度,不包括重组未完成的分片的长度。

+

TX packets

+

IP层已正常发送或转发的数据包的个数。

+

TX error

+

IP层发送失败的数据包的个数,失败原因包括封包无法路由,封包在协议栈内处理失败等。

+

TX dropped

+

MAC层由于发送失败而丢弃的数据包个数,失败原因包括网卡驱动处理封包失败等。

+

TX overrun

+

暂未使用。

+

TX bytes

+

IP层已正常发送或者转发的数据包的总长度。

+
+ +**示例 3** 设置IPv6的地址信息 + +```shell +OHOS:/$ ifconfig eth0 inet6 add 2001:a:b:c:d:e:f:d +NetifStatusCallback(eth0): nsc event: 0x8 +NetifStatusCallback(eth0): nsc status changed: 0 +NetifStatusCallback(eth0): nsc event: 0x200 +NetifStatusCallback(eth0): nsc event: 0x8 +NetifStatusCallback(eth0): nsc status changed: 1 +NetifStatusCallback(eth0): nsc event: 0x200 +NetifStatusCallback(eth0): nsc event: 0x200 +OHOS:/$ ifconfig +lo ip:127.0.0.1 netmask:255.0.0.0 gateway:127.0.0.1 + ip6: ::1/64 + HWaddr 00 MTU:0 Running Link UP +eth0 ip:192.168.1.10 netmask:255.255.255.0 gateway:192.168.1.1 + ip6: 2001:A:B:C:D:E:F:D/64 + HWaddr 66:2f:e5:bd:24:e6 MTU:1500 Running Default Link UP +``` + +**示例 4** 删除IPv6的地址信息 + +```shell +OHOS:/$ ifconfig eth0 inet6 del 2001:a:b:c:d:e:f:d +NetifStatusCallback(eth0): nsc event: 0x200 +OHOS:/$ ifconfig +lo ip:127.0.0.1 netmask:255.0.0.0 gateway:127.0.0.1 + ip6: ::1/64 + HWaddr 00 MTU:0 Running Link UP +eth0 ip:192.168.1.10 netmask:255.255.255.0 gateway:192.168.1.1 + HWaddr 66:2f:e5:bd:24:e6 MTU:1500 Running Default Link UP +``` + diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ipdebug.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ipdebug.md index 548f65d15c51535f892d631b071887503ce75cd5..e34e37d124e1ba50bc31a1187a538feac537ecc8 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ipdebug.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ipdebug.md @@ -15,11 +15,11 @@ ipdebug ## 使用指南 -输入命令ipdebug。 +举例:输入命令ipdebug。 ## 输出说明 -ipdebug打印信息如下: +**示例** ipdebug打印信息如下: ```shell OHOS # ipdebug diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-netstat.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-netstat.md index 5edf074e3a81d83485b0ad6e172e10a8db54e254..10806a9510493c1b45b9c267ea46c72e62b38f09 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-netstat.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-netstat.md @@ -17,17 +17,19 @@ netstat ## 参数说明 -无 +无。 ## 使用指南 -直接输入命令。 +无。 ## 使用实例 举例:输入netstat -**示例 1** netstat 打印信息 +## 输出说明 + +**示例** netstat 打印信息 ```shell OHOS # netstat @@ -46,8 +48,6 @@ udp 0 0 127.0.0.1:62180 127.0.0.1:62179 udp 0 0 127.0.0.1:62178 127.0.0.1:62177 ``` -## 输出说明 - **表 1** 输出说明 @@ -94,4 +94,3 @@ udp 0 0 127.0.0.1:62178 127.0.0.1:62177 >![](../public_sys-resources/icon-note.gif) **说明:** >形如“========== total sockets 32 ====== unused sockets 22 BootTime 27 s ========== ”,表示一共32个套接字,未使用套接字22个,距系统启动已经过27秒。 - diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping.md index 0e2eab6f1742ab583c94dd178bfb91931d953ce1..80a1f466e03d33b36f3cd9cdf674d9514c1aac2b 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping.md @@ -100,7 +100,7 @@ ping _\[-4\] \[-c cnt\] \[-f\] \[-i interval\] \[-q\] \[-s size\] _ ## 输出说明 -**示例 1** ping tftp 服务器地址 +**示例** ping tftp 服务器地址 ```shell OHOS:/$ ping 192.168.1.3 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-telnet.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-telnet.md index 86038471bc14c1e34c59f6b4db80e0adf241a945..a249d9457f6b2726c8e9470cda4938d0c4f48677 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-telnet.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-telnet.md @@ -60,7 +60,7 @@ telnet \[_on | off_\] ## 输出说明 -**示例 1** 输入 telnet on +**示例** 输入 telnet on ```shell OHOS # telnet on diff --git a/zh-cn/device-dev/kernel/kernel-standard-overview.md b/zh-cn/device-dev/kernel/kernel-standard-overview.md index c60169d1584ec22906b125c6edc471e3a63b06a4..e9d637cad9ddb30cef2eaed004a19365ac74be6a 100644 --- a/zh-cn/device-dev/kernel/kernel-standard-overview.md +++ b/zh-cn/device-dev/kernel/kernel-standard-overview.md @@ -15,4 +15,4 @@ LTS为长期支持版本,“长期支持”体现在对该版本内核的长 ## OpenHarmony内核版本选择 -OpenHarmony中Linux内核从LTS版本中选择合适的版本作为内核的基础版本,目前已完成对Linux-4.19及Linux-5.10完成适配及支持。 +OpenHarmony中Linux内核从LTS版本中选择合适的版本作为内核的基础版本,目前已完成对Linux-4.19及Linux-5.10的适配及支持。 diff --git a/zh-cn/device-dev/porting/Readme-CN.md b/zh-cn/device-dev/porting/Readme-CN.md index 5fa708769896553325b89e0ce0298992c6e23bea..0e2ddbcf47a503e7d89cbba36c2c5476f2c42be4 100755 --- a/zh-cn/device-dev/porting/Readme-CN.md +++ b/zh-cn/device-dev/porting/Readme-CN.md @@ -34,6 +34,7 @@ repo init -u https://gitee.com/openharmony-sig/manifest.git -b master -m devboar - [板级驱动适配](porting-chip-board-driver.md) - [HAL层实现](porting-chip-board-hal.md) - [系统组件调用](porting-chip-board-component.md) + - [lwIP组件适配](porting-chip-board-lwip.md) - [三方组件适配](porting-chip-board-bundle.md) - [XTS认证](porting-chip-board-xts.md) - [常见问题](porting-chip-faqs.md) diff --git a/zh-cn/device-dev/porting/porting-chip-board-lwip.md b/zh-cn/device-dev/porting/porting-chip-board-lwip.md index 794042aad52ae789bbcdc8dda943de5b28405b3c..5fc2525d714bf76fb6ca9ce1c877d6e7f4449840 100644 --- a/zh-cn/device-dev/porting/porting-chip-board-lwip.md +++ b/zh-cn/device-dev/porting/porting-chip-board-lwip.md @@ -1,48 +1,64 @@ -# lwip组件适配 +# lwIP组件适配 -lwip是一个小型开源的TCP/IP协议栈,LiteOS-M已对开源lwip做了适配和功能增强,lwip代码分为两部分: +lwIP是一个小型开源的TCP/IP协议栈,LiteOS-M已对开源lwIP做了适配和功能增强,lwIP代码分为两部分: -- third_party/lwip目录下是lwip开源代码,里面只做了少量的侵入式修改,为了适配增强功能。 +- third_party/lwip目录下是lwIP开源代码,里面只做了少量的侵入式修改,为了适配增强功能。 -- kernel/liteos_m/components/net/lwip-2.1目录下是lwip适配和功能增强代码,里面提供了lwip的默认配置文件。 +- kernel/liteos_m/components/net/lwip-2.1目录下是lwIP适配和功能增强代码,里面提供了lwIP的默认配置文件。 -如果需要使用lwip组件,请按如下步骤适配: +如果需要使用lwIP组件,请按如下步骤适配: -1. 在产品目录下新建一个目录用来存放配置文件,如lwip_adapter。 +1. 在产品目录下新建一个目录用来存放产品的适配文件,如lwip_adapter。 -2. 将kernel/liteos_m/components/net/lwip-2.1/porting目录下的include目录和build.gn复制到步骤1的lwip_adapter目录下。 +2. 在lwip_adapter目录下新建一个目录include,用来存放适配的头文件。 -3. 如果默认配置不能满足产品使用,可根据产品使用情况修改对应的配置,如关闭DHCP功能,将lwip_adapter/include/lwip/lwipopts.h中宏LWIP_DHCP的值由1改为0。 +3. 在include目录下新建目录lwip,并在lwip目录下新建头文件lwipopts.h,代码如下所示,如果默认配置不能满足产品使用,可自行根据产品使用情况修改配置,如关闭DHCP功能。 ``` - //#define LWIP_DHCP 1 - #define LWIP_DHCP 0 + #ifndef _LWIP_ADAPTER_LWIPOPTS_H_ + #define _LWIP_ADAPTER_LWIPOPTS_H_ + + #include_next "lwip/lwipopts.h" + + #undef LWIP_DHCP + #define LWIP_DHCP 0 // 关闭DHCP功能 + + #endif /* _LWIP_ADAPTER_LWIPOPTS_H_ */ ``` -4. 将lwip_adapter/BUILD.gn里的LWIP_PORTING_INCLUDE_DIRS修改为步骤1中lwip_adapter目录下的include路径。 +4. 将kernel/liteos_m/components/net/lwip-2.1/porting目录下的BUILD.gn复制到lwip_adapter目录下,并按如下修改。 ``` - #include_dirs += LWIP_PORTING_INCLUDE_DIRS - include_dirs += "//xxx/lwip_adapter/include" + import("//kernel/liteos_m/liteos.gni") + import("$LITEOSTHIRDPARTY/lwip/lwip.gni") + import("$LITEOSTOPDIR/components/net/lwip-2.1/lwip_porting.gni") + + module_switch = defined(LOSCFG_NET_LWIP_SACK) + module_name = "lwip" + kernel_module(module_name) { + sources = LWIP_PORTING_FILES + LWIPNOAPPSFILES - [ "$LWIPDIR/api/sockets.c" ] + include_dirs = [ "//utils/native/lite/include" ] + } + + #添加新增加的适配头文件路径include + config("public") { + include_dirs = [ "include" ] + LWIP_PORTING_INCLUDE_DIRS + LWIP_INCLUDE_DIRS + } ``` -5. 在产品的配置文件中设置编译lwip的开关和编译路径,如config.json。 +5. 在产品的配置文件(如config.json)中设置lwIP的编译路径,即步骤4中BUILD.gn的路径。 ``` { "subsystem": "kernel", "components": [ - { "component": "liteos_m", "features":["enable_ohos_kernel_liteos_m_lwip = true", "ohos_kernel_liteos_m_lwip_path = \"//xxx/lwip_adapter:lwip\"" ] } + { "component": "liteos_m", "features":["ohos_kernel_liteos_m_lwip_path = \"//xxx/lwip_adapter\"" ] } ] }, ``` -6. 其他模块需要引用lwip头文件时,头文件路径应该包含如下两个部分,且顺序不能变。 +6. 在产品的内核编译配置文件中,如kernel_config/debug.config,打开编译lwIP的开关。 ``` - include_dir = [ - "//xxx/lwip_adapter/include", #步骤4里的路径 - "//third_party/lwip/src/include", - ] + LOSCFG_NET_LWIP=y ``` - diff --git a/zh-cn/device-dev/porting/porting-chip-kernel-overview.md b/zh-cn/device-dev/porting/porting-chip-kernel-overview.md index c05a50ef6703ec00d2006d93739e98dbf0a01676..e2bc9d055847389c77cce1aa9410e33351e0b1da 100644 --- a/zh-cn/device-dev/porting/porting-chip-kernel-overview.md +++ b/zh-cn/device-dev/porting/porting-chip-kernel-overview.md @@ -6,7 +6,7 @@ ## 移植场景 -芯片架构适配是可选过程,如果在liteos\_m/kernel/arch目录下已经支持对应芯片架构,则可以跳过芯片架构适配,进行单板适配过程,否则需要进行芯片架构移植工作。 +芯片架构适配是可选过程,如果在liteos\_m/arch目录下已经支持对应芯片架构,则可以跳过芯片架构适配,进行单板适配过程,否则需要进行芯片架构移植工作。 ## 目录规范 @@ -25,22 +25,22 @@ ``` . +├── arch --- 内核指令架构层代码 +│ ├── arm --- arm32架构的代码 +│ │ ├── cortex-m3 --- cortex-m3架构的代码 +│ │ │ ├── iar --- iar编译工具链实现 +│ │ │ ├── keil --- keil编译工具链实现 +│ │ │ └── xxx --- xxx编译工具链实现 +│ │ └── cortex-m4 --- cortex-m4架构的代码 +│ │ ├── iar --- iar编译工具链实现 +│ │ ├── keil --- keil编译工具链实现 +│ │ └── xxx --- xxx编译工具链实现 +│ ├── include --- 所有的arch需要实现的函数定义,内核依赖 +│ └── risc-v --- risk-v架构 +│ └── gcc --- gcc编译工具链实现 ├── components --- 移植可选组件,依赖内核,单独对外提供头文件 ├── kal --- 内核抽象层,提供内核对外接口,当前支持cmsis接口和部分posix接口 ├── kernel --- 内核最小功能集代码 -│ ├── arch --- 内核指令架构层代码 -│ │ ├── arm --- arm32架构的代码 -│ │ │ ├── cortex-m3 --- cortex-m3架构的代码 -│ │ │ │ ├── iar --- iar编译工具链实现 -│ │ │ │ ├── keil --- keil编译工具链实现 -│ │ │ │ └── xxx --- xxx编译工具链实现 -│ │ │ └── cortex-m4 --- cortex-m4架构的代码 -│ │ │ ├── iar --- iar编译工具链实现 -│ │ │ ├── keil --- keil编译工具链实现 -│ │ │ └── xxx --- xxx编译工具链实现 -│ │ ├── include --- 所有的arch需要实现的函数定义,内核依赖 -│ │ └── risc-v --- risk-v架构 -│ │ └── gcc --- iar编译工具链实现 │ ├── include --- 内核最小功能集代码 │ └── src --- 内核最小功能集代码 └──utils --- 基础代码,作为依赖的最底层,被系统依赖 diff --git a/zh-cn/device-dev/porting/porting-linux-kernel.md b/zh-cn/device-dev/porting/porting-linux-kernel.md index b2b0bbde337dce6883db975107c5fe8153744296..1139514ab02e862a9d5e2a59ff9bcecab4c640c1 100644 --- a/zh-cn/device-dev/porting/porting-linux-kernel.md +++ b/zh-cn/device-dev/porting/porting-linux-kernel.md @@ -249,11 +249,11 @@ HDF(Hardware Driver Foundation)自测试用例,用于测试HDF框架和外 ``` 2. 推送依赖库和测试用例到树莓派。 ``` - hdc_std file send XXX\out\ohos-arm-release\hdf\hdf\libhdf_test_common.z.so /system/lib - hdc_std file send XXX\out\ohos-arm-release\tests\unittest\hdf\config\hdf_adapter_uhdf_test_config /data/test - hdc_std file send XXX\out\ohos-arm-release\tests\unittest\hdf\devmgr\DevMgrTest /data/test - hdc_std file send XXX\out\ohos-arm-release\tests\unittest\hdf\osal\OsalTest /data/test - hdc_std file send XXX\out\ohos-arm-release\tests\unittest\hdf\sbuf\SbufTest /data/test + hdc_std file send XXX\out\{device_name}\hdf\hdf\libhdf_test_common.z.so /system/lib + hdc_std file send XXX\out\{device_name}\tests\unittest\hdf\config\hdf_adapter_uhdf_test_config /data/test + hdc_std file send XXX\out\{device_name}\tests\unittest\hdf\devmgr\DevMgrTest /data/test + hdc_std file send XXX\out\{device_name}\tests\unittest\hdf\osal\OsalTest /data/test + hdc_std file send XXX\out\{device_name}\tests\unittest\hdf\sbuf\SbufTest /data/test ``` 方法二:移动到储存卡内,启动树莓派之后装载。 diff --git a/zh-cn/device-dev/porting/standard-system-porting-guide.md b/zh-cn/device-dev/porting/standard-system-porting-guide.md index dc6e872ae9ada02665b5dc07017b205267a159f7..da6a71e2e44f02213ca066457530ede7a7043ef7 100644 --- a/zh-cn/device-dev/porting/standard-system-porting-guide.md +++ b/zh-cn/device-dev/porting/standard-system-porting-guide.md @@ -81,7 +81,7 @@ ./build.sh --product-name MyProduct ``` -构建完成后,可以在“//out/ohos-arm-release/packages/phone/images”目录下看到构建出来的OpenHarmony镜像文件。 +构建完成后,可以在“//out/{device_name}/packages/phone/images”目录下看到构建出来的OpenHarmony镜像文件。 ## 内核移植 diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md b/zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md index 37ffc8be224da928db8db09b84d2e002e11ed004..0065746573984364de78731874b2dc5233104441 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md @@ -116,7 +116,7 @@ bash build/prebuilts_download.sh \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 + 编译所生成的文件都归档在out/{device_name}/目录下,结果镜像输出在 out/{device_name}/packages/phone/images/ 目录下。 2. 编译源码完成,请进行镜像烧录,具体请参见[镜像烧录](quickstart-standard-burn.md)。 diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md b/zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md index 7d79728f80b0d8d3ed76df147c3fa08280996d67..3100bf73961fc2403f9621f03a07661358f3349c 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md @@ -91,7 +91,7 @@ bash build/prebuilts_download.sh =====build Hi3516DV300 successful. ``` - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在out/ohos-arm-release/packages/phone/images/ 目录下。 + 编译所生成的文件都归档在out/{device_name}/目录下,结果镜像输出在out/{device_name}/packages/phone/images/ 目录下。 >![](../public_sys-resources/icon-note.gif) **说明:** >其他模块化编译操作,可参见[编译构建指导](../subsystems/subsys-build-standard-large.md)。 diff --git a/zh-cn/device-dev/subsystems/subsys-build-standard-large.md b/zh-cn/device-dev/subsystems/subsys-build-standard-large.md index 9259a8073d9ae1a35c3fc17d4757bee73d72dab9..59d6b22ec1f2d0a44d07ee139eb0df357a98c2e4 100644 --- a/zh-cn/device-dev/subsystems/subsys-build-standard-large.md +++ b/zh-cn/device-dev/subsystems/subsys-build-standard-large.md @@ -98,7 +98,7 @@ OpenHarmony侧的编译构建流程主要包括编译命令行解析,调用gn \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 - 编译完成后,结果镜像保存在 out/ohos-arm-release/packages/phone/images/ 目录下。 + 编译完成后,结果镜像保存在 out/{device_name}/packages/phone/images/ 目录下。 - 编译命令支持选项: @@ -230,6 +230,6 @@ OpenHarmony侧的编译构建流程主要包括编译命令行解析,调用gn 4. 编译输出。 - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 + 编译所生成的文件都归档在out/hi3516dv300/目录下,结果镜像输出在 out/hi3516dv300/packages/phone/images/ 目录下。 diff --git a/zh-cn/device-dev/subsystems/subsys-security-communicationverify.md b/zh-cn/device-dev/subsystems/subsys-security-communicationverify.md old mode 100755 new mode 100644 diff --git a/zh-cn/device-dev/subsystems/subsys-tel-guide.md b/zh-cn/device-dev/subsystems/subsys-tel-guide.md index 854d11747ab665a1829a2915b13f69de24c8dfeb..5718a31637056a193ee208b2d2ac9b7a0c4f36d0 100644 --- a/zh-cn/device-dev/subsystems/subsys-tel-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-tel-guide.md @@ -606,5 +606,5 @@ ohos_shared_library("ril_vendor") { // Modem厂商库名称 ### 调测验证 1. 编译代码。 -2. 查看/out/ohos-arm-release/telephony/ril\_adapter目录是否存在libril\_vendor.z.so,存在证明集成成功。否则检查代码,重新编译验证。 +2. 查看/out/{device_name}/telephony/ril\_adapter目录是否存在libril\_vendor.z.so,存在证明集成成功。否则检查代码,重新编译验证。 diff --git a/zh-cn/device-dev/subsystems/subsys-testguide-test.md b/zh-cn/device-dev/subsystems/subsys-testguide-test.md index 6d22490c57c905dc3a5f4e8542f877efe685c463..3788200ef39dc7fac2e1b141fa81ffeb1496ecd3 100644 --- a/zh-cn/device-dev/subsystems/subsys-testguide-test.md +++ b/zh-cn/device-dev/subsystems/subsys-testguide-test.md @@ -39,21 +39,23 @@ subsystem # 子系统 │ │ ├── unittest # 单元测试 │ │ │ ├── common # 公共用例 │ │ │ │ ├── BUILD.gn # 测试用例编译配置 -│ │ │ │ ├── testA_test.cpp # 单元测试用例源码 +│ │ │ │ └── testA_test.cpp # 单元测试用例源码 │ │ │ ├── phone # 手机形态用例 │ │ │ ├── ivi # 车机形态用例 │ │ │ └── liteos-a # ipcamera使用liteos内核的用例 -│ │ └── resource # 依赖资源 -│ │ └── ohos_test.xml +│ │ ├── moduletest # 模块测试 +│ │ ... +│ │ │ ├── moduleB # 模块B │ ├── test -│ │ └── moduletest # 模块测试 -│ │ ├── common -│ │ ├── phone -│ │ ├── ivi -│ │ └── liteos-a -│ │ ... -│ └── ohos_build # 编译入口配置 +│ │ └── resource # 依赖资源 +│ │ ├── moduleA # 模块A +│ │ │ ├── ohos_test.xml # 资源配置文件 +│ │ ... └── 1.txt # 资源 +│ │ +│ ├── ohos_build # 编译入口配置 +│ ... +│ ... ``` > **注意:** 测试用例根据不同设备形态差异分为通用用例和非通用用例,建议将通用用例存放在common目录下,非通用用例存放在相应设备形态目录下。 @@ -232,9 +234,13 @@ subsystem # 子系统 - 测试体建议按照模板分步实现。 - 用例描述信息按照标准格式@tc.xxx value书写,注释信息必须包含用例名称,用例描述,用例类型,需求编号四项。其中用例测试类型@tc.type参数的选取,可参考下表。 - | 测试类型名称|功能测试|性能测试|可靠性测试|安全测试|模糊测试| - | ------------|------------|------------|------------|------------|------------| - | 类型编码|FUNC|PERF|RELI|SECU|FUZZ| + | 测试类型名称|类型编码| + | ------------|------------| + |功能测试 |FUNC| + |性能测试 |PERF| + |可靠性测试 |RELI| + |安全测试 |SECU| + |模糊测试 |FUZZ| **JavaScript参考示例** @@ -632,9 +638,9 @@ subsystem # 子系统 测试依赖资源主要包括测试用例在执行过程中需要的图片文件,视频文件、第三方库等对外的文件资源。 依赖资源文件配置步骤如下: -1. 在部件或者模块的test目录下创建resource目录,存放需要的资源文件 +1. 在部件的test目录下创建resource目录,在resource目录下创建对应的模块,在模块目录中存放该模块所需要的资源文件。 -2. 在resource目录下创建一个ohos_test.xml文件,文件内容格式如下: +2. 在resource目录下对应的模块目录中创建一个ohos_test.xml文件,文件内容格式如下: ``` @@ -646,15 +652,15 @@ subsystem # 子系统 ``` -3. 在测试用例的编译配置文件中定义resource_config_file进行指引,用来指定对应的资源文件ohos_test.xml +3. 在测试用例的编译配置文件中定义resource_config_file进行指引,用来指定对应的资源文件ohos_test.xml。 ``` ohos_unittest("CalculatorSubTest") { - resource_config_file = "//system/subsystem/partA/calculator/test/resource/ohos_test.xml" + resource_config_file = "//system/subsystem/partA/test/resource/calculator/ohos_test.xml" } ``` >**说明:** >- target_name: 测试套的名称,定义在测试目录的BUILD.gn中。preparer: 表示该测试套执行前执行的动作。 - >- src="res": 表示测试资源位于test目录下的resource目录下,src="out" 表示位于out/release/$(部件)目录下。 + >- src="res": 表示测试资源位于test目录下的resource目录下,src="out":表示位于out/release/$(部件)目录下。 ## 测试用例执行 在执行测试用例之前,针对用例使用设备的不同,需要对相应配置进行修改,修改完成即可执行测试用例。 @@ -718,7 +724,7 @@ subsystem # 子系统 >- product-name:指定编译产品名称,例如Hi3516DV300。 >- build-target:指定所需要编译的用例,make_test表示指定全部用例,实际开发中可指定特定用例。 -编译完成后,测试用例将自动保存在out/ohos-arm-release/packages/phone/tests目录下。 +编译完成后,测试用例将自动保存在out/hi3516dv300/packages/phone/tests目录下。 #### 搭建执行环境 1. 在Windows环境创建测试框架目录Test,并在此目录下创建testcase目录 @@ -757,10 +763,10 @@ subsystem # 子系统 执行命令参数说明: ``` -t [TESTTYPE]: 指定测试用例类型,有UT,MST,ST,PERF等。(必选参数) - -tp [TESTTYPE]: 指定部件,可独立使用。 - -tm [TESTTYPE]: 指定模块,不可独立使用,需结合-tp指定上级部件使用。 - -ts [TESTTYPE]: 指定测试套,可独立使用。 - -tc [TESTTYPE]: 指定测试用例,不可独立使用,需结合-ts指定上级测试套使用。 + -tp [TESTPART]: 指定部件,可独立使用。 + -tm [TESTMODULE]: 指定模块,不可独立使用,需结合-tp指定上级部件使用。 + -ts [TESTSUITE]: 指定测试套,可独立使用。 + -tc [TESTCASE]: 指定测试用例,不可独立使用,需结合-ts指定上级测试套使用。 -h : 帮助命令。 ``` ### Linux环境执行 @@ -797,10 +803,10 @@ subsystem # 子系统 执行命令参数说明: ``` -t [TESTTYPE]: 指定测试用例类型,有UT,MST,ST,PERF等。(必选参数) - -tp [TESTTYPE]: 指定部件,可独立使用。 - -tm [TESTTYPE]: 指定模块,不可独立使用,需结合-tp指定上级部件使用。 - -ts [TESTTYPE]: 指定测试套,可独立使用。 - -tc [TESTTYPE]: 指定测试用例,不可独立使用,需结合-ts指定上级测试套使用。 + -tp [TESTPART]: 指定部件,可独立使用。 + -tm [TESTMODULE]: 指定模块,不可独立使用,需结合-tp指定上级部件使用。 + -ts [TESTSUITE]: 指定测试套,可独立使用。 + -tc [TESTCASE]: 指定测试用例,不可独立使用,需结合-ts指定上级测试套使用。 -h : 帮助命令。 ``` diff --git a/zh-cn/readme.md b/zh-cn/readme.md index a8aeda8b9cf5977171b6dffec98508f3d0248110..ac183bb6a815c6346024d80a7df0dcd9636c6b4b 100644 --- a/zh-cn/readme.md +++ b/zh-cn/readme.md @@ -17,7 +17,6 @@ - Security:[隐私与安全](device-dev/security/Readme-CN.md) - guide:开发示例 - - [碰一碰](device-dev/guide/device-wlan-touch.md) - [WLAN连接类产品](device-dev/guide/device-wlan.md)(LED外设控制、集成三方SDK) - [无屏摄像头类产品](device-dev/guide/device-iotcamera-control.md)(摄像头控制) - [带屏摄像头类产品](device-dev/guide/device-camera.md)(屏幕和摄像头控制、视觉应用开发) diff --git "a/zh-cn/readme/\344\272\213\344\273\266\351\200\232\347\237\245\345\255\220\347\263\273\347\273\237.md" "b/zh-cn/readme/\344\272\213\344\273\266\351\200\232\347\237\245\345\255\220\347\263\273\347\273\237.md" index 1a5d7443cde7eff1fc7ed84c056fa2c37a597334..3108c377f607055f8ba9b0b6d7e58f681d59ff99 100755 --- "a/zh-cn/readme/\344\272\213\344\273\266\351\200\232\347\237\245\345\255\220\347\263\273\347\273\237.md" +++ "b/zh-cn/readme/\344\272\213\344\273\266\351\200\232\347\237\245\345\255\220\347\263\273\347\273\237.md" @@ -36,17 +36,7 @@ OpenHarmony通过CES(Common Event Service,公共事件服务)为应用程 ## 使用说明 -以下模块的JS接口为非正式API,仅供Launcher、Settings、SystemUI等系统应用使用,不排除对这些接口进行变更的可能性,后续版本将提供正式API。 - -- commoneventdata.d.ts - -- commoneventpublishdata.d.ts - -- commoneventsubscribeinfo.d.ts - -- commoneventsubscriber.d.ts - -- @ohos.commonevent.d.ts +* [详细说明请参考: CommonEvent开发指南](../application-dev/ability/common-event.md) ## 相关仓 diff --git "a/zh-cn/readme/\346\265\213\350\257\225\345\255\220\347\263\273\347\273\237.md" "b/zh-cn/readme/\346\265\213\350\257\225\345\255\220\347\263\273\347\273\237.md" index afdf04d347b8a7e611c969de5d0046d2058e9179..f1223920bd2d9388ce35498a138de9a10af56b53 100755 --- "a/zh-cn/readme/\346\265\213\350\257\225\345\255\220\347\263\273\347\273\237.md" +++ "b/zh-cn/readme/\346\265\213\350\257\225\345\255\220\347\263\273\347\273\237.md" @@ -720,7 +720,7 @@ subsystem # 子系统 ``` ./build.sh --product-name Hi3516DV300 --build-target make_test ``` -编译完成后,测试用例将自动保存在out/ohos-arm-release/packages/phone/images/tests目录下。 +编译完成后,测试用例将自动保存在out/hi3516dv300/packages/phone/images/tests目录下。 >说明: Hi3516DV300为当前版本所支持的平台,make_test表示全部用例。根据不同需求,编译选项可进行不同选择: > - --product-name # 编译产品名称(必选) diff --git a/zh-cn/release-notes/OpenHarmony-v2.2-beta2.md b/zh-cn/release-notes/OpenHarmony-v2.2-beta2.md index 299ab8b061addc3c66058fabf6643d744f901ce8..1e56b9474b981b0fbc413b98f00bb63291de39e3 100644 --- a/zh-cn/release-notes/OpenHarmony-v2.2-beta2.md +++ b/zh-cn/release-notes/OpenHarmony-v2.2-beta2.md @@ -18,7 +18,7 @@ 轻量和小型系统新增特性功能如下: -- 新增轻量级linux版本构建能力。 +- 新增小型系统linux版本构建能力。 - 新增轻量级内核能力增强,包括文件系统增强、内核调试工具增强支持、内核模块支持可配置、三方芯片适配支持、支持ARM9架构等。 - 轻量级图形能力增强支持,包括支持多语言字体对齐、支持显示控件轮廓、支持点阵字体、供统一多后端框架支持多芯片平台等。 - DFX能力增强支持,包括HiLog功能增强、HiEvent功能增强,提供轻量级系统信息dump工具、提供重启维侧框架等。