svn / mbed / trunk / rpc.h

Revision 30, 16.2 kB (checked in by emilmont, 6 months ago)

Add additional M0 peripherals implementations, fix GCC stdio/uart

Line 
1/* mbed Microcontroller Library - RPC
2 * Copyright (c) 2008-2009 ARM Limited. All rights reserved.
3 */ 
4 
5#ifndef MBED_RPC_H
6#define MBED_RPC_H
7
8/* Section rpc
9 *  Helpers for rpc handling.
10 */
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <string.h>
15#include <ctype.h>
16#include "Base.h"
17
18#include "PinNames.h"
19#include <stdint.h>
20
21namespace mbed {
22
23/* Function parse_arg
24 *  Parses and returns a value from a string.
25 *
26 * Variable
27 *  arg - The string to pase
28 *  next - If not NULL a pointer to after the last
29 *    character parsed is written here
30 */
31template<typename T> T parse_arg(const char *arg, const char **next);
32
33inline char parse_char(const char *arg, const char **next) {
34    char c = *arg++;
35    if(c == '\\') {
36        c = *arg++;
37        switch(c) {
38        case 'a': c = '\a'; break;
39        case 'b': c = '\b'; break;
40        case 't': c = '\t'; break;
41        case 'n': c = '\n'; break;
42        case 'v': c = '\v'; break;
43        case 'f': c = '\f'; break;
44        case 'r': c = '\r'; break;
45        case 'x':
46            {
47                /* two-character hexadecimal */
48                char buf[3];
49                buf[0] = *arg++;
50                buf[1] = *arg++;
51                buf[2] = 0;
52                c = strtol(buf, NULL, 16); 
53            }
54            break;
55        default: 
56            if(isdigit(c)) {
57                /* three-character octal */
58                char buf[4];
59                buf[0] = c;
60                buf[1] = *arg++;
61                buf[2] = *arg++;
62                buf[3] = 0;
63                c = strtol(buf, NULL, 8); 
64            }
65            break;
66        }
67    }
68    *next = arg;
69    return c;
70}
71
72/* signed integer types */
73
74template<> inline int parse_arg<int>(const char *arg, const char **next) {
75    if(arg[0] == '\'') {
76        char c = parse_char(arg+1, &arg);
77        if(next != NULL) *next = arg+1;
78        return c;
79    } else {
80        return strtol(arg, const_cast<char**>(next), 0);       
81    }
82}
83
84template<> inline char parse_arg<char>(const char *arg, const char **next) {
85    return parse_arg<int>(arg,next);
86}
87
88template<> inline short int parse_arg<short int>(const char *arg, const char **next) {
89    return parse_arg<int>(arg,next);
90}
91
92template<> inline long int parse_arg<long int>(const char *arg, const char **next) {
93    return parse_arg<int>(arg,next);
94}
95
96template<> inline long long parse_arg<long long>(const char *arg, const char **next) {
97    return strtoll(arg, const_cast<char**>(next), 0);
98}
99
100/* unsigned integer types */
101
102template<> inline unsigned int parse_arg<unsigned int>(const char *arg, const char **next) {
103    if(arg[0] == '\'') {
104        char c = parse_char(arg+1, &arg);
105        if(next != NULL) *next = arg+1;
106        return c;
107    } else {
108        return strtoul(arg, const_cast<char**>(next), 0);       
109    }
110}
111
112template<> inline unsigned char parse_arg<unsigned char>(const char *arg, const char **next) {
113    return parse_arg<unsigned int>(arg,next);
114}
115
116template<> inline unsigned short int parse_arg<unsigned short int>(const char *arg, const char **next) {
117    return parse_arg<unsigned int>(arg,next);
118}
119
120template<> inline unsigned long int parse_arg<unsigned long int>(const char *arg, const char **next) {
121    return parse_arg<unsigned int>(arg,next);
122}
123
124template<> inline unsigned long long parse_arg<unsigned long long>(const char *arg, const char **next) {
125    return strtoull(arg, const_cast<char**>(next), 0);
126}
127
128/* floating types */
129
130template<> inline float parse_arg<float>(const char *arg, const char **next) {
131#if !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 410000
132    return strtof(arg,const_cast<char**>(next));
133#elif __ARMCC_VERSION >= 310000
134    /* bug in header means no using declaration for strtof */
135    return std::strtof(arg,const_cast<char**>(next));   
136#else
137    /* strtof not supported */
138    return strtod(arg,const_cast<char**>(next));
139#endif
140}
141
142template<> inline double parse_arg<double>(const char *arg, const char **next) {
143    return strtod(arg,const_cast<char**>(next));
144}
145
146template<> inline long double parse_arg<long double>(const char *arg, const char **next) {
147    return strtod(arg,const_cast<char**>(next));
148}
149
150/* string */
151
152template<> inline char *parse_arg<char*>(const char *arg, const char **next) {
153    const char *ptr = arg;
154    char *res = NULL;
155    if(*arg == '"') {
156        /* quoted string */
157        ptr = ++arg;
158        int len = 0;
159        /* find the end (and length) of the quoted string */
160        for(char c = *ptr; c != 0 && c != '"'; c = *++ptr) {
161            len++;
162            if(c == '\\') {
163                ptr++;
164            }
165        }
166        /* copy the quoted string, and unescape characters */
167        if(len != 0) {
168            res = new char[len+1];
169            char *resptr = res;
170            while(arg != ptr) {
171                *resptr++ = parse_char(arg, &arg);
172            }
173            *resptr = 0;
174        }
175    } else {
176        /* unquoted string */
177        while(isalnum(*ptr) || *ptr=='_') {
178            ptr++;
179        }
180        int len = ptr-arg;
181        if(len!=0) {
182            res = new char[len+1];
183            memcpy(res, arg, len);
184            res[len] = 0;
185        }
186    }
187
188    if(next != NULL) {
189        *next = ptr;
190    }
191    return res;
192}
193
194template<> inline const char *parse_arg<const char*>(const char *arg, const char **next) {
195    return parse_arg<char*>(arg,next);
196}
197
198/* Pins */
199
200
201inline PinName parse_pins(const char *str) {
202    const PinName pin_names[] = {p5, p6, p7, p8, p9, p10, p11, p12, p13, p14
203                                , p15, p16, p17, p18, p19, p20, p21, p22, p23
204                                , p24, p25, p26, p27, p28, p29, p30};
205
206    if(str[0] == 'P') { // Pn_n
207        uint32_t port = str[1] - '0';
208        uint32_t pin = str[3] - '0'; // Pn_n
209        uint32_t pin2 = str[4] - '0'; // Pn_nn
210        if(pin2 <= 9) {
211            pin = pin * 10 + pin2;
212        }
213#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
214        return (PinName)(LPC_GPIO0_BASE + port * 32 + pin);
215#elif defined(TARGET_LPC11U24)
216        return (PinName)(port * 32 + pin);
217#endif
218    } else if(str[0] == 'p') {  // pn
219        uint32_t pin = str[1] - '0'; // pn
220        uint32_t pin2 = str[2] - '0'; // pnn
221        if(pin2 <= 9) {
222                  pin = pin * 10 + pin2;
223        }
224        if(pin < 5 || pin > 30) {
225              return NC;
226        }
227        return pin_names[pin - 5];
228    } else if(str[0] == 'L') {  // LEDn
229        switch(str[3]) {
230            case '1' : return LED1;
231            case '2' : return LED2;
232            case '3' : return LED3;
233            case '4' : return LED4;
234        }
235    } else if(str[0] == 'U') {  // USB?X
236        switch(str[3]) {
237            case 'T' : return USBTX;
238            case 'R' : return USBRX;
239        }
240    }
241    return NC;
242}
243
244template<> inline PinName parse_arg<PinName>(const char *arg, const char **next) {
245    const char *ptr = arg;
246    PinName pinname = NC;
247    while(isalnum(*ptr) || *ptr=='_') {
248        ptr++;
249    }
250    int len = ptr-arg;
251    if(len!=0) {
252        pinname = parse_pins(arg);
253   
254    }
255    if(next != NULL) {
256        *next = ptr;
257    }
258    return pinname;
259}
260
261
262/* Function write_result
263 *  Writes a value in to a result string in an appropriate manner
264 *
265 * Variable
266 *  val - The value to write
267 *  result - A pointer to the array to write the value into
268 */
269template<typename T> void write_result(T val, char *result);
270
271/* signed integer types */
272
273template<> inline void write_result<char>(char val, char *result) {
274    result[0] = val;
275    result[1] = '\0';
276}
277
278template<> inline void write_result<short int>(short int val, char *result) {
279    sprintf(result, "%hi", val); 
280}
281
282template<> inline void write_result<int>(int val, char *result) {
283    sprintf(result, "%i", val); 
284}
285
286template<> inline void write_result<long int>(long int val, char *result) {
287    sprintf(result, "%li", val); 
288}
289
290template<> inline void write_result<long long int>(long long int val, char *result) {
291    sprintf(result, "%lli", val); 
292}
293
294/* unsigned integer types */
295
296template<> inline void write_result<unsigned char>(unsigned char val, char *result) {
297    result[0] = val;
298    result[1] = '\0';
299}
300
301template<> inline void write_result<unsigned short int>(unsigned short int val, char *result) {
302    sprintf(result, "%hu", val); 
303}
304
305template<> inline void write_result<unsigned int>(unsigned int val, char *result) {
306    sprintf(result, "%u", val); 
307}
308
309template<> inline void write_result<unsigned long int>(unsigned long int val, char *result) {
310    sprintf(result, "%lu", val); 
311}
312
313template<> inline void write_result<unsigned long long int>(unsigned long long int val, char *result) {
314    sprintf(result, "%llu", val); 
315}
316
317/* floating types */
318
319template<> inline void write_result<float>(float val, char *result) {
320    sprintf(result, "%.17g", val); 
321}
322
323template<> inline void write_result<double>(double val, char *result) {
324    sprintf(result, "%.17g", val); 
325}
326
327template<> inline void write_result<long double>(long double val, char *result) {
328    sprintf(result, "%.17Lg", val); 
329}
330
331
332/* string */
333
334template<> inline void write_result<char*>(char *val, char *result) {
335    if(val==NULL) {
336        result[0] = 0;
337    } else {
338        strcpy(result, val);
339    }
340}
341
342template<> inline void write_result<const char*>(const char *val, char *result) {
343    if(val==NULL) {
344        result[0] = 0;
345    } else {
346        strcpy(result, val);
347    }
348}
349
350
351inline const char *next_arg(const char* next) {
352    while(*next == ' ') next++;
353    if(*next == ',' || *next == '?') next++;
354    while(*next == ' ') next++;
355    return next;
356}
357
358
359/* Function rpc_method_caller
360 */
361template<class T, void (T::*member)(const char *,char *)> 
362void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
363    (static_cast<T*>(this_ptr)->*member)(arguments,result); 
364}
365
366
367/* Function rpc_method_caller
368 */
369template<class T, void (T::*member)()> 
370void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) { 
371    (static_cast<T*>(this_ptr)->*member)(); 
372    if(result != NULL) {
373        result[0] = '\0';
374    }
375}
376
377
378/* Function rpc_method_caller
379 */
380template<class T, typename A1, void (T::*member)(A1)> 
381void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
382
383    const char *next = arguments;
384    A1 arg1 = parse_arg<A1>(next_arg(next),NULL);
385
386    (static_cast<T*>(this_ptr)->*member)(arg1); 
387    if(result != NULL) {
388        result[0] = '\0';
389    }
390}
391
392
393/* Function rpc_method_caller
394 */
395template<class T, typename A1, typename A2, void (T::*member)(A1,A2)> 
396void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
397
398    const char *next = arguments;
399    A1 arg1 = parse_arg<A1>(next_arg(next),&next);
400    A2 arg2 = parse_arg<A2>(next_arg(next),NULL);
401
402    (static_cast<T*>(this_ptr)->*member)(arg1,arg2);
403    if(result != NULL) {
404        result[0] = '\0';
405    }
406}
407
408
409/* Function rpc_method_caller
410 */
411template<class T, typename A1, typename A2, typename A3, void (T::*member)(A1,A2,A3)> 
412void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
413
414    const char *next = arguments;
415    A1 arg1 = parse_arg<A1>(next_arg(next),&next);
416    A2 arg2 = parse_arg<A2>(next_arg(next),&next);
417    A3 arg3 = parse_arg<A3>(next_arg(next),NULL);
418
419    (static_cast<T*>(this_ptr)->*member)(arg1,arg2,arg3);
420    if(result != NULL) {
421        result[0] = '\0';
422    }
423}
424
425
426/* Function rpc_method_caller
427 */
428template<typename R, class T, R (T::*member)()> 
429void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) { 
430    R res = (static_cast<T*>(this_ptr)->*member)();
431    if(result != NULL) {
432        write_result<R>(res, result);
433    }
434}
435
436
437/* Function rpc_method_caller
438 */
439template<typename R, class T, typename A1, R (T::*member)(A1)> 
440void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
441
442    const char *next = arguments;
443    A1 arg1 = parse_arg<A1>(next_arg(next),NULL);
444
445    R res = (static_cast<T*>(this_ptr)->*member)(arg1);
446    if(result != NULL) {
447        write_result<R>(res, result);
448    }
449}
450
451
452/* Function rpc_method_caller
453 */
454template<typename R, class T, typename A1, typename A2, R (T::*member)(A1,A2)> 
455void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
456
457    const char *next = arguments;
458    A1 arg1 = parse_arg<A1>(next_arg(next),&next);
459    A2 arg2 = parse_arg<A2>(next_arg(next),NULL);
460
461    R res = (static_cast<T*>(this_ptr)->*member)(arg1,arg2);
462    if(result != NULL) {
463        write_result<R>(res, result);
464    }
465}
466
467
468/* Function rpc_method_caller
469 */
470template<typename R, class T, typename A1, typename A2, typename A3, R (T::*member)(A1,A2,A3)> 
471void rpc_method_caller(Base *this_ptr, const char *arguments, char *result) {
472
473    const char *next = arguments;
474    A1 arg1 = parse_arg<A1>(next_arg(next),&next);
475    A2 arg2 = parse_arg<A2>(next_arg(next),&next);
476    A3 arg3 = parse_arg<A3>(next_arg(next),NULL);
477
478    R res = (static_cast<T*>(this_ptr)->*member)(arg1,arg2,arg3);
479    if(result != NULL) {
480        write_result<R>(res, result);
481    }
482}
483
484
485/* Function rpc_function caller
486 */
487template<typename R, R (*func)()>
488void rpc_function_caller(const char *arguments, char *result) {
489    R res = (*func)();
490    if(result != NULL) {
491        write_result<R>(res, result);
492    }
493}
494
495
496/* Function rpc_function caller
497 */
498template<typename R, typename A1, R (*func)(A1)>
499void rpc_function_caller(const char *arguments, char *result) {
500    A1 arg1 = parse_arg<A1>(next_arg(arguments),NULL);
501    R res = (*func)(arg1);
502    if(result != NULL) {
503        write_result<R>(res, result);
504    }
505}
506
507
508/* Function rpc_function caller
509 */
510template<typename R, typename A1, typename A2, R (*func)(A1,A2)>
511void rpc_function_caller(const char *arguments, char *result) {
512
513    const char *next = arguments;
514    A1 arg1 = parse_arg<A1>(next_arg(next),&next);
515    A2 arg2 = parse_arg<A2>(next_arg(next),NULL);
516
517    R res = (*func)(arg1,arg2);
518    if(result != NULL) {
519        write_result<R>(res, result);
520    }
521}
522
523
524/* Function rpc_function caller
525 */
526template<typename R, typename A1, typename A2, typename A3, R (*func)(A1,A2,A3)>
527void rpc_function_caller(const char *arguments, char *result) {
528
529    const char *next = arguments;
530    A1 arg1 = parse_arg<A1>(next_arg(next),&next);
531    A2 arg2 = parse_arg<A2>(next_arg(next),&next);
532    A3 arg3 = parse_arg<A3>(next_arg(next),NULL);
533
534    R res = (*func)(arg1,arg2,arg3);
535    if(result != NULL) {
536        write_result<R>(res, result);
537    }
538}
539
540
541/* Function rpc_function caller
542 */
543template<typename R, typename A1, typename A2, typename A3, typename A4, R (*func)(A1,A2,A3,A4)>
544void rpc_function_caller(const char *arguments, char *result) {
545
546    const char *next = arguments;
547    A1 arg1 = parse_arg<A1>(next_arg(next),&next);
548    A2 arg2 = parse_arg<A2>(next_arg(next),&next);
549    A3 arg3 = parse_arg<A3>(next_arg(next),&next);
550    A4 arg4 = parse_arg<A4>(next_arg(next),NULL);
551
552    R res = (*func)(arg1,arg2,arg3,arg4);
553    if(result != NULL) {
554        write_result<R>(res, result);
555    }
556}
557
558
559struct rpc_method { 
560    const char *name;
561    typedef void (*caller_t)(Base*, const char*, char*);
562    typedef const struct rpc_method *(*super_t)(Base*);
563    union {
564        caller_t caller;
565        super_t super;
566    };
567};
568
569template<class C>
570const struct rpc_method *rpc_super(Base *this_ptr) {
571    return static_cast<C*>(this_ptr)->C::get_rpc_methods();
572}
573
574#define RPC_METHOD_END { NULL, NULL }
575#define RPC_METHOD_SUPER(C) { NULL, (rpc_method::caller_t)(rpc_method::super_t)rpc_super<C> }
576
577/* Function rpc
578 *  Parse a string describing a call and then do it
579 *
580 * Variables
581 *  call - A pointer to a string describing the call, which has
582 *    the form /object/method arg ... argn. Arguments are
583 *    delimited by space characters, and the string is terminated
584 *    by a null character.
585 *  result - A pointer to an array to write the result into.
586 */
587bool rpc(const char *buf, char *result = 0);
588
589
590} // namespace mbed
591
592#endif
Note: See TracBrowser for help on using the browser.