From 80906797f67542f2f76e801ac92b85c9921a1654 Mon Sep 17 00:00:00 2001 From: yafeng_wang Date: Wed, 24 Nov 2021 10:24:21 +0800 Subject: [PATCH] docs: Add some platform driver's documents Signed-off-by: yafeng_wang --- docker/standard/Readme-en.md | 2 +- docker/standard/Readme.md | 2 +- en/application-dev/Readme-EN.md | 6 +- .../hiappevent-guidelines.md | 123 + .../hiappevent-overview.md | 28 + .../application-event-logging/hiappevent.md | 5 + .../js-reference/apis/audio-management.md | 2004 ----------------- .../js-reference/apis/js-apis-audio.md | 939 ++++++++ .../js-reference/apis/js-apis-call.md | 439 ++++ .../js-reference/apis/js-apis-radio.md | 460 ++++ .../js-reference/apis/js-apis-sim.md | 388 ++++ .../js-reference/apis/js-apis-sms.md | 352 +++ .../quick-start/start-overview.md | 1 + en/device-dev/Readme-EN.md | 20 +- en/device-dev/driver/Readme-EN.md | 3 +- .../driver/driver-peripherals-usb-des.md | 1571 +++++++++++++ .../figures/USB_device_driver_model.png | Bin 0 -> 33914 bytes .../driver/figures/USB_host_driver_model.png | Bin 0 -> 42495 bytes en/device-dev/get-code/gettools-acquire.md | 2 +- en/device-dev/guide/Readme-EN.md | 3 +- en/device-dev/guide/device-clock-guide.md | 6 +- en/device-dev/guide/device-wlan-touch.md | 19 - en/device-dev/guide/device-wlan.md | 1 - en/device-dev/kernel/Readme-EN.md | 6 +- ...ernel-mini-extend-dynamic-loading-basic.md | 2 +- en/device-dev/kernel/kernel-mini-overview.md | 4 +- .../porting/porting-chip-kernel-overview.md | 28 +- .../porting/porting-linux-kernel-overview.md | 10 +- .../porting/standard-system-porting-guide.md | 2 +- .../quickstart-lite-steps-hi3516-program.md | 10 +- .../quickstart-lite-steps-hi3861-running.md | 2 +- .../quickstart-standard-docker-environment.md | 2 +- ...quickstart-standard-package-environment.md | 2 +- .../subsystems/development-guidelines.md | 2 +- .../figure/structure-of-a-signed-hap.png | Bin 0 -> 57445 bytes .../subsystems/subsys-build-standard-large.md | 4 +- .../subsys-security-communicationverify.md | 36 +- .../subsystems/subsys-security-overview.md | 27 +- .../subsys-security-rightmanagement.md | 4 +- .../subsystems/subsys-security-sigverify.md | 246 +- .../subsystems/subsys-testguide-test.md | 2 +- en/readme.md | 1 - en/readme/distributed-scheduler.md | 14 +- en/readme/figures/dms-architecture.png | Bin 0 -> 69257 bytes en/readme/test_subsystem.md | 2 +- zh-cn/application-dev/Readme-CN.md | 1 + .../ability/service-ability.md | 2 +- .../hiappevent-guidelines.md | 117 + .../hiappevent-overview.md | 28 + .../application-event-logging/hiappevent.md | 5 + .../apis/js-apis-basic-features-animator.md | 3 +- .../js-apis-basic-features-app-context.md | 15 +- .../js-apis-basic-features-configuration.md | 9 +- .../apis/js-apis-basic-features-logs.md | 15 +- .../apis/js-apis-basic-features-pop-up.md | 93 +- .../apis/js-apis-basic-features-routes.md | 111 +- .../apis/js-apis-basic-features-timer.md | 58 +- .../js-reference/apis/js-apis-fileio.md | 27 +- .../js-reference/apis/js-apis-sensor.md | 2 +- .../js-reference/apis/js-apis-update.md | 241 -- .../figures/{000000-3.png => 000000-5.png} | Bin ...-cn_image_0000001198530395.png => 1-2.png} | Bin .../figures/{1-1.gif => 1-3.gif} | Bin .../figures/11-1.gif | Bin 0 -> 5768 bytes .../figures/12.gif | Bin 0 -> 184418 bytes .../figures/{2-2.gif => 2-4.gif} | Bin .../figures/44.gif | Bin 0 -> 45338 bytes .../figures/SVID_20210301_193525_1.gif | Bin 58319 -> 0 bytes ...h-cn_image_0000001152773860.png => c3.png} | Bin .../{slategray-4.png => slategray-6.png} | Bin .../figures/zh-cn_image_0000001150368628.png | Bin 25962 -> 0 bytes ...1.png => zh-cn_image_0000001178875308.png} | Bin ...8.png => zh-cn_image_0000001179035242.png} | Bin ...9.png => zh-cn_image_0000001224354967.png} | Bin .../figures/\346\215\225\350\216\267.png" | Bin 0 -> 18159 bytes .../js-appendix-types.md | 4 +- .../js-components-basic-button.md | 10 +- .../js-components-basic-chart.md | 44 +- .../js-components-basic-image.md | 2 +- .../js-components-basic-input.md | 1 - .../js-components-basic-piece.md | 18 +- .../js-components-basic-qrcode.md | 67 +- .../js-components-canvas-canvas.md | 168 +- ...ponents-canvas-canvasrenderingcontext2d.md | 2 +- .../js-components-canvas-image.md | 4 +- .../js-components-canvas-offscreencanvas.md | 176 +- .../js-components-common-attributes.md | 16 +- .../js-components-common-events.md | 2 +- .../js-components-container-badge.md | 6 +- .../js-components-container-list-item.md | 2 +- .../js-components-custom-slot.md | 2 +- .../js-components-grid-col.md | 2 + .../js-components-grid-container.md | 2 +- .../js-components-media-video.md | 16 +- .../js-components-svg-animate.md | 2 +- .../js-components-svg-animatemotion.md | 2 +- .../js-framework-js-tag.md | 2 +- .../js-offscreencanvasrenderingcontext2d.md | 333 ++- .../ts-methods-media-query.md | 4 +- zh-cn/application-dev/media/audio-playback.md | 2 +- .../quick-start/installing-openharmony-app.md | 2 +- zh-cn/contribute/template/js-template.md | 494 ++-- zh-cn/device-dev/Readme-CN.md | 2 +- zh-cn/device-dev/driver/Readme-CN.md | 8 +- zh-cn/device-dev/driver/driver-hdf-sample.md | 6 +- .../driver/driver-peripherals-usb-des.md | 1551 +++++++++++++ .../driver/driver-platform-adc-des.md | 254 +++ .../driver/driver-platform-hdmi-des.md | 1003 +++++++++ .../driver/driver-platform-hdmi-develop.md | 384 ++++ .../driver/driver-platform-i3c-des.md | 620 +++++ .../driver/driver-platform-i3c-develop.md | 417 ++++ ...0\346\265\201\347\250\213\345\233\276.png" | Bin 0 -> 3523 bytes ...7\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 4384 bytes ...0\346\265\201\347\250\213\345\233\276.png" | Bin 0 -> 7488 bytes ...7\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 15177 bytes ...7\347\273\223\346\236\204\345\233\276.png" | Bin 0 -> 52253 bytes ...0\346\265\201\347\250\213\345\233\276.png" | Bin 0 -> 8146 bytes ...7\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 26534 bytes ...7\347\273\223\346\236\204\345\233\276.png" | Bin 0 -> 58566 bytes ...0\346\250\241\345\236\213\345\233\276.png" | Bin 0 -> 33914 bytes ...0\346\250\241\345\236\213\345\233\276.png" | Bin 0 -> 42495 bytes zh-cn/device-dev/get-code/gettools-acquire.md | 2 +- zh-cn/device-dev/guide/Readme-CN.md | 3 +- zh-cn/device-dev/guide/device-clock-guide.md | 6 +- zh-cn/device-dev/guide/device-wlan-touch.md | 19 - zh-cn/device-dev/guide/device-wlan.md | 3 +- zh-cn/device-dev/kernel/Readme-CN.md | 3 + ...7\347\224\250\346\203\205\345\206\265.png" | Bin 7206 -> 0 bytes .../kernel/kernel-mini-debug-lms.md | 293 +++ ...ernel-mini-extend-dynamic-loading-basic.md | 2 +- .../device-dev/kernel/kernel-mini-overview.md | 4 +- .../kernel/kernel-small-debug-lms.md | 477 ++++ .../kernel/kernel-small-debug-perf.md | 506 +++++ .../kernel-small-debug-shell-cmd-cpup.md | 2 +- .../kernel-small-debug-shell-cmd-date.md | 15 +- .../kernel-small-debug-shell-cmd-dmesg.md | 17 +- .../kernel-small-debug-shell-cmd-free.md | 2 +- .../kernel-small-debug-shell-cmd-help.md | 41 +- .../kernel-small-debug-shell-cmd-kill.md | 11 +- .../kernel-small-debug-shell-cmd-log.md | 6 +- .../kernel-small-debug-shell-cmd-memcheck.md | 5 +- .../kernel-small-debug-shell-cmd-oom.md | 34 +- .../kernel-small-debug-shell-cmd-pmm.md | 4 +- .../kernel-small-debug-shell-cmd-sem.md | 4 +- .../kernel-small-debug-shell-cmd-stack.md | 4 +- .../kernel/kernel-small-debug-shell-cmd-su.md | 2 +- .../kernel-small-debug-shell-cmd-swtmr.md | 5 +- .../kernel-small-debug-shell-cmd-sysinfo.md | 15 +- .../kernel-small-debug-shell-cmd-task.md | 4 +- .../kernel-small-debug-shell-cmd-top.md | 4 +- .../kernel-small-debug-shell-cmd-uname.md | 14 +- .../kernel-small-debug-shell-cmd-vmm.md | 9 +- .../kernel-small-debug-shell-cmd-watch.md | 11 +- .../kernel-small-debug-shell-file-cat.md | 2 +- .../kernel-small-debug-shell-file-cd.md | 2 +- .../kernel-small-debug-shell-file-chgrp.md | 2 +- .../kernel-small-debug-shell-file-chmod.md | 4 +- .../kernel-small-debug-shell-file-cp.md | 4 +- .../kernel-small-debug-shell-file-du.md | 2 +- .../kernel-small-debug-shell-file-format.md | 2 +- .../kernel-small-debug-shell-file-ls.md | 5 +- .../kernel-small-debug-shell-file-lsfd.md | 2 +- .../kernel-small-debug-shell-file-mount.md | 2 +- .../kernel-small-debug-shell-file-mv.md | 5 +- .../kernel-small-debug-shell-file-partinfo.md | 6 +- .../kernel-small-debug-shell-file-pwd.md | 2 +- .../kernel-small-debug-shell-file-rm.md | 4 +- .../kernel-small-debug-shell-file-rmdir.md | 2 +- .../kernel-small-debug-shell-file-statfs.md | 4 +- .../kernel-small-debug-shell-file-touch.md | 5 +- .../kernel-small-debug-shell-file-umount.md | 7 +- .../kernel-small-debug-shell-net-arp.md | 89 +- .../kernel-small-debug-shell-net-dhclient.md | 26 +- .../kernel-small-debug-shell-net-ifconfig.md | 369 +-- .../kernel-small-debug-shell-net-ipdebug.md | 4 +- .../kernel-small-debug-shell-net-netstat.md | 11 +- .../kernel-small-debug-shell-net-ping.md | 2 +- .../kernel-small-debug-shell-net-telnet.md | 2 +- .../kernel/kernel-standard-overview.md | 2 +- zh-cn/device-dev/porting/Readme-CN.md | 1 + .../porting/porting-chip-board-lwip.md | 58 +- .../porting/porting-chip-kernel-overview.md | 28 +- .../porting/porting-linux-kernel.md | 10 +- .../porting/standard-system-porting-guide.md | 2 +- .../quickstart-standard-docker-environment.md | 2 +- ...quickstart-standard-package-environment.md | 2 +- .../subsystems/subsys-build-standard-large.md | 4 +- .../subsys-security-communicationverify.md | 0 .../device-dev/subsystems/subsys-tel-guide.md | 2 +- .../subsystems/subsys-testguide-test.md | 60 +- zh-cn/readme.md | 1 - ...45\345\255\220\347\263\273\347\273\237.md" | 12 +- ...25\345\255\220\347\263\273\347\273\237.md" | 2 +- zh-cn/release-notes/OpenHarmony-v2.2-beta2.md | 2 +- 194 files changed, 11664 insertions(+), 3753 deletions(-) create mode 100644 en/application-dev/application-event-logging/hiappevent-guidelines.md create mode 100644 en/application-dev/application-event-logging/hiappevent-overview.md create mode 100644 en/application-dev/application-event-logging/hiappevent.md delete mode 100644 en/application-dev/js-reference/apis/audio-management.md create mode 100644 en/application-dev/js-reference/apis/js-apis-audio.md create mode 100644 en/application-dev/js-reference/apis/js-apis-call.md create mode 100644 en/application-dev/js-reference/apis/js-apis-radio.md create mode 100644 en/application-dev/js-reference/apis/js-apis-sim.md create mode 100644 en/application-dev/js-reference/apis/js-apis-sms.md create mode 100644 en/device-dev/driver/driver-peripherals-usb-des.md create mode 100644 en/device-dev/driver/figures/USB_device_driver_model.png create mode 100644 en/device-dev/driver/figures/USB_host_driver_model.png delete mode 100644 en/device-dev/guide/device-wlan-touch.md create mode 100644 en/device-dev/subsystems/figure/structure-of-a-signed-hap.png create mode 100644 en/readme/figures/dms-architecture.png create mode 100644 zh-cn/application-dev/application-event-logging/hiappevent-guidelines.md create mode 100644 zh-cn/application-dev/application-event-logging/hiappevent-overview.md create mode 100644 zh-cn/application-dev/application-event-logging/hiappevent.md delete mode 100644 zh-cn/application-dev/js-reference/apis/js-apis-update.md rename zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/{000000-3.png => 000000-5.png} (100%) rename zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/{zh-cn_image_0000001198530395.png => 1-2.png} (100%) rename zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/{1-1.gif => 1-3.gif} (100%) create mode 100644 zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/11-1.gif create mode 100644 zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/12.gif rename zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/{2-2.gif => 2-4.gif} (100%) create mode 100644 zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/44.gif delete mode 100644 zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/SVID_20210301_193525_1.gif rename zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/{zh-cn_image_0000001152773860.png => c3.png} (100%) rename zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/{slategray-4.png => slategray-6.png} (100%) delete mode 100644 zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/zh-cn_image_0000001150368628.png rename zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/{zh-cn_image_0000001181458721.png => zh-cn_image_0000001178875308.png} (100%) rename zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/{zh-cn_image_0000001135171488.png => zh-cn_image_0000001179035242.png} (100%) rename zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/{zh-cn_image_0000001181449919.png => zh-cn_image_0000001224354967.png} (100%) create mode 100644 "zh-cn/application-dev/js-reference/js-based-web-like-development-paradigm/figures/\346\215\225\350\216\267.png" create mode 100644 zh-cn/device-dev/driver/driver-peripherals-usb-des.md create mode 100755 zh-cn/device-dev/driver/driver-platform-adc-des.md create mode 100755 zh-cn/device-dev/driver/driver-platform-hdmi-des.md create mode 100755 zh-cn/device-dev/driver/driver-platform-hdmi-develop.md create mode 100755 zh-cn/device-dev/driver/driver-platform-i3c-des.md create mode 100755 zh-cn/device-dev/driver/driver-platform-i3c-develop.md create mode 100755 "zh-cn/device-dev/driver/figures/ADC\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" create mode 100755 "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" create mode 100755 "zh-cn/device-dev/driver/figures/HDMI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" create mode 100755 "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" create mode 100755 "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" create mode 100755 "zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" create mode 100755 "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" create mode 100755 "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" create mode 100644 "zh-cn/device-dev/driver/figures/USB-Device\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" create mode 100644 "zh-cn/device-dev/driver/figures/USB-Host\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" delete mode 100644 zh-cn/device-dev/guide/device-wlan-touch.md delete mode 100755 "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" create mode 100644 zh-cn/device-dev/kernel/kernel-mini-debug-lms.md create mode 100644 zh-cn/device-dev/kernel/kernel-small-debug-lms.md create mode 100644 zh-cn/device-dev/kernel/kernel-small-debug-perf.md mode change 100755 => 100644 zh-cn/device-dev/subsystems/subsys-security-communicationverify.md diff --git a/docker/standard/Readme-en.md b/docker/standard/Readme-en.md index cd12fd5a04d..35281709b33 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 ffedcc403d0..d13820b5911 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 7ec1ae37bf4..cd0d8d87e1c 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 00000000000..96222dc5942 --- /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 00000000000..7d3f414331c --- /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 00000000000..9f71ed849a4 --- /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 a58634ba548..00000000000 --- 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 00000000000..facaa2410ce --- /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 00000000000..16d5ceb279a --- /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 00000000000..69cac33509d --- /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 00000000000..9d27fea1ef6 --- /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 00000000000..a45f89399ee --- /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 bc4d355ab04..9fb98e63170 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 b99935770e4..bbe11a57349 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 eb21fdeec40..c2c3dea84df 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 00000000000..0dd421ec369 --- /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 GIT binary patch literal 33914 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 w%=Fmb#<(dd7<!I}$nsaI3Hd0Ria{L`0-UdM}Ff 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[](../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 a21f8de99fe..6b140777058 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 c9d006e9c4d..44f99359278 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 5ff4442e971..00000000000 --- 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 e4618dfb06c..dd1fb71a73a 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 01ff40387c6..ce9ce8eb85b 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 591fb131ef2..36fc1e438a4 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 e727b225c19..0e58d09e738 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 8f6702a1519..9941b2bc5ce 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 9f978170213..0a83bbfe9dc 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 82a71528671..44da08b0724 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 38c5419e03d..2e4cfcb2adf 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 2eab40b209a..e1c70aa53cf 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 e96a662f9cc..93f11715dc1 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 8e0b4e69770..8bfe22b959e 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 1f930477fe6..a7ca323e96c 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 GIT binary patch literal 57445 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

