i3ctransfer.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2019 Synopsys, Inc. and/or its affiliates.
  4. *
  5. * Author: Vitor Soares <vitor.soares@synopsys.com>
  6. */
  7. #include <ctype.h>
  8. #include <errno.h>
  9. #include <fcntl.h>
  10. #include <getopt.h>
  11. #include <stdint.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <sys/ioctl.h>
  16. #include <sys/stat.h>
  17. #include <i3cdev.h>
  18. const char *sopts = "d:r:w:vh";
  19. static const struct option lopts[] = {
  20. {"device", required_argument, NULL, 'd' },
  21. {"read", required_argument, NULL, 'r' },
  22. {"write", required_argument, NULL, 'w' },
  23. {"command", required_argument, NULL, 'c' },
  24. {"help", no_argument, NULL, 'h' },
  25. {"version", no_argument, NULL, 'v' },
  26. {0, 0, 0, 0}
  27. };
  28. static void print_usage(const char *name)
  29. {
  30. fprintf(stderr, "usage: %s options...\n", name);
  31. fprintf(stderr, " options:\n");
  32. fprintf(stderr, " -d --device <dev> device to use.\n");
  33. fprintf(stderr, " -r --read <data length> read data.\n");
  34. fprintf(stderr, " -w --write <data block> Write data block.\n");
  35. fprintf(stderr, " -h --help Output usage message and exit.\n");
  36. fprintf(stderr, " -v --version Output the version number and exit\n");
  37. }
  38. static int rx_args_to_xfer(struct i3c_priv_xfer *xfer, char *arg)
  39. {
  40. int len = strtol(optarg, NULL, 0);
  41. uint8_t *tmp;
  42. tmp = (uint8_t *)calloc(len, sizeof(uint8_t));
  43. if (!tmp)
  44. return -1;
  45. xfer->rnw = 1;
  46. xfer->len = len;
  47. xfer->data.in = (void *)tmp;
  48. return 0;
  49. }
  50. static int w_args_to_xfer(struct i3c_priv_xfer *xfer, char *arg)
  51. {
  52. char *data_ptrs[256];
  53. int len, i = 0;
  54. uint8_t *tmp;
  55. data_ptrs[i] = strtok(arg, ",");
  56. while (data_ptrs[i] && i < 255)
  57. data_ptrs[++i] = strtok(NULL, ",");
  58. tmp = (uint8_t *)calloc(i, sizeof(uint8_t));
  59. if (!tmp)
  60. return -1;
  61. for (len = 0; len < i; len++)
  62. tmp[len] = (uint8_t)strtol(data_ptrs[len], NULL, 0);
  63. xfer->len = len;
  64. xfer->data.in = (void *)tmp;
  65. return 0;
  66. }
  67. static void print_rx_data(struct i3c_priv_xfer *xfer)
  68. {
  69. uint8_t *tmp;
  70. int i;
  71. tmp = (uint8_t *)calloc(xfer->len, sizeof(uint8_t));
  72. if (!tmp)
  73. return;
  74. memcpy(tmp, (void *)(uintptr_t)xfer->data.out, xfer->len * sizeof(uint8_t));
  75. for (i = 0; i < xfer->len; i++) {
  76. fprintf(stdout, " 0x%02x", tmp[i]);
  77. if ((i + 1) % 8 == 0 && (i + 1) < xfer->len)
  78. fprintf(stdout, "\n");
  79. }
  80. fprintf(stdout, "\n");
  81. free(tmp);
  82. }
  83. int main(int argc, char *argv[])
  84. {
  85. struct i3c_ioc_priv_xfer *xfers;
  86. int file, ret, opt, i;
  87. int nxfers = 0;
  88. char *device = NULL;
  89. if (argc < 2) {
  90. print_usage(argv[0]);
  91. exit(EXIT_SUCCESS);
  92. }
  93. while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != EOF) {
  94. switch (opt) {
  95. case 'h':
  96. print_usage(argv[0]);
  97. exit(EXIT_SUCCESS);
  98. case 'v':
  99. fprintf(stderr, "%s - %s\n", argv[0], VERSION);
  100. exit(EXIT_SUCCESS);
  101. case 'd':
  102. device = optarg;
  103. break;
  104. case 'r':
  105. case 'w':
  106. nxfers++;
  107. break;
  108. default:
  109. print_usage(argv[0]);
  110. exit(EXIT_FAILURE);
  111. }
  112. }
  113. if (device == NULL) {
  114. fprintf(stderr, "No device selected\n");
  115. exit(EXIT_FAILURE);
  116. }
  117. file = open(device, O_RDWR);
  118. if (file < 0)
  119. exit(EXIT_FAILURE);
  120. xfers = (struct i3c_ioc_priv_xfer *)calloc(nxfers, sizeof(*xfers));
  121. if (!xfers)
  122. exit(EXIT_FAILURE);
  123. xfers->xfers = (struct i3c_priv_xfer *)calloc(I3C_IOC_PRIV_XFER_MAX_MSGS,
  124. sizeof(struct i3c_priv_xfer));
  125. if (!xfers->xfers)
  126. goto err_free_xfer;
  127. optind = 1;
  128. nxfers = 0;
  129. while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != EOF) {
  130. switch (opt) {
  131. case 'h':
  132. case 'v':
  133. case 'd':
  134. break;
  135. case 'r':
  136. if (rx_args_to_xfer(&xfers->xfers[nxfers], optarg)) {
  137. ret = EXIT_FAILURE;
  138. goto err_free_xfer_xfer;
  139. }
  140. nxfers++;
  141. break;
  142. case 'w':
  143. if (w_args_to_xfer(&xfers->xfers[nxfers], optarg)) {
  144. ret = EXIT_FAILURE;
  145. goto err_free_xfer_xfer;
  146. }
  147. nxfers++;
  148. break;
  149. }
  150. }
  151. xfers->nxfers = nxfers;
  152. if (ioctl(file, I3C_IOC_PRIV_XFER, xfers) < 0) {
  153. fprintf(stderr, "Error: transfer failed: %s\n", strerror(errno));
  154. ret = EXIT_FAILURE;
  155. goto err_free_xfer_xfer;
  156. }
  157. for (i = 0; i < nxfers; i++) {
  158. if (xfers->xfers[i].rnw) {
  159. fprintf(stdout, "Receive message for transaction %d\n", i+1);
  160. print_rx_data(&xfers->xfers[i]);
  161. }
  162. }
  163. ret = EXIT_SUCCESS;
  164. err_free_xfer_xfer:
  165. for (i = 0; i < nxfers; i++)
  166. free(xfers->xfers[i].data.in);
  167. free(xfers->xfers);
  168. err_free_xfer:
  169. free(xfers);
  170. return ret;
  171. }