From fd2d771d1ec124a89fa21e2a69b411020e21c6cd Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Mon, 5 Nov 2012 22:23:45 +0000 Subject: [PATCH 01/21] Add dev_read() function to driver to allow it to report current settings for each of the 8 PWMs via /dev/servoblaster. --- ServoBlaster/servoblaster.c | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 4d59df5..609a4a2 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -323,7 +323,55 @@ static int dev_open(struct inode *inod,struct file *fil) static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) { +#if 0 + int servo; + static int idx=0; + // Allow 10 chars per line: + static char returnedData[NUM_SERVOS * 10] = {0}; + + if (0 == *f_pos) + { + // Get fresh data + for (servo=0, idx=0; servo < NUM_SERVOS; ++servo) + { + if (wait_for_servo(servo)) + return -EINTR; + + idx += snprintf(returnedData+idx, sizeof(returnedData)-idx, + "%i %lu\n", + servo, + ctl->cb[servo*4+1].length / sizeof(uint32_t) + ); + } + } + + if (*f_pos >= idx) + { + //EOF + return 0; + } + else if ( (*f_pos + count) < idx ) + { + // Sufficient data to fulfil request + if (copy_to_user(buf,returnedData+fpos,count) { + return -EFAULT; + } + *f_pos+=count; + return count; + } + else + { + // Return all the data we have + const int nBytes = idx-*f_pos; + if (copy_to_user(buf,returnedData+*f_pos, nBytes) { + return -EFAULT; + } + *f_pos+=nBytes; + return nBytes; + } +#else return 0; +#endif } static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos) From 8002904e4edbaa4ee1b307fb2c13b9fbefbab2c2 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Sun, 11 Nov 2012 19:23:41 +0000 Subject: [PATCH 02/21] Enable dev_read code, plus fix a couple of syntax errors (the code hadn't been compiled). It appears to work at a cursory level: pi@raspberrypi ~/src/PiBits/ServoBlaster $ sudo insmod ./servoblaster.ko pi@raspberrypi ~/src/PiBits/ServoBlaster $ ls -l /dev/servoblaster crw-rw-rw- 1 root root 251, 0 Nov 11 19:22 /dev/servoblaster pi@raspberrypi ~/src/PiBits/ServoBlaster $ cat /dev/servoblaster 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 pi@raspberrypi ~/src/PiBits/ServoBlaster $ --- ServoBlaster/servoblaster.c | 16 +++++++--------- ServoBlaster/servoblaster.ko | Bin 9175 -> 9924 bytes 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 609a4a2..d88b6cb 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -323,7 +323,7 @@ static int dev_open(struct inode *inod,struct file *fil) static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) { -#if 0 + ssize_t bytesPrinted = 0; int servo; static int idx=0; // Allow 10 chars per line: @@ -348,30 +348,28 @@ static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) if (*f_pos >= idx) { //EOF - return 0; + bytesPrinted=0; } else if ( (*f_pos + count) < idx ) { // Sufficient data to fulfil request - if (copy_to_user(buf,returnedData+fpos,count) { + if (copy_to_user(buf,returnedData+*f_pos,count)) { return -EFAULT; } *f_pos+=count; - return count; + bytesPrinted=count; } else { // Return all the data we have const int nBytes = idx-*f_pos; - if (copy_to_user(buf,returnedData+*f_pos, nBytes) { + if (copy_to_user(buf,returnedData+*f_pos, nBytes)) { return -EFAULT; } *f_pos+=nBytes; - return nBytes; + bytesPrinted=nBytes; } -#else - return 0; -#endif + return bytesPrinted; } static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos) diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index 97c3285b1ba04452402aa7caeb9783ce06b46614..7d71d96e91d08400594100c8dc26eb3e39f09b0e 100644 GIT binary patch delta 2860 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 L*;SA6T~F{|Ii|0j From b4463ce8366b07dc272106a5b22a1fe69dc10e5a Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Sun, 11 Nov 2012 21:02:26 +0000 Subject: [PATCH 03/21] Update readme to show output format of /dev/servoblaster. Note that they show a value of 1 rather than the expected 0 initially. --- ServoBlaster/README.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ServoBlaster/README.txt b/ServoBlaster/README.txt index a7e0319..32566a0 100644 --- a/ServoBlaster/README.txt +++ b/ServoBlaster/README.txt @@ -22,6 +22,21 @@ echo 3=120 > /dev/servoblaster 120 is in units of 10us, so that is 1200us, or 1.2ms. +Upon reading, the device file provides feedback as to what position each servo +is currently set. For example, after starting the driver and running the +previous command, you would see: + +pi@raspberrypi ~ $ cat /dev/servoblaster +0 1 +1 1 +2 1 +3 120 +4 1 +5 1 +6 1 +7 1 +pi@raspberrypi ~ $ + When the driver is first loaded the GPIO pins are configure to be outputs, and their pulse widths are set to 0. This is so that servos don't jump to some arbitrary postion when you load the driver. Once you know where you want your From e3230cb8d25d3cfdb9a0961b5ff3eca84e99bd04 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Mon, 12 Nov 2012 23:49:39 +0000 Subject: [PATCH 04/21] Make servoblaster write pulse high length even when cnt=0. Also change default tick high from 1 to zero. --- ServoBlaster/README.txt | 2 +- ServoBlaster/servoblaster.c | 8 ++++---- ServoBlaster/servoblaster.ko | Bin 9924 -> 10048 bytes 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ServoBlaster/README.txt b/ServoBlaster/README.txt index 32566a0..f226580 100644 --- a/ServoBlaster/README.txt +++ b/ServoBlaster/README.txt @@ -39,7 +39,7 @@ pi@raspberrypi ~ $ When the driver is first loaded the GPIO pins are configure to be outputs, and their pulse widths are set to 0. This is so that servos don't jump to some -arbitrary postion when you load the driver. Once you know where you want your +arbitrary position when you load the driver. Once you know where you want your servos positioned, write a value to /dev/servoblaster to enable the respective output. When the driver is unloaded it attempts to shut down the outputs cleanly, rather than cutting some pulse short and causing a servo position to diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index d88b6cb..6616666 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -56,7 +56,7 @@ #define DMA_LEN 0x24 #define PWM_BASE (BCM2708_PERI_BASE + 0x20C000) #define PWM_LEN 0x28 -#define CLK_BASE (BCM2708_PERI_BASE + 0x101000) +#define CLK_BASE (BCM2708_PERI_BASE + 0x101000) #define CLK_LEN 0xA8 #define GPFSEL0 (0x00/4) @@ -236,7 +236,7 @@ int init_module(void) ctl->cb[i].info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5); ctl->cb[i].src = (uint32_t)(&ctl->pwmdata) & 0x7fffffff; ctl->cb[i].dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | 0x7e000000; - ctl->cb[i].length = sizeof(uint32_t) * 1; // default 1 tick high + ctl->cb[i].length = sizeof(uint32_t) * 0; // default 0 tick high ctl->cb[i].stride = 0; ctl->cb[i].next = (uint32_t)(ctl->cb + i + 1) & 0x7fffffff; // Set gpio lo @@ -404,9 +404,9 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPCLR0*4) & 0x00ffffff) | 0x7e000000; } else { ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPSET0*4) & 0x00ffffff) | 0x7e000000; - ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); - ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); } + ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); + ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); local_irq_enable(); return count; diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index 7d71d96e91d08400594100c8dc26eb3e39f09b0e..a01f814c52b0a14500047603725d75480825b4ca 100644 GIT binary patch delta 2134 zcmZXUe@s(X6vxkdZJ}t{o}N_g@+3u>{2iNU3!`wb4oZ3a<(D>w!Ws?&t5uhdNE zEP-8OG=cSDOmqp`YN`oYFnJ_SnIV}jCi5@WzIvlhvf&>~wnWFyEtkw}O>RH;{J7_R z?>T+FR;_Ixl7*S!H8)Zhwyb^VxmB&Ff*QL!{D;d|p#`ZyR%2FYkiG=40-!eTXbg($ z0akmQL0!}WQHZMXyl55eUlpP+YC$~-4@+`T$1^(M`M(zzABj*C2T6@N@touwqsdsO z2;ihu8lwO^;%flD^E8Dh$fwcX8Bc}*9b}bU5K?`1fSU%ac@FCU)-gadO-3yhGM;sg zPy_6YJ;(Ii3hE2~s}E3LLIZm)%eTs7rrV2)D^ejEf4sQ(s{?|%0kyC=^Ub4=?WZ7= z(3+0E`{)a!jd{LAB6I5KRG&$jLwf{md;pd3B1Y#>LcHGphgezT$sWGz_K%u9p zv4_QLZsCYwIL%udVD!<3$3-7Fb zh*OErZVgcfj=dg^>4L1rHP=!n65WF!ox|zWW2Yy`ZDY1DL>?P+g=-|;l)bse5TdGf zEYUX=GuZW}aW z+C~^j>CT>=OR2c|SLG|mx=x4fx zlqc2ttZIPD=TH$wjfxt#C}^Wk!c3z&M$O?dnld~P6^DO_7h%lJV#*ku9}m&IaDW=a zYTQ#9cwm(L`nI6}twP@}%#$EMi*Y$|c^U)sjc9<@;C|8{qK#@GQMX+Qkd?_Pn+5HZ zo~)eI0qWvrRlVdN7>M2+N9F2UI#a#^_hzV%cjCDotl?Dx)PlEDoB{nx*GmyWCy*@~f3wwpNyIaF@DWWZ%l0brof=)VB2=?yl@?>hresZj$?$wJE=& zSZ?X^F7aqfXIq1}qveCXCA)b~e#hQ*oo!tQyzQIvI}c&%e_i-D5-G6!WVRm2I6L^} z+|S>9fA0G4WqDT?CcpYTOxC66MAoGr6oez>Y(}o>#A*OLna15j3jVA~lP!%r$&iFe zl4>gyR8orHf0DhnLX#cqo+0D*G%{+FOyQLPv*eO3SL{zE`)nCx-X>w1? z(RUwxza)IKnUdI^MdmUKP@ie_dfz0@!qEh9mvIlkJ;wI{<{9g-6b^+^;vC{sk>Ylo zA!8E2MMk{;1h>PSmpLaH@twcM?HL2st%jYj4X5pB0I28mB3a@QMl9UV?NJtg8(@a9 z1>gbWZWL%jzK@F$g;tQKt8Ko1X4L?kV#I4zB_sD@Rn9Y<6Pz079ZsuxshZ4K4^YhQ zjhr6FR{a0r@p>dv-N={(K4@hd>_+&{@V#R+)U(F`CnqVQtI zS^ziW4!kDkHqI)}U5u@10Ij&mLgnp9rpz13a(pcMtgQbafCD?nX1MebK*9}s0heu* zoUqyNV>zFVW;xFC*^9btvwExv%QlN^&)6)EQX*;DPenl^t8%hU?6@aVnsY%A-5bbU zZpMCh2{bf(*xlOD^6yLQc9s9%={?%h=5}r5fzFPWwyr*OlyOJXA#ZzkuiI71?bf!w UmfnsYZ%22R+vSebse1bk=sZThTH*lP;^YGj5%& zxS^Prq<_rOXuDg+94+s43|6IJMk=VNWOKS7h*TU3GBA1JLigj374(mR8qZB{acJP) z&pqFB&w1ybdz0C7wR1ud`X)DAD<5v%c&BBt(<}!gcYX2?U(}yTQj22b9BPt23s45I zFYgK^#SVb#7By*#nM4+{M&6U{ppmsYt;i(J5)77{r?`F89nlO zyf`gE6||)kUZ^oc9jMzU<5_X?M&6T3&_?w8(eKn|=+Y&fF3sw+RZJ|kO(f`U^!K3O zkwt$dL7R{&vNe>T9k}ko^_MZ7hK!Z`gIa>rl-jpjoiVdiJ7ogw&r61JNdV2fIg2MS z+Ra!zo-M<5@dWsQA{aZ2c}BGa1w5suCd`HOK;;hTCE31+ zhJj-@S(eTMz+KpNLw-%2=YM(#!T&1^4!yTLW!@KwyV=*XA8t1G}~~ ztIzniY$iw6+)Ph77A4n{;a?9_4hKIyZTZ@A=gbfCH)qEWl5>@{>2sBb1!0ib+;uj& z8bBf&-F3n=>2@~=bL0fh9x{vb61jo1M3&tRHe(IIFj-$!CpgLWss`a5GK8~ACX4gu zRSn|2Ow6i!(WoG0>*~eZGVvmoTx9>cdci?r>l$$W2W5au9pI!gdJZf(0I8#Ds&~KFKyb53s-(2Dru83vi$DCG4UNi3K(?cCr8R zu_xToOoL4!m_%c{FCu1KDZZ~qOjEC?m+~0v@Rd+FB)jf=M z2tqGgbO7{m$8kn1S>wFG^*PRY&Id^OAQphVWQEI&`v5$Q-2hERl2>H63(M$1Ydx0P zi!3%T{h|Dp7zNgB5J1L9%`R%?Cx8{YMYSYOfpO!#*{yN6Xj+s|JAs?GAT6R+CL zpL)b*ek>*ZLCs&HkRr+28XF65OJAzJC=B_05DdP4^iXhgDEwM*B-|ev7(FpO;P-jC z9zGF{3>3X1exLe(vAEkC;Eu>pc;Lv$fZw~73;l174jz5O@7+Q!dn!b4bNXk`Veucp CrGU5q From 62f326001cf4e557b78e6d81791435ea377a20e0 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Tue, 13 Nov 2012 00:02:11 +0000 Subject: [PATCH 05/21] Refactor to amke the only difference between the code paths a little more obvious. --- ServoBlaster/servoblaster.c | 15 +++++++++------ ServoBlaster/servoblaster.ko | Bin 10048 -> 9896 bytes 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 6616666..172f5ea 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -400,13 +400,16 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * } if (wait_for_servo(servo)) return -EINTR; - if (cnt == 0) { - ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPCLR0*4) & 0x00ffffff) | 0x7e000000; - } else { - ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPSET0*4) & 0x00ffffff) | 0x7e000000; + + // Normally, the first GPIO transfer sets the output, while the second + // clears it after a delay. For the special case of a delay of 0, we + // ensure that the first GPIO transfer also clears the output. + { + const int gp_set_or_clr = ( cnt != 0 ? GPSET0 : GPCLR0 ); + ctl->cb[servo*4+0].dst = ((GPIO_BASE + gp_set_or_clr*4) & 0x00ffffff) | 0x7e000000; + ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); + ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); } - ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); - ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); local_irq_enable(); return count; diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index a01f814c52b0a14500047603725d75480825b4ca..bb50e0706ec6bba8ca82487df12e2643863bffff 100644 GIT binary patch delta 1524 zcmZXTUr1YL6u{5D*XWInq8OK$rS$rTM2e-iNophH!KKbgr$t-YO4pIN=+G`}?Q}3< zELrM98HUAuVT?}kwl6K~x)t(bOAF~FVPm{`&1lIc^;!&;m86a_I$-?2rP5OoMvKs-6@nNitE)yG z<~a)RnWbsf02nL!0q)o*)(lX-MEOLq4iY*j8oMSm#0~;HlrZO2%mbK5f_%$Mn1_62 zpm_A3P3YpRb|t5*85YbB&03*G`NDW`A(H>}heSRuCGzWNTMy$Ic(xeUnx#Wpp{^Zk z4abchb;*b-OGX^z9TT4AQ!s~`HY7L^D>UL^fm~AGj^EqD=F1IIQ&fyaSvB1$mFgQH zU)(8`ezQVSm#|T?lkOSnXg>gJU2+lS9+azb5ZjS$!V_jTZ&+_M##cmu zTi=WE@fu=nJe}Dwzbn{|_Ii2;{D)s1=u?Bf;1M<0cckyoV33{L^DvXP=>LyWHB5x!ihI5Qdq_)@j1a0ht}JbqaAdW^)TmYynr9UBUGc z`^n}OpPAVoHkWB}55O$jYwr}FTUgNU62ff8?iQ?UxxC)CyTz1~>2{a6*uv`DTw>PA zJcvhDb{es5Wr+&DX>$oa_PEWB>kC{%tli-jb53^5;Sv;f!ErEV#fF^|06yYdI6dMU zI2Yn+fK!}N&X17dae$ABwE%IV8DNo!<4_6BB>D{5gYLnaWVnoFiw{1&k(WrX<`gFm$+ex zGsU@qbiRWH5V3N=WX_XV2XPEL=d^PwoZUn$%#YlQg$0mQ*bpaXg8c%m0GV%{lVWTO zB@qPtl>q31D~|w8xS>CyDq|OAd3~2Z-CxyC{`BWmWy(imsmf$e?~=)m)nz{4_m3!~ zS+ZlFFrK;DaYLB#_ChH1{`tw!{7mG%&|G99IyJvAJLU5p=K9D&Bsx{L&iTCF|0^rr l9&U)vM5fNoVYtc_6Cch`pZ~z;>0|f1T11aO^K;i(@josqh)Dnd delta 1649 zcmZ9LZA@EL7{{M`OQEnbYb>$@XwR#WL@Ew8Ns$DONdS)jXKn3~2n|UvDRDcFGufxL zG@Pdd-~+R1S_5cI<^f!Fxo0$x&Z9n(OoP)2kQDZ*klAPjxT(WAFX23Z^XMSmF!b>Ti~&^*^tzWn@Auxw^LYn~k|eOK1UR)}3Wx zbP1z#sCDR&Mo}z*F=b1i`=}>T<7}Ds##I5UHvG>K%H)7)hqcP)kB`yvtabq~F8P!n@IwP8~b3&`c zg^YM~E>~ok428k4s>dU^h9+Rk=fk!Oi;>4lKzh%HWsLnOelO&)bGk>ugXnO|l5YEB z-i6R2u#<*^d8GotUnoCD_Pcg1LxYl>a?NN{oiiG(_7nTnaMwKhOn6ZQnEOf$hf|2D zVKsUq{Y}AA;cz$(RygFna_yc2wKcEQmhYC!WhblMcC)p*VqcSY;ACH|-yH~g2dbn1 zsj9-BQpwXB+~6sX-`f%F@w^q-&|OChd)i<2dwY)seN~126WI0tA^ZWO8OA#X^Res; z5sx13Pnygavjerx@#ZuwG&pa*9P?F8c-(^K3b%EHsY?ZF2+MBOV2K zKzt40F|ieI0?(Of;+)`Akm6yyC}JwWWnwzOEZ1|KS2*X1_)mPx^`Z{vt%nfo#|yM| z0JL!ik<@XJh!YQSeUb970xS|e01t^RXi$%Q9SaeSRudZlnmK)(L!4)bxY4>aWP1n~ zT5kYMan5q8oOe0RhK&UzVjDmy*OiQ-6Apo0{gMW7yP`SGQ=&qnqgOFZ?YE zDtnsuq7aT|?fgP0lXpW$$J>3~>u<3m;BouC!BhQSS$6Qa=f9UKJNL3D`PMy^Jmv54 oczXk0*;&B@?h`>@-+=5a=epY)@C@|y2YdQ@Wv3k7S8!bX7f7kY^#A|> From 210487e86824cda58f5d0111c2325af4001d7eee Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Tue, 13 Nov 2012 00:07:02 +0000 Subject: [PATCH 06/21] Update README to reflect new behaviour --- ServoBlaster/README.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ServoBlaster/README.txt b/ServoBlaster/README.txt index f226580..829106c 100644 --- a/ServoBlaster/README.txt +++ b/ServoBlaster/README.txt @@ -27,14 +27,14 @@ is currently set. For example, after starting the driver and running the previous command, you would see: pi@raspberrypi ~ $ cat /dev/servoblaster -0 1 -1 1 -2 1 +0 0 +1 0 +2 0 3 120 -4 1 -5 1 -6 1 -7 1 +4 0 +5 0 +6 0 +7 0 pi@raspberrypi ~ $ When the driver is first loaded the GPIO pins are configure to be outputs, and From 94c2aab61bf33f06f6b921eb9806128f05e5fb68 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Sun, 18 Nov 2012 13:47:30 +0000 Subject: [PATCH 07/21] Revert to original code re: setting delay, so we again have a delay of 1 for a pulse of zero. Will frig the display issues by using an array that stores written cnt rather than deriving it from actual register data. --- ServoBlaster/servoblaster.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 172f5ea..ad624ba 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -236,7 +236,7 @@ int init_module(void) ctl->cb[i].info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5); ctl->cb[i].src = (uint32_t)(&ctl->pwmdata) & 0x7fffffff; ctl->cb[i].dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | 0x7e000000; - ctl->cb[i].length = sizeof(uint32_t) * 0; // default 0 tick high + ctl->cb[i].length = sizeof(uint32_t) * 1; // default 1 tick high ctl->cb[i].stride = 0; ctl->cb[i].next = (uint32_t)(ctl->cb + i + 1) & 0x7fffffff; // Set gpio lo @@ -404,9 +404,10 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * // Normally, the first GPIO transfer sets the output, while the second // clears it after a delay. For the special case of a delay of 0, we // ensure that the first GPIO transfer also clears the output. - { - const int gp_set_or_clr = ( cnt != 0 ? GPSET0 : GPCLR0 ); - ctl->cb[servo*4+0].dst = ((GPIO_BASE + gp_set_or_clr*4) & 0x00ffffff) | 0x7e000000; + if (cnt == 0) { + ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPCLR0*4) & 0x00ffffff) | 0x7e000000; + } else { + ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPSET0*4) & 0x00ffffff) | 0x7e000000; ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); } From 4b87d814df3f243edf4bedb61ddeb995210137ba Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Sun, 18 Nov 2012 14:09:45 +0000 Subject: [PATCH 08/21] Add crude 'written_data' array so dev_read simply echos verbatim what was written to dev_write without probing the actual DMA control block data. This gives no clue as to whether the DMA control bloack has been programmed but does mean that Richard's control code - which has a special case for delay=0 - does not require changing. Next steps are to have an array per-process. --- ServoBlaster/servoblaster.c | 10 +++++----- ServoBlaster/servoblaster.ko | Bin 9896 -> 9925 bytes 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index ad624ba..9031eee 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -321,6 +321,8 @@ static int dev_open(struct inode *inod,struct file *fil) return 0; } +static int written_data[NUM_SERVOS] = { 0 }; + static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) { ssize_t bytesPrinted = 0; @@ -334,13 +336,10 @@ static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) // Get fresh data for (servo=0, idx=0; servo < NUM_SERVOS; ++servo) { - if (wait_for_servo(servo)) - return -EINTR; - idx += snprintf(returnedData+idx, sizeof(returnedData)-idx, - "%i %lu\n", + "%i %i\n", servo, - ctl->cb[servo*4+1].length / sizeof(uint32_t) + written_data[servo] ); } } @@ -411,6 +410,7 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); } + written_data[servo] = cnt; // Record data for use by dev_read local_irq_enable(); return count; diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index bb50e0706ec6bba8ca82487df12e2643863bffff..59cf14a125f7fc91951c800221f67daf7b9dfd33 100644 GIT binary patch delta 2742 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 Date: Sun, 18 Nov 2012 14:36:05 +0000 Subject: [PATCH 09/21] Add skeleton of allocation code for kmalloc and kfree. Currently allocates a dummy storage area. --- ServoBlaster/servoblaster.c | 14 +++++++++++++- ServoBlaster/servoblaster.ko | Bin 9925 -> 10421 bytes 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 9031eee..86cd4c5 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -315,12 +316,22 @@ void cleanup_module(void) unregister_chrdev_region(devno, 1); } - +// kmalloc the temporary data required for each user: +// *returnedData string for dev_read +// *useCommand buffer for dev_write to allow incremental writing of data. static int dev_open(struct inode *inod,struct file *fil) { + fil->private_data = kmalloc( 32, GFP_KERNEL ); + if (0 == fil->private_data) + { + printk(KERN_WARNING "ServoBlaster: Failed to allocate user data\n"); + return -ENOMEM; + } return 0; } +// This records the written count values. Cannot derive data directly from DMA +// control blocks as current algorithm has a special case for a count of zero. static int written_data[NUM_SERVOS] = { 0 }; static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) @@ -418,6 +429,7 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * static int dev_close(struct inode *inod,struct file *fil) { + if (0 != fil->private_data) kfree(fil->private_data); return 0; } diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index 59cf14a125f7fc91951c800221f67daf7b9dfd33..609d2714fb675b0237009439294da57b803bdca8 100644 GIT binary patch delta 2215 zcmZXVe@t6d6vxkdz%0-ru-cYTXuCqiWl9T=!jffUqb$1M1Vx>QEA{mu9fh*Co7YOMg#Y7jDppnc!T*4OrFlI(JXvEAvG{(f3MLegy)%m>1eV_Y1 z=l(eN=UaaAla2|ie%uI@@}x9szyuG$r01ep)BNa9eK45bIGg1HF2-xoJkd9RiQb4I~Q1Lr8vHpsoK8Q2cszgn^Lo4Y^H^o6!{8aHLYpH ziR4J`k2yt4ROV@iz>aJ7+W?!cpy>p12uFbS_}WzSOlqoUCY1;A+h4HnHFK?+d0`}x zfYEH@L?RK>aB&f-#k_>sJ6aU`S_DYUiLvfnWa3gRPMq5kTTd?M_X@^($W_u$@UfAWD|wurM_S=B>SR@^;kp+Tm8PMFIl2($t^l9e7ro6c6uX$ zQ*2dNr+@#Rd#ryz8Su(Jxli$?o$S1B$A!*fG5?D8R8D_ySW%d5Yh$vrbWGG+?tb*v zx$_Tp1>Uruo&Rp3{`VTondC3}aY2}7uN&-nZRG$?_AZuI@&Qcjy1_1NuwM-i=ecCn^_?K3*W#|zjIqa$y%5LcbOjrN$1T|xV;3U&wWaUHG))0ymIkDk?;9HO?8 zbs<*t>@;FmCA*9;8Q4uy2KHwL+sYhb%)kz05Jr4xVDFSUbZwQmhFbvW6dh#O%gTrE zRRMgKgOVrQzH~Z-U-JtX6;i})Ss?u!fCnp>4|a|L4XZnU>HD?hlQ5_ti%@qb`h~*H}M&ODCZdGH0LalX8r*3WgLKW zk#mJ}o%0XQCOq)ezlS*N!yC&D-JE{n5geF^e!3wv(@`SMV2p?dYn=ELUP^ACCE~0W zIKSogTb!$$RoK?thXEj4De`tQJdaCA?8Fnw*~dA=d4h<6jUg*AuyG^>HpK+9-t{yt zB_5LPctD8Y&s^v2xR1r$t|y{4r8V1at`&OOpxO9DFLsPJnicj3A_{6FmH|`|OL6}> zokR;j6A?RFB;sjp#&N}GnM+rh{MoD*TzJ#&OSxc0MR84I7V)(re;jirp=KSGTZb=Z z4OpWV%cRqhq27t*CCpl!LAD1v)|n)vBc?|yt6Q)@dV(V3BhsnO`e}yrxMg)4z~QvP zgO+RqI=Wtfnc%(rZnYOaSZmY4Xz^WfDzMu*?Y+Y~He`?Lbh%1btMqR6`8JEMOJzN((lM1jtI{(n{hmrEn9c66 z1wwK(2vvS~)fb3*dqZI_{)&!=z^@$l%E3@XVMpzH4XMzOGRQ{lZMD))@OlSAes44& z_j@CPlWSa?wJd+;aun5)t4l-RW@pU}V_slJ>`|2}r3x~=$s Se@L_AfcD=%sS;s|qvvmP9*(jA delta 1965 zcmZXUZA@Eb6vxlK&>nJJRmc_+3 z%7=X*rt`sw32vy<5Tk-ACd;xI{GetL4H`ZflZD_CmyBd4$fp_opWBCx)F-+3_x#U! zUd}nsbMM#3zUxg@Ioqwo&EVBhM>Z-(Z+5-n-}<#}Uh-bOw7IH$l)kC_pr%)I|Hvsy z>BBRx`y{^4>vpX0JUmAfqOtbl5CYrd#jismk?({4{?$yWc&d+YB%eW$q1DF&_8=|SsBMd=YYOKJ>M zN|Y!5LNA$5WE7WdX7RYqq)du7Tdg5aBRVd^wiVRxx1O?(PWn8nY)k|wr*Ws9gNbs6qi zh*tEy2TD!qJ&PEH(aXmmzAZJ2&tdcyi*I1`!FWqI-Y+#3t{}dlT|^}q*(2;_Wr>Cw zqIYv3Wy4A6Z3J)aB@_}=jYKVQXeU4vS$hpxG6#r)%$JEG%vXpmNTwubK=oN1GZQ;s zWuho^Od};|Q97kyo+{+RPx)HD*7`#5_)P zmx%z42Jje>Q)dDhNkfn1027&2JpvA51IdVFQgTXiPV!GCHrQmoin8Ip>KjU0m?3P; zguek)6UfBN9c0qNL}?B&dx_emeSnGRgOV4eeNr+dxe96l1i(b#gtfF65C`))B9o*| zvI;!Gjyg6VvKFu$ksSi{5=&w!dTje*^y!J|nmWW@AsqNP@EQz z<}`41Nrjz9v0e9m(bPdl4NIlW#CzM0v2Y`n>q6up&KDVNnvi-outl zl@O?e{-~tTqv&%CY-8;KIr15)dHw>POjGpuwiQv1K6mkfL7`6cSsVGnl9JFT@O95L zMW3*=L*sH1>l6o$0C+>b&6$=N&;PD%&3?Wl+nR%)+M(IcN0n(gSWtXWHLqx**Kv3c zJ0G?@_Bra|`^j+&?=PwkeyBCi3}CM}xk=`9LJ(i-!ZJ#=Rcz|BdnUVXW}E#nAg)F zbucs@h=s@E;pnKhu~n410#>)%O|ek?Ol&k1?DEI`2i(nWccTz4ztSlFc6}y3sXh8m O-BZF}TP#l19sLh;7CTP> From 90dfe77fd5a612abeb92c624638f23626c436a33 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Sun, 18 Nov 2012 14:55:27 +0000 Subject: [PATCH 10/21] Sketch out temporary data --- ServoBlaster/servoblaster.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 86cd4c5..40ea00b 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -316,6 +316,20 @@ void cleanup_module(void) unregister_chrdev_region(devno, 1); } +// This stores the /dev/servoblaster content for a given user process. +struct userReturnedData { + int idx=0; + char returnedData[NUM_SERVOS * 10]; +}; + +// This stores one user command (single line) for a given user process. +// e.g. "3=180" +// Line length is expected to be <32 +struct userCommandData { + int idx=0; + char commandData[32]; +}; + // kmalloc the temporary data required for each user: // *returnedData string for dev_read // *useCommand buffer for dev_write to allow incremental writing of data. From 38101f8a62515ec24df4953ad3409dd8fd285711 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Sun, 18 Nov 2012 14:57:55 +0000 Subject: [PATCH 11/21] fix dumb typo --- ServoBlaster/servoblaster.c | 4 ++-- ServoBlaster/servoblaster.ko | Bin 10421 -> 10421 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 40ea00b..6632c78 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -318,7 +318,7 @@ void cleanup_module(void) // This stores the /dev/servoblaster content for a given user process. struct userReturnedData { - int idx=0; + int idx; char returnedData[NUM_SERVOS * 10]; }; @@ -326,7 +326,7 @@ struct userReturnedData { // e.g. "3=180" // Line length is expected to be <32 struct userCommandData { - int idx=0; + int idx; char commandData[32]; }; diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index 609d2714fb675b0237009439294da57b803bdca8..93424f0a108960444e65da192899e0cda4730c40 100644 GIT binary patch delta 206 zcmdlQxHWJ?JGZ!*p`*EpiLsNhfsvzyk(sNZxwD0{o8jhp++AEEWqupZOeyb64^_Q3 z&p=M?r1~!9pOfRnls3nS+3_=(8Bd<4Dwbwu#1J2!o1YS&T$!Ac8efu`oLy{UW`HSJ zQdy8{VrmJM$jMAj%_{~9m_r2;OG`5Hi%d+-p!}57;^d;tf|AVqJQGvX$x>>mB9;tA bsU@XFd8sKbi6x18hUR952Ae0VDKP;6X+}mZ delta 206 zcmdlQxHWJ?JGZ#8iHoV3sj-QntC^dbv$>PGnTeybfx+f^++AEE@~_vn&tAwMmD#G? zxAE2%U6bR)ls3nS+3_=(SWcd&Dwbwq!4Myxo1YS&T$!Ac8efu`oLy{UVumSL zQdy8{VqyxF$jMAj%_{~97()dTOG`5Hi%d+6p!}57;^d;tf|AVqJQEYc$x>>mBE}3w bsU@XFd8sKbi6x18hUR7lCYvX#DKP;6qdi7@ From e993a088ebdb7815b24681dd3cb6d52f2f710227 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Sun, 18 Nov 2012 21:12:36 +0000 Subject: [PATCH 12/21] Change dev_read to use per-process data. --- ServoBlaster/servoblaster.c | 104 +++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 6632c78..b222372 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -316,31 +316,32 @@ void cleanup_module(void) unregister_chrdev_region(devno, 1); } -// This stores the /dev/servoblaster content for a given user process. -struct userReturnedData { - int idx; - char returnedData[NUM_SERVOS * 10]; -}; +// This struct is used to store all temporary data required per process +// which reads/writes the device file. +struct process_data +{ + // Stores the /dev/servoblaster content for a given user process. + // Allowing 10 chars per line. + int ret_idx; + char ret_data[NUM_SERVOS * 10]; -// This stores one user command (single line) for a given user process. -// e.g. "3=180" -// Line length is expected to be <32 -struct userCommandData { - int idx; - char commandData[32]; + // Stores one user command (single line) for a given user process. + // e.g. "3=180" + // Line length is expected to be <32 + int cmd_idx; + char cmd_data[32]; }; // kmalloc the temporary data required for each user: -// *returnedData string for dev_read -// *useCommand buffer for dev_write to allow incremental writing of data. static int dev_open(struct inode *inod,struct file *fil) { - fil->private_data = kmalloc( 32, GFP_KERNEL ); + fil->private_data = kmalloc( sizeof(struct process_data), GFP_KERNEL ); if (0 == fil->private_data) { printk(KERN_WARNING "ServoBlaster: Failed to allocate user data\n"); return -ENOMEM; } + memset(fil->private_data, 0, sizeof(struct process_data)); return 0; } @@ -351,47 +352,52 @@ static int written_data[NUM_SERVOS] = { 0 }; static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) { ssize_t bytesPrinted = 0; - int servo; - static int idx=0; - // Allow 10 chars per line: - static char returnedData[NUM_SERVOS * 10] = {0}; + struct process_data* const pdata = filp->private_data; - if (0 == *f_pos) + // Only proceed if we have private data, else return EOF. + if (0 != pdata) { - // Get fresh data - for (servo=0, idx=0; servo < NUM_SERVOS; ++servo) + int servo; + int* const idx = &(pdata->ret_idx); + char* const returnedData = pdata->ret_data; + + if (0 == *f_pos) { - idx += snprintf(returnedData+idx, sizeof(returnedData)-idx, - "%i %i\n", - servo, - written_data[servo] - ); + // Get fresh data + for (servo=0, *idx=0; servo < NUM_SERVOS; ++servo) + { + *idx += snprintf(returnedData+*idx, sizeof(pdata->ret_data)-*idx, + "%i %i\n", + servo, + written_data[servo] + ); + } } - } - if (*f_pos >= idx) - { - //EOF - bytesPrinted=0; - } - else if ( (*f_pos + count) < idx ) - { - // Sufficient data to fulfil request - if (copy_to_user(buf,returnedData+*f_pos,count)) { - return -EFAULT; + if (*f_pos >= *idx) + { + //EOF + bytesPrinted=0; + } + else if ( (*f_pos + count) < *idx ) + { + // Sufficient data to fulfil request + if (copy_to_user(buf,returnedData+*f_pos,count)) { + return -EFAULT; + } + *f_pos+=count; + bytesPrinted=count; + } + else + { + // Return all the data we have + const int nBytes = *idx-*f_pos; + if (copy_to_user(buf,returnedData+*f_pos, nBytes)) { + return -EFAULT; + } + *f_pos+=nBytes; + bytesPrinted=nBytes; } - *f_pos+=count; - bytesPrinted=count; - } - else - { - // Return all the data we have - const int nBytes = idx-*f_pos; - if (copy_to_user(buf,returnedData+*f_pos, nBytes)) { - return -EFAULT; - } - *f_pos+=nBytes; - bytesPrinted=nBytes; } return bytesPrinted; } From b14044eba1ce191794ba4ce0a891950be460ad79 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Sun, 18 Nov 2012 21:52:28 +0000 Subject: [PATCH 13/21] Refactor dev_write prior to allowing it to take partial strings. --- ServoBlaster/servoblaster.c | 70 ++++++++++++++++++----------------- ServoBlaster/servoblaster.ko | Bin 10421 -> 10364 bytes 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index b222372..f08ed14 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -404,45 +404,49 @@ static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos) { - int servo; - int cnt; - int n; char str[32]; - char dummy; - cnt = count < 32 ? count : 31; - if (copy_from_user(str, buf, cnt)) { + if (count > 31) count = 31; + if (copy_from_user(str, buf, count)) { return -EFAULT; } - str[cnt] = '\0'; - n = sscanf(str, "%d=%d\n%c", &servo, &cnt, &dummy); - if (n != 2) { - printk(KERN_WARNING "ServoBlaster: Failed to parse command (n=%d)\n", n); - return -EINVAL; - } - if (servo < 0 || servo >= NUM_SERVOS) { - printk(KERN_WARNING "ServoBlaster: Bad servo number %d\n", servo); - return -EINVAL; - } - if (cnt < 0 || cnt > cycle_ticks / 8 - 1) { - printk(KERN_WARNING "ServoBlaster: Bad value %d\n", cnt); - return -EINVAL; - } - if (wait_for_servo(servo)) - return -EINTR; + str[count] = '\0'; - // Normally, the first GPIO transfer sets the output, while the second - // clears it after a delay. For the special case of a delay of 0, we - // ensure that the first GPIO transfer also clears the output. - if (cnt == 0) { - ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPCLR0*4) & 0x00ffffff) | 0x7e000000; - } else { - ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPSET0*4) & 0x00ffffff) | 0x7e000000; - ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); - ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); + // Process the complete user string. + { + int servo; + int cnt; + int n; + char dummy; + n = sscanf(str, "%d=%d\n%c", &servo, &cnt, &dummy); + if (n != 2) { + printk(KERN_WARNING "ServoBlaster: Failed to parse command (n=%d)\n", n); + return -EINVAL; + } + if (servo < 0 || servo >= NUM_SERVOS) { + printk(KERN_WARNING "ServoBlaster: Bad servo number %d\n", servo); + return -EINVAL; + } + if (cnt < 0 || cnt > cycle_ticks / 8 - 1) { + printk(KERN_WARNING "ServoBlaster: Bad value %d\n", cnt); + return -EINVAL; + } + if (wait_for_servo(servo)) + return -EINTR; + + // Normally, the first GPIO transfer sets the output, while the second + // clears it after a delay. For the special case of a delay of 0, we + // ensure that the first GPIO transfer also clears the output. + if (cnt == 0) { + ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPCLR0*4) & 0x00ffffff) | 0x7e000000; + } else { + ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPSET0*4) & 0x00ffffff) | 0x7e000000; + ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); + ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); + } + written_data[servo] = cnt; // Record data for use by dev_read + local_irq_enable(); } - written_data[servo] = cnt; // Record data for use by dev_read - local_irq_enable(); return count; } diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index 93424f0a108960444e65da192899e0cda4730c40..eee1c25ed6594665b985a9ed28a946f404cf9f37 100644 GIT binary patch delta 2736 zcmZXUe{2**6vyA(kG5B+*;1fCxVG0H(neacz|m5K^h8iJpa-;A6x+kLP~?CDM?50t z4s8{IGgqc4BtVydkr-o3ssW88hkyYCNihWY17!D>jRnD=!RQ}^^S!$%InGITKl^=e zX5O1Ov-9nuhwiY0g?mbFzI1L;pAncH(d*^YdNC~4O)h0hu}dif#~vd?=7t4&R5J|8 zAS=@Vmgr7L$aonb6QDsK>j{}&1t^#yhoTnV$TqQq{5)GT$^we!bQ~~1-oxunb%hp( zqCJYmeg|;t$6~R}EKv2^vDlrlK;!n9ynz?1Z?mwXb-2TZG_)`Z(5RafMKcE#%?b*u z#ehSe(^|UpsRph+ zA%hZNo)4oLuv7m9W9%wXlat7RmolPDXOGiqZh}KpA{$?&C`IsCSGTqX7ff8y}W$0brS33hpZJP zK1|AD7LjuL3_oe;jnDRAOrOy?c-wlIF+UHb7h8Q8-p`MvPeOeoJ$IZRwF^T$z!iYw zgZLmnw`Htim3%`+Sr(;1tIrCmdL=)Uv6G$R)wXFkdWEfcidTf`6a+z^pkL4~>Ql*& z*(NZVU$i}&A29(8d~FUkVc`b`js}kq`_qEMgC&_OS?=_jnmNunbLUQV&YSwe)alcw z*F867&OCYW;HVv$V^959eYUpt>UWj(!q4ZHF*m=L zTVcIy1IXh&c{#i)PhxlZ?7RvV>jM0F_wq~mIs5|pZ}A&>6{fB%{z=|= zZqJvP%B%A$*b&}{?>7D(z9s%SzAy8O_;&HX@ondY1r=7;cz~_(K+6jx^sGf&7utZI zD#+nqp{;Q13K1k`eX{dmSk8WSH)Nc(H}FCtB& z0lp#K05AhP*q7t6#d6x)0h)--0BuAZK6xZv}7(x{)-lfrt}&$^JS(kcbI|iI~WK@~^bb+ajn~LgfOL0qZQqvNCEURd+qi8D&0G$nBP>8+gU?m!hkB%hi z=g~oWFO3)d>D(mur~6<;3Lwo%ocYhe0~r z!0#q}u(Wag2jjn%7MUI~{-|_vVASJUB`RMm^n4tV4NpOJioYgB&ri`UDSB;+eg`#` z=LBXm25=ugOzE&IMSq5xF6z1X-~c$B;-^bvq|wnio1(9z=--~u0f75Y7y$lB(T`Ge z2Hr*^jRKaWXgNjCPSFj?nvOy%50w{}yq|1F>&GdY^Lyp}td<{mI=8)cDzvn$UEkKy zx~0|I-r`%`x@MEJR{p=yx23b)SyLw*-qo$`>o%dGRv1=n_I0e^=&Y#`x~+Xv>&Dfc UzSZm3Ics?S#OA@?i6y500Co+QlK=n! delta 2641 zcmZ9Me{54#6vxkdZMSZ;rXVud&j(|yQ8cftY(ochG7S<2)qx^Tx49LVPM9zhlf{;} zMbu51wwkTLn8~n-F%@jW`go zXokZRHDpaQ79v=yFJ^k<%yc1v#A?luX_H|a`%*`OCyIz(FQlkWy;?fob5fTnh`uSk zuw65}>`hxmIGKr@#14yL^7plR3NGhOtw9`y92?5bvrDj2H|n|zDj_#smY45Xa2Dea0! zbZ>mn{3VkK7bgRg#%I{CThWa0%JbQ}yV|>Sr^?Jc<%n)mzEBYmwQfo0AyKzTbhbzo zzHFkOte#Hv0@kYc#LNQt?VkO5A=c#ydypi?25f)MZX#~$68|M01c#gVJdG%ULMVer~}yo zL_AS5S~J}*6>Em1Xz5ev8)YjUH3jkb^r$#{!f}H%!A?4=7fvFG-4@HvrfXwnf@_Lq z^>1@x=EV39juVoUU?cezj!A@1uy^xsfHv}ru1i1%5aKt&87NO>CncEMxgF{5bym80 zntV6zh@S3eC!Nnp=b5jd2D3v270q!GW(hn`6KD~jnm!Y$D^pf)A z`UgEUz@`drS&)#4#!kzTRy#O$Dxz_o&Wl_cuPWRo71jD0>-_$jTWi#1jrGfFZ}Ziy zsb6!uZ~Wz1&lb*oY{OV0`uOwPH&=aiTrFSnS@nmNe~bs_4N1~b_IXjIw4VK3R4pah zg89|bW!4DW&$?l~Yy@^K`v6vF25f{CEU1<)G9RqQ?uBh<`(a(|HP|GZf^A@bz|Ln2 zi>nHWxZ1tG9Q(*4!k0!HSXoJlc}?^C84_hNlNa;NUwQ;KU9NaH4cWocKc@6#h|8?CKrCuZ91jpf0!= zb4z#N2sx2>knQA;Gbl!XFXoHZUS>F@hdRhrdQ&hZcg(^yudllBVC%IdH>M(A>}zKJcwkMLgF$a z#o2Tix*zX+HLj0CM`q|(p$DKFME_~%_>BIKpeJVN3FyfgIsu*dU(0lX?O#-J>vwSb z@l>KqqI~)j?_2QT5VCp}>eK;UCp6!||7{kP$Sk$!rm*+Fa#FUu4MMNQ)Y)_mt+VvE zSaisu`z`uei;hC`!oH7O=8!apPFM!K#?Dn<8|G)zga<>i|AbuT{9L9iGg21)t3})K z>&P`e-)+%zExN=;t8(MBHL0=;SY^@87QK~?EUsvbSiH|$bj+e(vFI^2wfMAD%l20l z&8uBTZEcV2>T2tJqO&K|*4N$n@E(6Hd#h@G-SQQptEam&v~y3$zr0R3I`;PM*tOfg zyjJM0(4NlS-MxL?yLS4Qv%jkzDDCdrcayKKR$W26Lw$R9?+kS{b@X*`mrotvx@3|3 EFGih_yZ`_I From ef87ef88a79b33698c617aee39cd39eb25aee3ac Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Sun, 18 Nov 2012 23:15:35 +0000 Subject: [PATCH 14/21] Add code to allow dev_write to cope with partial writes (as will sometimes occur when using languages such as python to write to the dev file). Currently static data so same for all processes. --- ServoBlaster/servoblaster.c | 31 ++++++++++++++++++++++++------- ServoBlaster/servoblaster.ko | Bin 10364 -> 10404 bytes 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index f08ed14..ed831b5 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -329,7 +329,7 @@ struct process_data // e.g. "3=180" // Line length is expected to be <32 int cmd_idx; - char cmd_data[32]; + char cmd_str[32]; }; // kmalloc the temporary data required for each user: @@ -404,21 +404,38 @@ static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos) { - char str[32]; + char* end_of_line=0; + static int idx=0; + static char str[32]; + static const int max_idx = sizeof(str) - 1; - if (count > 31) count = 31; - if (copy_from_user(str, buf, count)) { + if ((idx+count) > max_idx) count = max_idx-idx; + if (copy_from_user(str, buf+idx, count)) { return -EFAULT; } - str[count] = '\0'; + idx+=count; + str[idx] = '\0'; + end_of_line = strchr(str, '\n'); + if (NULL == end_of_line) + { + if (31 == idx) { + // Full buf without '\n' + printk(KERN_WARNING "ServoBlaster: Failed to parse command (%s)\n", str); + return -EINVAL; + } + return count; // Incomplete line. + } + + // We've reached end of command, so terminate string at '\n' and reset idx. + *end_of_line = '\0'; + idx=0; // Process the complete user string. { int servo; int cnt; int n; - char dummy; - n = sscanf(str, "%d=%d\n%c", &servo, &cnt, &dummy); + n = sscanf(str, "%d=%d", &servo, &cnt); if (n != 2) { printk(KERN_WARNING "ServoBlaster: Failed to parse command (n=%d)\n", n); return -EINVAL; diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index eee1c25ed6594665b985a9ed28a946f404cf9f37..fcfa93bd22e3985bb3377a4179816d1bef60cc59 100644 GIT binary patch delta 2834 zcmZ8ieN0=|6+h1(;X%ygKoY(jY|4kTlx7B8Fk7QJNt?3Pv`)h|wzUIdSh2G)URv0by3xz!nUkSHL^rnw{}u8@kc9llZ|;(=!cd}nbb;E+3(ob zY2qv0_q)Gy&OKlEzV|*0p4mI&QuGrwOVOS8tg2T!mp|H@Fid_urD`V))iaSScIhc6 z?Mp{@{5kz~&!x1}KRBV<$CIi@7#7!wq}lZk4|((!g3UujMMPccZlX$yb__OC$#`GF zpopHf(b451yPj6HDZ>`IWPHB1_90O)y@&Ti7LDCw8xjT^aX^db__7)~nlUoLi0pbQ z0H@?RZ4@9-C(+Xu`)Pw{Z+aKe8~$Mgah(#+D;3dpqQ99*Po0th%#ve7eTXr$h-AeMUN`11AfH?P5G)W|s+H*3kbJz=PJ&G_%y+6P*10v&@h6q&1D z)t{lVH=82|H)Iwxg7>n03bGE!n6u44!SAC7 zzYx3!fd>X=xrvRIAR`P9KQJ8R`pH&IUfVEdF@2ar^EXUFv2Mk3LHx|}@TLn`U4QhR zRUAe7%I<{Wz+DN5RZCTSz%y&i?MoP4G`Vc)om#H_s-9YhkU`I6Cbyt{)|hR{>Xk}8 zrMUF;7<5O(4r@!{%wpDRMjW=@t;~v-t?rr_O&S(+wh$^!7;)w_oAGwDBw@_Xe{6k8 zQR3o6fzuj8__+9O!QJ4gg0f9#PS;Qp9B|4BHN6uvt@xOTuJaayLCV~BS>JnEA+p6bYRkRfo(cEih?T7_9 z_louwyIjcwz+VoO`anG(OK!(1uRil*L(dq+kOg$56a;f<~H{iSc2Hg=p2zE|<# zbl-HHJ@nGk_Oo9*yZP;T|K@2$xh(!(R%`98BJzv>mDMVrh>CKz$zCLOl{YB52$#E+ zpg4hNMEs%LZB=o(-VsK5t+FHvE8Hfk7R?n6)|h~NeuL+VxQb`5 z_!Q4ZQB&!*2Jr^#qO-CVPKPVqxF^qLo)_`_lUS{E7e}gLv5u$=hxCZpQdMQO*Q4=b zM^$+g-y`? z5%w};A<-4dm!$q(V3ZBsmx`ps4l@D-i2^uAM~J9j;wX?Ek1=B349mZZi^qtB78sG> zBJ2AQm=Sg>EPsT^ZUqjaK*sM8byz7%j_)7<3$SsL@iC&f#5swVB`z@{P^QKg8IB0wkYQqgll?3&IF24PF6qrLQugf;mRCaDnkrqVrO|#E9zN zmq@T-dy7O>VgTrP5(zLO@iE44;eK`UVjs~li8B&o5_QHf5&&*N<_o~g*-FHfp>4P) znXy+qv*q`N-^PuB#MC7&7FW*?RUc8Jb$qa-&=#2S?Z^&=>{#%-o8!ABkMVwK&xfAV zvpv7#IUbOlF=x+*pB-8M_!exxCEx_Ox7m?3u%VP3XZ^zbN!N%HWj6|KpfTivlOUJm z6X1=v@n3**{G9zsaNONn`~~nX@cS^?-><-DZqvUG&VQEN{y&1p_aiZ=iIqJPa4kSKhERhdHm<% zYTdc7w0o$h=SK(odq%^dANGud`i2HZ4@U;PzIG`O9S#i*WV9n*Uz<2rU*_|*O5IR6 zG;m-9#$GAtdunv>;32QCMe_cEk*Q}QxV7>Bc$mqL delta 2805 zcmZ8jeN0?c7C&!3V5S8G3i35A(;euH7W7euk8U7Kv30vj6(}ldb!IYPL8lhWn5D7V z84$lAPJ64aN$b4ECh8wr3>vG^WYkn^{Rb1GF=`xU`m%IaH#Moco493vXXc{gyUBgO z`}^H<&pG$p``*mSzF&G{P9=7D<6>k-TJrAcsNN(EnS!F z(I-mc`ntqyDi8i`&e>D}<|#3&UtU@Hmx+4Q5h~V}Zp1>HdR)(k(;lKH3yP2HM1ARP zMDKJ2;yO8>1@BMi(^QI_+Up-|)Rq)ycgjS4OYKDG%y9k!91o!{tDoaldR?h zvED|<^-IO@#eV!#DU)A2VM!d0=mcjU1%k<`12f5}c_z82#dY(fwv-n@##&Twh(4x= z{Ez7-=Va2RPU%sy{a`^ruM+{(XLK|5FI|a%9SgImi;ujw977Ne2Im>y>~lH+EfLkf zUs?GlDwU~*#i=b_UWsJ0etl(SO(7-I7ubMMLR5uI#M*giJl;<6OxenzeG9EUhkpg$ z0B)A+*yeL+WM~d@{>_6v0=)peYrfnp6srZp$Hl9b8_Q!DUA(#R0*)oUa9vz?;BI(C zp|xhKM?I>~?T+gzO{XmWM^dgoqDBbUpiXDfYA8OcA8pRgE7g2JT6zF;gCbyUwucf~ ztB^Qu-K>m>Pps~ZVVc%0=Io|uU0k1FPDeA|E|tdhvH6m`7ZqhfyqRBX4I})7_%eTU z;{-;|vMIfCBZ{h^J0H$0VZ94MFQE>!s);7sUd1Dxx4D`)@k~vl$+QPy6l{@sS#(xk zmbFS?`>U-%d~f@+ofM)4NE4#dUZK1%Zm~BbqbKaOO(B`;m_(8omN+5NAgU zs`$~~w!t@D6it|j=3X;L2T}dGxtF6S8BgU!mu>SmtQl4+T3TDXz1`clZ}INfa{ZQ; zmX@vCn!0zW;-j_Qw)&yY`k^)TK`~ZPE~*Nu=I<>yXD!cvYVXrN-*`9>yw4XLxzD%v z!N7qbF=zMtHSyS2jA2gn6Yy0AD&+}=& z@=*J(yU%|8pZVS^XB0&f-&DA)y){ItuvWU1MR8T7+w`4X^jB_DqT*nsTWJs{@az$v zRJyI_*Ai*sM;K0vsw%fBxn6WvZL*#$Bua>VRW4;n9IkRJ#o}!|7sV2uUBX`NRveK(IDg9L_>^&L?Onz5L9AJ;xQn9+B8OlJIQD#dYO^^ zOZ~LOcYzT$tTV&mO++4?t0RbaO=2&Q7Y;DOF2wpBL{Ua06k|jp$9O(~z>Kg|M5GHe_j`VClLK?;Fk^DCLXA(Em83~ zT5TM*Q=F))-4-;c4;c8Afj?p3LMZj8u5D{3pKss(AzyeDKRx5YKxjC8aBSGywngf} zgTc^nW_H}$riyRtE81JP%DK>JaQOc5VQ*`j6ao*1NA@4^wzf(>G&~+WFgg|<-G9Hg owMAUBsaG7?v`=X{;@)$G@yG6V_x_^aw9HT38TYH=pl9>{0fl$IhyVZp From b1bb608d4c702c16f01c93a8edf579ae39343129 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Sun, 18 Nov 2012 23:35:32 +0000 Subject: [PATCH 15/21] Allow dev_write to work per-process. --- ServoBlaster/servoblaster.c | 51 ++++++++++++++++++++--------------- ServoBlaster/servoblaster.ko | Bin 10404 -> 10356 bytes 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index ed831b5..162cf63 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -404,31 +404,38 @@ static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos) { - char* end_of_line=0; - static int idx=0; - static char str[32]; - static const int max_idx = sizeof(str) - 1; + char* str = 0; + struct process_data* const pdata = filp->private_data; + if (0 == pdata) return 0; - if ((idx+count) > max_idx) count = max_idx-idx; - if (copy_from_user(str, buf+idx, count)) { - return -EFAULT; - } - idx+=count; - str[idx] = '\0'; - end_of_line = strchr(str, '\n'); - if (NULL == end_of_line) + // Read user data into str { - if (31 == idx) { - // Full buf without '\n' - printk(KERN_WARNING "ServoBlaster: Failed to parse command (%s)\n", str); - return -EINVAL; - } - return count; // Incomplete line. - } + char* end_of_line=0; + static const int max_idx = sizeof(pdata->cmd_str) - 1; + int* const idx = &(pdata->cmd_idx); + str = pdata->cmd_str; - // We've reached end of command, so terminate string at '\n' and reset idx. - *end_of_line = '\0'; - idx=0; + if ((*idx+count) > max_idx) count = max_idx-*idx; + if (copy_from_user(str, buf+*idx, count)) { + return -EFAULT; + } + *idx+=count; + str[*idx] = '\0'; + end_of_line = strchr(str, '\n'); + if (NULL == end_of_line) + { + if (31 == *idx) { + // Full buf without '\n' + printk(KERN_WARNING "ServoBlaster: Failed to parse command (%s)\n", str); + return -EINVAL; + } + return count; // Incomplete line. + } + + // End of command, so terminate string at '\n' and reset idx. + *end_of_line = '\0'; + *idx=0; + } // Process the complete user string. { diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index fcfa93bd22e3985bb3377a4179816d1bef60cc59..f77c6adeb3978320813670a1a4563ae6728416fc 100644 GIT binary patch delta 2634 zcmZ9NeQeW37{{MqU$%B*q=Ug;86A^tfoXXME_xapY{r+m)w2s``pv# zp1b?qb*yRHHfUBZ3>E!k*3|n#du)TMVWKfi)DqE?Pq7iDHG5B~tvmX|!k}0@FTz07 z9BC!W(|L~s4VL~OIen34Z@-#CzEG?48#T@3i#(c{`IE>NS;zj)fa=a1jgB`v`_&Ay zFQl`a2(ym{K4kKR8WE2yBWfybiEJb~rZbJGL`{)3L|@i7jjCim1-;o5Nu}N}nSGbO zF7kyG^XjmMnnEjxZfi05u$)v&!MWL-AOaEs&gUee0Y=n+O$bJtBdNCDu*T*)s|yUN zgjhG5?7`lh13|BLAo#O)RMo!e3+bDDA%oYemOBrt4%=Z>V_x5b75A!MGCb5_Lc_#~ z@Kn!N55}TFN7Q&Q4stp$su}`b_2JCSAG|XpR{Gb z7J{vTM%B2_edyW*eGj@ETAL7O5;hAxDFtMHzYLWv!>F~W4%Df275;qf2}RL~^E$gy zCNlK-b!C=eb$rXHYN5Wc4rgAx!WZHs%PoD;B+5<0>Tq>zT*>1Tz|mu@RkZ7?jgCOf z%OOVeOBJWMr7taVQJ<>Q#+E>HM^!g#8jePro-?XC{h2ABD2iKLNnNOSVS2Z?m%6mV zjh;EHSIsHHE-I+z528O|dp#zd#;Pf96IF)YSipyd;tWolcPqmijFgF6hU3Z=(PFGd z{G-N&RSr3^QxZE8jp~wgOBTpIE)(~R`HDsSV|+GuN<%dMnbvzm2accfPBJg1cys*g z({?G@*44FZYL+#uTD!(t-C%uw?Q+Z7+Pa!5|F`LHr)Aw;c6ahEZRfj7TPTF5N%N8 z=9c2zR^^szXtsDgw?y%ZA(*V<3$#-rgtkK%^GcOkQI%J!--a7-NNmq5Mz9`Oed2ty z{Soc=;=jDo3|AqMH-!k-hBk(HqhpWMXv>Bxk{g{Y{ctlC5AtClX*H@jhlVj*!`e8`2^>XC%iY zFEEkVHE;nk4}hH59Z7sDv;^Nrv}__m9#PGt9pd_eP0CI&yD%GVN#S$G7NUB1Yc`9_ z*@gar!b6J3!iP=@Ex-@>i-{G5Oz7}+jBET!MD=O@z4Ye~B0kRkd~M?z=N;9|xIcdw zu@Z}q>s|TSzzOia$4bm02g{6W9uN4hn7b8^8C``k={@99hCYX7-2+{oppQZGGrdxd zpM-WKjDG~}OwgY~yAt$8Xm^7C92!M@wT;<$ z{U;@z9w}l`aiu5y@fPE&!T3U{U%*c@X*N|Pjn^dU#w5KpNq0i?E?!0KIY`X)^tgxK zecC|%(ERK+pz;rflEyzy(*7iUBT4^|r1=$!7ZdJ1{qmH7NKMj@l5_@Mr+DEV%S+N# zNxD8sZ%ouy1ZYV#K<`S@dz17#LRmasxt!YC_U`X!b9LF@XzRAOJ33tlot@UY8fmv5 zv^zSZqutgztN3+sc5Pj?9CLKpJNI?Nxk?(^-*WBQf52L2k-DR^+kT+S>FV0Q&stk2 NDobqslO=OB{{!>kYBvA? delta 2758 zcmZXVe{54#6vxl&kFA>b7}ZVnTHF>otP8v14z3`|C2C5pBPy|k_QY)N zfmoz9s#8Eq=F#p%uBs(%p#eQF@R|Pa&6`(=e97fJCNQS=6hw87$#-dSi~B&r7T9gX zm=Hs%7WX12xsU4Ev?jTdXs<;*suMLPml1tfzZG-1js#&?oy?|P336$tKb@t;71y$a zi5lZ|L|>Uniyx7bnkiOT#6=<@A>ni`!gWL^BPnu>?Mj%&wAU>3vaTS{H|PAZT^mBN zzQR!Khfq{EZ`I;?=Xm9PdL;_&9NVp%d=Cx8D%}Hmh-}v^n9O$mK;qB7vsXB2I#HiF z6pN@)-KK{0zi!_AHPjN-Em$$HJiQ~f(97bW$q~#`Q?}_8OI}9oIzlXVg5&aGi^J9c z8*7gF5qilaeF54HZI)v=W&$=sbMphuNv@sq(D^+NJ&az9-bpl4Za$Pgq(866N=3@hl|wx%-VGd}>$^SEu|+3Gcp^?18UWJZG)W85~PR z4T?9dcPnA>owZ`t5cTU8b7~1x7}X=JDQslBJ~gU`M`mQbt|$?4E_l~f1zC+<uTyAtgU-s;c`#SvgI{ZwfB1#jeL8@_S|U=M|~F@SNFH>pQHL; z->aTne6r|kv9oCQ$j+i?6lGleQe19rDJ7~G1@?05jT|DoIBhQ!Uc0KOV!gdW(Zm3r zKJm7_!WzJ@a7bKp6pG*Aw~2r36{d-NamrpKmN-;}#7akn>3Y7{?wG4|i=&PT#VtO^ z^OE=-&lWMgq(Z3_OG_%OKKx2FW2W8`71w0S1d^8|Z%F3ZQhpaRh`<(p!33SmW~@N!e#!mJ4ooclCqQ25TTHBU zn28-6Wj;)FM%pKsSlmTPLJY@SByC`j4PLxBH=+P03hH4#LKI@IA=)E3C^;mlF*{HI zI0J=`g2uO%#F3%9(g&)M2z3~mNgIrNO?)w9g`+KX#qks5kt_$-h@GZ4iGD%BKYH2>Js`hL8y9^&ybp3h0z&$IERkk($Qndx{w zFR7NwkIQ5JEdv+8pCi>$0eM(PTC;z2^MCGjDBj>XTJV-GC7VG==WV@UO_wtr>bthTZ|q z`*;SkPsRLuZubZ2rP~ek3N&Bq51{ja;~D<M+- Date: Wed, 21 Nov 2012 00:48:27 +0000 Subject: [PATCH 16/21] Following test and bug fix code now works as intended on partial writes. --- ServoBlaster/servoblaster.c | 11 ++++++++++- ServoBlaster/servoblaster.ko | Bin 10356 -> 10620 bytes 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 162cf63..2e56494 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -415,12 +415,20 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * int* const idx = &(pdata->cmd_idx); str = pdata->cmd_str; + printk(KERN_WARNING "ServoBlasterA: idx(%i),count(%u),max_idx (%i)\n", + *idx,count, max_idx + ); + if ((*idx+count) > max_idx) count = max_idx-*idx; - if (copy_from_user(str, buf+*idx, count)) { + if (copy_from_user(str+*idx, buf, count)) { return -EFAULT; } *idx+=count; str[*idx] = '\0'; + printk(KERN_WARNING "ServoBlasterB: idx(%i),count(%u),max_idx (%i) str(%s)EOS\n", + *idx, count, max_idx, str + ); + end_of_line = strchr(str, '\n'); if (NULL == end_of_line) { @@ -442,6 +450,7 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * int servo; int cnt; int n; + printk(KERN_WARNING "ServoBlasterc: str(%s)\n", str); n = sscanf(str, "%d=%d", &servo, &cnt); if (n != 2) { printk(KERN_WARNING "ServoBlaster: Failed to parse command (n=%d)\n", n); diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index f77c6adeb3978320813670a1a4563ae6728416fc..2c070d8c9e2957cb7330b2af63ae75ea4401fffb 100644 GIT binary patch delta 2106 zcmai!e{54#6vxkdUAHnj^I*Tat+S8ewh}jZ8=Y)qVmF2uGjJP2s}9%E6`78$SvwtO zp$}FyG0Y6^Vjuzf2>ihxiX-I@vZxtobRseMBL)+L{jp~NiGgH)K(biRX>SeDKYYo} z=brC9_ndQoyt~-3)HNlGAC&~Wae(fG*rCO;KobOjQt8@c{O*Cz zZgxx4x=qm%k{H(iN+$p4R;KklNsAfeccM1vN(5^!C7zZqCu|*_gD#keo8%+9QTi|{ zO5ZCWYwG}g07B6sfLwqb2`k1nNbf`iB@~Q;PfK)5A>HK;#a+HHbfc`rDA`#dtb=

ODQ6fdI)zPXgv?F;EOSOksPm!lshG0Bs0voaYcO~gU~=gL@&NjahC zU@_|f-Zx7pbb!u;0x-Mi#6`%{Xm=%Y;9wkgbI_1JcS2 z5Y0c8OqQBu3erWZE4?6vbxJTZ7uK`jus&f>qoz4kH`E=7n&b&x1=GFHvG8d~7fTD7 zqJ_Y8Y97V)VT>GAjf1M4GF+k~KCI6l*cA;PYE`2Xehi4BOAYH{AFfh;Pp@%@^uf81 zu4ACKhXTKib|cz`hjwi=l?=cE00C@gu+3r1e0Grc&!b^QK8_b_3Hx`q)ZP-Nw8#^N zNkMEA*lgBwV!IH@HvVqN8%LkacauFZZCUv#Du=K+L;#<&_7-$#iKEW2e$*Y->F`gp zzGc6Z8PrAtz|1*=dMyh%b5^w)k)LF%?#PbZ-9m9)-7_tlnwk{F(YW4G-_o+FzO8k0 zLlgVqkxoy`26>==%w9RLy2dj+Iux*1j;^lR+c(yWs!TFoU1)Y}-0mHDbGUV|&mZuP zwEo{5*&i6OSNd0PettVnXWyC2*;;d9;lILoHjrQBDYGH_NWPOfS2)=mHYfJg70!s7 zKQ9)nwC&!w#Z@=+Rzu`L?e(r>=H~iYw!f$%vcKqcLA2zu+r<^eHvF^pu;rFj#&%3+ zVdpLRtlc6B{cNYDTKwoS_O7K$IKw`+R2#oUhokIXNj|${k+OTt06iiTODe>RkFs-? zBGz0YiDnzyR#GKgXQL(6qN|XdEU6NkZR{(=d?EW2F=%5&rB$L-%r=%*86Cv{>E;Y@ULXcB z!5npV;tGhAkTXhr4HNV6B_ypBaJOg$Sww6m;#S;huG@*YdWEx_>n_e7P7S%u>cs-E zLzQ18b_4uG>;(9gbAj^?=OPgc%fee-j)j|$R9Hc7ac0KJpWc>?-Og=d#-ENg{iWmM8?^QxfeN5qOMhtxHx{3-Y2xdIS4>-Ug+C>z;j{L2qi* z-=M7fubB3(=L3TS9`BGJrz>3O8x8Ck9&t1^al7B^_lykq0t3TCj;6-QimF}W-ws(q A`2YX_ delta 1825 zcmZXUZA@EL7{{M`+d@G|y1<}sKtWPW#H|~ZQ8Tp@5MKr<6K8ceU@hpuS(CRx3gO8o)gJE*qMf>1&m-4RU-IzrCByns?nMNLwPn!sj~aj2^jgL0ThT%#qCTx%_^i z)csULWBuNy1I>-@x+eG2&HG%<4W9Zv%v#XSek-Vq+Y7f1%wObX=3+0KA>z1J1rezsJJN+G*vaf^?u;||*c0Nun_@ao`>+Is;; ziAMk?h@Akld_K>a;9N$EIRGofJb*PKwy1FX@0=T)w>dj>7`F`~;Kw7g_h8eU5|RR( zB4XfKvg5U1AYvg2A{Mqx{w_>RMBNtI58^Q3=m*$Od>Q{4#FsEW5!X!;@mF*q%?Q9E zH>_|fL`)RRMIOZjoLiiFW5#agtmO<6F~KPDRcwIICpl+`uVG^Dzl;Bq0~J8qmU%J)GZvejlRuFcU#h$z3TAe`dbhZykFQpLFGSp) zebCkQ=5TLUcrfrr*GQlz*cUz#>T`SQxjk?q5bR5PN8BFw|BV@S9d`r=1ARjyxO@*c h^t>G&7(VXyxcI!cZzOPhFccmf9&$H$;?|mD;y Date: Wed, 21 Nov 2012 01:00:36 +0000 Subject: [PATCH 17/21] Factor out process_command_string() --- ServoBlaster/servoblaster.c | 77 ++++++++++++++++++++--------------- ServoBlaster/servoblaster.ko | Bin 10620 -> 10751 bytes 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 2e56494..0604e58 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -402,6 +402,49 @@ static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) return bytesPrinted; } +// This function takes a single null terminated command string of this +// sort of format; +// 2=130 +// where in this case, servo 2 is given a high duration of 130. +ssize_t process_command_string(const char str[]) +{ + int servo; + int cnt; + int n; + printk(KERN_WARNING "ServoBlasterc: str(%s)\n", str); + n = sscanf(str, "%d=%d", &servo, &cnt); + if (n != 2) { + printk(KERN_WARNING "ServoBlaster: Failed to parse command (n=%d)\n", n); + return -EINVAL; + } + if (servo < 0 || servo >= NUM_SERVOS) { + printk(KERN_WARNING "ServoBlaster: Bad servo number %d\n", servo); + return -EINVAL; + } + if (cnt < 0 || cnt > cycle_ticks / 8 - 1) { + printk(KERN_WARNING "ServoBlaster: Bad value %d\n", cnt); + return -EINVAL; + } + if (wait_for_servo(servo)) + return -EINTR; + + // Normally, the first GPIO transfer sets the output, while the second + // clears it after a delay. For the special case of a delay of 0, we + // ensure that the first GPIO transfer also clears the output. + if (cnt == 0) { + ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPCLR0*4) & 0x00ffffff) | 0x7e000000; + } else { + ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPSET0*4) & 0x00ffffff) | 0x7e000000; + ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); + ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); + } + written_data[servo] = cnt; // Record data for use by dev_read + local_irq_enable(); + return 0; +} + +// dev_write separates the user input (delimited by \n) into strings for passing +// to process_command_string() static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos) { char* str = 0; @@ -447,38 +490,8 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * // Process the complete user string. { - int servo; - int cnt; - int n; - printk(KERN_WARNING "ServoBlasterc: str(%s)\n", str); - n = sscanf(str, "%d=%d", &servo, &cnt); - if (n != 2) { - printk(KERN_WARNING "ServoBlaster: Failed to parse command (n=%d)\n", n); - return -EINVAL; - } - if (servo < 0 || servo >= NUM_SERVOS) { - printk(KERN_WARNING "ServoBlaster: Bad servo number %d\n", servo); - return -EINVAL; - } - if (cnt < 0 || cnt > cycle_ticks / 8 - 1) { - printk(KERN_WARNING "ServoBlaster: Bad value %d\n", cnt); - return -EINVAL; - } - if (wait_for_servo(servo)) - return -EINTR; - - // Normally, the first GPIO transfer sets the output, while the second - // clears it after a delay. For the special case of a delay of 0, we - // ensure that the first GPIO transfer also clears the output. - if (cnt == 0) { - ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPCLR0*4) & 0x00ffffff) | 0x7e000000; - } else { - ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPSET0*4) & 0x00ffffff) | 0x7e000000; - ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); - ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); - } - written_data[servo] = cnt; // Record data for use by dev_read - local_irq_enable(); + ssize_t error = process_command_string(str); + if (error < 0) count=error; } return count; diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index 2c070d8c9e2957cb7330b2af63ae75ea4401fffb..ee05a757811dae2067a0ed112178fb107a1d8f0c 100644 GIT binary patch delta 2658 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 From 1b8dbeed2112d82b91e94b2eb5391221672118a7 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Wed, 21 Nov 2012 01:07:17 +0000 Subject: [PATCH 18/21] Increase space available for cmd_str ready for taking multiple commands in one go. --- ServoBlaster/servoblaster.c | 7 +++---- ServoBlaster/servoblaster.ko | Bin 10751 -> 10751 bytes 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 0604e58..b935cc0 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -325,11 +325,10 @@ struct process_data int ret_idx; char ret_data[NUM_SERVOS * 10]; - // Stores one user command (single line) for a given user process. - // e.g. "3=180" - // Line length is expected to be <32 + // Stores up to NUM_SERVOS user commands (of up to 10 chars) per user process. + // e.g. "1=60\n2=45\n3=180\n" int cmd_idx; - char cmd_str[32]; + char cmd_str[NUM_SERVOS * 10]; }; // kmalloc the temporary data required for each user: diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index ee05a757811dae2067a0ed112178fb107a1d8f0c..273e94b4634eef33c3d7d27c578e80b1950ede23 100644 GIT binary patch delta 258 zcmew#{6BcZ3?@kxhRIJa2rPK~@BjbT3=9E}GZpwx(6TID;#?4Ke?0BozZ{uMb0=TaRX-~OLG@jQzJt+ zBR6A13rAxhbTr-U#>2)fa{5eW>i)gcHq5vYu$@aHj_-WfRin)b;w$+xEEwYBbMsT; zOEQzQxOW;Y%-ZjnUi_}u)I z_>#=z?D*p3#GKTU%7Ro=Lkp;Qa%FN(Dp@r@V%z`# From 0439809e27c6c4d99ec5a32f7590cc9ddc493d43 Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Wed, 21 Nov 2012 01:48:14 +0000 Subject: [PATCH 19/21] Use max_idx rather than hardcoded data. --- ServoBlaster/servoblaster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index b935cc0..30dbb1c 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -474,7 +474,7 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * end_of_line = strchr(str, '\n'); if (NULL == end_of_line) { - if (31 == *idx) { + if (max_idx == *idx) { // Full buf without '\n' printk(KERN_WARNING "ServoBlaster: Failed to parse command (%s)\n", str); return -EINVAL; From e712bd86ba60751ca95277be2782f759214be51a Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Wed, 21 Nov 2012 03:15:12 +0000 Subject: [PATCH 20/21] All works as intended now. Commands can be written partially, and a single write to the device file may contain multiple commands. To achieve both of these the driver now only parses the commands on dev_close(). --- ServoBlaster/servoblaster.c | 64 ++++++++++++++--------------------- ServoBlaster/servoblaster.ko | Bin 10751 -> 10451 bytes 2 files changed, 25 insertions(+), 39 deletions(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 30dbb1c..6838839 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -51,7 +51,6 @@ #include #include #include -//#include "servoblaster.h" #define GPIO_LEN 0xb4 #define DMA_LEN 0x24 @@ -410,7 +409,6 @@ ssize_t process_command_string(const char str[]) int servo; int cnt; int n; - printk(KERN_WARNING "ServoBlasterc: str(%s)\n", str); n = sscanf(str, "%d=%d", &servo, &cnt); if (n != 2) { printk(KERN_WARNING "ServoBlaster: Failed to parse command (n=%d)\n", n); @@ -442,63 +440,51 @@ ssize_t process_command_string(const char str[]) return 0; } -// dev_write separates the user input (delimited by \n) into strings for passing -// to process_command_string() +// Read user data into buffer until full. static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos) { - char* str = 0; struct process_data* const pdata = filp->private_data; if (0 == pdata) return 0; - // Read user data into str { - char* end_of_line=0; static const int max_idx = sizeof(pdata->cmd_str) - 1; int* const idx = &(pdata->cmd_idx); - str = pdata->cmd_str; - - printk(KERN_WARNING "ServoBlasterA: idx(%i),count(%u),max_idx (%i)\n", - *idx,count, max_idx - ); if ((*idx+count) > max_idx) count = max_idx-*idx; - if (copy_from_user(str+*idx, buf, count)) { + if (copy_from_user(pdata->cmd_str + *idx, buf, count)) { return -EFAULT; } *idx+=count; - str[*idx] = '\0'; - printk(KERN_WARNING "ServoBlasterB: idx(%i),count(%u),max_idx (%i) str(%s)EOS\n", - *idx, count, max_idx, str - ); - - end_of_line = strchr(str, '\n'); - if (NULL == end_of_line) - { - if (max_idx == *idx) { - // Full buf without '\n' - printk(KERN_WARNING "ServoBlaster: Failed to parse command (%s)\n", str); - return -EINVAL; - } - return count; // Incomplete line. - } - - // End of command, so terminate string at '\n' and reset idx. - *end_of_line = '\0'; - *idx=0; - } - - // Process the complete user string. - { - ssize_t error = process_command_string(str); - if (error < 0) count=error; } return count; } +// dev_close separates the user input (delimited by \n) into strings for passing +// to process_command_string() then frees up all process data static int dev_close(struct inode *inod,struct file *fil) { - if (0 != fil->private_data) kfree(fil->private_data); + struct process_data* const pdata = fil->private_data; + if (0 != pdata) + { + static const int max_idx = sizeof(pdata->cmd_str) - 1; + char* cmd_str = pdata->cmd_str; + char* command; + cmd_str[max_idx] = 0; // Ensure command string is null terminated. + + // Execute all commands. + command = strsep(&cmd_str, "\n"); + while( NULL != command ) { + if (*command != 0) { + printk(KERN_DEBUG "ServoBlaster: Command %s\n", command); + (void)process_command_string(command); + } + command = strsep(&cmd_str, "\n"); + } + + // Free process data. + kfree(pdata); + } return 0; } diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index 273e94b4634eef33c3d7d27c578e80b1950ede23..4569ae75dfc40ec2e9148206700bcf02d6e56477 100644 GIT binary patch delta 1937 zcmZXUe@s(X6vxkdwB#cTT@x1hQt4#n*8!V-^RKc!ywK;ENCCW&)I(UZ1+OYj%O|Nq2rtN5 zDBb~`$-uT)a=Ugt*+81E)wi@Z*_!HG8|!w|X)Q0eyi#Y2wia|rI9nK! z^6^@sv2e%m;9&2N$5QR16UD@evluek^9Mft<*3g;>hq3Z@9M^=t|*v;H;Q8zDz;;2 zr9FDXctSQl+;@ETyKS32cy&>}(iUF2zWbvuqps4ElDwFQznd!c{xtw?xY}H$S1EV_ zZZlU&wb*N}(a)|0aN#)V5u7pCNE7&zxyDdi01%VVP*y1~7UG67tE`seZi2D`-zS_f z;#op_Iet(0+lYS>j+A5B8mnwC!4`t21P^8KF=4s{zsVp$xK)Drs#QK&j&+3QYV1<2 z0V5SxeH%by_GAu4bpV{BVyj+&S;0A?O!?hp8UPmAz7OCrlin+!Ls9nwn255Q#!T{S zX8Y>^9%es4h}jKrhS>!HxXc53@iwy);DMk{m(eD{S|%-YpAK0)KnqcDrcJP2&?V>> zyu_sVF{TS(PUzdq3;@J=aEKNb4v&evQ=sd`JJ2!d(ksjk+NrSDGASud&?)SD1-k{q zM756+U{bod$fU${bidb9<_eJ$GYW1Zs&7#xC^_EYCc$RG zHX?7Jok`unr1!gp-9>C<2ahmJ6V+aT%gjA=)=WMc<}Rufk^S%H;m_q&t2|T-D$@qK z0Yyv+ODeXT4`!^qAX~XYM&>~rswkCAc&wsAs*ZkEaaszTVmnCCMC6bB6m{10aRA@9 zOp})5@W-FkEi_==PR#oAz00(WKmR1Mn&a`QW;N&K$_2Vi%Pq4YS2wHKf&VI5%>lTY zS$b|STwGE8tZd1_7pqUd#2-kualDOBY1>n} z<0-u#&DJs9d!zk+oU)p9?tx(+Ua{^BXbsTQGdS$&@%Ovm>G8RH2fY5nBi=1qy|B9v zy9d0>v%W3b^Zz$yyfrZ~(C_vR`MeEHHeu*}*WWih+R*fZ&>pYPJ=#Cw?;jp&XljJ$ T@tQ}HLHs+9tlx$6>o@)jP)NlL delta 2318 zcmai#ZETZO6oAkBZY{NLqcC7?>9)F$QgC29HW;u#H-Rh>TyYcXoNH%WY;mkjS8(`) zRxG3@BQh@`gv_j(8Bht7lpryn#g9ZIkr5@~hnjX>$wW+$kcg33&v|>Bkom)Rxqa^W zxaXdG@40tBY|C{W(Tj2QXw3zU!m|8V4~%93tQi1M{*%l71`x|A61#tQG*8 zuoXTX==U439Y>uXTPwD^xGKRB3#C1lBUveP=+21NSQ;}H(5@|+JUn$be0io@bu`;) zie>KeNxDr(v!$3ok^W$+6Q0Y2mS4$i(0`HXv^o#i;LRz8{++B$bu1;SuA4v~TM6g` z5J{j0k5RAKBQ)xnftilo3Fieu6%*yn!G)*>wlY!%~w2gAyLZvE} z$?v;0GoJ$alUdSt`y-MMosA4)?_I~$%P~2MQ}D-xWmCDFvJ`jgTeQpg?vea;2o^RDD_+66c{1u1OtCG@$7TXF|mg9xBFC%h4l+at8S`94T}lH>7sSV0~9Ca{%Y zOJa+kDGJ+gY&?D{JV87w4^PVh%H#2m!eet#@v#^#eoSJ*r*sGvrl%X%tlqe(xzW72 zaq~)ZOWR8PYimy2db~%_wl=NratHSM+6VfFg6@EGt$rvNFxC$(RkHP^heET=ZEN*j z*RZkPyR^aS+cOw6*6&%`u)BZQj#@pb@nB%qnD+l0Q;C-mvH0w7VQ$mRwcVvQ6ux~u#TBVT`TkB)N0nIt`(xptzIHaVRd=f zC|V}bqDMa?%)*x%G0H~8Zdr|4AV1rr%;TU3~f_;WA6X^0JyP_>; z57FgX1uI)@5HD7^Ntf z?6|V8h%e!F#mg?qoIi4=khG9#&KV*u=nfI%JwW!6!$a->Xe7A>NdZrBo+s`ExJulH z0g10*;b48!(bN&q--M*`O`I)CcA>IXJ6(*se%{pwjyRkff_yk2!e2uU6wz#8;OVx#{qBFdH6r^?NLf)tsazJlD2 z9g?>o3;tBW`7iHJPh>%+cvK$+nKH$v6W1<%`3dQq3Nks+lUk4|0G&rcCObW~1^F2+ zw>+`{lQMBne@2v191r`TcAYpaXH&H+#0injuRGCJhc~0}Q9Sc3xnq{RW0ve@ztm(=n3-Gfr+wSYIs-mc#&np@Z}^^10zSA*TY+vl=7_c;gL_Mq4K z>QJ+}`M=8GKEJ!!+{6t7UZ;C-2o;T7(Z46?@dcXAW-hzjL(YKLAN2YLo6V*~kKs>& O*^E{>f2vO!8~z1J)JNt3 From e59ad99d57f036a898c3bf0ebada753094349f2b Mon Sep 17 00:00:00 2001 From: Robin Mallinson Date: Wed, 21 Nov 2012 22:46:23 +0000 Subject: [PATCH 21/21] Change dev_read() to output data suitable for direct write back through the dev file. --- ServoBlaster/servoblaster.c | 2 +- ServoBlaster/servoblaster.ko | Bin 10451 -> 10451 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index 6838839..bfc9223 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -365,7 +365,7 @@ static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) for (servo=0, *idx=0; servo < NUM_SERVOS; ++servo) { *idx += snprintf(returnedData+*idx, sizeof(pdata->ret_data)-*idx, - "%i %i\n", + "%i=%i\n", servo, written_data[servo] ); diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index 4569ae75dfc40ec2e9148206700bcf02d6e56477..b3d47d8380642ba35a2a63f5516f539e1d416394 100644 GIT binary patch delta 79 zcmV-V0I>hlQPWYd&kGkcLNhQ$LpV4vH#9UuK|w<`MKv}!H8Ydu3q%1uvnvdq0RcC& l$_<7H6qCj95U}Pd*llM??M6PD`pH=iJd=hNBD01TO%gT=9ESh^ delta 81 zcmV-X0IvVjQPWYd&kGkbGBq+YLPj|_IWtB!GD9*jLPSDEGB}gw3q%1Rvnvdq0h6T- n5VP40cL)^pTZg>JJuPIDz32kFNTBh