MVzduc?~)$+`~Fvngj@{nrU3-Z-$L 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 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 6149a7ce057..11159d39de4 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 747ecce03eb..8b15372203c 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 8436c859d8d..dfc7051d811 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 c037ff22c31..ac5aa3e7466 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 c3293c74dab..7a3b845eda1 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 eef3ae0cc0f..ec46001bd38 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 GIT binary patch literal 69257 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ν#1Qn7ZFG-(c}7w%{;$)O49U*OVT) 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:** 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 3dabd771aad..16e9eb71a33 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 e0c861c6ae1..908875bb421 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 00000000000..c283e3a95e8 --- /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 00000000000..2075f94f3c3 --- /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 00000000000..e79ac250ded --- /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 81e08630864..86b57fc066d 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 201556ce619..65a177cbc07 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 6b0aa3826a5..8f590bf1a2c 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 8b172bec109..1b26f76e3b1 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 82706369ec3..4ac34ca0b8a 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 8c933dc7b27..bf73f723558 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 d81c74fcbee..9a1375fc025 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 b451a76cf11..f4e52b91d20 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 54657bc2757..75d83aca39a 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 65e4dd111d0..00000000000 --- 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 GIT binary patch literal 5768 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%0Dw`gFrAyJUxIlF2&) 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 literal 0 HcmV?d00001 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 GIT binary patch literal 0 HcmV?d00001 literal 58319 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ςQz}46KNLxS4m}?D7Uy7LKt|r`hu%#pP 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
{eq@;mA3B*jkzYBaw#T@dQhJQ8aC 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 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 GIT binary patch literal 0 HcmV?d00001 literal 25962 zcmdRV^;29yvvv|BxI=JV9D);^;O+zo!FRDN7J^%Fx5eEZ0xV&12=1N$8{AzMcRt>G z@Bi@C`@^X@Gp9~NO!6>dRZFh70G* z@Y+RNLHgCtamu}y39_}6n$)XTb#a&v<|r?7bSFhamshWFdj9jg9&juJzIp|GR+5#{ z^)NZ|MKLq}H0$~$p8x5S{^=NgM}zh7J7{&FMW^K4pYdg5 z?>YIs&)x;m2BISK{Pus3D*2)7cID4A#abYtKmPxHhrWh~_dn$4wxT^uBk#X{=zQ~h ze`}3Mc~I*}8-MP5vBv)hD~Ls7dg%36&w9YQkIU`*86<$QfUEn==638DEq)(sxza@_ z70Q&^UmRkkKK%jVkBT0fgQBeGAoEYnv|F^1+z+MUbWE~* zHBrBCe5j6YGpmNSlt;{E;y2?pbCIN8h$qc)kHp!}3`RkgJ1)7Xgz9a{=iiMdU!roC z)5A@d1IGY84P0z93w|a8DacNBasDRI15t-{B>?n`j zjah-uA*&+!dLk>)iCP;a?$E9YbQ0#cZRlY&cPcuurF*t$=mE^$LJ$q

