libxcoder  3.5.1
ni_rsrc_update_logan.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Copyright (C) 2022 NETINT Technologies
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18  * SOFTWARE.
19  *
20  ******************************************************************************/
21 
22 /*!*****************************************************************************
23  *
24  * \file ni_rsrc_update_logan.c
25  *
26  * @date May 10, 2019
27  *
28  * \brief NETINT T408 resource update utility program
29  *
30  * @author
31  *
32  ******************************************************************************/
33 
34 #include <stdio.h>
35 #include <fcntl.h>
36 #include <string.h>
37 
38 #if defined(__linux__) || defined(__APPLE__)
39 #include <unistd.h>
40 #include <sys/types.h>
41 #endif
42 
43 #include "ni_defs_logan.h"
44 #include "ni_rsrc_api_logan.h"
45 #include "ni_rsrc_priv_logan.h"
46 #include "ni_util_logan.h"
47 
48 #ifdef _WIN32
49 #include "ni_getopt_logan.h"
50 #define DEV_NAME_PREFIX "\\\\.\\Scsi"
51 #elif defined(__linux__)
52 #define DEV_NAME_PREFIX "/dev/nvme"
53 #define NVME_PCI_PREFIX "nvme/nvme"
54 #define NVME_SUBSYS_PREFIX "nvme-subsystem/nvme-subsys"
55 #elif defined(__APPLE__)
56 #define DEV_NAME_PREFIX "/dev/disk"
57 #endif
58 
59 /*!******************************************************************************
60  * \brief get the NVMe device's character device name (e.g. /dev/nvmeX)
61  *
62  * \param p_in_buf whole device name passed in
63  * p_out_buf full device name without name-space/partition-number
64  * out_buf_len maximum size of output buffer
65  *
66  * \return 0 if value device name is found, -1 otherwise
67  ******************************************************************************/
68 static int get_device_name(const char *p_in_buf, char *p_out_buf, int out_buf_len)
69 {
70  FILE *cmd_fp;
71  char cmd[128] = {'\0'};
72  char cmd_ret[128] = {'\0'};
73  const char *p_src;
74  char *p_dst;
75 
76  if (!p_in_buf || !p_out_buf)
77  {
78  return -1;
79  }
80 
81  p_src = p_in_buf;
82  p_dst = p_out_buf;
83 #ifdef _WIN32
84  ni_log(NI_LOG_TRACE, "In Windows block name equals to device name\n");
85  snprintf(p_out_buf, out_buf_len, "%s", p_in_buf);
86  return 0;
87 #elif defined(XCODER_LINUX_VIRTIO_DRIVER_ENABLED)
88  ni_log(NI_LOG_TRACE, "The block path is same as device path in Linux virtual machine with VirtIO driver.\n");
89  snprintf(p_out_buf, out_buf_len, "%s", p_in_buf);
90  return 0;
91 #elif defined(__APPLE__)
92  snprintf(p_out_buf, out_buf_len, "%s", p_in_buf);
93  return 0;
94 #else
95 #ifdef __ANDROID__
96  ni_log(NI_LOG_TRACE, "For Android, assume index block namespace is same as device index\n");
97  p_src = strstr(p_in_buf, "/nvme");
98  if (p_src != NULL)
99  {
100  int len = strlen("/nvme");
101  strcpy(p_out_buf, p_in_buf);
102  p_src += len;
103  p_dst += len;
104  while (isdigit(*p_src))
105  {
106  *p_dst++ = *p_src++;
107  }
108  *p_dst = '\0';
109  return 0;
110  }
111 #else
112  // Note, we are using udevadm through terminal instead of libudev.c to avoid requiring extra kernel dev packges
113  snprintf(cmd, sizeof(cmd) - 1, "udevadm info -q path -n %s", p_in_buf);
114 
115  // check p_in_buf exists in /dev/ folder. If not, return NI_LOGAN_RETCODE_FAILURE
116  if (access(p_in_buf, F_OK) == -1)
117  {
119  }
120 
121  // look for child block in sysfs mapping tree
122  cmd_fp = popen(cmd, "r");
123  if (!cmd_fp)
124  {
126  }
127 
128  if (fgets(cmd_ret, sizeof(cmd_ret)/sizeof(cmd_ret[0]), cmd_fp) != NULL)
129  {
130  p_src = strstr(cmd_ret, NVME_PCI_PREFIX);
131  if (p_src != NULL)
132  {
133  p_src += strlen(NVME_PCI_PREFIX);
134  }
135  else
136  {
137  p_src = strstr(cmd_ret, NVME_SUBSYS_PREFIX);
138  if (p_src != NULL)
139  {
140  p_src += strlen(NVME_SUBSYS_PREFIX);
141  }
142  else
143  {
144  // Not found.
145  ni_log(NI_LOG_ERROR, "Failed to parse NVMe udev path %s.\n", cmd_ret);
146  pclose(cmd_fp);
147  return -1;
148  }
149  }
150  strcpy(p_out_buf, DEV_NAME_PREFIX);
151  p_dst += strlen(DEV_NAME_PREFIX);
152  while (isdigit(*p_src))
153  {
154  *p_dst++ = *p_src++;
155  }
156  *p_dst = '\0';
157  pclose(cmd_fp);
158  return 0;
159  }
160 #endif
161  else
162  {
163  ni_log(NI_LOG_TRACE, "Failed to find device name.\n");
164  pclose(cmd_fp);
165  return -1;
166  }
167 #endif
168 }
169 
170 static void display_help(void)
171 {
172  printf("-------- ni_rsrc_update_logan v%s --------\n"
173  "Update NetInt Logan transcoder resource (encoders and decoders) status.\n"
174  "-a <nvme_device> Create a resource entry for a newly active transcoder. (eg. /dev/nvme0) \n"
175  "-d <nvme_device> Delete the resource entry for a removed transcoder card. (eg. /dev/nvme0)\n"
176  "-r Init transcoder card resource regardless firmware release version to \n"
177  " libxcoder_logan version compatibility. Must be used with -a option.\n"
178  " Default: only init cards with compatible firmware version.\n"
179  "-c Only init if all cards are fully compatible. Must be used with -a option.\n"
180  " Default: init as many fully and partially cards as possible.\n"
181  "-l Set loglevel of libxcoder_logan API.\n"
182  " [none, fatal, error, info, debug, trace]\n"
183  " Default: info\n"
184  "-v Show libxcoder_logan version.\n"
185  "-h Display this help and exit.\n", NI_LOGAN_XCODER_REVISION);
186 }
187 
188 /*!******************************************************************************
189  * \brief
190  *
191  * \param
192  *
193  * \return
194  ******************************************************************************/
195 int main(int argc, char *argv[])
196 {
197  int opt, rc = 0;
198  char char_dev_name[64];
199  int should_match_rev = 1;
200  int init_no_compat_check = 0;
201  int init_only_if_full_compat = 0;
202  int add_dev = 0;
203  int delete_dev = 0;
204 
205  if (argc == 1) {
206  display_help();
207  return 0;
208  }
209 
210  // arg handling
211  while ((opt = getopt(argc, argv, "hvrca:d:l:")) != -1) {
212  switch (opt) {
213  case 'a':
214 #ifdef __linux__
215  rc = get_device_name(optarg, char_dev_name, sizeof(char_dev_name));
216  add_dev = 1;
217 #endif
218  break;
219  case 'd':
220 #ifdef __linux__
221  rc = get_device_name(optarg, char_dev_name, sizeof(char_dev_name));
222  delete_dev = 1;
223 #endif
224  break;
225  case 'r':
226  init_no_compat_check = 1;
227  break;
228  case 'c':
229  init_only_if_full_compat = 1;
230  break;
231  case 'l':
232  if (!strcmp(optarg, "none")) {
234  } else if (!strcmp(optarg, "fatal")) {
236  } else if (!strcmp(optarg, "error")) {
238  } else if (!strcmp(optarg, "info")) {
240  } else if (!strcmp(optarg, "debug")) {
242  } else if (!strcmp(optarg, "trace")) {
244  } else {
245  fprintf(stderr, "unknown log level selected: %s", optarg);
246  return 1;
247  }
248  break;
249  case 'v':
250  printf("%s\n", NI_LOGAN_XCODER_REVISION);
251  return 0;
252  case 'h':
253  default:
254  display_help();
255  return 0;
256  }
257  }
258 
259  // check option
260  if (add_dev && delete_dev)
261  {
262  fprintf(stderr, "Error: can not add and delete device at the same time\n\n");
263  display_help();
264  return 1;
265  }
266 
267  if (init_no_compat_check && init_only_if_full_compat)
268  {
269  fprintf(stderr, "Error: -r option cannot be used with -c option\n\n");
270  display_help();
271  return 1;
272  }
273 
274  if ((init_no_compat_check || init_only_if_full_compat) && !add_dev)
275  {
276  fprintf(stderr, "Error: %s option must be used with -a option\n\n",
277  init_no_compat_check ? "-r" : "-c");
278  display_help();
279  return 1;
280  }
281 
282  // process options
283  if (init_no_compat_check)
284  {
285  should_match_rev = 0;
286  }
287  else if (init_only_if_full_compat)
288  {
289  should_match_rev = 2;
290  }
291 
292  if (add_dev)
293  {
294  if (rc || (rc = ni_logan_rsrc_add_device(char_dev_name, should_match_rev)))
295  printf("%s not added as transcoder.\n", optarg);
296  else
297  printf("Added transcoder %s successfully.\n", char_dev_name);
298  return rc;
299  }
300  else if (delete_dev)
301  {
302  if (rc || (rc = ni_logan_rsrc_remove_device(char_dev_name)))
303  printf("%s not removed as transcoder.\n", optarg);
304  else
305  printf("Removed transcoder %s successfully.\n", char_dev_name);
306  return rc;
307  }
308 }
Common NETINT definitions used by all modules.
@ NI_LOGAN_RETCODE_FAILURE
#define NI_LOGAN_XCODER_REVISION
Definition: ni_defs_logan.h:62
int getopt(int argc, char *argv[], const char *optstring)
char * optarg
void ni_log_set_level(ni_log_level_t level)
Set ni_log_level.
Definition: ni_log_logan.c:138
void ni_log(ni_log_level_t level, const char *fmt,...)
print log message using ni_log_callback
Definition: ni_log_logan.c:120
@ NI_LOG_NONE
Definition: ni_log_logan.h:62
@ NI_LOG_DEBUG
Definition: ni_log_logan.h:66
@ NI_LOG_TRACE
Definition: ni_log_logan.h:67
@ NI_LOG_FATAL
Definition: ni_log_logan.h:63
@ NI_LOG_ERROR
Definition: ni_log_logan.h:64
@ NI_LOG_INFO
Definition: ni_log_logan.h:65
int ni_logan_rsrc_add_device(const char *dev, int should_match_rev)
Add an NetInt h/w device into resource pool on the host.
int ni_logan_rsrc_remove_device(const char *dev)
Remove an NetInt h/w device from resource pool on the host.
Exported definitions related to resource management of NI T-408 devices.
Private definitions related to resource management of NI T-408 devices.
int main(int argc, char *argv[])
Exported utility routines definition.