styx.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. /*
  2. * styx.c
  3. *
  4. * A Styx fileserver for a Lego RCX
  5. *
  6. * Nigel Roles
  7. * Vita Nuova
  8. *
  9. * This is a heavily modified version of test5.c
  10. *
  11. * I couldn't have done this without Kekoa...
  12. *
  13. *
  14. * The contents of this file are subject to the Mozilla Public License
  15. * Version 1.0 (the "License"); you may not use this file except in
  16. * compliance with the License. You may obtain a copy of the License at
  17. * http://www.mozilla.org/MPL/
  18. *
  19. * Software distributed under the License is distributed on an "AS IS"
  20. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  21. * License for the specific language governing rights and limitations
  22. * under the License.
  23. *
  24. * The Original Code is Librcx sample program code, released February 9,
  25. * 1999.
  26. *
  27. * The Initial Developer of the Original Code is Kekoa Proudfoot.
  28. * Portions created by Kekoa Proudfoot are Copyright (C) 1999
  29. * Kekoa Proudfoot. All Rights Reserved.
  30. *
  31. * Contributor(s): Kekoa Proudfoot <kekoa@graphics.stanford.edu>
  32. */
  33. //#include "stdlib.h"
  34. #include "rom.h"
  35. #include "lib9.h"
  36. #include "styx.h"
  37. #include "llp.h"
  38. #define ASSERT(cond) if (!(cond)) fatal(__LINE__)
  39. #define FATAL fatal(__LINE__)
  40. #define PROGRESS progress(__LINE__)
  41. #if 0
  42. #define ABP
  43. #endif
  44. uchar *send_fid_reply_payload(void);
  45. void send_fid_reply(uchar type, ushort tag, ushort fid, uchar *msg, short len);
  46. void send_error_reply(unsigned short tag, char *msg);
  47. static unsigned short msgcount;
  48. static unsigned char compressed_incoming[150];
  49. static unsigned char incoming[1024];
  50. static unsigned char compressed_reply[150];
  51. short compressed_reply_len;
  52. static unsigned char reply[1024];
  53. unsigned short reply_len;
  54. unsigned short transmitted_reply_len;
  55. unsigned char alternating_bit;
  56. static uchar dir[116];
  57. uchar prepared;
  58. uchar reader_count;
  59. uchar dispatch[6];
  60. /* ROM pseudofunctions */
  61. static inline void
  62. set_data_pointer (void *ptr)
  63. {
  64. play_sound_or_set_data_pointer(0x1771, (short)ptr, 0);
  65. }
  66. static inline char
  67. check_valid (void)
  68. {
  69. char valid;
  70. check_for_data(&valid, NULL);
  71. return valid;
  72. }
  73. static inline int
  74. receive_message (void *ptr, int len)
  75. {
  76. char bytes = 0;
  77. receive_data(ptr, len, &bytes);
  78. /* Bytes includes checksum, since we don't want that, return bytes-1 */
  79. return bytes - 1;
  80. }
  81. static inline void
  82. send_message (void *ptr, int len)
  83. {
  84. if (len)
  85. while (send_data(0x1776, 0, ptr, len));
  86. }
  87. int
  88. poll_power(void)
  89. {
  90. static short debounce = 0;
  91. static short state = -1;
  92. short status;
  93. get_power_status(0x4000, &status);
  94. if (state != status)
  95. debounce = 0;
  96. else if (debounce < 10)
  97. debounce++;
  98. state = status;
  99. return debounce >= 10 ? state : -1;
  100. }
  101. static void
  102. progress(short line)
  103. {
  104. set_lcd_number(LCD_UNSIGNED, line, LCD_DECIMAL_0);
  105. refresh_display();
  106. }
  107. static void
  108. fatal(short line)
  109. {
  110. set_lcd_segment(LCD_STANDING);
  111. progress(line);
  112. while (poll_power() != 0)
  113. ;
  114. }
  115. typedef struct Reader {
  116. ushort tag;
  117. ushort fid;
  118. ushort offset;
  119. ushort count;
  120. struct Reader *next;
  121. } Reader;
  122. typedef struct DirectoryEntry {
  123. char *name;
  124. uchar qid;
  125. const struct DirectoryEntry *sub;
  126. short (*read)(const struct DirectoryEntry *dp, ushort tag, ushort fid, ushort offset, ushort count);
  127. short (*write)(const struct DirectoryEntry *dp, ushort offset, ushort count, uchar *buf);
  128. } DirectoryEntry;
  129. #define QID_ROOT 0
  130. #define QID_MOTOR 1
  131. #define QID_MOTOR_0 2
  132. #define QID_MOTOR_1 3
  133. #define QID_MOTOR_2 4
  134. #define QID_MOTOR_012 5
  135. #define QID_SENSOR 6
  136. #define QID_SENSOR_0 7
  137. #define QID_SENSOR_1 8
  138. #define QID_SENSOR_2 9
  139. typedef struct Sensor {
  140. sensor_t sensor;
  141. uchar active;
  142. uchar greater;
  143. ushort thresh;
  144. Reader *reader;
  145. } Sensor;
  146. Sensor sensor[3];
  147. short
  148. atoin(char *s, short lim)
  149. {
  150. short total = 0;
  151. while (*s && lim) {
  152. char c = *s++;
  153. if (c >= '0' && c <= '9')
  154. total = total * 10 + c - '0';
  155. else
  156. break;
  157. lim--;
  158. }
  159. return total;
  160. }
  161. short
  162. itoa(char *buf, short value)
  163. {
  164. char *bp = buf;
  165. short divisor;
  166. if (value < 0) {
  167. *bp++ = '-';
  168. value = -value;
  169. }
  170. if (value == 0)
  171. *bp++ = '0';
  172. else {
  173. divisor = 10000;
  174. while (divisor > value)
  175. divisor /= 10;
  176. while (divisor) {
  177. *bp++ = '0' + value / divisor;
  178. value %= divisor;
  179. divisor /= 10;
  180. }
  181. }
  182. return bp - buf;
  183. }
  184. Reader *
  185. readercreate(ushort tag, ushort fid, ushort offset, ushort count)
  186. {
  187. Reader *rp = malloc(sizeof(Reader));
  188. rp->tag = tag;
  189. rp->fid = fid;
  190. rp->offset = offset;
  191. rp->count = count;
  192. rp->next = 0;
  193. reader_count++;
  194. return rp;
  195. }
  196. void
  197. readerfree(Reader *rp)
  198. {
  199. free(rp);
  200. reader_count--;
  201. }
  202. int
  203. senderrorreset(Reader *rp, void *magic)
  204. {
  205. send_error_reply(rp->tag, "reset");
  206. return 1;
  207. }
  208. void
  209. readerlistfindanddestroy(Reader **rpp, int (*action)(Reader *rp, void *magic), void *magic)
  210. {
  211. while (*rpp) {
  212. Reader *rp = *rpp;
  213. if ((*action)(rp, magic)) {
  214. *rpp = rp->next;
  215. readerfree(rp);
  216. }
  217. else
  218. rpp = &(rp->next);
  219. }
  220. }
  221. void
  222. allreaderlistfindanddestroy(int (*action)(Reader *rp, void *magic), void *magic)
  223. {
  224. short i;
  225. for (i = 0; i < 3; i++)
  226. readerlistfindanddestroy(&sensor[i].reader, action, magic);
  227. }
  228. short
  229. sensorwrite(const DirectoryEntry *dp, ushort offset, ushort count, uchar *data)
  230. {
  231. short i;
  232. Sensor *sp;
  233. uchar greater;
  234. short type, mode;
  235. ushort k;
  236. if (offset != 0)
  237. return -1;
  238. i = dp->qid - QID_SENSOR_0;
  239. sp = &sensor[i];
  240. k = count;
  241. if (k == 0)
  242. return -1;
  243. switch (data[0]) {
  244. case 'b':
  245. type = SENSOR_TYPE_TOUCH;
  246. mode = SENSOR_MODE_PULSE;
  247. break;
  248. case 'l':
  249. type = SENSOR_TYPE_TOUCH;
  250. mode = SENSOR_MODE_RAW;
  251. break;
  252. default:
  253. return -1;
  254. }
  255. data++; k--;
  256. if (k == 0)
  257. return -1;
  258. if (*data == '>') {
  259. greater = 1;
  260. data++;
  261. k--;
  262. }
  263. else if (*data == '<') {
  264. greater = 0;
  265. data++;
  266. k--;
  267. }
  268. else
  269. greater = 1;
  270. if (k == 0)
  271. return -1;
  272. readerlistfindanddestroy(&sp->reader, senderrorreset, 0);
  273. set_sensor_passive(SENSOR_0 + i);
  274. sp->sensor.type = type;
  275. sp->sensor.mode = mode;
  276. sp->thresh = atoin(data, k);
  277. sp->sensor.raw = 0;
  278. sp->sensor.value = 0;
  279. sp->sensor.boolean = 0;
  280. sp->active = 1;
  281. sp->greater = greater;
  282. set_sensor_active(SENSOR_0 + i);
  283. return count;
  284. }
  285. void
  286. send_read_reply(ushort tag, ushort fid, ushort offset, ushort len, uchar *answer, short answerlen)
  287. {
  288. uchar *out = send_fid_reply_payload();
  289. ushort actual;
  290. if (offset < answerlen) {
  291. actual = answerlen - offset;
  292. if (actual > len)
  293. actual = len;
  294. memcpy(out + 3, answer + offset, actual);
  295. }
  296. else
  297. actual = 0;
  298. out[0] = actual;
  299. out[1] = actual >> 8;
  300. out[2] = 0;
  301. send_fid_reply(Rread, tag, fid, 0, actual + 3);
  302. }
  303. void
  304. send_sensor_read_reply(ushort tag, ushort fid, ushort offset, ushort count, short value)
  305. {
  306. short answerlen;
  307. char answer[8];
  308. /* reply is countlow counthigh pad data[count] */
  309. answerlen = itoa(answer, value);
  310. send_read_reply(tag, fid, offset, count, answer, answerlen);
  311. }
  312. int
  313. sensortriggered(Sensor *sp)
  314. {
  315. if (sp->greater)
  316. return sp->sensor.value >= sp->thresh;
  317. else
  318. return sp->sensor.value < sp->thresh;
  319. }
  320. short
  321. sensorread(const struct DirectoryEntry *dp, ushort tag, ushort fid, ushort offset, ushort count)
  322. {
  323. short i;
  324. Sensor *sp;
  325. i = dp->qid - QID_SENSOR_0;
  326. sp = sensor + i;
  327. if (!sp->active)
  328. return -1;
  329. if (sensortriggered(sp))
  330. send_sensor_read_reply(tag, fid, offset, count, sp->sensor.value);
  331. else {
  332. /* add to queue */
  333. Reader *rp = readercreate(tag, fid, offset, count);
  334. rp->next = sp->reader;
  335. sp->reader = rp;
  336. }
  337. return 0;
  338. }
  339. void
  340. sensorpoll(void)
  341. {
  342. short i;
  343. Sensor *sp;
  344. if ((dispatch[0] & 0x80) == 0) {
  345. return;
  346. }
  347. dispatch[0] &= 0x7f;
  348. /* do the following every 3 ms with a following wind */
  349. for (i = 0; i < 3; i++) {
  350. sp = sensor + i;
  351. if (sp->active) {
  352. /*
  353. * read sensor 4 times to reduce debounce on each
  354. * edge to effectively 25 counts, or 75ms
  355. * allowing about 8 pulses a second
  356. */
  357. read_sensor(SENSOR_0 + i, &sp->sensor);
  358. read_sensor(SENSOR_0 + i, &sp->sensor);
  359. read_sensor(SENSOR_0 + i, &sp->sensor);
  360. read_sensor(SENSOR_0 + i, &sp->sensor);
  361. if (sensortriggered(sp)) {
  362. /* complete any outstanding reads */
  363. while (sp->reader) {
  364. Reader *rp = sp->reader;
  365. sp->reader = rp->next;
  366. send_sensor_read_reply(rp->tag, rp->fid, rp->offset, rp->count, sp->sensor.value);
  367. readerfree(rp);
  368. }
  369. }
  370. }
  371. }
  372. }
  373. short
  374. motorparse(uchar *flag, short *mode, short *power, uchar *data)
  375. {
  376. switch (data[0]) {
  377. case 'f': *mode = MOTOR_FWD; break;
  378. case 'r': *mode = MOTOR_REV; break;
  379. case 's': *mode = MOTOR_STOP; break;
  380. case 'F': *mode = MOTOR_FLOAT; break;
  381. case '-': return 1;
  382. default:
  383. return 0;
  384. }
  385. if (data[1] >= '0' && data[1] <= '7')
  386. *power = data[1] - '0';
  387. else
  388. return 0;
  389. *flag = 1;
  390. return 1;
  391. }
  392. short
  393. motorwrite(const DirectoryEntry *dp, ushort offset, ushort count, uchar *data)
  394. {
  395. short mode[3], power[3];
  396. uchar flag[3];
  397. short i;
  398. if (offset != 0)
  399. return -1;
  400. flag[0] = flag[1] = flag[2] = 0;
  401. if (dp->qid == QID_MOTOR_012) {
  402. if (count != 6)
  403. return -1;
  404. if (!motorparse(flag, mode, power, data)
  405. || !motorparse(flag + 1, mode + 1, power + 1, data + 2)
  406. || !motorparse(flag + 2, mode + 2, power + 2, data + 4))
  407. return -1;
  408. }
  409. else {
  410. if (count != 2)
  411. return -1;
  412. i = dp->qid - QID_MOTOR_0;
  413. if (!motorparse(flag + i, mode + i, power + i, data))
  414. return -1;
  415. }
  416. for (i = 0; i < 3; i++)
  417. if (flag[i])
  418. control_motor(MOTOR_0 + i, mode[i], power[i]);
  419. return count;
  420. }
  421. const uchar qid_root[8] = { QID_ROOT, 0, 0, 0x80 };
  422. const DirectoryEntry dir_root[], dir_slash[];
  423. const DirectoryEntry dir_motor[] = {
  424. { "..", QID_ROOT, dir_root },
  425. { "0", QID_MOTOR_0, 0, 0, motorwrite },
  426. { "1", QID_MOTOR_1, 0, 0, motorwrite },
  427. { "2", QID_MOTOR_2, 0, 0, motorwrite },
  428. { "012", QID_MOTOR_012, 0, 0, motorwrite },
  429. { 0 }
  430. };
  431. const DirectoryEntry dir_sensor[] = {
  432. { "..", QID_ROOT, dir_root },
  433. { "0", QID_SENSOR_0, 0, sensorread, sensorwrite },
  434. { "1", QID_SENSOR_1, 0, sensorread, sensorwrite },
  435. { "2", QID_SENSOR_2, 0, sensorread, sensorwrite },
  436. { 0 }
  437. };
  438. const DirectoryEntry dir_root[] = {
  439. { "..", QID_ROOT, dir_slash },
  440. { "motor", QID_MOTOR, dir_motor },
  441. { "sensor", QID_SENSOR, dir_sensor },
  442. { 0 }
  443. };
  444. const DirectoryEntry dir_slash[] = {
  445. { "/", QID_ROOT, dir_root },
  446. { 0 }
  447. };
  448. const DirectoryEntry *qid_map[] = {
  449. /* QID_ROOT */ &dir_slash[0],
  450. /* QID_MOTOR */ &dir_root[1],
  451. /* QID_MOTOR_0 */ &dir_motor[1],
  452. /* QID_MOTOR_1 */ &dir_motor[2],
  453. /* QID_MOTOR_2 */ &dir_motor[3],
  454. /* QID_MOTOR_012 */ &dir_motor[4],
  455. /* QID_SENSOR */ &dir_root[2],
  456. /* QID_SENSOR_0 */ &dir_sensor[1],
  457. /* QID_SENSOR_1 */ &dir_sensor[2],
  458. /* QID_SENSOR_2 */ &dir_sensor[3],
  459. };
  460. #define QID_MAP_MAX (sizeof(qid_map) / sizeof(qid_map[0]))
  461. typedef struct Fid {
  462. struct Fid *next;
  463. ushort fid;
  464. uchar open;
  465. uchar qid[8];
  466. } Fid;
  467. Fid *fids;
  468. Fid *
  469. fidfind(ushort fid)
  470. {
  471. Fid *fp;
  472. for (fp = fids; fp && fp->fid != fid; fp = fp->next)
  473. ;
  474. return fp;
  475. }
  476. Fid *
  477. fidcreate(ushort fid, const uchar qid[8])
  478. {
  479. Fid *fp;
  480. fp = malloc(sizeof(Fid));
  481. ASSERT(fp);
  482. fp->open = 0;
  483. fp->fid = fid;
  484. fp->next = fids;
  485. memcpy(fp->qid, qid, 8);
  486. fids = fp;
  487. return fp;
  488. }
  489. int
  490. matchfp(Reader *rp, void *magic)
  491. {
  492. if (rp->fid == ((Fid *)magic)->fid) {
  493. return 1;
  494. }
  495. return 0;
  496. }
  497. void
  498. fiddelete(Fid *fp)
  499. {
  500. Fid **fpp;
  501. /* clobber any outstanding reads on this fid */
  502. allreaderlistfindanddestroy(matchfp, fp);
  503. /* now clobber the fid */
  504. for (fpp = &fids; *fpp; fpp = &(*fpp)->next)
  505. if (*fpp == fp) {
  506. *fpp = fp->next;
  507. free(fp);
  508. return;
  509. }
  510. FATAL;
  511. }
  512. const DirectoryEntry *
  513. nthentry(const DirectoryEntry *dp, ushort n)
  514. {
  515. const DirectoryEntry *sdp;
  516. ASSERT(dp->sub);
  517. for (sdp = dp->sub; sdp->name; sdp++)
  518. if (strcmp(sdp->name, "..") != 0) {
  519. if (n == 0)
  520. return sdp;
  521. n--;
  522. }
  523. return 0;
  524. }
  525. int
  526. fidwalk(Fid *fp, char name[28])
  527. {
  528. const DirectoryEntry *sdp;
  529. const DirectoryEntry *dp;
  530. if (fp->open)
  531. return -1;
  532. ASSERT(fp->qid[0] < QID_MAP_MAX);
  533. dp = qid_map[fp->qid[0]];
  534. if (dp->sub == 0)
  535. return -1;
  536. for (sdp = dp->sub; sdp->name; sdp++)
  537. if (strcmp(sdp->name, name) == 0) {
  538. fp->qid[0] = sdp->qid;
  539. fp->qid[3] = sdp->sub ? 0x80 : 0;
  540. return 1;
  541. }
  542. return 0;
  543. }
  544. void
  545. mkdirent(const DirectoryEntry *dp, uchar *dir)
  546. {
  547. memset(dir, 0, DIRLEN);
  548. strcpy(dir, dp->name);
  549. strcpy(dir + 28, "lego");
  550. strcpy(dir + 56, "lego");
  551. dir[84] = dp->qid;
  552. dir[92] = dp->sub ? 0555 : 0666;
  553. dir[93] = dp->sub ? (0555 >> 8) : (0666 >> 8);
  554. dir[95] = dp->sub ? 0x80 : 0;
  555. }
  556. int
  557. fidstat(Fid *fp, uchar *dir)
  558. {
  559. const DirectoryEntry *dp;
  560. if (fp->open)
  561. return -1;
  562. ASSERT(fp->qid[0] < QID_MAP_MAX);
  563. dp = qid_map[fp->qid[0]];
  564. mkdirent(dp, dir);
  565. return 1;
  566. }
  567. int
  568. fidopen(Fid *fp, uchar mode)
  569. {
  570. if (fp->open
  571. || (mode & ORCLOSE)
  572. /*|| (mode & OTRUNC) */)
  573. return 0;
  574. if (fp->qid[3] && (mode == OWRITE || mode == ORDWR))
  575. /* can't write directories */
  576. return 0;
  577. fp->open = 1;
  578. return 1;
  579. }
  580. short
  581. fidread(Fid *fp, ushort tag, ushort offset, ushort count)
  582. {
  583. short k;
  584. uchar *p;
  585. const DirectoryEntry *dp;
  586. uchar *buf;
  587. ASSERT(fp->qid[0] < QID_MAP_MAX);
  588. dp = qid_map[fp->qid[0]];
  589. if (fp->qid[3] & 0x80) {
  590. if (!fp->open)
  591. return -1;
  592. if (count % DIRLEN != 0 || offset % DIRLEN != 0)
  593. return -1;
  594. count /= DIRLEN;
  595. offset /= DIRLEN;
  596. buf = send_fid_reply_payload();
  597. p = buf + 3;
  598. for (k = 0; k < count; k++) {
  599. const DirectoryEntry *sdp = nthentry(dp, offset + k);
  600. if (sdp == 0)
  601. break;
  602. mkdirent(sdp, p);
  603. p += DIRLEN;
  604. }
  605. /* a read beyond just returns 0
  606. if (k == 0 && count)
  607. return -1;
  608. */
  609. k *= DIRLEN;
  610. buf[0] = k;
  611. buf[1] = k >> 8;
  612. buf[2] = 0;
  613. send_fid_reply(Rread, tag, fp->fid, 0, k + 3);
  614. return 0;
  615. }
  616. /* right, that's that out of the way */
  617. if (!dp->read)
  618. return -1;
  619. return (*dp->read)(dp, tag, fp->fid, offset, count);
  620. }
  621. short
  622. fidwrite(Fid *fp, ushort offset, ushort count, uchar *buf)
  623. {
  624. const DirectoryEntry *dp;
  625. if (fp->qid[3] & 0x80)
  626. return -1; /* can't write directories */
  627. if (!fp->open)
  628. return -1;
  629. ASSERT(fp->qid[0] < QID_MAP_MAX);
  630. dp = qid_map[fp->qid[0]];
  631. if (!dp->write)
  632. return -1; /* no write method */
  633. return (*dp->write)(dp, offset, count, buf);
  634. }
  635. int
  636. rlencode(unsigned char *out, int limit, unsigned char *in, int len)
  637. {
  638. unsigned char *ip, *op;
  639. int oc, zc;
  640. if (len == 0)
  641. return -1;
  642. ip = in;
  643. op = out;
  644. zc = 0;
  645. oc = 0;
  646. for (;;) {
  647. int last = ip >= in + len;
  648. if (*ip != 0 || last)
  649. {
  650. switch (zc) {
  651. case 1:
  652. if (oc >= len - 1)
  653. return -1;
  654. *op++ = 0;
  655. oc++;
  656. break;
  657. case 2:
  658. if (oc >= len - 2)
  659. return -1;
  660. *op++ = 0;
  661. *op++ = 0;
  662. oc += 2;
  663. break;
  664. case 0:
  665. break;
  666. default:
  667. if (oc >= len - 2)
  668. return -1;
  669. *op++ = 0x88;
  670. *op++ = zc - 2;
  671. oc += 2;
  672. break;
  673. }
  674. zc = 0;
  675. }
  676. if (last)
  677. break;
  678. if (*ip == 0x88) {
  679. if (oc >= len - 2)
  680. return -1;
  681. *op++ = 0x88;
  682. *op++ = 0x00;
  683. oc += 2;
  684. }
  685. else if (*ip == 0x00)
  686. {
  687. zc++;
  688. }
  689. else {
  690. if (oc >= len - 1)
  691. return -1;
  692. *op++ = *ip;
  693. oc++;
  694. }
  695. ip++;
  696. }
  697. return oc;
  698. }
  699. int
  700. rldecode(unsigned char *out, unsigned char *in, int len)
  701. {
  702. int oc, k;
  703. oc = 0;
  704. while (len) {
  705. if (*in != 0x88) {
  706. *out++ = *in++;
  707. oc++;
  708. len--;
  709. continue;
  710. }
  711. in++;
  712. switch (*in) {
  713. case 0:
  714. *out++ = 0x88;
  715. oc++;
  716. break;
  717. default:
  718. k = *in + 2;
  719. oc += k;
  720. while (k-- > 0)
  721. *out++ = 0;
  722. }
  723. in++;
  724. len -= 2;
  725. }
  726. return oc;
  727. }
  728. void
  729. prepare_transmission(void)
  730. {
  731. if (prepared)
  732. return;
  733. compressed_reply_len = rlencode(compressed_reply + 3, sizeof(compressed_reply) - 3, reply, reply_len);
  734. if (compressed_reply_len < 0) {
  735. memcpy(compressed_reply + 3, reply, reply_len);
  736. compressed_reply_len = reply_len;
  737. compressed_reply[2] = 0x0;
  738. }
  739. else
  740. compressed_reply[2] = LLP_COMPRESSION;
  741. if (reader_count)
  742. compressed_reply[2] |= LLP_POLL_PERIODIC;
  743. compressed_reply[2] |= !alternating_bit;
  744. compressed_reply_len++;
  745. compressed_reply[0] = compressed_reply_len;
  746. compressed_reply[1] = compressed_reply_len >> 8;
  747. compressed_reply_len += 2;
  748. prepared = 1;
  749. }
  750. void
  751. transmit(void)
  752. {
  753. prepare_transmission();
  754. transmitted_reply_len = reply_len;
  755. send_message(compressed_reply, compressed_reply_len);
  756. }
  757. void
  758. flush_reply_buffer(void)
  759. {
  760. if (reply_len > transmitted_reply_len)
  761. memcpy(reply, reply + transmitted_reply_len, reply_len - transmitted_reply_len);
  762. reply_len -= transmitted_reply_len;
  763. prepared = 0;
  764. }
  765. void
  766. send_reply(unsigned char type, unsigned short tag, unsigned char *msg, short len)
  767. {
  768. uchar *p = reply + reply_len;
  769. p[0] = type;
  770. p[1] = tag & 0xff;
  771. p[2] = tag >> 8;
  772. if (msg)
  773. memcpy(p + 3, msg, len);
  774. reply_len += len + 3;
  775. prepared = 0;
  776. }
  777. void
  778. send_error_reply(unsigned short tag, char *msg)
  779. {
  780. short len;
  781. uchar *p = reply + reply_len;
  782. p[0] = Rerror;
  783. p[1] = tag & 0xff;
  784. p[2] = tag >> 8;
  785. len = (short)strlen(msg);
  786. if (len > 64)
  787. len = 64;
  788. memcpy(p + 3, msg, len);
  789. reply_len += 67;
  790. prepared = 0;
  791. }
  792. uchar *
  793. send_fid_reply_payload(void)
  794. {
  795. return reply + reply_len + 5;
  796. }
  797. void
  798. send_fid_reply(uchar type, ushort tag, ushort fid, uchar *msg, short len)
  799. {
  800. uchar *p = reply + reply_len;
  801. p[0] = type;
  802. p[1] = tag & 0xff;
  803. p[2] = tag >> 8;
  804. p[3] = fid & 0xff;
  805. p[4] = fid >> 8;
  806. if (msg)
  807. memcpy(p + 5, msg, len);
  808. reply_len += len + 5;
  809. prepared = 0;
  810. }
  811. int
  812. matchtag(Reader *rp, void *oldtag)
  813. {
  814. if (rp->tag == (ushort)oldtag) {
  815. return 1;
  816. }
  817. return 0;
  818. }
  819. void
  820. flushtag(ushort oldtag)
  821. {
  822. /* a little inefficient this - there can be at most one match! */
  823. allreaderlistfindanddestroy(matchtag, (void *)oldtag);
  824. }
  825. void
  826. process_styx_message(unsigned char *msg, short len)
  827. {
  828. unsigned char type;
  829. ushort tag, oldtag, fid, newfid;
  830. ushort offset, count;
  831. short extra;
  832. Fid *fp, *nfp;
  833. short written;
  834. uchar buf[2];
  835. ASSERT(len >= 3);
  836. type = *msg++; len--;
  837. tag = (msg[1] << 8) | msg[0]; len -= 2; msg += 2;
  838. switch (type) {
  839. case Tnop:
  840. send_reply(Rnop, tag, 0, 0);
  841. goto done;
  842. case Tflush:
  843. ASSERT(len == 2);
  844. oldtag = (msg[1] << 8) | msg[0];
  845. flushtag(oldtag);
  846. send_reply(Rflush, tag, 0, 0);
  847. goto done;
  848. }
  849. /* all other messages take a fid as well */
  850. ASSERT(len >= 2);
  851. fid = (msg[1] << 8) | msg[0]; len -= 2; msg += 2;
  852. fp = fidfind(fid);
  853. switch (type) {
  854. case Tattach:
  855. ASSERT(len == 56);
  856. if (fp) {
  857. fid_in_use:
  858. send_error_reply(tag, "fid in use");
  859. }
  860. else {
  861. fp = fidcreate(fid, qid_root);
  862. send_fid_reply(Rattach, tag, fid, fp->qid, 8);
  863. }
  864. break;
  865. case Tclunk:
  866. case Tremove:
  867. ASSERT(len == 0);
  868. if (!fp) {
  869. no_such_fid:
  870. send_error_reply(tag, "no such fid");
  871. }
  872. else {
  873. fiddelete(fp);
  874. if (type == Tremove)
  875. send_error_reply(tag, "can't remove");
  876. else
  877. send_fid_reply(Rclunk, tag, fid, 0, 0);
  878. }
  879. break;
  880. case Tclone:
  881. ASSERT(len == 2);
  882. newfid = (msg[1] << 8) | msg[0];
  883. nfp = fidfind(newfid);
  884. if (!fp)
  885. goto no_such_fid;
  886. if (fp->open) {
  887. send_error_reply(tag, "can't clone");
  888. break;
  889. }
  890. if (nfp)
  891. goto fid_in_use;
  892. nfp = fidcreate(newfid, fp->qid);
  893. send_fid_reply(Rclone, tag, fid, 0, 0);
  894. break;
  895. case Twalk:
  896. ASSERT(len == 28);
  897. if (!fidwalk(fp, msg))
  898. send_error_reply(tag, "no such name");
  899. else
  900. send_fid_reply(Rwalk, tag, fid, fp->qid, 8);
  901. break;
  902. case Tstat:
  903. ASSERT(len == 0);
  904. if (!fidstat(fp, dir))
  905. send_error_reply(tag, "can't stat");
  906. else
  907. send_fid_reply(Rstat, tag, fid, dir, 116);
  908. break;
  909. ASSERT(len == 0);
  910. case Tcreate:
  911. ASSERT(len == 33);
  912. send_error_reply(tag, "can't create");
  913. break;
  914. case Topen:
  915. ASSERT(len == 1);
  916. if (!fidopen(fp, msg[0]))
  917. send_error_reply(tag, "can't open");
  918. else
  919. send_fid_reply(Ropen, tag, fid, fp->qid, 8);
  920. break;
  921. case Tread:
  922. ASSERT(len == 10);
  923. offset = (msg[1] << 8) | msg[0];
  924. count = (msg[9] << 8) | msg[8];
  925. if (fidread(fp, tag, offset, count) < 0)
  926. send_error_reply(tag, "can't read");
  927. break;
  928. case Twrite:
  929. ASSERT(len >= 11);
  930. offset = (msg[1] << 8) | msg[0];
  931. count = (msg[9] << 8) | msg[8];
  932. msg += 11;
  933. len -= 11;
  934. ASSERT(count == len);
  935. written = fidwrite(fp, offset, count, msg);
  936. if (written < 0)
  937. send_error_reply(tag, "can't write");
  938. else {
  939. buf[0] = written;
  940. buf[1] = written >> 8;
  941. send_fid_reply(Rwrite, tag, fid, buf, 2);
  942. }
  943. break;
  944. default:
  945. FATAL;
  946. }
  947. done:
  948. ;
  949. }
  950. void
  951. process_llp_message(unsigned char *msg, short len)
  952. {
  953. short styxlen;
  954. switch (msg[0]) {
  955. case 0x45:
  956. case 0x4d:
  957. if (len != 5)
  958. FATAL;
  959. styxlen = compressed_incoming[0] | (compressed_incoming[1] << 8);
  960. /* transfer the transmitted checksum to the end */
  961. compressed_incoming[styxlen + 2 - 1] = msg[3];
  962. /* check alternating bit */
  963. #ifdef ABP
  964. if ((compressed_incoming[2] & 1) != alternating_bit ||
  965. ((msg[0] & 8) != 0) != alternating_bit) {
  966. transmit();
  967. break;
  968. }
  969. #endif
  970. alternating_bit = !alternating_bit;
  971. flush_reply_buffer();
  972. if (styxlen > 1) {
  973. if (compressed_incoming[2] & LLP_COMPRESSION) {
  974. /* decompress everything but length and link header */
  975. styxlen = rldecode(incoming, compressed_incoming + 3, styxlen - 1);
  976. process_styx_message(incoming, styxlen);
  977. }
  978. else
  979. process_styx_message(compressed_incoming + 3, styxlen - 1);
  980. }
  981. transmit();
  982. break;
  983. default:
  984. FATAL;
  985. }
  986. }
  987. int
  988. main (void)
  989. {
  990. int count = 0;
  991. char buf[16];
  992. char temp[64];
  993. mem_init();
  994. memset(temp,0, sizeof(temp));
  995. /* Initialize */
  996. init_timer(&temp[6], &dispatch[0]);
  997. init_power();
  998. init_sensors();
  999. init_serial(&temp[4], &temp[6], 1, 1);
  1000. set_lcd_number(LCD_UNSIGNED, 0, LCD_DECIMAL_0);
  1001. set_lcd_segment(LCD_WALKING);
  1002. refresh_display();
  1003. set_data_pointer(compressed_incoming);
  1004. alternating_bit = 0;
  1005. compressed_reply_len = 0;
  1006. reply_len = 0;
  1007. prepared = 0;
  1008. while (poll_power() != 0) {
  1009. /* If a message has arrived, send a response with opcode inverted */
  1010. if (check_valid()) {
  1011. int len = receive_message(buf, sizeof(buf));
  1012. msgcount++;
  1013. process_llp_message(buf, len);
  1014. }
  1015. sensorpoll();
  1016. }
  1017. return 0;
  1018. }