RD>>u82l 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 ZK4&(PT?w4&?fWSI>1i2j)~P#1{vRHO8ixP? 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 GIT binary patch literal 18159 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 literal 0 HcmV?d00001 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 d3bbd07fb3a..7328c141b88 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 4eca5ccf03a..3a54e3a6412 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 67c9c8e63a2..60d22aeea22 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 704c9f3b77d..10f52594e1d 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 0c2e0d61898..2c6fc5216f9 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 5e597d4f8f4..fc9a08fe4a1 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 5c33671af04..2cc06af6065 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 e7924a562c6..7a063a973f1 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 90ef4151b83..ab70e867521 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 57fcaecc1c7..283448a511b 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 0ea82bfafff..4839d31b104 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 3f5927d0d93..3d73f5c0caa 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 d6a6b72cee3..2afa827c57f 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 d7ece1e0766..175f7261e65 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 c86a6f192f1..950e5b04754 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 802a3928dcf..992ec8d7ec5 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 3b6adb4e57e..ad2e7f024dd 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 cb3dfc15044..8a46fbcb110 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 c06026e572a..d4310dd129f 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 684c959120c..11f862e5d95 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 0676cf58862..cf008a31ce8 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 ad219bdef77..932a679a158 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 8cfd911e7f6..687a36b1700 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 2f134e3079d..d5d209d7369 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 834f0a58f72..822b3dabfe2 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 a8a40172a2f..6c30391ab3b 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 803445fddfc..9c0a408adef 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 17116f4e45c..d3ed210b806 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 0cc2f0686ff..93cb1965a5a 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 00000000000..cb0f0ef8a5a --- /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 00000000000..1a9702a722f --- /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 00000000000..8b606fcc991 --- /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 00000000000..9f4f0bb802c --- /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 00000000000..2c65adfc71c --- /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 00000000000..ba621631c0e --- /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 GIT binary patch literal 3523 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 literal 0 HcmV?d00001 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 GIT binary patch literal 4384 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 literal 0 HcmV?d00001 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 GIT binary patch literal 7488 zcmeHscT|(v*Dn6Bj3A&WMF?R=1Pe`+P7)LgA_5B1AyE)fP%wm&5CVdrNDBf2(jtgx zXb}(ykibZbf)JDvdWKK}MoJQr&~tH|x!=8i-*wlz>#pyQ_q^x4XRr6{y`SgobJpI^ zu34K)h$)DPh=@p7T)to{A|l$e-S_%!_jdc{oOsptYX`#C+)Sjr8!)#$*y(-F>YRv3 z1y+3H)~@aG-iMc+5h5azEkBHcFynUa8CI8r2N!^#;Hfa?naf7hPmYZM$kUx|` zPgLGVZ2S`Wt0LkKxF`~GIO?nEe^32i_XgxoEWIgAz*2^WS9W9e51RgjX?xXe?5cph zXK@MfH#b(FX4p9F(4aJ}Z%x-h8acf*Iw?#r7V^>t7U7&E@<=2c5SdW zgNojTT-aV*El!)arkW!4<`_@j7vnX?8<$b;tec0=)h}Q= zpylndI#rL&vFF1;)zrSMF&>_KbqCP&N-ao|b-U00)>z_Xr12ut?KtE+p%W>&{%&b9 zDa-Fo-s_ik*yrmv)(dMLH9+k;X}`?Ki_%dm9oZFd#pfct?&yb=pqFmb3K)zIEoEQR zF|NX1Jj z``pZlMdyVF4U|BsPFfqdv71~sVtOgkCpGRnIFuz1t`eg!mA=apSarQJLrsI4w?xAB40dgCH-^lE+hsba1dN3Vx_ z$U+Y+@{I)tA@{8lxla71lYyLy;-0%6Ur!b%!XtZb&-r#Td{nxIW}fIjDPxC7L(n9` zJQq*Z>p4qD`!Dcqx|!{D2^EefLsvu54ugqSPC~`57yHZY&}X26$7CrQhFzCcVi1yO zj^z%=IMtARXx9fwPJ|4qAALEb4vi!+dw=>_|Vo2o*_`uvCOelTLEo4Cq1|*ikrRXke zrMrKrCw=r7@Kl&hg&$1d?AJ|6&b@En4Dfonj^+I6CQUecFL!WyBK;u8x^lDfC~}hp znQ%;PX3t|dB-B-qEO3COmxW!v76Z`&0Z*76B4^I(NUIBy5tfbq4L6&f&Yx*(w+^su ziqxX`ERYRCjGFJqY4l~eFcYggebFqV)8E{7!D>l3!a;i6475C6aE;oJYiLcSe0=<7 z=<{j;E2M#GARO>)U`JE1-?|KCVF}E0ld#B+)UljerHs0y{=kqvZ`2p1pjVOV*pIjW zwuCL0U;spZkF-C^P<5sdIt$fleV?zU_(IZ^qgXAAl+2?oHeUy(lvCO1cYD!W9}@cM zsL`1*$oW+l)BE%2swJjQA8`q(dFm)Ibl0vqhtubA`?bM{doQ7WQ;_PNxiw^xA%4u_iEBVv>Z|vgab97k z(z%4aAkb)pfP=O4*d!fln>(k?eRDJ~Zkl6)Wvw#{$zSTiYnY6x**$F#KhP5`Es&NN zRfbNZd<^ea@%`$;%q7*5+aiT(k<0+t0W@BOXHtqE3ReSIU*W^@uczE!2Xd(GI^8^FGdpp2n1DVw)um)RYpA=;Bv@14-zMv`xrrGO0_0z)* z->dpZ8ovLzJg&LGkXQJ1ebD|mXjx32j5<1+^Dh0UJR$XVhBOR7AUxaar(PMlc=+IC zsI|<^>CM5m0HaH$PO2v?3l^JdV}2e1;@I9i*w%&y+7-$?a#U9T!L94F@jGtL;6D-FA6@SmjU*^8x+D!B(g~iTMt9;=V!HlMPp_|LhNS04oZ=-9IbyJNq zwPJd%U(Pf9@b*Ui%-#xO@ysgU_>;F)I# zB^7$VMx(eoWe?eEWr|ExY(bIx`>8KPjZMYNzLj zg3{F%K!^BYJE$CG0A1CnH5LzXfc17inCzU~r9`O|JoeTM8o$fGz(gJRIB9;5?&)k| z;;*+QbD31cTj=_VLubBRyE;$foS6k3B9E6Ck=x*O8#X>6_fe~_3*p1K+OQ{CTmK2; z3iIU?4$!NS0c5GMGI;KcwYm4ouK6?`lIi6~e>hTzBpp0-0_CbU-8!C?#_X6Z z?y6b8Hu&&Bf{7xDWlx55`qq^>jm?SkUy&;TLRX&Irb?%$012*>VEK zo0m$?25dfRiW0|4G`l>}i)Gsr-dsYb(vV}KHOJo6@=#zHrhC|*mnW}e5GRg}&%BWb z*-QrCrM>GwOSGe&mFb3Lgm&}7i*x>bL;*K!K(Egg` z0nuUnk72$t9`~?sDyH)e+H{QeELh}bGgw2QTk|UF8BU0PBFE{t$Jy7O?=F%~43vB_ z(L-(=pAQ}74J;9UFMqS4W*z3|lvtT`i(GS>pO>}Jy>=B-l;#>brO@`LJ0QfPG>H(E zOc3M|-cTG89#BkJxtyqKIYf7|U})wACS}`49lm_7)$M^vNB>vTqGQ83=pFZRSun!Y zl#9jVj;}>~jg@7QltRYvecPaoCl<{zkJ%iNtW1`J8vwEoZb6xUHZbY4HRAR@GpU;h>UdWDUQpD?x&hbP{q3bxRArNGi6 zg4G9Mx;6{!f|$+O&*&Y*HE5u(w-ZqKQI!*N7p6v+$@Xp!gvO9jzX1Ow8S!c*13S`&2ix5XT;c34mv1*w3%!qs0 zsAh4qU5lax0U)89DH$jPlz3AjFi4gTaCl?qzp7>YqttE?r%GH zq3ZC#h5o^oTled0)19&ODMz9}zbdF4JfL-L#Y8jrVuv8b%BitNzdgxfwQ35^(lZrG zGkXw=58H00q1Un_R_#{o_DpGFKem%82GRw|jB1OAm%?6D$a|s}Z+YjY%F}i^Va8^O z*GJJC(C1{M3Fgp02A`kDIZpWi<3k~nY=Gmk)9uv+3Sxy#oX@T=^qw7)2wVp)<{M=5 zR&w=w_VV15qFpvT;Bw(>?2$ViN@~>~=N70Tuu-4!`9&H( z@$AH=@!#J(BLQ%LbFKPGl*UoqF4mbpA(eiPH#j#k1uK^bsq2NysS(*WuqI9JtnqgY z?@p!Pnb3!#59C_B&I1T|i6K>OKQCLSQ)D7*6g5$T5|iaNDX5jH?Xy#aJ=b6DU+q^& z9`JsI`Mw?FLeOry^#`7L4RP0+(qb!=sg?yA3{NHcgUT+$F^~F@-w1o5O@v0jz|rG8 z7pM$lC94nOeqhKXLZ}=e33J8m;NxlB;$)Q>JdN{xW2{Lyv;pX$xKPv)I7%_C;(gXo z%r$|GDKZ%qtS}od_*>PhqPeD-(4NG~$VNq*6yel-h0m+=fKr$^Szgn_CQ-YoYDjGW8ZQ4J zn#HDnx#aJ1RJ?3aTY!EeWGMB?Ud{f!Ew&Vm#BUvR$g%x~J6&o{EbrZ9D z(0pJ%?n<7R3XoD{z_(P14#kfg>lfb4>3a|)O77-LhMsY*Jq(^vKHv&@m)XBAviZa? zuY^)fqZ~0&$d$EIE;&rR^hM`tT+#hLfdh^zVfOSFC+hD?^FU89qoJjWe=Ubv1>QMQ zij|vGZC?(N?ah>bP2TvO`;uw)ZB!chi=UzU-af3}>>V*V!lwcpxlVoD!&oM^?H+$CSy6%7*2kDX4YH5^p8qJhkALQ0WFt~J@ za>}Az@6wdS4JEqHaUI`2m7rPJO!V$rAj|OU`nX5pu4lQ+jz%@yle@DG6KTWjasTM^ z3B@ZV1VtqSG59`n;_%koywZVnZ^?k@i1OKrPn>Oa9|E+MtnM34c1xsd^?0)^GA?mDvwHhxx64rkWA^tQ@}sVD1RK7Yg$hkfQ4OU-=r+*hdT@RvtH1Lj;WN(+J?EH zTRJ2Hav>07ze7T}+aGY-GFWGlz`J6hY@`oWC?LI0Qf9WyO>+y2^W5Uf3v%4-^ zVcbWTE4w#a9rxUO`hm93^cz%ck!`;i*+CUW@(kNYE4Mg;^z%7REE$Y$b}!V=={JN_ zE7g8UnS%MUvahacTxyfNKcJCgvQU;1?3P0ymUmB_M-jVK?6tm6uQ*PrEaF@X0ZRN> zetiK_jh6RxQy!d7_L_OU=P?Ddv=Y{Zx(a5tO|B%65oB&v5793_md>kRfy`C^i01`i zL&I6%^QE;kIkY;qgrxj#@3yUjHm^RmTb|;-v?3}7U;E^n`!ItYK>95y^8=SPJ^EG^ zUnH1=lzIV`UOiJhM{8-KEIkKnG3=Cl#RuiF4!0CNuD50AL6fTK(*uj{Z4Jr5ErYKy zt!v3J?$whWj185#AK{-4fNyt|9MPVFml(Nh(i*jZ9T9l%HItWA?~ju}zOL)L?IyH>dO$_;O7yhQ?Zgp{{ECaobh9Eb0U`=GuMAg}iuA6!r6>gV+}M36@pS>X7hFU2emrD zyRSUIrh7oT4f@VLg^z&sN*6T+UpH>3&@;MK2;xS~X7gn}HZOP5ClP1Ek2wE`7k@;N zMQ%9!Pqk3+AMyXH)o9y{ISnkgl-?Y*AXX$psdB>FB|hYjp>m3yExi$4*CiM4^Ey+x zbsJYW7&>Xu=BuV#cCrXjF?vo$PZ}Hi<@5TR|7djA%6w(J=~#0feHqd0>(lF`=|~j< zuDi=YSyXOlvWg4CKzo3``!YpN*>rJ=kybKIeXrdN9OVzzIQsZ2O95;DVvpSGo=j8B zAjIdKoaH&t_VywC3#u4{iobGu!kb}lqO+CbvV6iaU1y$0YarUVoZQZ2w-%f7Vu5oq z;(^(ViV=W0uzA~QQY?7VoWAuiF~#>syP@nigv7E#^kI0h;%r!MWay%roR_WjJFN0k zz*i3G&=8Msw|H;<%fA~%A!U5B~|4ngJ0P{uQP znY-6+Z|w1W@v#4~b|voN^bYl=q*P$sG|_mXBjk8cKzYiWL%p}|hv5Pm6Lq1$_O%HB zlcX#JwwUt_4>jOd(^jrjNPCoN-1h(h@4q@PX`!RUv}7wV>f-wMx7^Wr!!di@anZqs~v4s>`f6Ou9MRi`~dXf5{ZJV$Ow7vDDr@GYOaLH|bD9gkooSt7s zW?FM`Vm6Z8FaH!SDiL@*g%jkkkv{3s9ZQ=l=qSMLkv@$L+Ay4o1#YLk#-$YJRuAwQ zYx|NtPX~`2ES5Lj0a}Qp_~#p8UpW4xeI5MA(|`FjU{Pw0aR$oUjhk!iyKhEZIFfL^)wv zXxbYz!dfP*7B!pXElz73Hc07Q*v9WQ|469Ty7~s~B6+hm8K=x*1zs)BuN#&FQYYw> zP`}a>g!pg`m>o5@7%@30^)Hvwc4kNqYYw;O9Q5Y}6<#6Ek9t|-gv7xOW&H%p0JvL+#VZ` zUqVWP_)@@@1OI#3!p7jg>TKrH|34Mu0`0W5g;M3MtJP*XF?HKjPZ5iY))&gnZbtnN D)J8K? literal 0 HcmV?d00001 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 GIT binary patch literal 15177 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 DB#C#Q literal 0 HcmV?d00001 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 GIT binary patch literal 52253 zcmeFZcT`hb*FK6}LBs|q^&m~U3IXYgR1r|B5C|&LOQZ$}&9mDMc+3dB~Y|nh=oOyd+TaBKUg_eefhF(Km zS(k?9=pGHtVf4wv;5%|Grw@UD4!P>8DbW;nu+4!lj#}T=x=lk<5>B`K_!#*5)H8Ks zR~ni#U#Nc%HNkVA($KV)YAD~<_k=C(ZN=*2_YQ)0PJHEjT7)n(rR0wyFF>l!Tz~tv zaTdz0&B>p59@6pP0wn0j6~Qy9&o8}cys2!_b%{|z^@z5Oc;3m}(-pLbTfU!G5~n-}Fyz?YetXK*CJMghpkZC`7d3ef7?+6~(vB`|7OH zNv_P(TZAUxNgOAh^w+C*`9WC9+aV9syR%B_;p=TL&MX;pn2};HD5*>MF5>9f5BOfa zn}6$tGExV3HhDSP=76>KNiI<#7LReMlfY(5e_h9^*GYP!=1DHgU)KiewV4$gdseB1g?bI5t|O#8#kgKYL8#Y@ z)HM%$1*UXT!2Z|O30&2QzqZi-|MHEbJ%#Rc6glq3@f|w)=VT&2Y&Z7(Adv2p>l2>F z)jV1~#%wO*JYNHo=4xgjY6g9H;O{fr=IXcKJkyGGX{|15=T=jE)=5%zbXp?wO||c! z*H0w6cT~pmdrrOLx#kIf)}1Qh-yGz)B#T?ajvY8>Hho5FoG+_Q+b9+CFPaUIYA&^z ziq8n!n%iQAVXgFDO66VjqP(nX;_z2uh`2MNfd@iUY3r&XNw54Mb(nqpE`+gp)pv6% zRG#8fWR))^058|{{&`NZTfJblKOsuwbaW=_1?6=#y_TcYuum%tNm_4=LYR)lLgNh! z37Ksl^mZC2G11KYSU-|)Mqqd)Y5Vp|$bGingPZN81g9FU4>y}x;?{^ehT>{W!e)6M zed=<82u-6#oE(>oC}T1>fU84iG#pl75nnxtHE2gQvpptOdNb9K>Vt&QAxg9qKXOVt zT1pb5xV3l_9wNjOueol*9TShRvPs+8~TCEeAB#yYgyD` z&VRAVOgCWETCthLAiw$Qb?wfw|Hn@jH-5j;@mS+^g~0>DsPyiels5Cy`nw$d^CXsA zrH_xazU5DGS$DjXRg;f0tKH{M{0@Q=F%`)z|BabeH(gCV`|=JhzQQFBzG-w*&nUH2&x| z_3CZp;$KTS=E4I%R@Us{`7a2l)^n^H`n{WbYeBh<5}^*xBoUv=vZoG#Jd&Pb8uu$Q zD+tXZ6QjA(8)Wf|xGsWMimy{nDb`SYW6&S_)Z&SRn6~F$mJ$DueP}{|e5mgUHqS0X znU(!5VV?ZF?N#|}VE5-{5~@(xPH!W@Ng>WTF48)r64`Lr9Xe?pGky*pjh^*G*T4UPf)(rxvT`0-dPkz_XUC4KDca$2E{`uGR;sHlp3=-)hkY`(W&o=KkES}Q z^HB~>$Pq5n%cL|#nZ>Byg)N`K zxS3s3_>%Uad|OKG5Tb6cC_b~g*e@6(%$tF-`wM+8ujU6X4fq$05CQu}`Lvv5By3`c z%rG+ut(nNRu4l5(d_&wRurJ;aeb@RPO2Q%!;QoP0(&wq}CK{c<+FA1>{pVGTll?lQ zk=X=$CR&fy@*}Di(!gj^-jtX0t-;-1JnVUalv6Jcf@ysHz*}YFaie(3WkC(|V;+d&o^{9Ikglj>odXtME8^pqvgrU3tMznsTqo z*RwTOcIJHVNc2;sb8V_-uY*W%0Ru8r`04rFV*~r3WBH449s7FQL;eEqG>jm2x$!n} zmAFAL5#5?%4BY$q=9s3D73-0Vyn<1ep})n^!@%HI`L6#K!Ts8Y=w*ce&kTZNS%SEA z2)#hh1JrQCYhi;{&*U{@#c^$=A=l9nI1-%>J?5T0k#U;l@`> z=aC`qaD{0sov2Ao)pf$9*{LdK^M03!K%YNHd{wf;rtq4JO%c67fG4RG%^Ei6Zz@Sb zdyJEbNR5Y7e{b<6rqp|)g8Dw2pU9gV8ok&8uZa@XYRD@~!c4-=4YSbj3h~(0^HCwq z9tNlK)`0z7Es0EoNcaMQ)cMac1cvYKz0Q_g!Yp;8MvLWTIGa~k^@!ae5o5V1yQe!t z%Qd6d7h%$_71z6hM;7m1+56l?mp=6$gYNCl?YEnJpI!akHH5=^@vTkT=IN0*;SS_X zoB30U6xz2ggvjb!?%6oAtgzoV>X=hfdmZv~Q`U59xI`#4W9i-R6Wx3+ik&Py*xDX| z2(o*TuLm#mtLE65_WBV;?vUIN&ze76@kYJY2Ckck`=Du_*H0Grf zZf}HP+U{%_vf9)c5BZ`ti~u31ZvB8gHE+3mX233+!`Hzd5&P-{r?2S*0XR)^^(~UY z;{7tIGvdFs;K?}A-a_3e{Ycb0aR%lyxJhvsB~`PY5P{a*u4mhTvBnEu?$n7n4(0ZQ zX8|oZ)iTr`%90r-yUMeaZu_dIQ%^^6qS?ABZy0Y}mN&LbC)VLvksN#8ONY+?*;F95-xh%arbt=I`#uTk0G?3^rL=&1t*>#FypFr1)*Fa%j z6HhCyUrW}hdsyso5%( zayH4X|JyX~@&tB3h@bHSHkRiqOM--wt%J_qXfj#hLQbs^!gr%cz)4NZMApBV7O|bO2IPN6ahyMb*v+8e&{Okt z!@KtpVsU_s7hT2^94sEm#ruBE-GNNb=RmLC;hih^f#c%KpiF;vEMu>qrLnvdlWFv2 z=%u_3w^zvA2BftPHbdF^MmSv7+Tfkbn5EU;Tb~2kYDdR!kL}ba~Jru zUFbyQmiK#JJzRnHw0^f0%b~wnR_v$Qc;q6K;32nOuSgkzAINWSM2^oF(JqatvM51B zs}_(;Y07H`$OPxpZA>)@q@7DVo+W>mK5s0DK4XietLN%q_EAFSIz-lb& z|1RtB+Cod=y7S&W)7$=w>fIWn@B~U}QpFvAx91tnYzH?d4_YVsu+`yINLfnjcc7}t+7TkxCu|*?~{0dx_W(Ge$3{3$_ZWa(f=|pSO zBvo57liX|NXTy8B>6RE=J7FIHFN532IEo^9791(z$|XS!&f_Hd>kVtf6CC?xvdl8^ z!%av`W<@7}H+vVlmK{)BtMB=fhar6K;lp3}G}Ni6%Vx3b?(8)`;CV&&hJeq6y;^*^K>yDFNnyOB0XAC}RCzvj4I9z_KT&RyD2kF?& zkFP2A-Y4bRo#CtVL{)sdCI8Rv~G}= zk^cUSx#y}ge{%V5Yp7v_^J#KAZ+_m)!A6i#$DfmLp2f*m)*6LAc6LH> z&I!cYozKJY#j2T?;R?&4k2rm>KV~ghDZjq8WT{@WNLhX_9p$jmNYe?Y=_ zNw_XIIjwXPG)Nu0`)P`Oscr!C0<(0&-E{mEM;B9EPP;m}0h5i}`pC&S2B`$1x=+-^gE%xmtC@^7vf;TQp{%eu+3V3_ zF46zycs9`!HL}>}6b9#Inc&!O{qQq6(ejQSVT2NI^_(a;<*bOL>mbi+X&Ts zVA;JV^PX#V!{YBsWaD-|o1$t}km*C~z3P=V4R-Jd%YLj54`v7&O{3Nd!tN-r8X-+X z6ei)?!NGpY0b+D-)8Ar^FjS*gwOKnqk9iu|T;wP#0r6HX@glXNaF_8G%#>ZC011b( zRACSn@_15aOev4!oOdTbpPYZYhwO-i1t0&^>hFur&e!(QiT(}4CEg99Yf?lCWamGm zsP5^#?AYZM;_&?0sm4h#KN8xAVm;2#oje$P0X85Sf43Zt*l-`vd^=*3>xEZpl&=SR z>TdJ1OkTXkKjenjws2^g;5kLP#b-JRBJ));8MH%?KJCnQ^*40X#IlldS0H7tNz>y4 zB~wp3>3UATRu63Af{tRrsw)ad@tVWGbt-r3#u}N)-WRt^tyxGuH#8P()m4NcG<-Qf zG;0c?PUlO?@rx8wXL>adnTHl!JLC_l{P!1n#bVSNAkgw1DSIM6ijHT?dCEUFEU%Z44QPY6Cz83RA zW*9EWV#zxTa~9HZ=Cl#W(u_vPh^g+l(P;emX36XDU7VS7HlhzxQ%puTvhCmoG^w>%`@?sL|EE z6CtsT-AGOITvjZ#6C$X>qviE7z1A^sVBCSE{CD91%(so-5OwU!FWn_F@f6`tN{2I!?ca@66z z?3#ag|MCdPqnbJ;OTM|Ar${UTz?_>TDb)RUB>-@2{B2(|;=A>1$m;+^fK*w)9HwBXB&V9Eu{^Fp<@>yek(TXw(;2ApPW@ZLOhc8jqUTOMy1?(wm z)9pRM%OFoDSbpw__V}PYfhTeP>@D<4sk{v75-}-}nRqs1**w2ty|-v8N~Y%pA=+C) zUxm~3A~mlRf^kt%`IE_*?t^7pDW|;(CMn1pkmwLkka&F=>FcIDdA9yP#VaM$QUHII zm;Zs{9RLV9??h`RH?W?1b@sfLxi?_B^r4eD7@+b1StoF3yA8RqUbgK4?nwTIgnx)y z`_1xo`o$9q*rX%VqR&P^$_&x=sXu3|Eh#V&C|!SNF@=T({~Sx%#ORs90i`+MQ>uV7 z+M?)OGCA~@&;m;jv+_OjLHfO~fb;Y|L!_g*Z@L1b`9?=w8G_Z{<1Z+OZ-ID4^LHs& z(OhK4GSjS4S5b^$m0I}&NAr&Qz0^XmqG>orI`%h~y0Qc-nyaFoVlZ*nI|9|xVg9DF!ghg2BH5K*hzVeK#OZHE?_2>ug{&5zQUVrQ8 zDtkhcn3L;esXE8L!l)Y_eo!O)y@%{#@dId!P@z^S@soE(Us8ptvUN^VY%cwSsma1pv)v{W=4v%=%Bwp5`8>YD>T%wDR>}iDkiTeiJc|z za!{JsFM&Syg0}~Cybklfklxo%>M}Y^3i$B}nRep)Dj`10vDe6hJtx}H!=v1hq`oxk zFxV~d)-mF1i?+G(u!FJbXl~)q8e@)#Vd3h-o%3^i?y6=(#O~@^E|IaCdo>FWOAMb+ ze7R5iTPrn{=!taCUr>~|zA;!R18oAQL}HZ^M|Fbznx@W^9M3z-DO zxobr{?tB%fr4wo%wcu^>H(<1>Iv)Fq18Vqs$GERPkVRXpW zyF>qcfI)zpQ3aoMuP5ZOb1>!WU%Kj&kZcsK-&5_fiZmB9t%VOml1r5m*yy_p(Bs^p4!!X3fD3pNT$HdVH{cNiN z!IoAUbCTU5MIL*Sul~5*KjuK>5%+W6{yNRoYvRQLkA8}eX&meAW!_Ve<3|@iSG=0` zCjy+eTY;Uth?R;H9vxP2@ZP>A#xH5~m`}{Hx|q-R2lEE~zr=Vd)5>;WuRy`1b*~^_ zB7udKU(At6{M=A``_C`zi3U&@VB*4u7+VY18X?osuKWl*E5^}&bdL7I`CrDS#bROC z8|cLu_vJAxq9d$hy5r1#>CxlVL(lUe?YU@1wu!{AL5HXNwFR=$nTb5i3psw?Q-P7gqfI@gP`satKRz7n>f6MWi20PS(4nxOe&Eht^@OL-F4`0j zdfF_4)FotPS%I2qvYe+zudFp3Vs?b`ZCI|hVrMxg*{=~`!8#}VGNZbS)I!Yj6aGfs zbnuAa4LwENT4`1r5ilJ=0OF29O)9x$&oPDZUEejC}9ZE;(3DTwm#r7D!+FKICbA2xKoGbc)iLp%BmI?4mTgC23Y-I zinl@)zB+nj!9J`34i^-#*EzZYXNG~ZSOrqxQEw)GcQh$Q71~rTIeoj$BKd10L zUt%vx9y=Rxy*+RGI@*zbcv*0es%o)<8?azgN(p}oF~eLjkMzO1F=jd496RuYF!uKm z2Jf{&X8_zAnFoq~A6Cjsazy=l_YmJ+(Pc^bfNj3ZR14O{6AQk%Q;Q4+-}tifKYC9{ zNdS3~cYGtM@Wd<6gJh5y1!x#OchxYzzf43QBd6M%)!4kE z_%2gZNFW@zwQ_5qT1d5dz~!W80Eto=TxxPpO{*NkaYpH$1M=L9K94LwsmJNE_Y7d- zy6v1`8_M=+GR1307!IWUXelil2`5IpYYH|&d1ipHrD=F^88`o7pgthhwBp&8pwZ)z z{%K9oI^9U8I{Tk7eI7>3K-PG$ZAPH5409uW-)D{KLD_SgkL|a2%jP!HPg)nP{I->8 z>I@hI&6!LOK~9Bng{l+nFWyejx;TpCdvQ8=kr-xfAp_q()4)mdx!ZLg- z0WZxOKZLa#AU^8_oIAG$hi7lQ)Tku6i<3QDspy622wp#?5C&%+9LjGl(2?IeZ6Ldz zm_iWt!cj5;%-N8;rv#0BMbtGh2WMuN0HtKYF7D4*9r^IaC^NH5ps2)b z>XT>X^Ha>ilwC#D8;?GcF*S_?VtHrs@xsfA%WexxtA0ep!AlfYTG~5*#U7%^OW5(> zkp+y)C&nR}{my|pzd6P_lPbS5#(ZSYqv#aLA8pm!B8IuO&2a{v3v#^?~RlvLJYE@MWmAkv`A>tsUNVuQ9xr$h!a)q$9q3PS;yxJj9 zJ_Pj;6@0p=V|R;PGy|X%A0&00!!qYHVKHrO#*zE3z>w0v_95;$LI(!uBL3i%-s>d! z$sNU9vvOs)7IV1V_6JZ)$-qZ}WLQPM>uIO#wq3DjYnN;iI-YWuIsE2Yu0^;am&GQa zBC&h=F-0TK#&~1%vSY?+9obQp^YPn_Q9}CTPFp`R!WW7V#8MTZ0)sF^Lpc(jWkh09 zGCG&tsA>Ea_EvZUGR^KYvbA}weQ5w+ekO(36R~#e^}FP$=!W*1&BXhoN1y-728eEL z%i3~V7iC}D=EzeWOcPnLqpTMcp*+j2cB8Ch4TT#*=M%l)yPggbgWFX$Q!J2T$*DFE zx&AjuxDTvTBneIQC4IAjXsVvuz#=vp9glR#sPPV+A;xr9l= z@gvy_RfCCXS$bF!;{wV{41jqSoO@1bF|+(g#EJ%Zq6#8khJ-c&d8;@`X{RuJ47r z4s;E@{Yp$K_MXN~z>@zO!JASE#Lg=%v&Dn`56s$UajRufjHuFvby(3)P#jK=u!jB2 zA+W#-t%$jNztxmuu@vU?TlVEFBwVh+iE@%l+- z>NGeh@C0T&T!&@2sCV6TAs_Lev)oGr9Es8B z{4nqo@jQw?z{%j;Bl{g4V`#lwtSO~3KR&%IuJ%ZE*urD7m2(7f(nO))3jT3HdnqZ{ z{z8GlRdD{meHfpg`IO*f*lK4^$0EIbNN;?YSPZuqq>hIa+Qm7C6NxAN(8IE|W_np^FKRFUTtOLd#m0)V zMpK}*BY1?D@Sm-DxK%jVO`f*atzBGnnBQKz&H2lL2#z9=m!%02_=VAA2vo6dxMxyJ z#xx3k-+t*v(8={JN@tP)?2MuFbiZC(I6FoAxJ({T)eTg{V(f zWxTaFh4fps$I`FUg?5hf!n6{uS|sGB(&s`-G0tY?*?qi5=?@t;dL6`_J{W#p$YBZh z(~YNKT{{hrL6zMitOg{*JM34hnSBWsB;WiPy`-Jv|I{{>oHWSZi6?74N@B|flhGNnmn41r!RDUncbd~-#X2P)h_$l_tWoGN1?;<3$@#&4vVb`GOSsrdEKU!JK zV9zE^#+C`ci844rS)d5aD?Kmmm)@NjJ zn8clo&*R%pa-YAQGI*{$_3;gH!ON%-W0zTQ;h=lqCpIP|xNMM)Laf|RdbV3)VqU&yro17pf#7|Q z{_B0M7k4E?k0<+0hBX`Xy(ncAOxD@_gv^MrI&Rq-G^BrqUa$Oq`@+387IO9cMla)# zOWC=k20^ufj?-NQ*;DyE`2pVcx%cr;%V49l;YE4(xhrfisWuLDxnE#j72l5=p&V49 zukHkQ@nAk9Cvb`L!~Fj;0GTh@IjZe;t7L9O;;|_aeYupVGwuV(r6M%^xFxElP>9a3 zcN)SP!jdYTZ*<-)QD_+d&~R9|ShHJ_G4hj5>yYwbzE?m%)6hlY=718~Cfa&4dP zfis5b;z)frhFI+hakaKG+t#0Pr{8rHq%x%c``m-gh6zOpCIZu%$xkeW^~Z?>OZ{VK zle&kbUIx`xf#`SxujwkR!0qZqSSC#r>g!L-zzn^~e&YjyB(Pe|SskU0v zQjMsYNNN3+V5to7_Kd!cdJ`;6z6Aj-wQ|yZg!K-2B(THHerTdlNT*Fn=nt#w#-XAT z7LbOE-S)j!hyWs#d4s=p!$sEmBI-6Fgu0E5GT(>Nl9dBqD63@vwa5W%b-6_gbhMU# zaNU1gwe$N&Hdj}Mx#4Y7)u#D0>HV<}#OU5?#9xlWE!)Y{Js601na5N7zMH27nIW`* ze`{}NDvS@CDS+)TL4#x>kD%CN*(4L3jRR%?rCGARN~H4GR7U#`pMj|a0nk-lf4D_1 zrEN^J%3_It?H-WC+xH_2itmoOBs>(u4GQtT9`X>HHjyTaK@&4K9(9kb!5YLh+Br~Gd#giz1T)vnw}u{5#24ugUMBn7 z6@#-VQ=^-BTLIr|me&-+VR-Q?#=iN7)TQ zVcsO%YGv&d-vojWT7g)Rg;6UY-!#>UJAn+k%9n5E8LZM4fHugZCx}o}a!w|cfdtWO zu`z$}_J*wc2Pa!ySVPODtsbwLNh9dAt+UdHLAcB9NA^2T;Ezk92R!y)HY>#RbyA0Fr_9MYf}1ZS z&GcW->gad{54{J`4>zV6zmChCq4wE* zBN_pJt+G;vBhBE|FXbz8PPDeC#k(jOT>aXHum5p-0EzF*GSmD?JIG`$uSgm$GeSL_ z)M~l3gSu^$QS;Hy$~5;er&jqnq}xaDv{*^d`BHbMLf8pH2 zQ7#qS)fKe1QtcY$zVM=v(s4TUS4EZuS6HcU>PXA@w(1g5_z@-h->0wLgT+AKViw&x zP8)Vi^H~zvTNplfQgS@9YE{CCB7_7)-6YX$?*Ct$wUbLW(jZYPKIdW3!@%n}0-7Uqp z31^7H^ErZ^W=mQix?YxKCy9Vwern|VubR2G_Vwr31wVU>5{MMO8uZpYOe6jQ$JB1G zoi{To-dUqWKUX7uK)}2)roH_l?oCS?tR}#uP`kVKq@j9@v237T8Y;;z(S`Z;K5I1tZ<_UG<+=2VBk`?j*)5F!sbtC*aFfg&!p8=`Fv2?deZk=GBYN z3X3ErrVbct(dXY^Qid*Tas2%9t)w%g1eVvHEAJuHEizFQOn9B#J`@BLzkstz;h0g{ zJ7RSf9j0)38kBez>?$iU47sOCW&>Tt>=wZ=M0DfB+O0Z#dh>NUnv>Z7crwlBstsek z!LCL#HawoCf9*w`w3OwrF|;aus>_VwbIlK-W!bnDctO#A*h;udG6@vkRqmDZdynAf z?tNEvO;EpBOKWH@?o@1^m*P|~AK=J|d`uY)@{_2Nic$!6;ItI8&{<}eO^Hn0`TH-d z5e!t05-dT*Rb`~(!>M2>!cDSf@m`LtQ9Qq})2d*TxPx~Ay3?3KbLM|G_!+86AWNx? zkL9U%j-T06*=TP5kb^cXHYN`p6%#e%3$(KDc2R*CDCXyNEG!lo56?3O>(Ay7n$~Q8 zmp2`yg@0}zAAg%g>3@5Fff#-UxUE0;J?YzDJfPu!Bz&E_fwjWCMj&!!!M ztn5$)A`>L#%D(QPHqNY_&`uH znAfpZ+lI`lxMmj!zJpO{8=7x!qu% z*>cn^GBmRKiGN8%~^%@<% znuA!Q^nxU-=CO}+=F%!&-^np*)0qtAF|)^!S-}oI&b}Gm`@6ejt|x;iC^*J1uDUkY z^iO-j{{+sMH*-S0IWqPqItT?qa?V1ohhr=vkU|iACmUp={(@Ws9>Z*#vdnq}1RLX2rQ5GXDLc!42S~HaD&Z|ij&_5tj zs1ux`OaWDJ&1aDw)h?IE_fsm%$_9(iE)U7j+d_DtK<@ZvFA$LIKQ`>5;rj|wh}=rbUstypkjv1)V~&6W2t zwZ&hdx$RRG9}75>y8C4a6$b41wvs7Fy&4trU%yIu0bR@&2at%7w=KopMKTQ{a)7q+ z7`ZCsJ230KPM9vXjOB5!#3s02TQSzoVdwTfmc&`YHZ1x+?W17<_CFQRYa&>KOu9Sg2u&5)eq`W1fZ#j71cYrYO#wQz7xFUT7JoCsXpgnK$P*)c!Rki$&5lWBgp zA89YPD6Q)BGMCjP*Wjbp*hbw&z}GqXarPb|CDlm!A_WnwIcn48WQXCuVu0Go8|;iO zJP*`T`R!_Y?H7qU%kp>;L0edsjO0_ECzpCt2z%vbf0oxn%TJZzCK zoPcJosc??9uxC{rRkes5pUV2y(UDy&#z|%mK$6zl5AbF++<(8O3&FfGM)UgW6h7{) z;V^Vi`@5z>;Z_P5Q2V1odA2r7-@6CbYoOXKVk!o^)pKfyY8pYT zr&iY2Yr<&k6TwL~U)up5w&NiP+611X}pI-Ec7`j$V* zF>&r}BO(Zpf-4v#)E@U-jyEiR6{v9Zzb3Z!5tjiPz^`P^jy)GW#g#zmFpKn?Ee=@# zoSnhX-8AKFXEke0ert_e=6_ROtIc5%cPyH^5TGS!j8a|+826WDNg8uN=pP<5l?6vA z4I_d3cR2dNxM{0RqphQZulU^GH(r7}HE>3pEg9=Wr<}o!v;VpA#`a#!f}P0#`bz1J4MU4B_^yaZe+go!W24wURWo=cg?=;n&dZ3U$`k7?g4GKu7tYss0 zC#gjvkK~)p(gGhS+UCu@h?i}V=(z;N@c8I@zqHI>;*BT;In6Ooc-+`G1_38<7h;p3BGe~XtDH!trB?@US1UOo5ADP}r+Mrs}+Lapp#vQ_Iw z$CoV5^^^f70f4wO3CR&ow^K6q1{OTz-%|2S_Hm3pZ*e(_5KZwgY2 z|85|z_Qu}H3m(B551zzstX=9+u)giP^Kott2?>wKmsTco$|7>n5rNlGy^cUrjX9hYNQRfr)O4|MIXB$lt9iE9*dZ&2Ob0ZlI`!aG}2GM&m1 zs(fRkL_FaFpO8DR0hdewOniOMe(Kt}IYZE1W6PuLz4Pwah8YDFao8*6Oy29lp`M!#-kR;Y zekan5{_%9qQXf}u619}n7klwiCI$}7A#nOcAX$78v+XXnf{vAGsttsQ5UMNY^c z`g2l`y-?NL;VSGrC0iqf6+E7(Ya3H0<`Gf^S>0h=6~lYt;^O4K0neQZ#IqEkS#sJaeiv9DRE+jia)&%D(pqn(7{#hZ=T(zeNoUo^vme4$1 z0I*@|Sy4y8u4`<WE&6-l$vb>T9jRoBn-^qQ|$2T>$PivqQs2y#@6UypbWB=aKC{k8t2;osmFjMhz zcaChNUlOfDM?s}1yuC)*S-@^MdNjQ``j|n(=l|Xu@z}-^+hS3^a50?iMv=kG#ye$$ zn#&gNV7i6Ws=Cu5A22ToCBr-6k4hRtw!++lUa#G)2+8G zBy#j36GeXWv}0!MMJdpH){l~|n>hOmrTmd>1SrH#=X4hLDNyo7*yf5>9$}lGekVs^ z5qjKpe`kKX3@NaDq_wct{_wcZG3us?&&qy{4#$AmLq`WEM8E>8i2-#+4$RM*Jyrr^ zDOdQUi3LeqOV1YQ)^~kG1qyfj95pz1KYK`-@Uh_054#mNEVLcNp^acbA@VG#$au(VMv~d{HcIx0tF`s|W|-T7tgJ4; zB_1A%t-_jWca{#?=nkU7y<8ckJW*3%ipt-SGD59agCU6x*Mr>w(7lxGy1XUWedTp{ zrC8JFl@MxIe=mk;kNMaW%R><0&=1)=1Vt$TB;ZRy9Eoo09vr-i{0FXJW(n| z^w_y+OM9ux2%tB-U%-rwPV-8LG`bl3j%pKgcS!7YHxEP#d9+In4fLGi;{8rHR=;-g zS)VDi<TCk(*Q0Y@5m zT=CBLNF7o)Dy0w6CT^jL=oTZ|8<)Fi?HD*J~}8 z=K_+B3;auAnh2y9T^F!wyRXX$S*PO~Z~wSr4H_NWsp9uOf zI{2r8GB|x6%J8H0wpPwjn)mLl53_%mEWberk)%!n7EFW5LSyQT+vay<(aMiIwTQjc z&)o{9h>6r$`gcV`XsKbh27>|h2x{A5JBD7KtQMGezu+$;1SFcbU?2rdm1>n5L>i@d zZ(q*$n3h(=7_WJgzzEDuFbJw&ylwI>#_52)i!hiXS}tR?FX+a~1!XESb?v*Z=zhR` z_17mAv@GIeWyDQy<@!1`KQjtF+BNvzM1SYR5tOY~)b)U^;_l zaRI9Rr%I(0Z>kuUa{GdAGH4!H-eyu_q@vYS;?8az>_L*nHs_2}mBfB1OJ1t-GML}3 zwu5)Ziy)#O)~@ff;mk1Ttrx*!_z>zibwS2AbyT&-qw--a1@trO(s?|2CI==W<%yl( zqa0R%H&fGL^aGz-anTtJxq~S{=1L`K6Lp?g3^#5hGytzqa@S!gT zE~C`}4N!S`jDjXwk+Am!Ds+Bj51uK6$`Hoj9_~S#+<%( z?l-Jl?Q?u!;`v(WMXh#rYN)qdCoZuI$Y%2dN`wv%4u1H4f*_o$GkUhwjG+*;Bd^US zTJ`?W3XS%$E;N9$*bhkBYN6u~&W-3>pXekMKD@Cn74&ZHRmm}`TJ#|;z4Ir+nq<;^ zmm6X;@RKecPGz#(CRPQQd^X=RAB~G8)~GXAn)>2mFvSV$lcN)s_7mIY=3axK z!NPlLBnYxLJbEx6Z3N|r>#e`9HwBRCxpE4}+8!sE98AY#2di=TwvAV#yX{)Qtadtw zP3a7~FT@B7hMGG}+L64Tpk1`Dq$%ayb(gyT)i7s8wtEO|5-P6FuDw1*8_ie(HIV-~ zJK?>MgmIwu?`1?Yg1KpQrCk%g4m0p$Vcpt4`n7F|N7S+Dnh_6m?=Q!kd%` znG4J~oswMZ<#G<*F^o}v31UmHiA{~Id$}$|vv=S)Y1V-_I9OgL-hD={Omq(wXcn|% zUWW$ds|Z5t%0`~^rprbus+htn0L}E-*846}nwRZH`Fdfypgsg)kJVVsJ%@@<+^RXj zX%qY=!qK^Z{ghaEWQ}(uZ6_cJdFG{K#tj97?ozqcVyU=m?>lb7VcW{}fjV$6PY>x1 z=@($amTFA)9thA?`ThDm*(EP9&PVO?OitQg`S>LRGLa)eD0w2_q<_$coM^JhXzuR> zW9GTeXaVaA@EHNa$cc4t;zHrZGEz;oz<4~O5Pa+k07{^FHRHVF33#gwbZ`%|FS&V4 z3fbsjKbogvW1qVQKICF|a@`X4M_-hQgs!3M*^+yiSAusx>ZaIbKn&zSXU}h@k|TKp zeJnFRC`q8`o^gzV`B2u00R}Z|OmBpUn6OREunD`y&*BTw2}|k29bx3rJZN^dSUbLn zt0DT6=0weg`qNw5l#M97|QzPP5E{=Av8^g7_>G;XavxS0P7hLB;_FYBuIRgo*< z&9F0*fu+g`BON>LIWh#${Ac?Kbaf%%BGKUNM5e+XQ#ky->ga>+yy%*iM>sDt+Ethl z|B1`2i0-=@6KI(hxc@=m&&M)!j;J{#ypwuISecZ zGnFOmGRrOz56Ws?j=O|W`&InTozVG95lrpyi)d{u$rE@?01rcAhlC7F5H9orJ7WR(=;8Ysjqg#O{kpNfrxue-Zj z%iSK5aJNViijcjOgpfUZk##Up493!?vKJwH*%?dL!OT#~TGou+DEmHH##qAd{n2u_ z+|N1RbAG>be$P42^KYY>&*!?{*ZX>Juh+}4oYeAOgZX{FZ*Ahv6#MeR-Mfb6(aJCI zszEmyft#TbS8Dw>Z!)xpnsXy8vav?h^^cnT%@=1)azn-rOX)?x@E*#<={$qdwfG#5-lVyt;zy z5iL0i{LTK_TrgdJI`?SM#bApaTCwsj5d>-PR9VjE_Q{Y5PHwz{DzQaNZujMq_>UTc z+>qb|ydeHOt2y@n!K~(`E1ki0Ft9p#mq32(BSyRAEq(2V3mf+w=E*v zSd|?z?2(|kn6B_i3*9Na_}&xvsjlEJHP?BmcRSG1Yu)J5$?{XL@#Z!D(f&NnLCB=% zdCbe(32M&NDt|hDWMlKGq zUBTSCI$l^RK%&R~=mp}M4nE8L!8Vrud@@<)L%sAnKE1mx#~65W;sXg zC{KfMNAsSQrz>Up`_Nu#))SFFDIic9PMz_KWz;aOiDl7DVxZtQStV7V3}XKd3n`{w zZNcwK{ToTWMoDc*(7&5_uLfxrFbMCP)Iyd^FbH#2L1Ek!{(bZbit*>m@ z_H^gqtf4884WxU*WxWDmf;`hE5$chdI|)3|IRP9uBB8nn(}z1&M> z+~<=zf=}6)qyJl8n8tiHQG&)N6Z6U9Q zdX6)CCa=XlKUs#t86xfIh5o*WLnM-Kqz%BDA^c2_F|xIsN(|XQa!VgWF^^%!469*u zCL!_D<;Ua<*~-qM%zb$vKkD&I9%Omz!-zNucBaWp_{?eFzWl@YVYQnQIcqE!tU5-ZNwHP zw~4yCsiG(1;gYv0gp?EGBs6b-NG*B84+S%5sFPug-=*ZhevupgNuMdWr(1NNlWHyQ z3#V)+&h~l z?U!7}9gb37TZ{#M*vGhV9I6*Z#m_F8elL-J*$o>FUwZhFfim?=B5@e5Yrz%`4J{3Y z$0QAtQNj;2c$(cO$RcMQyWZ=yBwD7oOgqKIg+xa}t~0i9M<#f+oAtFG2z!t>+1x1X z_b%Gu5SJ$wO|deIh`s}}y`?a0WFsiXHIw0$w=R{N&eU+%vq*NgZA3U{1UsrX`Djal zaRvdk(b694Q2HJQ#JIl~puaeHE0fQ$=dfsJV@Gb)chBQ8l*>&@O#SE62L~BLV46#V z<$JAN9%$SC&|n2r7Shmua`#d3mKM4e6tY+AtwuwyDf4e$Y&-L5a?}w^xw8QpBd>f^q9fom!eO&JNT|l9wpqP55yD9_yAO9bjT6Q`l zF?;ga&@?ucOV$X3RZuTy)j>6Gtl-dF=GtGAhH9jg7X9^S{NB|bHm4~L;EHzYQ-bm1L!VFNKv0OiW81R#{E@p0Od_gOhq@!Rx4DzUxjVR` zd%Y_7+7EY4Q9i!cn^V*Pw8YoO#1}J)0+X2PJc!A5&NM$WaXmRG;m<@ES6-N;HJ;zl zj^))ococXzfU)pQi`9|Ebz;bkqJTDdZgw%sGGzkafqrtqw8MW zv5V)P!a)YIIrfBE!|{lnJv*zZ zM=24Xheq!q_Aq6*rB-mX$gUEvMN1*=jsE6l{n)_cm`lt|g92z?+Xw=pHAgq6;TJh0|Zny}=lWP|Yv53`GSZatUd zit{%NlyE(i*=KcK;R$-dZ#lrv0^P)E2YV1|_{+kCDV znk%H>4b=~4Xbt5JD8!z^&P3KfEHZU95U4#6dqc+~_D0z*YVh^0=Axl-Sm}-h@1*60 zLH0C4-Y!n=FyTzOTsJ*8w3oM8ZbEDGL%s%MNw2y+0pZ?`M=>*!P57))>_##JEMnpT z1N5_#FCO1rM^$oPjj%4-SY1)Vng1iY6I0g7bj{X`)@wGZa4{n-#iBRSP+2_vjwXQP zExe}Q^lsBJ&FfXl-q})&=gSaOeVe!S+@L+@fnHs`oQCshZ&;p<<})RE>PAgu5b}m= z1YpdtLH1k+KF}#sV?s-UKfkzn7dA?KBtmbL*g(J3U7kVZ)Zl;>e0I(Bmfya8PUtD* z40FMBQN>^x&C{?4mA%^`9UiL4ls29xD598qrf%lR(3nEgQe?WR{!L@dP@QQ6&E0hegaJqZC6!O(5chb-erTa!Rk|h>|_l_F6$`bwCT$cK?q@y4qnT)<> z-L}&pw6m(>xD0xHBB`ci8PG%@wF?Z79;=$f!GqxAP1|qSZc4>Ah76zM) z=+Aa|msRwoZ@kg--1o7Hgfw9kwEk+Xd0vFVZ`!n*HrDKqGiI`>aoO1->_dL{Fh~q-5bKAn`iM?^7T(~} z$O_DvT{fwDJNWYrhx<*9N8+`~X=>t_`>B@C3m5m5Ntup%k!qv%b<}L;5?u$DaYTpZ z%0UJOI9hO9YQBYLf(pZtPnPGSdALQ7Ro<%(3mB*#RaA}h36JK~1@j8OdUDdace0tY z)=#rjL=Fw649V85loF6ie zzM_HDO>PGUuNAhx4jAQa5I*F!rqrsCnQo@$q^RzvpsIHVi{M!3lKfgW0F^jNNOBae z+Iy1z7O0Op1@Mc`qsHi7fv|Lmy+X#4cBrVco72%O__Mc1*}L-_T0^RMBJ&M1Vww~2 zWhaFw{NTvQP)qM)fY94)ETfk9sL_R<6FS~vdgnK1 z%j}>XF;8u1({uuKjU2g>>1xkl)pMcIYjwPwMK=jCIfAb(7}DxBXPe7vb}}lrnCm5z z9N1o57U|TtGD6GdYP*cP7&8(zb9NU`*dA@DEm#!QGp!TV++*`Tq+d)&98(UbST7=< zFaM#%A`_~!=IKG*$d(6AGwJWyOIzn{47z2LwSIq0$Pna)wV4K```~DhxpJQQz9HAP z>F!qXi}cu}l3}e=`zBV1tyVf6XOOT%KVs6sE@brM$Ti$QvF^zWT6+?6&N$)nq;uWOzbqI79n#uoTw@{lO(Cu0nrt{=O@-p7h5^JRL{ z5PB?HOianIy!~eEP_SH=$_c-l=VWW&OV_>X88ue*B8&8x4QW;uY%-7;`ew_%bickV?E()67i(%R;HCoR}WHtcn^wdMX>eb;@WtU2@3-q=H+m2BQD zhEi`~vb#sv75W1GrncTtLg2iL5oASpaS1BjYI_o|l{s`g#D96bSkm{^F;@>EF zIHS~`J7SGb@`Ou6Jn^rNyI-MTWTZR%O@7tx|i6qfBy8VzEDf8Q`vA-R!rQr%GB%kx`d=nlAp*1pV&%PCXe zE#v((MB{F;i9xsUt>1rT$El96C&ynW;eAv3`M0jN1%LXIe>TB*!%hS`)y{eOmg!6F z-(Fq*c z_1A!v>?eo1rm}KQ){+)Qe9|Ev6fM`y;pS72#%%xF7hW^DXu~aeKU3CCUPT~>kC!A- zumMIurAfyz~UkEjz#L2D@7Ss#!6v9XkBm6W|{$a6|K6a(cgJ1Tx)VwDrq$ z!%y}*^LG=z8anWH^Jzdbzrd!%s|gca9T6c!Se5=)ZxXa?pQ-qTFa zF8sDsl2Q*aRYkh)4o;>Ie>lrS7o@6(Nl3uX*^8nwRW%!k;DW%6ksiK`9r7M=R)zJ$(AxDE5J zXM1rz5ios~K$unWUOzT+76=u7xCvrz5iuiEU~?PyuTL0lNnEt1TF~B9^;fm$iib_q z>I8WhW$95^Wwj2AygvYC|E3tWs2Xu`(e*{F$aEg &eNi{TXCioUfA`+i!=jc>6w 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 Sy`KO-L3&zuH7nKcJ^L?&NyNec literal 0 HcmV?d00001 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 GIT binary patch literal 26534 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 FtUOuHR>G462RTc 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 Aj{pDw literal 0 HcmV?d00001 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 GIT binary patch literal 33914 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 w%=Fmb#<(dd7<!I}$nsaI3Hd0Ria{L`0-UdM}Ff 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[](../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 29da041335c..ce9d01e0c1e 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 a29494b1407..d42e3f024bf 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 2736daf4e21..00000000000 --- 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 026cb3d7e59..53dd5ce855b 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 b63423d773e..3197acaa99c 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 GIT binary patch literal 0 HcmV?d00001 literal 7206 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 a6B+Bs!3L=9az6V12e7qrw5&4sPW&$#jUTlD 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 00000000000..faf8e495fd9 --- /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 d18b1cfc921..49d9521d209 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 0966779d95c..cb0c2d42c1e 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 00000000000..708a386da74 --- /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 00000000000..6fa440f4f72 --- /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 be52d26dcbe..73dc510cc0a 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 a7359f79e99..dbe35452076 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 a64be9d9455..285837cbed1 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 d37eb4f96c8..3ef00f87b00 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 5a1b32501a8..a5e1a75b0fb 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 2326ebaa81f..dbcead042dd 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 d143978cd0d..8edb4bcf120 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 1b6d0f6369d..989f35f97a1 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 1e947e576b9..dc61c380e00 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 fca464be3de..16627c7f06e 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 0419b1128bb..3b8d57161af 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 73e950e6b90..22c5d257813 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 184b1fe6bdf..3c84c74d273 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 d8c1b45ec5c..48e4f83a588 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 43069734367..6daeaee0acc 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 ea62b034cbc..a6a6fee99c9 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 514f1594cfa..b6126ec614d 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 da30027e1a1..913f54dd166 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 3cdef6ee4ea..3a458138182 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 4ba183c88dd..7a7bb9c4560 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 a5142c76fa9..9e04dbf213c 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 3396a5f6bee..ccaa2af58e6 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 22aafd1c9d2..0d12a471cf0 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 d3cc5ebd5a3..8dec87d6b6e 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 dd3cb63667b..13718a5a578 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 57e9708b449..1ba75a22e23 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 586fa16f707..e1631934f03 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 a1fb4a932fd..5dee2d60e82 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 685e878c4ae..bf08c222220 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 43551e38c86..1ff71d655ef 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 2c0dfaad23e..1c57edf36c0 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 7620a18cf87..8c768cff95f 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 dbb092db964..108f538119c 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 121a2b16f46..d9c59e6ffbe 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 5d568e398b5..c73affdd12d 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 58d3d624c65..628c69d6743 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 7a10c652a07..a22e0cd4538 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 4356532dc2c..46beb6e133a 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 b1a4b7ef3ea..34c657e197e 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 0afc2536a82..01be24bbbb9 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 e6e68c7c605..75aa986e55d 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 548f65d15c5..e34e37d124e 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 5edf074e3a8..10806a95104 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 0e2eab6f174..80a1f466e03 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 86038471bc1..a249d9457f6 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 c60169d1584..e9d637cad9d 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 5fa70876989..0e2ddbcf47a 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 794042aad52..5fc2525d714 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 c05a50ef670..e2bc9d05584 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 b2b0bbde337..1139514ab02 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 dc6e872ae9a..da6a71e2e44 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 37ffc8be224..00657465739 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 7d79728f80b..3100bf73961 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 9259a8073d9..59d6b22ec1f 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 854d11747ab..5718a316370 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 6d22490c57c..3788200ef39 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 a8aeda8b9cf..ac183bb6a81 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 1a5d7443cde..3108c377f60 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 afdf04d347b..f1223920bd2 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 299ab8b061a..1e56b9474b9 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工具、提供重启维侧框架等。 -- Gitee