1 /*
2  * cmd_control.c
3  *
4  * A command interpreter for OpenIPMI
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2004 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public License
14  *  as published by the Free Software Foundation; either version 2 of
15  *  the License, or (at your option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU Lesser General Public
30  *  License along with this program; if not, write to the Free
31  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33 
34 #include <errno.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <OpenIPMI/ipmiif.h>
40 #include <OpenIPMI/ipmi_cmdlang.h>
41 
42 /* Internal includes, do not use in your programs */
43 #include <OpenIPMI/internal/ipmi_malloc.h>
44 
45 static void
control_list_handler(ipmi_entity_t * entity,ipmi_control_t * control,void * cb_data)46 control_list_handler(ipmi_entity_t *entity, ipmi_control_t *control,
47 		     void *cb_data)
48 {
49     ipmi_cmd_info_t *cmd_info = cb_data;
50     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
51     char            control_name[IPMI_CONTROL_NAME_LEN];
52 
53     if (cmdlang->err)
54 	return;
55 
56     ipmi_control_get_name(control, control_name, sizeof(control_name));
57 
58     ipmi_cmdlang_out(cmd_info, "Name", control_name);
59 }
60 
61 static void
control_list(ipmi_entity_t * entity,void * cb_data)62 control_list(ipmi_entity_t *entity, void *cb_data)
63 {
64     ipmi_cmd_info_t *cmd_info = cb_data;
65     char            entity_name[IPMI_ENTITY_NAME_LEN];
66 
67     ipmi_entity_get_name(entity, entity_name, sizeof(entity_name));
68     ipmi_cmdlang_out(cmd_info, "Entity", NULL);
69     ipmi_cmdlang_down(cmd_info);
70     ipmi_cmdlang_out(cmd_info, "Name", entity_name);
71     ipmi_cmdlang_out(cmd_info, "Controls", NULL);
72     ipmi_cmdlang_down(cmd_info);
73     ipmi_entity_iterate_controls(entity, control_list_handler, cmd_info);
74     ipmi_cmdlang_up(cmd_info);
75     ipmi_cmdlang_up(cmd_info);
76 }
77 
78 static void
control_dump(ipmi_control_t * control,ipmi_cmd_info_t * cmd_info)79 control_dump(ipmi_control_t *control, ipmi_cmd_info_t *cmd_info)
80 {
81     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
82     int             num;
83     char            *str;
84     int             len;
85     int             val, val2, val3;
86     int             i, j, k;
87 
88     ipmi_cmdlang_out(cmd_info, "Type", ipmi_control_get_type_string(control));
89     ipmi_cmdlang_out_bool(cmd_info, "Generates events",
90 			  ipmi_control_has_events(control));
91     ipmi_cmdlang_out_bool(cmd_info, "Settable",
92 			  ipmi_control_is_settable(control));
93     ipmi_cmdlang_out_bool(cmd_info, "Readable",
94 			  ipmi_control_is_readable(control));
95     num = ipmi_control_get_num_vals(control);
96     ipmi_cmdlang_out_int(cmd_info, "Num Values", num);
97     len = ipmi_control_get_id_length(control);
98     if (len) {
99 	str = ipmi_mem_alloc(len);
100 	if (!str) {
101 	    cmdlang->err = ENOMEM;
102 	    cmdlang->errstr = "Out of memory";
103 	    goto out_err;
104 	}
105 	len = ipmi_control_get_id(control, str, len);
106 	ipmi_cmdlang_out_type(cmd_info, "Id",
107 			      ipmi_control_get_id_type(control),
108 			      str, len);
109 	ipmi_mem_free(str);
110     }
111 
112     switch (ipmi_control_get_type(control)) {
113     case IPMI_CONTROL_LIGHT:
114 	val = ipmi_control_light_set_with_setting(control);
115 	if (val) {
116 	    ipmi_cmdlang_out(cmd_info, "Set with", "settings");
117 	    for (j=0; j<num; j++) {
118 		ipmi_cmdlang_out(cmd_info, "Light", NULL);
119 		ipmi_cmdlang_down(cmd_info);
120 		ipmi_cmdlang_out_int(cmd_info, "Number", j);
121 		val = ipmi_control_light_has_loc_ctrl(control, j);
122 		ipmi_cmdlang_out_bool(cmd_info, "Local Control", val);
123 		for (i=IPMI_CONTROL_COLOR_BLACK;
124 		     i<IPMI_CONTROL_COLOR_ORANGE;
125 		     i++)
126 		{
127 		    val = ipmi_control_light_is_color_sup(control, j, i);
128 		    if (val)
129 			ipmi_cmdlang_out(cmd_info, "Color",
130 					 ipmi_get_color_string(i));
131 		}
132 		ipmi_cmdlang_up(cmd_info);
133 	    }
134 	} else {
135 	    ipmi_cmdlang_out(cmd_info, "Set with", "transitions");
136 	    for (i=0; i<num; i++) {
137 		ipmi_cmdlang_out(cmd_info, "Light", NULL);
138 		ipmi_cmdlang_down(cmd_info);
139 		ipmi_cmdlang_out_int(cmd_info, "Number", i);
140 		val = ipmi_control_get_num_light_values(control, i);
141 		ipmi_cmdlang_out_int(cmd_info, "Num Values", val);
142 		for (j=0; j<val; j++) {
143 		    ipmi_cmdlang_out(cmd_info, "Value", NULL);
144 		    ipmi_cmdlang_down(cmd_info);
145 		    ipmi_cmdlang_out_int(cmd_info, "Number", j);
146 		    val2 = ipmi_control_get_num_light_transitions(control,
147 								  i, j);
148 		    ipmi_cmdlang_out_int(cmd_info, "Num Transitions", val2);
149 		    for (k=0; k<val2; k++) {
150 			ipmi_cmdlang_out(cmd_info, "Transition", NULL);
151 			ipmi_cmdlang_down(cmd_info);
152 			ipmi_cmdlang_out_int(cmd_info, "Number", k);
153 			val3 = ipmi_control_get_light_color(control, i, j, k);
154 			ipmi_cmdlang_out(cmd_info, "Color",
155 					 ipmi_get_color_string(val3));
156 			ipmi_cmdlang_out_int(cmd_info, "Time",
157 					     ipmi_control_get_light_color_time
158 					     (control, i, j, k));
159 			ipmi_cmdlang_up(cmd_info);
160 		    }
161 		    ipmi_cmdlang_up(cmd_info);
162 		}
163 		ipmi_cmdlang_up(cmd_info);
164 	    }
165 	}
166 	break;
167 
168     case IPMI_CONTROL_IDENTIFIER:
169 	ipmi_cmdlang_out_int(cmd_info, "Max Length",
170 			     ipmi_control_identifier_get_max_length(control));
171 	break;
172 
173     case IPMI_CONTROL_DISPLAY:
174 	break;
175 
176     case IPMI_CONTROL_RELAY:
177     case IPMI_CONTROL_ALARM:
178     case IPMI_CONTROL_RESET:
179     case IPMI_CONTROL_POWER:
180     case IPMI_CONTROL_FAN_SPEED:
181     case IPMI_CONTROL_ONE_SHOT_RESET:
182     case IPMI_CONTROL_OUTPUT:
183     case IPMI_CONTROL_ONE_SHOT_OUTPUT:
184 	break;
185     }
186     return;
187 
188  out_err:
189     ipmi_control_get_name(control, cmdlang->objstr,
190 			 cmdlang->objstr_len);
191     cmdlang->location = "cmd_control.c(control_dump)";
192 }
193 
194 static void
control_info(ipmi_control_t * control,void * cb_data)195 control_info(ipmi_control_t *control, void *cb_data)
196 {
197     ipmi_cmd_info_t *cmd_info = cb_data;
198     char            control_name[IPMI_CONTROL_NAME_LEN];
199 
200     ipmi_control_get_name(control, control_name, sizeof(control_name));
201 
202     ipmi_cmdlang_out(cmd_info, "Control", NULL);
203     ipmi_cmdlang_down(cmd_info);
204     ipmi_cmdlang_out(cmd_info, "Name", control_name);
205     control_dump(control, cmd_info);
206     ipmi_cmdlang_up(cmd_info);
207 }
208 
209 static void
control_set_done(ipmi_control_t * control,int err,void * cb_data)210 control_set_done(ipmi_control_t *control,
211 		 int            err,
212 		 void           *cb_data)
213 {
214     ipmi_cmd_info_t *cmd_info = cb_data;
215     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
216     char            control_name[IPMI_CONTROL_NAME_LEN];
217 
218     ipmi_cmdlang_lock(cmd_info);
219     if (err) {
220 	cmdlang->errstr = "Error setting control";
221 	cmdlang->err = err;
222 	ipmi_control_get_name(control, cmdlang->objstr,
223 			      cmdlang->objstr_len);
224 	cmdlang->location = "cmd_control.c(control_set_done)";
225 	goto out;
226     }
227 
228     ipmi_control_get_name(control, control_name, sizeof(control_name));
229     ipmi_cmdlang_out(cmd_info, "Set done", control_name);
230 
231  out:
232     ipmi_cmdlang_unlock(cmd_info);
233     ipmi_cmdlang_cmd_info_put(cmd_info);
234 }
235 
236 static void
control_set(ipmi_control_t * control,void * cb_data)237 control_set(ipmi_control_t *control, void *cb_data)
238 {
239     ipmi_cmd_info_t      *cmd_info = cb_data;
240     ipmi_cmdlang_t       *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
241     int                  *data = NULL;
242     unsigned char        *ucdata = NULL;
243     int                  num;
244     int                  i;
245     int                  rv;
246     int                  curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
247     int                  argc = ipmi_cmdlang_get_argc(cmd_info);
248     char                 **argv = ipmi_cmdlang_get_argv(cmd_info);
249     ipmi_light_setting_t *s = NULL;
250 
251 
252     num = ipmi_control_get_num_vals(control);
253     if ((argc - curr_arg) < num) {
254 	/* Not enough parameters */
255 	cmdlang->errstr = "Not enough parameters";
256 	cmdlang->err = EINVAL;
257 	goto out_err;
258     }
259 
260     switch (ipmi_control_get_type(control)) {
261     case IPMI_CONTROL_LIGHT:
262 	if (!ipmi_control_light_set_with_setting(control))
263 	    goto normal_val_set;
264 
265 	s = ipmi_alloc_light_settings(num);
266 	if (!s) {
267 	    cmdlang->errstr = "Out of memory";
268 	    cmdlang->err = ENOMEM;
269 	    goto out_err;
270 	}
271 
272 	for (i=0; i<num; i++) {
273 	    int val;
274 
275 	    if (strcmp(argv[curr_arg], "lc") == 0) {
276 		ipmi_light_setting_set_local_control(s, i, 1);
277 		continue;
278 	    } else if (strcmp(argv[curr_arg], "nolc") == 0) {
279 		ipmi_light_setting_set_local_control(s, i, 0);
280 	    } else {
281 		cmdlang->errstr = "Invalid local control setting";
282 		cmdlang->err = EINVAL;
283 		goto out_err;
284 	    }
285 	    curr_arg++;
286 
287 	    ipmi_cmdlang_get_color(argv[curr_arg], &val, cmd_info);
288 	    if (cmdlang->err)
289 		goto out_err;
290 	    rv = ipmi_light_setting_set_color(s, i, val);
291 	    if (rv) {
292 		cmdlang->errstr = "Error setting color";
293 		cmdlang->err = rv;
294 		goto out_err;
295 	    }
296 	    curr_arg++;
297 
298 	    ipmi_cmdlang_get_int(argv[curr_arg], &val, cmd_info);
299 	    if (cmdlang->err) {
300 		cmdlang->errstr = "Invalid on time";
301 		goto out_err;
302 	    }
303 	    rv = ipmi_light_setting_set_on_time(s, i, val);
304 	    if (rv) {
305 		cmdlang->errstr = "Error setting on time";
306 		cmdlang->err = rv;
307 		goto out_err;
308 	    }
309 	    curr_arg++;
310 
311 	    ipmi_cmdlang_get_int(argv[curr_arg], &val, cmd_info);
312 	    if (cmdlang->err) {
313 		cmdlang->errstr = "Invalid off time";
314 		goto out_err;
315 	    }
316 	    rv = ipmi_light_setting_set_off_time(s, i, val);
317 	    if (rv) {
318 		cmdlang->errstr = "Error setting off time";
319 		cmdlang->err = rv;
320 		goto out_err;
321 	    }
322 	    curr_arg++;
323 	}
324 
325 	ipmi_cmdlang_cmd_info_get(cmd_info);
326 	rv = ipmi_control_set_light(control, s, control_set_done,
327 				    cmd_info);
328 	if (rv) {
329 	    ipmi_cmdlang_cmd_info_put(cmd_info);
330 	    cmdlang->errstr = "Error setting light control";
331 	    cmdlang->err = rv;
332 	    goto out_err;
333 	}
334 	ipmi_free_light_settings(s);
335 	break;
336 
337     case IPMI_CONTROL_IDENTIFIER:
338 	num = ipmi_control_identifier_get_max_length(control);
339 	ucdata = ipmi_mem_alloc(num);
340 	if (!ucdata) {
341 	    cmdlang->errstr = "Out of memory";
342 	    cmdlang->err = ENOMEM;
343 	    goto out_err;
344 	}
345 	for (i=0; i<num; i++) {
346 	    ipmi_cmdlang_get_uchar(argv[curr_arg], &ucdata[i], cmd_info);
347 	    if (cmdlang->err) {
348 		cmdlang->errstr = "value invalid";
349 		goto out_err;
350 	    }
351 	    curr_arg++;
352 	}
353 
354 	ipmi_cmdlang_cmd_info_get(cmd_info);
355 	rv = ipmi_control_identifier_set_val(control, ucdata, i,
356 					     control_set_done, cmd_info);
357 	if (rv) {
358 	    ipmi_cmdlang_cmd_info_put(cmd_info);
359 	    cmdlang->errstr = "Error setting id control";
360 	    cmdlang->err = rv;
361 	    goto out_err;
362 	}
363 	ipmi_mem_free(ucdata);
364 	break;
365 
366     case IPMI_CONTROL_DISPLAY:
367 	cmdlang->errstr = "Setting displays not currently supported";
368 	cmdlang->err = ENOSYS;
369 	goto out_err;
370 	break;
371 
372     case IPMI_CONTROL_RELAY:
373     case IPMI_CONTROL_ALARM:
374     case IPMI_CONTROL_RESET:
375     case IPMI_CONTROL_POWER:
376     case IPMI_CONTROL_FAN_SPEED:
377     case IPMI_CONTROL_ONE_SHOT_RESET:
378     case IPMI_CONTROL_OUTPUT:
379     case IPMI_CONTROL_ONE_SHOT_OUTPUT:
380     normal_val_set:
381 	data = ipmi_mem_alloc(num * sizeof(int));
382 	if (!data) {
383 	    cmdlang->errstr = "Out of memory";
384 	    cmdlang->err = ENOMEM;
385 	    goto out_err;
386 	}
387 	for (i=0; i<num; i++) {
388 	    ipmi_cmdlang_get_int(argv[curr_arg], &data[i], cmd_info);
389 	    if (cmdlang->err) {
390 		cmdlang->errstr = "value invalid";
391 		goto out_err;
392 	    }
393 	    curr_arg++;
394 	}
395 
396 	ipmi_cmdlang_cmd_info_get(cmd_info);
397 	rv = ipmi_control_set_val(control, data, control_set_done, cmd_info);
398 	if (rv) {
399 	    ipmi_cmdlang_cmd_info_put(cmd_info);
400 	    cmdlang->errstr = "Error setting control";
401 	    cmdlang->err = rv;
402 	    goto out_err;
403 	}
404 	ipmi_mem_free(data);
405 	break;
406     }
407     return;
408 
409  out_err:
410     ipmi_control_get_name(control, cmdlang->objstr,
411 			 cmdlang->objstr_len);
412     cmdlang->location = "cmd_control.c(control_set)";
413     if (s)
414 	ipmi_free_light_settings(s);
415     if (ucdata)
416 	ipmi_mem_free(ucdata);
417     if (data)
418 	ipmi_mem_free(data);
419 }
420 
421 static void
control_get_light_done(ipmi_control_t * control,int err,ipmi_light_setting_t * s,void * cb_data)422 control_get_light_done(ipmi_control_t       *control,
423 		       int                  err,
424 		       ipmi_light_setting_t *s,
425 		       void                 *cb_data)
426 {
427     ipmi_cmd_info_t *cmd_info = cb_data;
428     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
429     int             i, num;
430     int             rv;
431 
432     ipmi_cmdlang_lock(cmd_info);
433     if (err) {
434 	cmdlang->errstr = "Error setting control";
435 	cmdlang->err = err;
436 	goto out;
437     }
438 
439     num = ipmi_light_setting_get_count(s);
440     for (i=0; i<num; i++) {
441 	int val;
442 
443 	ipmi_cmdlang_out(cmd_info, "Light", NULL);
444 	ipmi_cmdlang_down(cmd_info);
445 	ipmi_cmdlang_out_int(cmd_info, "Num", i);
446 	rv = ipmi_light_setting_in_local_control(s, i, &val);
447 	if (rv) {
448 	    cmdlang->errstr = "Error getting if in local control";
449 	    cmdlang->err = rv;
450 	    goto out;
451 	}
452 	ipmi_cmdlang_out_bool(cmd_info, "Local Control", val);
453 	if (!val) {
454 	    rv = ipmi_light_setting_get_color(s, i, &val);
455 	    if (rv) {
456 		cmdlang->errstr = "Error getting color";
457 		cmdlang->err = rv;
458 		goto out;
459 	    }
460 	    ipmi_cmdlang_out(cmd_info, "Color", ipmi_get_color_string(val));
461 
462 	    rv = ipmi_light_setting_get_on_time(s, i, &val);
463 	    if (rv) {
464 		cmdlang->errstr = "Error getting on time";
465 		cmdlang->err = rv;
466 		goto out;
467 	    }
468 	    ipmi_cmdlang_out_int(cmd_info, "On Time", val);
469 
470 	    rv = ipmi_light_setting_get_off_time(s, i, &val);
471 	    if (rv) {
472 		cmdlang->errstr = "Error getting off time";
473 		cmdlang->err = rv;
474 		goto out;
475 	    }
476 	    ipmi_cmdlang_out_int(cmd_info, "Off Time", val);
477 	}
478 	ipmi_cmdlang_up(cmd_info);
479     }
480 
481  out:
482     if (cmdlang->err) {
483 	ipmi_control_get_name(control, cmdlang->objstr,
484 			      cmdlang->objstr_len);
485 	cmdlang->location = "cmd_control.c(control_get_light_done)";
486     }
487     ipmi_cmdlang_unlock(cmd_info);
488     ipmi_cmdlang_cmd_info_put(cmd_info);
489 }
490 
491 static void
control_get_id_done(ipmi_control_t * control,int err,unsigned char * val,int length,void * cb_data)492 control_get_id_done(ipmi_control_t *control,
493 		    int            err,
494 		    unsigned char  *val,
495 		    int            length,
496 		    void           *cb_data)
497 {
498     ipmi_cmd_info_t *cmd_info = cb_data;
499     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
500 
501     ipmi_cmdlang_lock(cmd_info);
502     if (err) {
503 	cmdlang->errstr = "Error setting control";
504 	cmdlang->err = err;
505 	goto out;
506     }
507 
508     ipmi_cmdlang_out_binary(cmd_info, "Data", (char *) val, length);
509 
510  out:
511     if (cmdlang->err) {
512 	ipmi_control_get_name(control, cmdlang->objstr,
513 			      cmdlang->objstr_len);
514 	cmdlang->location = "cmd_control.c(control_get_light_done)";
515     }
516     ipmi_cmdlang_unlock(cmd_info);
517     ipmi_cmdlang_cmd_info_put(cmd_info);
518 }
519 
520 static void
control_get_done(ipmi_control_t * control,int err,int * val,void * cb_data)521 control_get_done(ipmi_control_t *control,
522 		 int            err,
523 		 int            *val,
524 		 void           *cb_data)
525 {
526     ipmi_cmd_info_t *cmd_info = cb_data;
527     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
528     int             i, num;
529     char            control_name[IPMI_CONTROL_NAME_LEN];
530 
531     ipmi_control_get_name(control, control_name, sizeof(control_name));
532 
533     ipmi_cmdlang_lock(cmd_info);
534     if (err) {
535 	cmdlang->errstr = "Error setting control";
536 	cmdlang->err = err;
537 	goto out;
538     }
539 
540     ipmi_cmdlang_out(cmd_info, "Control", NULL);
541     ipmi_cmdlang_down(cmd_info);
542     ipmi_cmdlang_out(cmd_info, "Name", control_name);
543     num = ipmi_control_get_num_vals(control);
544     for (i=0; i<num; i++) {
545 	ipmi_cmdlang_out(cmd_info, "Value", NULL);
546 	ipmi_cmdlang_down(cmd_info);
547 	ipmi_cmdlang_out_int(cmd_info, "Num", i);
548 	ipmi_cmdlang_out_int(cmd_info, "Value", val[i]);
549 	ipmi_cmdlang_up(cmd_info);
550     }
551     ipmi_cmdlang_up(cmd_info);
552 
553  out:
554     if (cmdlang->err) {
555 	ipmi_control_get_name(control, cmdlang->objstr,
556 			      cmdlang->objstr_len);
557 	cmdlang->location = "cmd_control.c(control_get_light_done)";
558     }
559     ipmi_cmdlang_unlock(cmd_info);
560     ipmi_cmdlang_cmd_info_put(cmd_info);
561 }
562 
563 static void
control_get(ipmi_control_t * control,void * cb_data)564 control_get(ipmi_control_t *control, void *cb_data)
565 {
566     ipmi_cmd_info_t      *cmd_info = cb_data;
567     ipmi_cmdlang_t       *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
568     int                  rv;
569 
570 
571     switch (ipmi_control_get_type(control)) {
572     case IPMI_CONTROL_LIGHT:
573 	if (!ipmi_control_light_set_with_setting(control))
574 	    goto normal_val_get;
575 
576 	ipmi_cmdlang_cmd_info_get(cmd_info);
577 	rv = ipmi_control_get_light(control, control_get_light_done, cmd_info);
578 	if (rv) {
579 	    ipmi_cmdlang_cmd_info_put(cmd_info);
580 	    cmdlang->errstr = "Error getting light control";
581 	    cmdlang->err = rv;
582 	    goto out_err;
583 	}
584 	break;
585 
586     case IPMI_CONTROL_IDENTIFIER:
587 	ipmi_cmdlang_cmd_info_get(cmd_info);
588 	rv = ipmi_control_identifier_get_val(control,
589 					     control_get_id_done, cmd_info);
590 	if (rv) {
591 	    ipmi_cmdlang_cmd_info_put(cmd_info);
592 	    cmdlang->errstr = "Error getting id control";
593 	    cmdlang->err = rv;
594 	    goto out_err;
595 	}
596 	break;
597 
598     case IPMI_CONTROL_DISPLAY:
599 	cmdlang->errstr = "Getting displays not currently supported";
600 	cmdlang->err = ENOSYS;
601 	goto out_err;
602 	break;
603 
604     case IPMI_CONTROL_RELAY:
605     case IPMI_CONTROL_ALARM:
606     case IPMI_CONTROL_RESET:
607     case IPMI_CONTROL_POWER:
608     case IPMI_CONTROL_FAN_SPEED:
609     case IPMI_CONTROL_ONE_SHOT_RESET:
610     case IPMI_CONTROL_OUTPUT:
611     case IPMI_CONTROL_ONE_SHOT_OUTPUT:
612     normal_val_get:
613 	ipmi_cmdlang_cmd_info_get(cmd_info);
614 	rv = ipmi_control_get_val(control, control_get_done, cmd_info);
615 	if (rv) {
616 	    ipmi_cmdlang_cmd_info_put(cmd_info);
617 	    cmdlang->errstr = "Error getting control";
618 	    cmdlang->err = rv;
619 	    goto out_err;
620 	}
621 	break;
622     }
623     return;
624 
625  out_err:
626     ipmi_control_get_name(control, cmdlang->objstr,
627 			 cmdlang->objstr_len);
628     cmdlang->location = "cmd_control.c(control_get)";
629 }
630 
631 static int
control_event_handler(ipmi_control_t * control,int * valid_vals,int * vals,void * cb_data,ipmi_event_t * event)632 control_event_handler(ipmi_control_t *control,
633 		      int            *valid_vals,
634 		      int            *vals,
635 		      void           *cb_data,
636 		      ipmi_event_t   *event)
637 {
638     ipmi_cmd_info_t *evi;
639     char            control_name[IPMI_CONTROL_NAME_LEN];
640     int             rv;
641     char            *errstr;
642     int             i;
643     int             num;
644 
645     ipmi_control_get_name(control, control_name, sizeof(control_name));
646 
647     evi = ipmi_cmdlang_alloc_event_info();
648     if (!evi) {
649 	rv = ENOMEM;
650 	errstr = "Out of memory";
651 	goto out_err;
652     }
653 
654     ipmi_cmdlang_out(evi, "Object Type", "Control");
655     ipmi_cmdlang_out(evi, "Name", control_name);
656     ipmi_cmdlang_out(evi, "Operation", "Event");
657     num = ipmi_control_get_num_vals(control);
658     for (i=0; i<num; i++) {
659 	if (!valid_vals[i])
660 	    continue;
661 	ipmi_cmdlang_out(evi, "Value", NULL);
662 	ipmi_cmdlang_down(evi);
663 	ipmi_cmdlang_out_int(evi, "Number", i);
664 	ipmi_cmdlang_out_int(evi, "Value", vals[i]);
665 	ipmi_cmdlang_up(evi);
666     }
667     if (event) {
668 	ipmi_cmdlang_out(evi, "Event", NULL);
669 	ipmi_cmdlang_down(evi);
670 	ipmi_cmdlang_event_out(event, evi);
671 	ipmi_cmdlang_up(evi);
672     }
673     ipmi_cmdlang_cmd_info_put(evi);
674     return IPMI_EVENT_NOT_HANDLED;
675 
676  out_err:
677     ipmi_cmdlang_global_err(control_name,
678 			    "cmd_control.c(ipmi_cmdlang_control_change)",
679 			    errstr, rv);
680     if (evi)
681 	ipmi_cmdlang_cmd_info_put(evi);
682     return IPMI_EVENT_NOT_HANDLED;
683 }
684 
685 void
ipmi_cmdlang_control_change(enum ipmi_update_e op,ipmi_entity_t * entity,ipmi_control_t * control,void * cb_data)686 ipmi_cmdlang_control_change(enum ipmi_update_e op,
687 			    ipmi_entity_t      *entity,
688 			    ipmi_control_t      *control,
689 			    void               *cb_data)
690 {
691     char            *errstr;
692     int             rv;
693     ipmi_cmd_info_t *evi;
694     char            control_name[IPMI_CONTROL_NAME_LEN];
695 
696     ipmi_control_get_name(control, control_name, sizeof(control_name));
697 
698     evi = ipmi_cmdlang_alloc_event_info();
699     if (!evi) {
700 	rv = ENOMEM;
701 	errstr = "Out of memory";
702 	goto out_err;
703     }
704 
705     ipmi_cmdlang_out(evi, "Object Type", "Control");
706     ipmi_cmdlang_out(evi, "Name", control_name);
707 
708     switch (op) {
709     case IPMI_ADDED:
710 	ipmi_cmdlang_out(evi, "Operation", "Add");
711 	if (ipmi_cmdlang_get_evinfo())
712 	    control_dump(control, evi);
713 
714 	if (ipmi_control_has_events(control)) {
715 	    rv = ipmi_control_add_val_event_handler(control,
716 						    control_event_handler,
717 						    NULL);
718 	    if (rv) {
719 		ipmi_cmdlang_global_err
720 		    (control_name,
721 		     "cmd_control.c(ipmi_cmdlang_control_change)",
722 		     "Unable to set event handler for control",
723 		     rv);
724 	    }
725 	}
726 	break;
727 
728 	case IPMI_DELETED:
729 	    ipmi_cmdlang_out(evi, "Operation", "Delete");
730 	    break;
731 
732 	case IPMI_CHANGED:
733 	    ipmi_cmdlang_out(evi, "Operation", "Change");
734 	    if (ipmi_cmdlang_get_evinfo())
735 		control_dump(control, evi);
736 	    break;
737     }
738 
739     ipmi_cmdlang_cmd_info_put(evi);
740     return;
741 
742  out_err:
743     ipmi_cmdlang_global_err(control_name,
744 			    "cmd_control.c(ipmi_cmdlang_control_change)",
745 			    errstr, rv);
746     if (evi)
747 	ipmi_cmdlang_cmd_info_put(evi);
748 }
749 
750 static ipmi_cmdlang_cmd_t *control_cmds;
751 
752 static ipmi_cmdlang_init_t cmds_control[] =
753 {
754     { "control", NULL,
755       "- Commands dealing with controls",
756       NULL, NULL, &control_cmds },
757     { "list", &control_cmds,
758       "- List all the entities in the system",
759       ipmi_cmdlang_entity_handler, control_list, NULL },
760     { "info", &control_cmds,
761       "<control> - Dump information about an control",
762       ipmi_cmdlang_control_handler, control_info, NULL },
763     { "set", &control_cmds,
764       "<control> <values> - Set the value of a control.  The settings"
765       " depend on control type, most take one or more integer values. "
766       " An identifier type takes one or more unsigned characters.  A"
767       " light set with settings take the form 'lc|nolc <color> <on time>"
768       " <off time>.  lc and nolc turn on or of local control, the over"
769       " values should be obvious.",
770       ipmi_cmdlang_control_handler, control_set, NULL },
771     { "get", &control_cmds,
772       "<control> - Get the value of a control",
773       ipmi_cmdlang_control_handler, control_get, NULL },
774 };
775 #define CMDS_CONTROL_LEN (sizeof(cmds_control)/sizeof(ipmi_cmdlang_init_t))
776 
777 int
ipmi_cmdlang_control_init(os_handler_t * os_hnd)778 ipmi_cmdlang_control_init(os_handler_t *os_hnd)
779 {
780     return ipmi_cmdlang_reg_table(cmds_control, CMDS_CONTROL_LEN);
781 }
782