PageRenderTime 59ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/src/modules/mindstorm/src/filesystem.cpp

https://bitbucket.org/hagish/love-kinect-mindstorm
C++ | 530 lines | 498 code | 28 blank | 4 comment | 45 complexity | 6d6660bbdc9189949941fbb9f715c145 MD5 | raw file
  1. #include "filesystem.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include <string>
  6. #if WIN32
  7. #include "windows.h"
  8. #endif
  9. #include "error.h"
  10. #include "brick.h"
  11. using namespace std;
  12. using namespace nxt;
  13. #define MAX_WRITE_BYTES 0x3AAA
  14. #define MAX_READ_BYTES 0xffff
  15. #define OPEN_WRITE 0x81
  16. #define OPEN_WRITE_LINEAR 0x89
  17. #define OPEN_WRITE_LINEAR_DATA 0x8B
  18. Filesystem::Filesystem(Connection *connection){
  19. this->connection = connection;
  20. this->file_list_size = 0;
  21. }
  22. Filesystem::~Filesystem(){
  23. free(this->file_list);
  24. }
  25. void Filesystem::download_file(string pc_name, string nxt_name){
  26. FILE *to;
  27. unsigned int i,file_size;
  28. unsigned char *data;
  29. Nxt_file from;
  30. if((to =fopen(pc_name.c_str(),"wb"))==NULL){
  31. throw Nxt_exception("download_file","Filesystem", PC_FILE_ERROR);
  32. }
  33. from = this->open_file(nxt_name, READ);
  34. file_size = from.size;
  35. data =(unsigned char *) malloc(file_size*sizeof(unsigned char));
  36. read_file(from, data, file_size);
  37. i=0;
  38. while(i<file_size){
  39. fputc(data[i], to);
  40. i++;
  41. }
  42. free(data);
  43. fclose(to);
  44. close_file(from);
  45. return;
  46. }
  47. void Filesystem::delete_file(string file_name, bool reply){
  48. unsigned int name_length;
  49. unsigned char command[24];
  50. unsigned char answer[NXT_BUFFER_SIZE];
  51. unsigned int i=0;
  52. name_length = file_name.length();
  53. if(name_length > MAX_NAME_LENGTH){
  54. file_name.erase(MAX_NAME_LENGTH+1);
  55. name_length=MAX_NAME_LENGTH;
  56. }
  57. command[0]=0x16; //command length
  58. command[1]=0x00;
  59. if(reply){
  60. command[2]=0x01;
  61. }
  62. else{
  63. command[2]=0x81;
  64. }
  65. command[3]=0x85;
  66. while(i<name_length){
  67. command[i+4]=file_name[i];
  68. i++;
  69. }
  70. while(i<MAX_NAME_LENGTH){
  71. command[i+4]='\0';
  72. i++;
  73. }
  74. connection->send(&command[0],24);
  75. if(reply){
  76. connection->receive(&answer[0],25);
  77. if(answer[4]){
  78. throw Nxt_exception("delete_file","Filesystem", 0x00FF & answer[4]);
  79. }
  80. }
  81. }
  82. void Filesystem::upload_file(string pc_name, string nxt_name){
  83. FILE *from;
  84. unsigned int i,file_size;
  85. unsigned char *data;
  86. string file_ext;
  87. Nxt_file to;
  88. if((from =fopen(pc_name.c_str(),"rb"))==NULL){
  89. throw Nxt_exception("upload_file","Filesystem", PC_FILE_ERROR);
  90. }
  91. fseek( from, 0L, SEEK_END );
  92. file_size = ftell( from );
  93. fseek( from, 0, SEEK_SET);
  94. file_ext = nxt_name.substr( nxt_name.find_last_of(".")+1);
  95. i=0;
  96. while(i<file_ext.length()){
  97. file_ext[i] = std::tolower(file_ext[i]);
  98. i++;
  99. }
  100. if(file_ext == "ric" || file_ext == "rxe"){
  101. to = open_file(nxt_name, WRITE_LINEAR, file_size);
  102. }
  103. else{
  104. to = open_file(nxt_name, WRITE, file_size);
  105. }
  106. data = (unsigned char *) malloc(file_size * sizeof(unsigned char));
  107. i=0;
  108. while(i<file_size){
  109. data[i] = fgetc(from);
  110. i++;
  111. }
  112. write_file(to, data, file_size);
  113. free(data);
  114. fclose(from);
  115. close_file(to);
  116. return;
  117. }
  118. int Filesystem::get_first(string wild_card, Nxt_file *file){
  119. Nxt_file temp;
  120. unsigned char answer[NXT_BUFFER_SIZE];
  121. unsigned char command[24];
  122. unsigned int i=0;
  123. unsigned int name_length = wild_card.length();
  124. if(name_length > MAX_NAME_LENGTH){
  125. wild_card.erase(MAX_NAME_LENGTH+1);
  126. name_length=MAX_NAME_LENGTH;
  127. }
  128. command[0]=0x16; //command length
  129. command[1]=0x00;
  130. command[2]=0x01;
  131. command[3]=0x86;
  132. while(i<name_length){
  133. command[i+4]=wild_card[i];
  134. i++;
  135. }
  136. while(i<MAX_NAME_LENGTH){
  137. command[i+4]='\0';
  138. i++;
  139. }
  140. connection->send(&command[0],24);
  141. connection->receive(&answer[0],30);
  142. if(answer[4]){
  143. if((unsigned int) answer[4]!= FILE_NOT_FOUND){
  144. throw Nxt_exception("get_first","Filesystem", 0x00FF & answer[4]);
  145. }
  146. else{
  147. return 0;
  148. }
  149. }
  150. file->handle = answer[5];
  151. i=0;
  152. while(i<MAX_NAME_LENGTH){
  153. file->name[i] = answer[6+i];
  154. //printf("command[%d]: 0x%x\n", i+6, answer[i+6]);
  155. i++;
  156. }
  157. //cout << file->name << endl;
  158. file->size = (0xFF & answer[26]) | ((0xFF & answer[27]) << 8)| ((0xFF & answer[28]) << 16)| ((0xFF & answer[29]) << 24);
  159. temp.handle = file->handle;
  160. try{
  161. close_file(temp);
  162. }
  163. catch (Nxt_exception& e){
  164. if( e.error_code() != HANDLE_ALREADY_CLOSED){
  165. throw Nxt_exception("get_first","Filesystem", 0x00FF & answer[4]);
  166. }
  167. }
  168. return 1;
  169. }
  170. int Filesystem::get_next(int handle, Nxt_file *file){
  171. Nxt_file temp;
  172. unsigned char answer[NXT_BUFFER_SIZE];
  173. unsigned char command[5];
  174. unsigned int i=0;
  175. command[0] = 0x03;
  176. command[1] = 0x00;
  177. command[2] = 0x01;
  178. command[3] = 0x87;
  179. command[4] = handle;
  180. connection->send(&command[0],5);
  181. connection->receive(&answer[0],30);
  182. if(answer[4]){
  183. if( (unsigned int) answer[4]!= FILE_NOT_FOUND){
  184. throw Nxt_exception("get_next","Filesystem", 0x00FF & answer[4]);
  185. }
  186. else{
  187. return 0;
  188. }
  189. }
  190. file->handle = answer[5];
  191. i=0;
  192. while(i<MAX_NAME_LENGTH){
  193. file->name[i] = answer[6+i];
  194. i++;
  195. }
  196. file->size = (0xFF & answer[26]) | ((0xFF & answer[27]) << 8)| ((0xFF & answer[28]) << 16)| ((0xFF & answer[29]) << 24);
  197. temp.handle = file->handle;
  198. try{
  199. close_file(temp);
  200. }
  201. catch (Nxt_exception& e){
  202. if(e.error_code () != HANDLE_ALREADY_CLOSED){
  203. throw Nxt_exception("get_next","Filesystem", 0x00FF & answer[4]);
  204. }
  205. }
  206. return 1;
  207. }
  208. unsigned int Filesystem::update_file_list(string wild_card){
  209. unsigned int idx;
  210. Nxt_file temp;
  211. free(file_list);
  212. if(this->get_first(wild_card, &temp)){
  213. file_list = (Nxt_file*) malloc(sizeof(Nxt_file));
  214. file_list[0] = temp;
  215. file_list_size = 1;
  216. }
  217. else{
  218. file_list_size =0;
  219. return file_list_size;
  220. }
  221. idx=0;
  222. while(this->get_next(file_list[idx].handle, &temp)){
  223. file_list = (Nxt_file *) realloc(file_list, (file_list_size+1)* sizeof(Nxt_file));
  224. file_list[idx+1] = temp;
  225. file_list_size++;
  226. idx++;
  227. }
  228. return file_list_size;
  229. }
  230. unsigned int Filesystem::create_file_list(string wild_card){
  231. return update_file_list(wild_card);
  232. }
  233. unsigned int Filesystem::get_file_list_size(){
  234. return file_list_size;
  235. }
  236. Nxt_file Filesystem::get_file_list_element(unsigned int idx){
  237. if(idx>=file_list_size){
  238. Nxt_file empty;
  239. empty.handle =0;
  240. empty.name[0] = '\0';
  241. empty.size =0;
  242. return empty;
  243. }
  244. else{
  245. return file_list[idx];
  246. }
  247. }
  248. //This is so ugly
  249. unsigned int Filesystem::get_free_flash(){
  250. Brick *temp = new Brick(this->connection);
  251. unsigned int temp2 = temp->get_flash_memory();
  252. delete(temp);
  253. return temp2;
  254. }
  255. Nxt_file Filesystem::open_read(string file_name){
  256. Nxt_file file;
  257. unsigned int name_length;
  258. unsigned char command[24];
  259. unsigned char answer[NXT_BUFFER_SIZE];
  260. unsigned int i=0;
  261. name_length = file_name.length();
  262. if(name_length > MAX_NAME_LENGTH){
  263. file_name.erase(MAX_NAME_LENGTH+1);
  264. name_length=MAX_NAME_LENGTH;
  265. }
  266. command[0]=0x16; //command length
  267. command[1]=0x00;
  268. command[2]=0x01;
  269. command[3]=0x80;
  270. while(i<name_length){
  271. command[i+4]=file_name[i];
  272. i++;
  273. }
  274. while(i<MAX_NAME_LENGTH){
  275. command[i+4]='\0';
  276. i++;
  277. }
  278. connection->send(&command[0],24);
  279. connection->receive(&answer[0],10);
  280. if(answer[4]){
  281. throw Nxt_exception("open_read","Filesystem", 0x00FF & answer[4]);
  282. }
  283. file.handle = answer[5];
  284. file.size = (0xFF & answer[6]) | ((0xFF & answer[7]) << 8)| ((0xFF & answer[8]) << 16)| ((0xFF & answer[9]) << 24);
  285. i=0;
  286. while(i<MAX_NAME_LENGTH){
  287. file.name[i] = file_name[i];
  288. i++;
  289. }
  290. return file;
  291. }
  292. Nxt_file Filesystem::open_append(string file_name){
  293. Nxt_file file;
  294. unsigned int name_length;
  295. unsigned char command[24];
  296. unsigned char answer[NXT_BUFFER_SIZE];
  297. unsigned int i=0;
  298. name_length = file_name.length();
  299. if(name_length > MAX_NAME_LENGTH){
  300. file_name.erase(MAX_NAME_LENGTH+1);
  301. name_length=MAX_NAME_LENGTH;
  302. }
  303. command[0]=0x16; //command length
  304. command[1]=0x00;
  305. command[2]=0x01;
  306. command[3]=0x8C;
  307. while(i<name_length){
  308. command[i+4]=file_name[i];
  309. i++;
  310. }
  311. while(i<MAX_NAME_LENGTH){
  312. command[i+4]='\0';
  313. i++;
  314. }
  315. connection->send(&command[0],24);
  316. connection->receive(&answer[0],10);
  317. if(answer[4]){
  318. throw Nxt_exception("open_append","Filesystem", 0x00FF & answer[4]);
  319. }
  320. file.handle = answer[5];
  321. file.size = (0xFF & answer[6]) | ((0xFF & answer[7]) << 8)| ((0xFF & answer[8]) << 16)| ((0xFF & answer[9]) << 24);
  322. i=0;
  323. while(i<MAX_NAME_LENGTH){
  324. file.name[i] = file_name[i];
  325. i++;
  326. }
  327. return file;
  328. }
  329. Nxt_file Filesystem::open_write(string file_name, unsigned int file_size, char type){
  330. Nxt_file file;
  331. unsigned int name_length;
  332. unsigned char command[28];
  333. unsigned char answer[NXT_BUFFER_SIZE];
  334. unsigned int i=0;
  335. name_length = file_name.length();
  336. if(name_length > MAX_NAME_LENGTH){
  337. file_name.erase(MAX_NAME_LENGTH+1);
  338. name_length=MAX_NAME_LENGTH;
  339. }
  340. command[0]=0x1A; //command length
  341. command[1]=0x00;
  342. command[2]=0x01;
  343. command[3]=type;
  344. while(i<name_length){
  345. command[i+4]=file_name[i];
  346. i++;
  347. }
  348. while(i<MAX_NAME_LENGTH){
  349. command[i+4]='\0';
  350. i++;
  351. }
  352. command[24] = file_size & 0xff;
  353. command[25] = (file_size >> 8 ) & 0xff;
  354. command[26] = (file_size >> 16) & 0xff;
  355. command[27] = (file_size >> 24) & 0xff;
  356. connection->send(&command[0],28);
  357. connection->receive(&answer[0],6);
  358. if(answer[4]){
  359. throw Nxt_exception("open_write","Filesystem", 0x00FF & answer[4]);
  360. }
  361. file.handle = answer[5];
  362. file.size = file_size;
  363. i=0;
  364. while(i<MAX_NAME_LENGTH){
  365. file.name[i] = file_name[i];
  366. i++;
  367. }
  368. return file;
  369. }
  370. void Filesystem::close_file(Nxt_file &file){
  371. unsigned char command[5];
  372. unsigned char answer[NXT_BUFFER_SIZE];
  373. command[0]=0x03; //command length
  374. command[1]=0x00;
  375. command[2]=0x01;
  376. command[3]=0x84;
  377. command[4]= file.handle;
  378. connection->send(&command[0],5);
  379. connection->receive(&answer[0],6);
  380. if(answer[4]){
  381. throw Nxt_exception("close","Filesystem", 0x00FF & answer[4]);
  382. }
  383. file.name[0] = '\0';
  384. file.handle = 0;
  385. file.size = 0;
  386. return;
  387. }
  388. unsigned int Filesystem::read_file(Nxt_file &file, unsigned char *buffer, unsigned int num_bytes){
  389. unsigned short int bytes_to_read=0;
  390. unsigned int i,j;
  391. i=num_bytes/MAX_READ_BYTES;
  392. j=0;
  393. while(j<i){
  394. this->read_command(file, &buffer[j*MAX_READ_BYTES], MAX_READ_BYTES);
  395. j++;
  396. }
  397. bytes_to_read = num_bytes%MAX_READ_BYTES;
  398. if(bytes_to_read){
  399. this->read_command(file, &buffer[i*MAX_READ_BYTES],bytes_to_read);
  400. }
  401. return bytes_to_read + (i*MAX_READ_BYTES);
  402. }
  403. unsigned short int Filesystem::read_command(Nxt_file &file, unsigned char *buffer, unsigned short int num_bytes){
  404. unsigned char command[7];
  405. unsigned char *answer = (unsigned char *) malloc((num_bytes*sizeof(unsigned char))+8);
  406. unsigned short int bytes_to_read,i;
  407. command[0]=0x05; //command length
  408. command[1]=0x00;
  409. command[2]=0x01;
  410. command[3]=0x82;
  411. command[4]= file.handle;
  412. command[5] = num_bytes & 0x00ff;
  413. command[6] = (num_bytes >> 8 & 0x00ff);
  414. connection->send(&command[0],7);
  415. connection->receive(&answer[0],8+num_bytes);
  416. if(answer[4]){
  417. throw Nxt_exception("read_command","Filesystem", 0x00FF & answer[4]);
  418. }
  419. bytes_to_read = (0xFF & answer[6]) | ((0xFF & answer[7]) << 8);
  420. if(bytes_to_read != (num_bytes)){
  421. throw Nxt_exception("read_command","Filesystem", UNDEFINED_FILE_ERROR);
  422. }
  423. i=0;
  424. while(i<num_bytes){
  425. buffer[i]=answer[8+i];
  426. i++;
  427. }
  428. free(answer);
  429. return bytes_to_read;
  430. }
  431. //returns bytes wtritten
  432. unsigned int Filesystem::write_file(Nxt_file &file, unsigned char *buffer, unsigned int num_bytes){
  433. unsigned short int bytes_to_write=0;
  434. unsigned int i,j;
  435. i=num_bytes/MAX_WRITE_BYTES;
  436. j=0;
  437. while(j<i){
  438. this->write_command(file, &buffer[j*MAX_WRITE_BYTES], MAX_WRITE_BYTES);
  439. j++;
  440. }
  441. bytes_to_write = num_bytes%MAX_WRITE_BYTES;
  442. if(bytes_to_write){
  443. this->write_command(file, &buffer[i*MAX_WRITE_BYTES],bytes_to_write);
  444. }
  445. return bytes_to_write + (i*MAX_WRITE_BYTES);
  446. }
  447. unsigned short int Filesystem::write_command(Nxt_file &file, unsigned char *buffer, unsigned short int num_bytes){
  448. unsigned char answer[NXT_BUFFER_SIZE];
  449. unsigned int i;
  450. unsigned short int bytes_to_write, bytes_written;
  451. if(num_bytes>MAX_WRITE_BYTES){
  452. return 0;
  453. }
  454. bytes_to_write = num_bytes + 3;
  455. unsigned char *command = (unsigned char *) malloc ( (num_bytes*sizeof(unsigned char))+5);
  456. command[0]= bytes_to_write & 0xff; //command length
  457. command[1]= (bytes_to_write >> 8) & 0xff;
  458. command[2]=0x01;
  459. command[3]=0x83;
  460. command[4]= file.handle;
  461. i=0;
  462. while(i<num_bytes){
  463. command[i+5]=buffer[i];
  464. i++;
  465. }
  466. connection->send(&command[0], num_bytes+5);
  467. connection->receive(&answer[0],8);
  468. free(command);
  469. if(answer[4]){
  470. throw Nxt_exception("write_command","Filesystem", 0x00FF & answer[4]);
  471. }
  472. bytes_written = (0xFF & answer[6]) | ((0xFF & answer[7]) << 8);
  473. if(bytes_written != (num_bytes)){
  474. throw Nxt_exception("write_command","Filesystem", UNDEFINED_FILE_ERROR);
  475. }
  476. return bytes_written;
  477. }
  478. Nxt_file Filesystem::open_file(string file_name, File_mode mode, unsigned int file_size ){
  479. Nxt_file file;
  480. if(mode == READ){
  481. return open_read(file_name);
  482. }
  483. if(mode == WRITE){
  484. return open_write(file_name, file_size, OPEN_WRITE);
  485. }
  486. if(mode == WRITE_LINEAR){
  487. return open_write(file_name, file_size, OPEN_WRITE_LINEAR);
  488. }
  489. if(mode==WRITE_LINEAR_DATA){
  490. return open_write(file_name, file_size, OPEN_WRITE_LINEAR_DATA);
  491. }
  492. if(mode== APPEND){
  493. return open_append(file_name);
  494. }
  495. file.handle=0;
  496. file.name[0] = '\0';
  497. file.size = 0;
  498. return file;
  499. }
  500. void Filesystem::delete_file(Nxt_file &file, bool reply){
  501. return this->delete_file(file.name, reply);
  502. }