1 #include <nm_core.h>
2 #include <nm_form.h>
3 #include <nm_utils.h>
4 #include <nm_string.h>
5 #include <nm_window.h>
6 #include <nm_menu.h>
7 #include <nm_vector.h>
8 #include <nm_database.h>
9 #include <nm_usb_devices.h>
10 #include <nm_qmp_control.h>
11 #include <nm_usb_plug.h>
12
13 static const char NM_LC_USB_FORM_MSG[] = "Device";
14
15 static void nm_usb_attach_init_windows(nm_form_t *form);
16 static void nm_usb_detach_init_windows(nm_form_t *form);
17 static void nm_usb_plug_list(nm_vect_t *devs, nm_vect_t *names);
18 static int nm_usb_plug_get_data(const nm_str_t *name, nm_usb_data_t *usb,
19 const nm_vect_t *usb_list);
20 static int nm_usb_unplug_get_data(nm_usb_data_t *usb, const nm_vect_t *db_list);
21 static void nm_usb_plug_update_db(const nm_str_t *name, const nm_usb_data_t *usb);
22
23 enum {
24 NM_LBL_USB_DEV = 0, NM_FLD_USB_DEV,
25 NM_FLD_COUNT
26 };
27
28 static nm_field_t *fields[NM_FLD_COUNT + 1];
29
nm_usb_attach_init_windows(nm_form_t * form)30 static void nm_usb_attach_init_windows(nm_form_t *form)
31 {
32 if (form) {
33 nm_form_window_init();
34 nm_form_data_t *form_data = (nm_form_data_t *)form_userptr(form);
35 if (form_data)
36 form_data->parent_window = action_window;
37 } else {
38 werase(action_window);
39 werase(help_window);
40 }
41
42 nm_init_side();
43 nm_init_action(_(NM_MSG_USB_ATTACH));
44 nm_init_help_edit();
45
46 nm_print_vm_menu(NULL);
47 }
48
nm_usb_detach_init_windows(nm_form_t * form)49 static void nm_usb_detach_init_windows(nm_form_t *form)
50 {
51 if (form) {
52 nm_form_window_init();
53 nm_form_data_t *form_data = (nm_form_data_t *)form_userptr(form);
54 if (form_data)
55 form_data->parent_window = action_window;
56 } else {
57 werase(action_window);
58 werase(help_window);
59 }
60
61 nm_init_side();
62 nm_init_action(_(NM_MSG_USB_DETACH));
63 nm_init_help_edit();
64
65 nm_print_vm_menu(NULL);
66 }
67
nm_usb_plug(const nm_str_t * name,int vm_status)68 void nm_usb_plug(const nm_str_t *name, int vm_status)
69 {
70 nm_form_data_t *form_data = NULL;
71 nm_form_t *form = NULL;
72 nm_str_t buf = NM_INIT_STR;
73 nm_vect_t usb_devs = NM_INIT_VECT;
74 nm_vect_t usb_names = NM_INIT_VECT;
75 nm_vect_t db_result = NM_INIT_VECT;
76 nm_usb_data_t usb = NM_INIT_USB_DATA;
77 size_t msg_len = mbstowcs(NULL, _(NM_LC_USB_FORM_MSG), strlen(_(NM_LC_USB_FORM_MSG)));
78
79 /* check for usb enabled first */
80 nm_str_format(&buf, NM_USB_CHECK_SQL, name->data);
81 nm_db_select(buf.data, &db_result);
82
83 if (vm_status && nm_str_cmp_st(nm_vect_str(&db_result, 0), NM_DISABLE) == NM_OK) {
84 nm_warn(_(NM_MSG_USB_DIS));
85 goto out;
86 }
87
88 nm_usb_plug_list(&usb_devs, &usb_names);
89
90 if (usb_names.n_memb == 0) {
91 nm_warn(_(NM_MSG_USB_MISS));
92 goto out;
93 }
94
95 nm_usb_attach_init_windows(NULL);
96
97 form_data = nm_form_data_new(
98 action_window, nm_usb_attach_init_windows, msg_len, NM_FLD_COUNT / 2, NM_TRUE);
99
100 if (nm_form_data_update(form_data, 0, 0) != NM_OK)
101 goto out;
102
103 fields[0] = nm_field_label_new(0, form_data);
104 fields[1] = nm_field_enum_new(0, form_data,
105 (const char **)usb_names.data, false, false);
106 fields[2] = NULL;
107
108 set_field_buffer(fields[0], 0, _(NM_LC_USB_FORM_MSG));
109 field_opts_off(fields[1], O_STATIC);
110 set_field_buffer(fields[1], 0, *usb_names.data);
111 nm_fields_unset_status(fields);
112
113 form = nm_form_new(form_data, fields);
114 nm_form_post(form);
115
116 if (nm_form_draw(&form) != NM_OK)
117 goto out;
118
119 if ((nm_usb_plug_get_data(name, &usb, &usb_devs)) != NM_OK)
120 goto out;
121
122 if (vm_status)
123 if (nm_qmp_usb_attach(name, &usb) != NM_OK)
124 goto out;
125
126 nm_usb_plug_update_db(name, &usb);
127
128 out:
129 NM_FORM_EXIT();
130 nm_form_free(form);
131 nm_form_data_free(form_data);
132 nm_fields_free(fields);
133 nm_vect_free(&usb_names, NULL);
134 nm_vect_free(&usb_devs, nm_usb_vect_free_cb);
135 nm_vect_free(&db_result, nm_str_vect_free_cb);
136 nm_str_free(&buf);
137 nm_str_free(&usb.serial);
138 }
139
nm_usb_unplug(const nm_str_t * name,int vm_status)140 void nm_usb_unplug(const nm_str_t *name, int vm_status)
141 {
142 nm_form_data_t *form_data = NULL;
143 nm_form_t *form = NULL;
144 nm_str_t buf = NM_INIT_STR;
145 nm_usb_data_t usb_data = NM_INIT_USB_DATA;
146 nm_usb_dev_t usb_dev = NM_INIT_USB;
147 nm_vect_t usb_names = NM_INIT_VECT;
148 nm_vect_t db_result = NM_INIT_VECT;
149 size_t msg_len = mbstowcs(NULL, _(NM_LC_USB_FORM_MSG), strlen(_(NM_LC_USB_FORM_MSG)));
150
151 usb_data.dev = &usb_dev;
152
153 nm_str_format(&buf, NM_USB_GET_SQL, name->data);
154 nm_db_select(buf.data, &db_result);
155
156 if (!db_result.n_memb) {
157 nm_warn(_(NM_MSG_USB_NONE));
158 goto out;
159 }
160
161 nm_usb_unplug_list(&db_result, &usb_names, true);
162
163 nm_usb_detach_init_windows(NULL);
164
165 form_data = nm_form_data_new(
166 action_window, nm_usb_detach_init_windows, msg_len, NM_FLD_COUNT / 2, NM_TRUE);
167
168 if (nm_form_data_update(form_data, 0, 0) != NM_OK)
169 goto out;
170
171 fields[0] = nm_field_label_new(0, form_data);
172 fields[1] = nm_field_enum_new(0, form_data,
173 (const char **)usb_names.data, false, false);
174 fields[2] = NULL;
175
176 set_field_buffer(fields[0], 0, _(NM_LC_USB_FORM_MSG));
177 field_opts_off(fields[1], O_STATIC);
178 set_field_buffer(fields[1], 0, *usb_names.data);
179 nm_fields_unset_status(fields);
180
181 form = nm_form_new(form_data, fields);
182 nm_form_post(form);
183
184 if (nm_form_draw(&form) != NM_OK)
185 goto out;
186
187 if (nm_usb_unplug_get_data(&usb_data, &db_result) != NM_OK)
188 goto out;
189
190 if (vm_status)
191 (void) nm_qmp_usb_detach(name, &usb_data);
192
193 nm_str_format(&buf, NM_USB_DELETE_SQL,
194 name->data,
195 usb_dev.name.data,
196 usb_dev.vendor_id.data,
197 usb_dev.product_id.data,
198 usb_data.serial.data);
199 nm_db_edit(buf.data);
200
201 out:
202 NM_FORM_EXIT();
203 nm_form_free(form);
204 nm_form_data_free(form_data);
205 nm_fields_free(fields);
206 nm_vect_free(&usb_names, NULL);
207 nm_vect_free(&db_result, nm_str_vect_free_cb);
208 nm_usb_data_free(&usb_data);
209 nm_str_free(&buf);
210 }
211
nm_usb_check_plugged(const nm_str_t * name)212 int nm_usb_check_plugged(const nm_str_t *name)
213 {
214 int rc = NM_ERR;
215 nm_vect_t db_result = NM_INIT_VECT;
216 nm_str_t query = NM_INIT_STR;
217
218 nm_str_format(&query, NM_USB_GET_SQL, name->data);
219 nm_db_select(query.data, &db_result);
220
221 if (!db_result.n_memb) {
222 rc = NM_OK;
223 }
224
225 nm_vect_free(&db_result, nm_str_vect_free_cb);
226 nm_str_free(&query);
227
228 return rc;
229 }
230
nm_usb_unplug_list(const nm_vect_t * db_list,nm_vect_t * names,bool num)231 void nm_usb_unplug_list(const nm_vect_t *db_list, nm_vect_t *names, bool num)
232 {
233 size_t dev_count = db_list->n_memb / NM_USB_IDX_COUNT;
234 nm_str_t buf = NM_INIT_STR;
235
236 for (size_t n = 0; n < dev_count; n++) {
237 size_t idx_shift = NM_USB_IDX_COUNT * n;
238
239 if (num) {
240 nm_str_format(&buf, "%zu:%s [serial:%s]", n + 1,
241 nm_vect_str_ctx(db_list, NM_SQL_USB_NAME + idx_shift),
242 nm_vect_str_ctx(db_list, NM_SQL_USB_SERIAL + idx_shift));
243 } else {
244 nm_str_format(&buf, "%s [serial:%s]",
245 nm_vect_str_ctx(db_list, NM_SQL_USB_NAME + idx_shift),
246 nm_vect_str_ctx(db_list, NM_SQL_USB_SERIAL + idx_shift));
247 }
248 nm_vect_insert(names, buf.data, buf.len + 1, NULL);
249 }
250
251 nm_str_free(&buf);
252 }
253
nm_usb_plug_list(nm_vect_t * devs,nm_vect_t * names)254 static void nm_usb_plug_list(nm_vect_t *devs, nm_vect_t *names)
255 {
256 nm_usb_get_devs(devs);
257 nm_str_t dev_name = NM_INIT_STR;
258
259 for (size_t n = 0; n < devs->n_memb; n++) {
260 nm_str_format(&dev_name, "%zu:%s", n + 1, nm_usb_name(devs->data[n])->data);
261 nm_vect_insert(names, dev_name.data, dev_name.len + 1, NULL);
262
263 nm_debug("usb >> %03u:%03u %s:%s %s\n",
264 *nm_usb_bus_num(devs->data[n]),
265 *nm_usb_dev_addr(devs->data[n]),
266 nm_usb_vendor_id(devs->data[n])->data,
267 nm_usb_product_id(devs->data[n])->data,
268 nm_usb_name(devs->data[n])->data);
269 }
270
271 nm_vect_end_zero(names);
272 nm_str_free(&dev_name);
273 }
274
nm_usb_plug_get_data(const nm_str_t * name,nm_usb_data_t * usb,const nm_vect_t * usb_list)275 static int nm_usb_plug_get_data(const nm_str_t *name, nm_usb_data_t *usb,
276 const nm_vect_t *usb_list)
277 {
278 int rc = NM_ERR;
279 nm_str_t buf = NM_INIT_STR;
280 nm_str_t input = NM_INIT_STR;
281 nm_vect_t db_list = NM_INIT_VECT;
282 uint32_t idx;
283 char *fo;
284
285 nm_get_field_buf(fields[1], &input);
286 if (!input.len) {
287 nm_warn(_(NM_MSG_USB_EMPTY));
288 goto out;
289 }
290
291 nm_str_copy(&buf, &input);
292 if ((fo = strchr(buf.data, ':')) == NULL) {
293 /* Reinsurance, "fo" will always be OK */
294 nm_warn(_(NM_MSG_USB_EDATA));
295 goto out;
296 }
297
298 nm_str_trunc(&input, 0);
299 nm_str_add_text(&input, fo + 1);
300
301 *fo = '\0';
302 idx = nm_str_stoui(&buf, 10);
303 usb->dev = usb_list->data[idx - 1];
304
305 nm_usb_get_serial(usb->dev, &usb->serial);
306
307 nm_str_format(&buf, NM_USB_EXISTS_SQL,
308 name->data,
309 usb->dev->name.data,
310 usb->dev->vendor_id.data,
311 usb->dev->product_id.data,
312 (usb->serial.data) ? usb->serial.data : "NULL");
313
314 nm_db_select(buf.data, &db_list);
315
316 if (db_list.n_memb) {
317 nm_warn(_(NM_MSG_USB_ATTAC));
318 goto out;
319 }
320
321 rc = NM_OK;
322 out:
323 nm_str_free(&buf);
324 nm_str_free(&input);
325 nm_vect_free(&db_list, nm_str_vect_free_cb);
326
327 return rc;
328 }
329
nm_usb_unplug_get_data(nm_usb_data_t * usb,const nm_vect_t * db_list)330 static int nm_usb_unplug_get_data(nm_usb_data_t *usb, const nm_vect_t *db_list)
331 {
332 int rc = NM_ERR;
333 nm_str_t buf = NM_INIT_STR;
334 nm_str_t input = NM_INIT_STR;
335 uint32_t idx, idx_shift;
336 char *fo;
337
338 nm_get_field_buf(fields[1], &input);
339 if (!input.len) {
340 nm_warn(_(NM_MSG_USB_EMPTY));
341 goto out;
342 }
343
344 nm_str_copy(&buf, &input);
345 if ((fo = strchr(buf.data, ':')) == NULL) {
346 /* Reinsurance, "fo" will always be OK */
347 nm_warn(_(NM_MSG_USB_EDATA));
348 goto out;
349 }
350
351 *fo = '\0';
352 idx = nm_str_stoui(&buf, 10);
353 idx_shift = --idx * NM_USB_IDX_COUNT;
354 nm_debug("s:%s, idx=%u\n", buf.data, idx);
355
356 nm_str_copy(&usb->dev->name,
357 nm_vect_str(db_list, NM_SQL_USB_NAME + idx_shift));
358 nm_str_copy(&usb->dev->vendor_id,
359 nm_vect_str(db_list, NM_SQL_USB_VID + idx_shift));
360 nm_str_copy(&usb->dev->product_id,
361 nm_vect_str(db_list, NM_SQL_USB_PID + idx_shift));
362 nm_str_copy(&usb->serial,
363 nm_vect_str(db_list, NM_SQL_USB_SERIAL + idx_shift));
364
365 rc = NM_OK;
366 out:
367 nm_str_free(&buf);
368 nm_str_free(&input);
369
370 return rc;
371 }
372
nm_usb_plug_update_db(const nm_str_t * name,const nm_usb_data_t * usb)373 static void nm_usb_plug_update_db(const nm_str_t *name, const nm_usb_data_t *usb)
374 {
375 nm_str_t query = NM_INIT_STR;
376
377 nm_str_format(&query, NM_USB_ADD_SQL,
378 name->data,
379 usb->dev->name.data,
380 usb->dev->vendor_id.data,
381 usb->dev->product_id.data,
382 (usb->serial.data) ? usb->serial.data : "NULL");
383
384 nm_db_edit(query.data);
385
386 nm_str_free(&query);
387 }
388 /* vim:set ts=4 sw=4: */
389