xref: /third_party/toybox/toys/other/i2ctools.c (revision 0f66f451)
10f66f451Sopenharmony_ci/* i2ctools.c - i2c tools
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2018 The Android Open Source Project
40f66f451Sopenharmony_ci *
50f66f451Sopenharmony_ci * https://www.kernel.org/doc/Documentation/i2c/
60f66f451Sopenharmony_ci *
70f66f451Sopenharmony_ci * Note: -y must have the same value in each toy for `confirm`.
80f66f451Sopenharmony_ci *
90f66f451Sopenharmony_ci * TODO: i2cdetect -q/-r and the "auto" mode?
100f66f451Sopenharmony_ci * TODO: i2cdump non-byte modes, -r FIRST-LAST?
110f66f451Sopenharmony_ci * TODO: i2cget non-byte modes? default to current read address?
120f66f451Sopenharmony_ci * TODO: i2cset -r? -m MASK? c/s modes, p mode modifier?
130f66f451Sopenharmony_ci
140f66f451Sopenharmony_ciUSE_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_BIN))
150f66f451Sopenharmony_ciUSE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_BIN))
160f66f451Sopenharmony_ciUSE_I2CGET(NEWTOY(i2cget, "<3>3fy", TOYFLAG_USR|TOYFLAG_BIN))
170f66f451Sopenharmony_ciUSE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_BIN))
180f66f451Sopenharmony_ci
190f66f451Sopenharmony_ciconfig I2CDETECT
200f66f451Sopenharmony_ci  bool "i2cdetect"
210f66f451Sopenharmony_ci  default y
220f66f451Sopenharmony_ci  help
230f66f451Sopenharmony_ci    usage: i2cdetect [-aqry] BUS [FIRST LAST]
240f66f451Sopenharmony_ci    usage: i2cdetect -F BUS
250f66f451Sopenharmony_ci    usage: i2cdetect -l
260f66f451Sopenharmony_ci
270f66f451Sopenharmony_ci    Detect i2c devices.
280f66f451Sopenharmony_ci
290f66f451Sopenharmony_ci    -a	All addresses (0x00-0x7f rather than 0x03-0x77 or FIRST-LAST)
300f66f451Sopenharmony_ci    -F	Show functionality
310f66f451Sopenharmony_ci    -l	List available buses
320f66f451Sopenharmony_ci    -q	Probe with SMBus Quick Write (default)
330f66f451Sopenharmony_ci    -r	Probe with SMBus Read Byte
340f66f451Sopenharmony_ci    -y	Answer "yes" to confirmation prompts (for script use)
350f66f451Sopenharmony_ci
360f66f451Sopenharmony_ciconfig I2CDUMP
370f66f451Sopenharmony_ci  bool "i2cdump"
380f66f451Sopenharmony_ci  default y
390f66f451Sopenharmony_ci  help
400f66f451Sopenharmony_ci    usage: i2cdump [-fy] BUS CHIP
410f66f451Sopenharmony_ci
420f66f451Sopenharmony_ci    Dump i2c registers.
430f66f451Sopenharmony_ci
440f66f451Sopenharmony_ci    -f	Force access to busy devices
450f66f451Sopenharmony_ci    -y	Answer "yes" to confirmation prompts (for script use)
460f66f451Sopenharmony_ci
470f66f451Sopenharmony_ciconfig I2CGET
480f66f451Sopenharmony_ci  bool "i2cget"
490f66f451Sopenharmony_ci  default y
500f66f451Sopenharmony_ci  help
510f66f451Sopenharmony_ci    usage: i2cget [-fy] BUS CHIP ADDR
520f66f451Sopenharmony_ci
530f66f451Sopenharmony_ci    Read an i2c register.
540f66f451Sopenharmony_ci
550f66f451Sopenharmony_ci    -f	Force access to busy devices
560f66f451Sopenharmony_ci    -y	Answer "yes" to confirmation prompts (for script use)
570f66f451Sopenharmony_ci
580f66f451Sopenharmony_ciconfig I2CSET
590f66f451Sopenharmony_ci  bool "i2cset"
600f66f451Sopenharmony_ci  default y
610f66f451Sopenharmony_ci  help
620f66f451Sopenharmony_ci    usage: i2cset [-fy] BUS CHIP ADDR VALUE... MODE
630f66f451Sopenharmony_ci
640f66f451Sopenharmony_ci    Write an i2c register. MODE is b for byte, w for 16-bit word, i for I2C block.
650f66f451Sopenharmony_ci
660f66f451Sopenharmony_ci    -f	Force access to busy devices
670f66f451Sopenharmony_ci    -y	Answer "yes" to confirmation prompts (for script use)
680f66f451Sopenharmony_ci*/
690f66f451Sopenharmony_ci
700f66f451Sopenharmony_ci#define FOR_i2cdetect
710f66f451Sopenharmony_ci#define TT this.i2ctools
720f66f451Sopenharmony_ci#include "toys.h"
730f66f451Sopenharmony_ci
740f66f451Sopenharmony_ci#include <linux/i2c.h>
750f66f451Sopenharmony_ci#include <linux/i2c-dev.h>
760f66f451Sopenharmony_ci
770f66f451Sopenharmony_ciprintf_format static void confirm(const char *fmt, ...)
780f66f451Sopenharmony_ci{
790f66f451Sopenharmony_ci  va_list va;
800f66f451Sopenharmony_ci
810f66f451Sopenharmony_ci  if (FLAG(y)) return;
820f66f451Sopenharmony_ci
830f66f451Sopenharmony_ci  va_start(va, fmt);
840f66f451Sopenharmony_ci  vfprintf(stderr, fmt, va);
850f66f451Sopenharmony_ci  va_end(va);
860f66f451Sopenharmony_ci  if (!yesno(1)) error_exit("Exiting");
870f66f451Sopenharmony_ci}
880f66f451Sopenharmony_ci
890f66f451Sopenharmony_cistatic int i2c_open(int bus, int slave, int chip)
900f66f451Sopenharmony_ci{
910f66f451Sopenharmony_ci  int fd;
920f66f451Sopenharmony_ci
930f66f451Sopenharmony_ci  snprintf(toybuf, sizeof(toybuf), "/dev/i2c-%d", bus);
940f66f451Sopenharmony_ci  fd = xopen(toybuf, O_RDONLY);
950f66f451Sopenharmony_ci  if (slave) xioctl(fd, slave, (void *)(long)chip);
960f66f451Sopenharmony_ci  return fd;
970f66f451Sopenharmony_ci}
980f66f451Sopenharmony_ci
990f66f451Sopenharmony_cistatic unsigned long i2c_get_funcs(int bus)
1000f66f451Sopenharmony_ci{
1010f66f451Sopenharmony_ci  int fd = i2c_open(bus, 0, 0);
1020f66f451Sopenharmony_ci  unsigned long result;
1030f66f451Sopenharmony_ci
1040f66f451Sopenharmony_ci  xioctl(fd, I2C_FUNCS, &result);
1050f66f451Sopenharmony_ci  close(fd);
1060f66f451Sopenharmony_ci  return result;
1070f66f451Sopenharmony_ci}
1080f66f451Sopenharmony_ci
1090f66f451Sopenharmony_cistatic int i2c_read_byte(int fd, int addr, int *byte)
1100f66f451Sopenharmony_ci{
1110f66f451Sopenharmony_ci  union i2c_smbus_data data;
1120f66f451Sopenharmony_ci  struct i2c_smbus_ioctl_data ioctl_data = { .read_write = I2C_SMBUS_READ,
1130f66f451Sopenharmony_ci    .size = I2C_SMBUS_BYTE_DATA, .command = addr, .data = &data };
1140f66f451Sopenharmony_ci
1150f66f451Sopenharmony_ci  memset(&data, 0, sizeof(data));
1160f66f451Sopenharmony_ci  if (ioctl(fd, I2C_SMBUS, &ioctl_data)==-1) return -1;
1170f66f451Sopenharmony_ci  *byte = data.byte;
1180f66f451Sopenharmony_ci  return 0;
1190f66f451Sopenharmony_ci}
1200f66f451Sopenharmony_ci
1210f66f451Sopenharmony_cistatic int i2c_quick_write(int fd, int addr)
1220f66f451Sopenharmony_ci{
1230f66f451Sopenharmony_ci  struct i2c_smbus_ioctl_data ioctl_data = { .read_write = I2C_SMBUS_QUICK,
1240f66f451Sopenharmony_ci    .size = 0, .command = addr };
1250f66f451Sopenharmony_ci
1260f66f451Sopenharmony_ci  return ioctl(fd, I2C_SMBUS, &ioctl_data);
1270f66f451Sopenharmony_ci}
1280f66f451Sopenharmony_ci
1290f66f451Sopenharmony_cistatic void i2cdetect_dash_F(int bus)
1300f66f451Sopenharmony_ci{
1310f66f451Sopenharmony_ci  struct { int mask; const char *name; } funcs[] = {
1320f66f451Sopenharmony_ci    {I2C_FUNC_I2C, "I2C"},
1330f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_QUICK, "SMBus Quick Command"},
1340f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_WRITE_BYTE, "SMBus Send Byte"},
1350f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_READ_BYTE, "SMBus Receive Byte"},
1360f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_WRITE_BYTE_DATA, "SMBus Write Byte"},
1370f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_READ_BYTE_DATA, "SMBus Read Byte"},
1380f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_WRITE_WORD_DATA, "SMBus Write Word"},
1390f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_READ_WORD_DATA, "SMBus Read Word"},
1400f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_PROC_CALL, "SMBus Process Call"},
1410f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_WRITE_BLOCK_DATA, "SMBus Write Block"},
1420f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_READ_BLOCK_DATA, "SMBus Read Block"},
1430f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_BLOCK_PROC_CALL, "SMBus Block Process Call"},
1440f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_PEC, "SMBus PEC"},
1450f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_WRITE_I2C_BLOCK, "I2C Write Block"},
1460f66f451Sopenharmony_ci    {I2C_FUNC_SMBUS_READ_I2C_BLOCK, "I2C Read Block"},
1470f66f451Sopenharmony_ci  };
1480f66f451Sopenharmony_ci  unsigned long sup = i2c_get_funcs(bus);
1490f66f451Sopenharmony_ci  int i;
1500f66f451Sopenharmony_ci
1510f66f451Sopenharmony_ci  printf("Functionalities implemented by %s:\n", toybuf);
1520f66f451Sopenharmony_ci  for (i = 0; i < ARRAY_LEN(funcs); ++i)
1530f66f451Sopenharmony_ci    printf("%-32s %s\n", funcs[i].name, (sup & funcs[i].mask) ? "yes" : "no");
1540f66f451Sopenharmony_ci}
1550f66f451Sopenharmony_ci
1560f66f451Sopenharmony_cistatic int i2cdetect_dash_l(struct dirtree *node)
1570f66f451Sopenharmony_ci{
1580f66f451Sopenharmony_ci  int suffix_len = strlen("/name");
1590f66f451Sopenharmony_ci  int bus;
1600f66f451Sopenharmony_ci  char *fname, *p;
1610f66f451Sopenharmony_ci  unsigned long funcs;
1620f66f451Sopenharmony_ci
1630f66f451Sopenharmony_ci  if (!node->parent) return DIRTREE_RECURSE; // Skip the directory itself.
1640f66f451Sopenharmony_ci
1650f66f451Sopenharmony_ci  if (sscanf(node->name, "i2c-%d", &bus)!=1) return 0;
1660f66f451Sopenharmony_ci  funcs = i2c_get_funcs(bus);
1670f66f451Sopenharmony_ci
1680f66f451Sopenharmony_ci  fname = dirtree_path(node, &suffix_len);
1690f66f451Sopenharmony_ci  strcat(fname, "/name");
1700f66f451Sopenharmony_ci  xreadfile(fname, toybuf, sizeof(toybuf));
1710f66f451Sopenharmony_ci  free(fname);
1720f66f451Sopenharmony_ci  if ((p = strchr(toybuf, '\n'))) *p = 0;
1730f66f451Sopenharmony_ci
1740f66f451Sopenharmony_ci  // "i2c-1	i2c	Synopsys DesignWare I2C adapter		I2C adapter"
1750f66f451Sopenharmony_ci  printf("%s\t%-10s\t%-32s\t%s\n", node->name,
1760f66f451Sopenharmony_ci         (funcs & I2C_FUNC_I2C) ? "i2c" : "?", toybuf,
1770f66f451Sopenharmony_ci         (funcs & I2C_FUNC_I2C) ? "I2C Adapter" : "?");
1780f66f451Sopenharmony_ci
1790f66f451Sopenharmony_ci  return 0;
1800f66f451Sopenharmony_ci}
1810f66f451Sopenharmony_ci
1820f66f451Sopenharmony_civoid i2cdetect_main(void)
1830f66f451Sopenharmony_ci{
1840f66f451Sopenharmony_ci  if (FLAG(l)) {
1850f66f451Sopenharmony_ci    if (toys.optc) error_exit("-l doesn't take arguments");
1860f66f451Sopenharmony_ci    dirtree_flagread("/sys/class/i2c-dev", DIRTREE_SHUTUP, i2cdetect_dash_l);
1870f66f451Sopenharmony_ci  } else if (FLAG(F)) {
1880f66f451Sopenharmony_ci    if (toys.optc != 1) error_exit("-F BUS");
1890f66f451Sopenharmony_ci    i2cdetect_dash_F(atolx_range(*toys.optargs, 0, INT_MAX));
1900f66f451Sopenharmony_ci  } else {
1910f66f451Sopenharmony_ci    int bus, first = 0x03, last = 0x77, fd, row, addr, byte;
1920f66f451Sopenharmony_ci
1930f66f451Sopenharmony_ci    if (FLAG(a)) {
1940f66f451Sopenharmony_ci      first = 0x00;
1950f66f451Sopenharmony_ci      last = 0x7f;
1960f66f451Sopenharmony_ci    }
1970f66f451Sopenharmony_ci
1980f66f451Sopenharmony_ci    if (toys.optc!=1 && toys.optc!=3) help_exit("Needs 1 or 3 arguments");
1990f66f451Sopenharmony_ci    bus = atolx_range(*toys.optargs, 0, INT_MAX);
2000f66f451Sopenharmony_ci    if (toys.optc==3) {
2010f66f451Sopenharmony_ci      first = atolx_range(toys.optargs[1], 0, 0x7f);
2020f66f451Sopenharmony_ci      last = atolx_range(toys.optargs[2], 0, 0x7f);
2030f66f451Sopenharmony_ci      if (first > last) error_exit("first > last");
2040f66f451Sopenharmony_ci    }
2050f66f451Sopenharmony_ci
2060f66f451Sopenharmony_ci    confirm("Probe chips 0x%02x-0x%02x on bus %d?", first, last, bus);
2070f66f451Sopenharmony_ci
2080f66f451Sopenharmony_ci    fd = i2c_open(bus, 0, 0);
2090f66f451Sopenharmony_ci    printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
2100f66f451Sopenharmony_ci    for (row = 0; row <= 0x70; row += 16) {
2110f66f451Sopenharmony_ci      xprintf("%02x:", row & 0xf0);
2120f66f451Sopenharmony_ci      for (addr = row; addr<row+16; ++addr) {
2130f66f451Sopenharmony_ci        if (addr<first || addr>last) printf("   ");
2140f66f451Sopenharmony_ci        else {
2150f66f451Sopenharmony_ci          if (ioctl(fd, I2C_SLAVE, addr) == -1) {
2160f66f451Sopenharmony_ci            if (errno == EBUSY) {
2170f66f451Sopenharmony_ci              xprintf(" UU");
2180f66f451Sopenharmony_ci              continue;
2190f66f451Sopenharmony_ci            }
2200f66f451Sopenharmony_ci            perror_exit("ioctl(I2C_SLAVE)");
2210f66f451Sopenharmony_ci          }
2220f66f451Sopenharmony_ci          if ((FLAG(r) ? i2c_read_byte(fd, addr, &byte)
2230f66f451Sopenharmony_ci                       : i2c_quick_write(fd, addr)) == -1) xprintf(" --");
2240f66f451Sopenharmony_ci          else xprintf(" %02x", addr);
2250f66f451Sopenharmony_ci        }
2260f66f451Sopenharmony_ci      }
2270f66f451Sopenharmony_ci      putchar('\n');
2280f66f451Sopenharmony_ci    }
2290f66f451Sopenharmony_ci    close(fd);
2300f66f451Sopenharmony_ci  }
2310f66f451Sopenharmony_ci}
2320f66f451Sopenharmony_ci
2330f66f451Sopenharmony_ci#define CLEANUP_i2cdetect
2340f66f451Sopenharmony_ci#define FOR_i2cdump
2350f66f451Sopenharmony_ci#include "generated/flags.h"
2360f66f451Sopenharmony_ci
2370f66f451Sopenharmony_civoid i2cdump_main(void)
2380f66f451Sopenharmony_ci{
2390f66f451Sopenharmony_ci  int bus = atolx_range(toys.optargs[0], 0, INT_MAX);
2400f66f451Sopenharmony_ci  int chip = atolx_range(toys.optargs[1], 0, 0x7f);
2410f66f451Sopenharmony_ci  int fd, row, addr, byte;
2420f66f451Sopenharmony_ci
2430f66f451Sopenharmony_ci  confirm("Dump chip 0x%02x on bus %d?", chip, bus);
2440f66f451Sopenharmony_ci
2450f66f451Sopenharmony_ci  fd = i2c_open(bus, FLAG(f) ? I2C_SLAVE_FORCE : I2C_SLAVE, chip);
2460f66f451Sopenharmony_ci  printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef\n");
2470f66f451Sopenharmony_ci  for (row = 0; row<=0xf0; row += 16) {
2480f66f451Sopenharmony_ci    xprintf("%02x:", row & 0xf0);
2490f66f451Sopenharmony_ci    for (addr = row; addr<row+16; ++addr) {
2500f66f451Sopenharmony_ci      if (!i2c_read_byte(fd, addr, &byte)) printf(" %02x", byte);
2510f66f451Sopenharmony_ci      else {
2520f66f451Sopenharmony_ci        printf(" XX");
2530f66f451Sopenharmony_ci        byte = 'X';
2540f66f451Sopenharmony_ci      }
2550f66f451Sopenharmony_ci      toybuf[addr-row] = isprint(byte) ? byte : (byte ? '?' : '.');
2560f66f451Sopenharmony_ci    }
2570f66f451Sopenharmony_ci    printf("    %16.16s\n", toybuf);
2580f66f451Sopenharmony_ci  }
2590f66f451Sopenharmony_ci  close(fd);
2600f66f451Sopenharmony_ci}
2610f66f451Sopenharmony_ci
2620f66f451Sopenharmony_ci#define CLEANUP_i2cdump
2630f66f451Sopenharmony_ci#define FOR_i2cget
2640f66f451Sopenharmony_ci#include "generated/flags.h"
2650f66f451Sopenharmony_ci
2660f66f451Sopenharmony_civoid i2cget_main(void)
2670f66f451Sopenharmony_ci{
2680f66f451Sopenharmony_ci  int bus = atolx_range(toys.optargs[0], 0, INT_MAX);
2690f66f451Sopenharmony_ci  int chip = atolx_range(toys.optargs[1], 0, 0x7f);
2700f66f451Sopenharmony_ci  int addr = atolx_range(toys.optargs[2], 0, 0xff);
2710f66f451Sopenharmony_ci  int fd, byte;
2720f66f451Sopenharmony_ci
2730f66f451Sopenharmony_ci  confirm("Read register 0x%02x from chip 0x%02x on bus %d?", addr, chip, bus);
2740f66f451Sopenharmony_ci
2750f66f451Sopenharmony_ci  fd = i2c_open(bus, FLAG(f) ? I2C_SLAVE_FORCE : I2C_SLAVE, chip);
2760f66f451Sopenharmony_ci  if (i2c_read_byte(fd, addr, &byte)==-1) perror_exit("i2c_read_byte");
2770f66f451Sopenharmony_ci  printf("0x%02x\n", byte);
2780f66f451Sopenharmony_ci  close(fd);
2790f66f451Sopenharmony_ci}
2800f66f451Sopenharmony_ci
2810f66f451Sopenharmony_ci#define CLEANUP_i2cget
2820f66f451Sopenharmony_ci#define FOR_i2cset
2830f66f451Sopenharmony_ci#include "generated/flags.h"
2840f66f451Sopenharmony_ci
2850f66f451Sopenharmony_civoid i2cset_main(void)
2860f66f451Sopenharmony_ci{
2870f66f451Sopenharmony_ci  int bus = atolx_range(toys.optargs[0], 0, INT_MAX);
2880f66f451Sopenharmony_ci  int chip = atolx_range(toys.optargs[1], 0, 0x7f);
2890f66f451Sopenharmony_ci  int addr = atolx_range(toys.optargs[2], 0, 0xff);
2900f66f451Sopenharmony_ci  char *mode = toys.optargs[toys.optc-1];
2910f66f451Sopenharmony_ci  int fd, i;
2920f66f451Sopenharmony_ci  struct i2c_smbus_ioctl_data ioctl_data;
2930f66f451Sopenharmony_ci  union i2c_smbus_data data;
2940f66f451Sopenharmony_ci
2950f66f451Sopenharmony_ci  memset(&data, 0, sizeof(data));
2960f66f451Sopenharmony_ci  if (strlen(mode)!=1) help_exit("mode too long");
2970f66f451Sopenharmony_ci  if (*mode=='b' && toys.optc==5) {
2980f66f451Sopenharmony_ci    ioctl_data.size = I2C_SMBUS_BYTE_DATA;
2990f66f451Sopenharmony_ci    data.byte = atolx_range(toys.optargs[3], 0, 0xff);
3000f66f451Sopenharmony_ci  } else if (*mode=='w' && toys.optc==5) {
3010f66f451Sopenharmony_ci    ioctl_data.size = I2C_SMBUS_WORD_DATA;
3020f66f451Sopenharmony_ci    data.word = atolx_range(toys.optargs[3], 0, 0xffff);
3030f66f451Sopenharmony_ci  } else if (*mode=='i' && toys.optc>=5) {
3040f66f451Sopenharmony_ci    if (toys.optc-4>I2C_SMBUS_BLOCK_MAX) error_exit("too much data");
3050f66f451Sopenharmony_ci    ioctl_data.size = I2C_SMBUS_I2C_BLOCK_DATA;
3060f66f451Sopenharmony_ci    for (i = 0; i<toys.optc-4; ++i)
3070f66f451Sopenharmony_ci      data.block[i+1] = atolx_range(toys.optargs[3+i], 0, 0xff);
3080f66f451Sopenharmony_ci    data.block[0] = toys.optc-4;
3090f66f451Sopenharmony_ci  } else help_exit("syntax error");
3100f66f451Sopenharmony_ci
3110f66f451Sopenharmony_ci  confirm("Write register 0x%02x from chip 0x%02x on bus %d?", addr, chip, bus);
3120f66f451Sopenharmony_ci
3130f66f451Sopenharmony_ci  fd = i2c_open(bus, FLAG(f) ? I2C_SLAVE_FORCE : I2C_SLAVE, chip);
3140f66f451Sopenharmony_ci  ioctl_data.read_write = I2C_SMBUS_WRITE;
3150f66f451Sopenharmony_ci  ioctl_data.command = addr;
3160f66f451Sopenharmony_ci  ioctl_data.data = &data;
3170f66f451Sopenharmony_ci  xioctl(fd, I2C_SMBUS, &ioctl_data);
3180f66f451Sopenharmony_ci  close(fd);
3190f66f451Sopenharmony_ci}
320