1 /**
2 * (c) 2001-2006 Nathan Hjelm <hjelmn@users.sourceforge.net>
3 * v1.5.2.1 rio.c
4 *
5 * c version of librioutil
6 * all sources are c style gnu (c-set-style in emacs)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Library Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 **/
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26
27 #include <unistd.h>
28 #include <time.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <string.h>
32
33 #include <sys/stat.h>
34 #include <sys/time.h>
35
36 #if defined (HAVE_LIBGEN_H)
37 #include <libgen.h>
38 #endif
39
40 #include "rioi.h"
41 #include "driver.h"
42
43 struct player_device_info player_devices[] = {
44 /* Rio 600/800/900 and Nike psa[play Use bulk endpoint 2 for read/write */
45 {VENDOR_DIAMOND01, PRODUCT_RIO600 , 0x2, 0x2, RIO600 , 3},
46 {VENDOR_DIAMOND01, PRODUCT_RIO800 , 0x2, 0x2, RIO800 , 3},
47 {VENDOR_DIAMOND01, PRODUCT_PSAPLAY, 0x2, 0x2, PSAPLAY , 3},
48 {VENDOR_DIAMOND01, PRODUCT_RIO900 , 0x2, 0x2, RIO900 , 3},
49 /* Rio S-Series Uses bulk endpoint 1 for read and 2 for write */
50 {VENDOR_DIAMOND01, PRODUCT_RIOS30 , 0x1, 0x2, RIOS30 , 4},
51 {VENDOR_DIAMOND01, PRODUCT_RIOS35 , 0x1, 0x2, RIOS35 , 4},
52 {VENDOR_DIAMOND01, PRODUCT_RIOS10 , 0x1, 0x2, RIOS10 , 4},
53 {VENDOR_DIAMOND01, PRODUCT_RIOS50 , 0x1, 0x2, RIOS50 , 4},
54 {VENDOR_DIAMOND01, PRODUCT_FUSE , 0x1, 0x2, RIOFUSE , 5},
55 {VENDOR_DIAMOND01, PRODUCT_CHIBA , 0x1, 0x2, RIOCHIBA , 5},
56 {VENDOR_DIAMOND01, PRODUCT_CALI , 0x1, 0x2, RIOCALI , 5},
57 {VENDOR_DIAMOND01, PRODUCT_CALI256, 0x1, 0x2, RIOCALI , 5},
58 {VENDOR_DIAMOND01, PRODUCT_RIOS11 , 0x1, 0x2, RIOS11 , 4},
59 /* Rio Riot Uses bulk endpoint 2 for read and 1 for write */
60 {VENDOR_DIAMOND01, PRODUCT_RIORIOT, 0x2, 0x1, RIORIOT , 3},
61 {VENDOR_DIAMOND01, PRODUCT_NITRUS, 0x1, 0x2, RIONITRUS, 5},
62 {0}
63 };
64
65
66 /* statically defined functions */
67 static int set_time_rio (rios_t *rio);
68 static int return_intrn_info_rio(rios_t *rio);
69
70 /* read the supported file types from the rio */
read_ftypes_rio(rios_t * rio)71 static int read_ftypes_rio (rios_t *rio) {
72 int i, ret;
73
74 for (i = 0 ; i < 3 ; i++) {
75 if ((ret = send_command_rio(rio, 0x60, 0, 0)) != URIO_SUCCESS)
76 return ret;
77 if ((ret = send_command_rio(rio, 0x63, i, 0)) != URIO_SUCCESS)
78 return ret;
79
80 read_block_rio (rio, NULL, 64, RIO_FTS);
81 read_block_rio (rio, NULL, 64, RIO_FTS);
82 }
83
84 return 0;
85 }
86
87 /*
88 open_rio:
89 Open rio.
90
91 PostCondition:
92 - An initiated rio instance.
93 - NULL if an error occured.
94 */
open_rio(rios_t * rio,int number,int debug,int fill_structures)95 int open_rio (rios_t *rio, int number, int debug, int fill_structures) {
96 int ret;
97
98 if (rio == NULL)
99 return -1;
100
101 memset(rio, 0, sizeof(rios_t));
102
103 rio->debug = debug;
104 rio->log = stderr;
105
106 rio_log (rio, 0,
107 "open_rio: creating new rio instance. device: 0x%08x\n", number);
108
109 if (debug) {
110 rio_log (rio, 0, "open_rio: setting usb driver verbosity level to %i\n",
111 debug);
112
113 usb_setdebug(debug);
114 }
115
116 rio->abort = 0;
117
118 /* open the USB device (this calls the underlying driver) */
119 if ((ret = usb_open_rio (rio, number)) != 0) {
120 rio_log (rio, ret, "open_rio: could not open a Rio device\n");
121
122 return ret;
123 }
124
125 ret = set_time_rio (rio);
126 if (ret != URIO_SUCCESS && fill_structures != 0) {
127 close_rio (rio);
128
129 return ret;
130 }
131
132 send_command_rio(rio, 0x61, 0, 0);
133 send_command_rio(rio, 0x61, 0, 0);
134 send_command_rio(rio, 0x65, 0, 0);
135
136 read_ftypes_rio (rio);
137
138 unlock_rio (rio);
139
140 if (fill_structures != 0) {
141 ret = return_intrn_info_rio (rio);
142 if (ret != URIO_SUCCESS) {
143 close_rio (rio);
144
145 return ret;
146 }
147 }
148
149 rio_log (rio, 0, "open_rio: new rio instance created.\n");
150
151 return URIO_SUCCESS;
152 }
153
154 /*
155 set_time_rio:
156 Only sets the rio's time these days.
157 */
set_time_rio(rios_t * rio)158 static int set_time_rio (rios_t *rio) {
159 long int curr_time;
160 struct timeval tv;
161 struct timezone tz;
162 struct tm *tmp;
163 int ret;
164
165 /*
166 * the rio has no concept of timezones so we need to take
167 * the local time into account when setting the time.
168 * now using the (non)obselete gettimeofday function
169 * i am not sure if this is the best way
170 *
171 */
172 gettimeofday (&tv, &tz);
173 tmp = localtime ((const time_t *)&(tv.tv_sec));
174
175 rio_log (rio, 0, "librioutil/rio.c set_time_rio: Setting device time from system clock: %s\n", asctime(tmp));
176
177 curr_time = tv.tv_sec - 60 * tz.tz_minuteswest;
178
179 if (tmp->tm_isdst != -1)
180 curr_time += 3600 * tmp->tm_isdst;
181
182 ret = send_command_rio (rio, 0x60, 0, 0);
183 if (ret != URIO_SUCCESS)
184 return ret;
185
186 /* tell the rio what time it is, assuming your system clock is correct */
187 ret = send_command_rio (rio, RIO_TIMES, curr_time >> 16, curr_time & 0xffff);
188 if (ret != URIO_SUCCESS)
189 return ret;
190
191 return URIO_SUCCESS;
192 }
193
194 /*
195 close_rio:
196 Close connection with rio and free buffer.
197 */
close_rio(rios_t * rio)198 void close_rio (rios_t *rio) {
199 if (try_lock_rio (rio) != 0)
200 return;
201
202 rio_log (rio, 0, "close_rio: entering...\n");
203
204 wake_rio (rio);
205
206 /* close connection */
207 usb_close_rio (rio);
208 rio->dev = NULL;
209
210 /* release the memory used by this instance */
211 free_info_rio (rio);
212
213 unlock_rio (rio);
214
215 rio_log (rio, 0, "close_rio: complete\n");
216 }
217
get_file_info_rio(rios_t * rio,rio_file_t * file,u_int8_t memory_unit,u_int16_t file_no)218 int get_file_info_rio(rios_t *rio, rio_file_t *file,
219 u_int8_t memory_unit, u_int16_t file_no) {
220 int ret;
221
222 if (file == NULL)
223 return -1;
224
225 if ((ret = wake_rio(rio)) != URIO_SUCCESS)
226 return ret;
227
228 memset (file, 0, sizeof (rio_file_t));
229
230 /* TODO -- Clean up code so it is easier to associate this with Riot
231 * The RIOT doesn't need to do this to delete a file. */
232 if (return_type_rio (rio) != RIORIOT) {
233 /* send command to get file header */
234 if ((ret = send_command_rio(rio, RIO_FILEI, memory_unit, file_no))
235 != URIO_SUCCESS)
236 return ret;
237
238 /* command was successful, read 2048 bytes of data from Rio */
239 if ((ret = read_block_rio(rio, (unsigned char *)file, sizeof(rio_file_t), RIO_FTS))
240 != URIO_SUCCESS)
241 return ret;
242
243 /* library handles endianness */
244 file_to_me(file);
245
246 /* no file exists with number 0, they are listed from 1 */
247 if (file->file_no == 0)
248 return -ENOENT;
249 } else {
250 /* for the RIOT to delete files (does this also work with downloads?) */
251 file->riot_file_no = file_no;
252 }
253
254 return URIO_SUCCESS;
255 }
256
257 /*
258 generate_mem_list_rio:
259
260 Generates the info->memory field of the rio structure.
261 */
generate_mem_list_rio(rios_t * rio)262 int generate_mem_list_rio (rios_t *rio) {
263 int i, ret;
264 rio_mem_t memory;
265 int num_mem_units = MAX_MEM_UNITS;
266
267 mlist_rio_t *list = rio->info.memory;
268
269 rio_log (rio, 0, "create_mem_list_rio: entering...\n");
270
271 memset(list, 0, sizeof(mlist_rio_t) * MAX_MEM_UNITS);
272
273 if (return_type_rio(rio) == RIORIOT) {
274 /* Riots have only one memory unit */
275 ret = get_memory_info_rio (rio, &memory, 0);
276
277 if (ret != URIO_SUCCESS)
278 return ret;
279
280 list[0].size = memory.size;
281 list[0].free = memory.free;
282
283 ret = generate_flist_riohd (rio);
284
285 if (ret != URIO_SUCCESS)
286 return ret;
287 } else {
288 for (i = 0 ; i < num_mem_units ; i++) {
289 ret = get_memory_info_rio (rio, &memory, i);
290
291 if (ret == ENOMEM)
292 break; /* not an error */
293 else if (ret != URIO_SUCCESS)
294 return ret;
295
296 list[i].size = memory.size;
297 list[i].free = memory.free;
298 strncpy(list[i].name, memory.name, 32);
299
300 ret = generate_flist_riomc (rio, i);
301
302 if (ret != URIO_SUCCESS)
303 return ret;
304 }
305 }
306
307 rio_log (rio, 0, "create_mem_list_rio: complete\n");
308
309 return URIO_SUCCESS;
310 }
311
get_memory_info_rio(rios_t * rio,rio_mem_t * memory,u_int8_t memory_unit)312 int get_memory_info_rio(rios_t *rio, rio_mem_t *memory, u_int8_t memory_unit) {
313 int ret;
314
315 if (!rio)
316 return -1;
317
318 if ((ret = wake_rio(rio)) != URIO_SUCCESS)
319 return ret;
320
321 if (send_command_rio(rio, RIO_MEMRI, memory_unit, 0) != URIO_SUCCESS)
322 return -1;
323
324 /* command was successful, read 256 bytes from Rio */
325 if ((ret = read_block_rio(rio, (unsigned char *)memory, 256, RIO_FTS)) != URIO_SUCCESS)
326 return ret;
327
328 /* swap to big endian if needed */
329 mem_to_me(memory);
330
331 /* if requested memory unit is out of range Rio returns 256 bytes of 0's */
332 if (memory->size == 0)
333 return ENOMEM; /* not an error */
334
335 return URIO_SUCCESS;
336 }
337
338 /* this should work better that before */
update_free_intrn_rio(rios_t * rio,u_int8_t memory_unit)339 void update_free_intrn_rio (rios_t *rio, u_int8_t memory_unit) {
340 rio_mem_t memory;
341
342 get_memory_info_rio(rio, &memory, memory_unit);
343
344 rio->info.memory[memory_unit].free = memory.free;
345 }
346
return_type_rio(rios_t * rio)347 int return_type_rio(rios_t *rio) {
348 return ((struct rioutil_usbdevice *)rio->dev)->entry->type;
349 }
350
351 /*
352 first generation : Rio300 (Unsupported)
353 second generation: Rio500 (Unsupported)
354 third generation : Rio600, Rio800, Rio900, psa[play, Riot
355 fourth generation: S-Series
356 fith generation : Fuse, Chiba, Cali
357 Nitrus, Eigen, Karma (Unsupported)
358 */
return_generation_rio(rios_t * rio)359 int return_generation_rio (rios_t *rio) {
360 return ((struct rioutil_usbdevice *)rio->dev)->entry->gen;
361 }
362
return_version_rio(rios_t * rio)363 float return_version_rio (rios_t *rio) {
364 return rio->info.firmware_version;
365 }
366
367 /*
368 return_intrn_info_rio:
369 BIG function that fills the rio_info structure.
370
371 renamed from return_info_rio
372 */
return_intrn_info_rio(rios_t * rio)373 static int return_intrn_info_rio(rios_t *rio) {
374 rio_info_t *info = &rio->info;
375 rio_prefs_t prefs;
376 riot_prefs_t riot_prefs;
377
378 unsigned char desc[256];
379 unsigned char cmd;
380
381 int ret;
382 int i;
383
384 if ((ret = try_lock_rio (rio)) != 0)
385 return ret;
386
387 memset (info, 0, sizeof (rio_info_t));
388
389 /*
390 * Send the initialize set of commands to the RIO
391 */
392 ret = send_command_rio(rio, 0x66, 0, 0);
393 if (ret != URIO_SUCCESS) {
394 rio_log (rio, ret, "return_info_rio: Error sending command\n");
395 UNLOCK(ret);
396 }
397
398 ret = send_command_rio(rio, 0x65, 0, 0);
399 if (ret != URIO_SUCCESS) {
400 rio_log (rio, ret, "return_info_rio: Error sending command\n");
401 UNLOCK(ret);
402 }
403
404 /*
405 retrieve non-changable values
406 */
407 cmd = RIO_DESCP;
408 ret = send_command_rio(rio, cmd, 0, 0);
409 if (ret != URIO_SUCCESS) {
410 rio_log (rio, ret, "return_info_rio: error sending command.\n");
411 UNLOCK(ret);
412 }
413
414 ret = read_block_rio(rio, desc, 256, RIO_FTS);
415 if (ret != URIO_SUCCESS) {
416 rio_log (rio, ret, "return_info_rio: Error reading device info\n", cmd);
417
418 UNLOCK(ret);
419 }
420
421 info->firmware_version = (desc[5] + (0.1) * (desc[4] >> 4)
422 + (0.01) * (desc[4] & 0xf));
423 memmove (info->serial_number, &desc[0x60], 16);
424
425 /*
426 * this is where we set which structure to use to fill the
427 * prefs
428 */
429
430 if ((ret = generate_mem_list_rio(rio)) != URIO_SUCCESS)
431 return ret;
432
433 /*
434 retrieve changeable values
435 */
436 /* iTunes sends this set of commands before RIO_PREFR */
437 cmd = RIO_PREFR;
438 if ((ret = send_command_rio(rio, cmd, 0, 0)) == URIO_SUCCESS) {
439 rio_log (rio, ret, "return_info_rio: Preference read command successful\n");
440
441 if (return_type_rio (rio) != RIORIOT) { /* All but the RIOT */
442
443 /* Read a block into the prefs structure */
444 ret = read_block_rio(rio, (unsigned char *)&prefs, RIO_MTS, RIO_FTS);
445 if (ret != URIO_SUCCESS) {
446 rio_log (rio, ret, "return_info_rio: Error reading data after command 0x%x\n", cmd);
447 UNLOCK(ret);
448 }
449
450 /* Copy the prefs into the info structure */
451 memcpy(info->name, prefs.name, 17);
452 info->volume = prefs.volume;
453 info->playlist = prefs.playlist;
454 info->contrast = prefs.contrast - 1;
455 info->sleep_time = prefs.sleep_time % 5;
456 info->treble = prefs.treble;
457 info->bass = prefs.bass;
458 info->eq_state = prefs.eq_state % 8;
459 info->repeat_state = prefs.repeat_state % 4;
460 info->light_state = prefs.light_state % 6;
461 info->random_state = 0; /* RIOT Only */
462 info->the_filter_state = 0; /* RIOT Only */
463
464 } else { /* This is a RIOT */
465 /* Read a block into the riot_prefs structure */
466 ret = read_block_rio(rio, (unsigned char *)&riot_prefs, RIO_MTS, RIO_FTS);
467 if (ret != URIO_SUCCESS) {
468 rio_log (rio, ret, "return_info_rio: Error reading data from RIOT after command 0x%x\n",cmd);
469 UNLOCK(ret);
470 }
471
472 /* Copy the riot_prefs into the info structure */
473 memcpy(info->name, riot_prefs.name, 17);
474 info->volume = riot_prefs.volume;
475 info->contrast = riot_prefs.contrast - 1; /* do we really need the -1 */
476 info->sleep_time = riot_prefs.sleep_time;
477 info->treble = riot_prefs.treble;
478 info->bass = riot_prefs.bass;
479 info->repeat_state = riot_prefs.repeat_state % 4; /* Do we really need the mod 4? */
480 info->light_state = riot_prefs.light_state;
481 info->random_state = riot_prefs.random_state;
482 info->the_filter_state = riot_prefs.the_filter_state;
483 info->eq_state = 0; /* Not on RIOT */
484 info->playlist = 0; /* Not on RIOT */
485 }
486 } else /* Failed the read */
487 rio_log (rio, -1, "return_info_rio: Rio did not respond to Preference read command.\n");
488
489 /*
490 memory
491 */
492 for (i = 0 ; info->memory[i].size && i < MAX_MEM_UNITS ; i++)
493 info->total_memory_units++;
494
495 UNLOCK(URIO_SUCCESS);
496 }
497
498 static void sane_info_copy (rio_info_t *info, rio_prefs_t *prefs);
499
500 /*
501 set_info_rio:
502 Set preferences on rio.
503
504 PreCondition:
505 - An initiated rio instance (Rio S-Series does not support this command).
506 - A pointer to a filled info structure.
507
508 PostCondition:
509 - URIO_SUCCESS if the preferences get set.
510 - < 0 if an error occured.
511 */
set_info_rio(rios_t * rio,rio_info_t * info)512 int set_info_rio(rios_t *rio, rio_info_t *info) {
513 rio_prefs_t pref_buf;
514 int ret;
515 unsigned char cmd;
516
517 if ((ret = try_lock_rio (rio)) != 0)
518 return ret;
519
520 /* noting to write */
521 if (info == NULL)
522 return -1;
523
524 cmd = RIO_PREFR;
525 if ((ret = send_command_rio(rio, cmd, 0, 0)) != 0) {
526 rio_log (rio, ret, "set_info_rio: Error sending command\n");
527
528 UNLOCK(ret);
529 }
530
531 ret = read_block_rio(rio, (unsigned char *)&pref_buf, RIO_MTS, RIO_FTS);
532 if (ret != URIO_SUCCESS) {
533 rio_log (rio, ret, "Error reading data after command 0x%x\n", cmd);
534
535 UNLOCK(ret);
536 }
537
538 sane_info_copy (info, &pref_buf);
539
540 if ((ret = wake_rio(rio)) != URIO_SUCCESS)
541 UNLOCK(ret);
542
543 cmd = RIO_PREFS;
544 if ((ret = send_command_rio(rio, cmd, 0, 0)) != 0) {
545 rio_log (rio, ret, "set_info_rio: Error sending command\n");
546
547 UNLOCK(ret);
548 }
549
550 ret = read_block_rio(rio, NULL, 64, RIO_FTS);
551 if (ret != URIO_SUCCESS) {
552 rio_log (rio, ret, "set_info_rio: error reading data after command 0x%x\n", cmd);
553
554 UNLOCK(ret);
555 }
556
557 if ((ret = write_block_rio(rio, (unsigned char *)&pref_buf, RIO_MTS, NULL)) != URIO_SUCCESS)
558 rio_log (rio, ret, "set_info_rio: error writing preferences\n");
559
560 UNLOCK(ret);
561 }
562
563 /*
564 sane_info_copy:
565 Make sure all values of info are sane and put them into prefs.
566 */
sane_info_copy(rio_info_t * info,rio_prefs_t * prefs)567 static void sane_info_copy (rio_info_t *info, rio_prefs_t *prefs) {
568 prefs->eq_state = ((info->eq_state < 7) ? info->eq_state : 7);
569 prefs->treble = ((info->treble < 9) ? info->treble : 9);
570 prefs->bass = ((info->bass < 9) ? info->bass : 9);
571 prefs->repeat_state = ((info->repeat_state < 2) ? info->repeat_state : 2);
572 prefs->sleep_time = ((info->sleep_time < 9) ? info->sleep_time : 9);
573 prefs->light_state = ((info->light_state < 5) ? info->light_state : 5);
574 prefs->contrast = ((info->contrast < 9) ? info->contrast + 1 : 10);
575 prefs->volume = ((info->volume < 20) ? info->volume : 20);
576
577 /* i don't think it would be a good idea to set this */
578 /* prefs->playlist */
579
580 if (strlen(info->name) > 0)
581 strncpy(prefs->name, info->name, 16);
582 }
583
584 /*
585 format_mem_rio:
586
587 Erase a memory unit.
588 */
format_mem_rio(rios_t * rio,u_int8_t memory_unit)589 int format_mem_rio (rios_t *rio, u_int8_t memory_unit) {
590 u_int32_t ret, pd;
591
592 if ((ret = try_lock_rio (rio)) != 0)
593 return ret;
594
595 rio_log (rio, 0, "librioutil/rio.c format_mem_rio: erasing memory unit %i\n", memory_unit);
596
597 /* don't need to call wake_rio here */
598
599 if (rio->progress)
600 rio->progress (0, 100, rio->progress_ptr);
601
602 if ((ret = send_command_rio(rio, RIO_FORMT, memory_unit, 0)) != URIO_SUCCESS)
603 UNLOCK(ret);
604
605 while (1) {
606 if ((ret = read_block_rio(rio, NULL, 64, RIO_FTS)) != URIO_SUCCESS)
607 UNLOCK(ret);
608
609 /* newer players (Fuse, Chiba, Cali) return their progress */
610 if (strstr((char *)rio->buffer, "SRIOPR") != NULL) {
611 sscanf ((char *)rio->buffer, "SRIOPR%02d", &pd);
612
613 if (rio->progress)
614 rio->progress (pd, 100, rio->progress_ptr);
615 } else if (strstr((char *)rio->buffer, "SRIOFMTD") != NULL) {
616 /* format operation completed successfully */
617 break;
618 } else {
619 rio_log (rio, -1, "librioutil/rio.c format_mem_rio: erase failed\n");
620
621 UNLOCK(-1);
622 }
623 }
624
625 if (rio->progress)
626 rio->progress (100, 100, rio->progress_ptr);
627
628 rio_log (rio, 0, "librioutil/rio.c format_mem_rio: erase complete\n");
629
630 UNLOCK(URIO_SUCCESS);
631 }
632
633 /*
634 update_rio:
635
636 Update the firmware on a Rio. Function supports all rioutil supported players.
637 */
update_rio(rios_t * rio,char * file_name)638 int update_rio (rios_t *rio, char *file_name) {
639 rio_log (rio, 0, "update_rio: function depricated. use firmware_upgrade_rio instead.\n");
640
641 return firmware_upgrade_rio (rio, file_name);
642 }
643
firmware_upgrade_rio(rios_t * rio,char * file_name)644 int firmware_upgrade_rio (rios_t *rio, char *file_name) {
645 /* a block size of 0x2000 bytes is used by the original software */
646 size_t blocksize = 0x2000;
647 unsigned char fileBuffer[blocksize];
648
649 struct stat statinfo;
650 int size, blocks, x;
651
652 u_int32_t *intp;
653 int firm_fd;
654
655 int ret, pg;
656 int player_generation;
657
658 if (file_name == NULL || stat(file_name, &statinfo) < 0)
659 return -EINVAL;
660
661 size = statinfo.st_size;
662
663
664 rio_log (rio, 0, "librioutil/rio.c firmware_upgrade_rio: updating firmware of generation %d rio...\n",
665 player_generation);
666
667
668 if ((ret = wake_rio(rio)) != URIO_SUCCESS)
669 UNLOCK(ret);
670
671 /* some upgrades require that the memory unit be erased */
672 rio_log (rio, 0, "librioutil/rio.c firmware_upgrade_rio: formatting internal memory\n");
673 if ((ret = format_mem_rio (rio, 0)) != URIO_SUCCESS)
674 UNLOCK(ret);
675
676 if ((ret = try_lock_rio (rio)) != 0)
677 return ret;
678
679 player_generation = return_generation_rio (rio);
680
681
682 /* try to open the firmware file */
683 if ((firm_fd = open(file_name, O_RDONLY)) < 0)
684 UNLOCK(errno);
685
686 /* it is not necessary to check the .lok file as the player will reject bad input */
687 rio_log (rio, 0, "librioutil/rio.c firmware_upgrade_rio: sending firmware update device command...\n");
688
689 if ((ret = send_command_rio(rio, RIO_UPDAT, 0x1, 0)) != URIO_SUCCESS) {
690 rio_log (rio, 0, "librioutil/rio.c firmware_upgrade_rio: device did not respond to command.\n");
691
692 close (firm_fd);
693 UNLOCK(ret);
694 }
695
696 if ((ret = read_block_rio(rio, rio->buffer, 64, RIO_FTS)) != URIO_SUCCESS) {
697 rio_log (rio, 0, "librioutil/rio.c firmware_upgrade_rio: device did not respond as expected.\n");
698
699 close (firm_fd);
700 UNLOCK(ret);
701 }
702
703 rio_log (rio, 0, "librioutil/rio.c firmware_upgrade_rio: device acknowleged command.\n");
704
705 if (player_generation > 3)
706 rio_log (rio, 0, "librioutil/rio.c firmware_upgrade_rio: erasing...\n");
707 else
708 rio_log (rio, 0, "librioutil/rio.c firmware_upgrade_rio: writing firmware...\n");
709
710 /* send the size of the firmware data */
711 memset(rio->buffer, 0, 64);
712 intp = (u_int32_t *)rio->buffer;
713
714 intp[0] = arch32_2_little32(size);
715
716 if ((ret = write_block_rio(rio, rio->buffer, 64, NULL)) != URIO_SUCCESS)
717 UNLOCK(ret);
718
719 /* on newer players the first write apparently erases the device (data is still sent) */
720 for (blocks = size / blocksize, x = 0 ; x < blocks; x++) {
721 /* read in a chunk of file */
722 read(firm_fd, fileBuffer, blocksize);
723
724 if (player_generation == 5) {
725 /* newer players return the progress of the erase */
726 if (strstr ((char *)rio->buffer, "SRIOPR") != NULL) {
727 sscanf ((char *)rio->buffer, "SRIOPR%02d", &pg);
728
729 if (rio->progress != NULL)
730 rio->progress (pg, 200, rio->progress_ptr);
731 } else if (strstr ((char *)rio->buffer, "SRIODONE") != NULL) {
732 if (rio->progress != NULL)
733 rio->progress (100, 100, rio->progress_ptr);
734
735 close (firm_fd);
736 return URIO_SUCCESS;
737 }
738 } else if (rio->buffer[1] == 2) {
739 /* on older rios (third generation) it appears a 2 is returned to indicate the update
740 was successful */
741 break;
742 } if (rio->progress != NULL)
743 /* assume the block was received ok */
744 rio->progress ((player_generation == 4) ? x : x/2, blocks, rio->progress_ptr);
745
746 if (player_generation > 3)
747 write_block_rio (rio, fileBuffer, blocksize, NULL);
748 }
749
750 if (player_generation > 3) {
751 /* if this is a newer player the update is not quite done */
752 rio_log (rio, 0, "librioutil/rio.c firmware_upgrade_rio: writing firmware...\n");
753
754 /* it takes a moment before the rio is ready to continue */
755 usleep (1000);
756
757 /* half-way mark on the progress bar */
758 if (rio->progress != NULL)
759 rio->progress (blocks/2, blocks, rio->progress_ptr);
760
761 lseek(firm_fd, 0, SEEK_SET);
762
763 /* write firmware */
764 for (x = 0 ; x < blocks ; x++) {
765 /* read in a chunk of file */
766 read (firm_fd, fileBuffer, blocksize);
767
768 write_block_rio (rio, fileBuffer, blocksize, NULL);
769
770 /* the rio expects the first block to be sent three times */
771 if (x == 0) {
772 write_block_rio (rio, fileBuffer, blocksize, NULL);
773 write_block_rio (rio, fileBuffer, blocksize, NULL);
774 }
775
776 if (rio->progress != NULL)
777 rio->progress (x/2 + blocks/2, blocks, rio->progress_ptr);
778 }
779 }
780
781 /* make sure the progress bar reaches 100% */
782 if (rio->progress != NULL)
783 rio->progress (blocks, blocks, rio->progress_ptr);
784
785 close(firm_fd);
786
787 rio_log (rio, 0, "librioutil/rio.c firmware_upgrade_rio: firmware update complete\n");
788
789 UNLOCK(URIO_SUCCESS);
790 }
791
792 /*
793 wake_rio:
794
795 internal function to send a common set of commands
796 */
wake_rio(rios_t * rio)797 int wake_rio (rios_t *rio) {
798 int ret;
799
800 if (!rio || !rio->dev)
801 return -EINVAL;
802
803 if ((ret = send_command_rio(rio, 0x66, 0, 0)) != URIO_SUCCESS)
804 return ret;
805
806 send_command_rio(rio, 0x61, 0, 0);
807 send_command_rio(rio, 0x65, 0, 0);
808 send_command_rio(rio, 0x60, 0, 0);
809
810 return URIO_SUCCESS;
811 }
812
813 /* frees the info ptr in rios_t structure */
free_info_rio(rios_t * rio)814 void free_info_rio (rios_t *rio) {
815 int i;
816 flist_rio_t *tmp, *ntmp;
817
818 for (i = 0 ; i < MAX_MEM_UNITS ; i++)
819 for (tmp = rio->info.memory[i].files ; tmp ; tmp = ntmp) {
820 ntmp = tmp->next;
821 free(tmp);
822 }
823 }
824
825 /* New Functions -- Aug 8 2001 */
826 /*
827 update_info_rio:
828
829 funtion updates the info portion of the rio_instance structure
830 */
update_info_rio(rios_t * rio)831 int update_info_rio (rios_t *rio) {
832 if (rio == NULL)
833 return -EINVAL;
834
835 free_info_rio (rio);
836
837 return return_intrn_info_rio (rio);
838 }
839
840
841 /*
842 return_mem_units_rio:
843
844 returns to total number of memory units an instance has.
845 */
return_mem_units_rio(rios_t * rio)846 int return_mem_units_rio (rios_t *rio) {
847 if (rio == NULL)
848 return -EINVAL;
849
850 return rio->info.total_memory_units;
851 }
852
853 /*
854 return_free_mem_rio:
855
856 returns the free space on a memory unit (in kiB)
857 */
return_free_mem_rio(rios_t * rio,u_int8_t memory_unit)858 int return_free_mem_rio (rios_t *rio, u_int8_t memory_unit) {
859 if (rio == NULL)
860 return -EINVAL;
861
862 if (memory_unit >= MAX_MEM_UNITS) {
863 rio_log (rio, -2, "return_free_mem_rio: memory unit %02x out of range.\n",
864 memory_unit);
865 return -2;
866 }
867
868 return FREE_SPACE(memory_unit);
869 }
870
871 /*
872 return_used_mem_rio:
873
874 returns the used space on a memory unit (in kiB)
875 */
return_used_mem_rio(rios_t * rio,u_int8_t memory_unit)876 int return_used_mem_rio (rios_t *rio, u_int8_t memory_unit) {
877 if (rio == NULL)
878 return -EINVAL;
879
880 if (memory_unit >= MAX_MEM_UNITS) {
881 rio_log (rio, -2, "return_used_mem_rio: memory unit %02x out of range.\n",
882 memory_unit);
883 return -2;
884 }
885
886 return (MEMORY_SIZE(memory_unit) - FREE_SPACE(memory_unit));
887 }
888
889 /*
890 return_total_mem_rio:
891
892 returns the size of a memory unit (in kiB)
893 */
return_total_mem_rio(rios_t * rio,u_int8_t memory_unit)894 int return_total_mem_rio (rios_t *rio, u_int8_t memory_unit) {
895 if (rio == NULL)
896 return -EINVAL;
897
898 if (memory_unit >= MAX_MEM_UNITS) {
899 rio_log (rio, -2, "return_total_mem_rio: memory unit %02x out of range.\n",
900 memory_unit);
901 return -2;
902 }
903
904 return MEMORY_SIZE(memory_unit);
905 }
906
907 /*
908 return_file_name_rio:
909
910 returns the file name associated with a song_id/mem_id
911 */
return_file_name_rio(rios_t * rio,u_int32_t song_id,u_int8_t memory_unit)912 char *return_file_name_rio(rios_t *rio, u_int32_t song_id,
913 u_int8_t memory_unit) {
914 flist_rio_t *tmp;
915 char *ntmp;
916
917 if (rio == NULL)
918 return NULL;
919
920 if (memory_unit >= MAX_MEM_UNITS) {
921 rio_log (rio, -2, "return_file_name_rio: memory unit %02x out of range.\n",
922 memory_unit);
923 return NULL;
924 }
925
926 /* find the file */
927 for (tmp = rio->info.memory[memory_unit].files ; tmp ; tmp = tmp->next)
928 if (tmp->num == song_id)
929 break;
930
931 if (tmp == NULL)
932 return NULL;
933
934 ntmp = (char *)calloc(strlen(tmp->name) + 1, 1);
935 strncpy(ntmp, tmp->name, strlen(tmp->name));
936
937 return ntmp;
938 }
939
return_file_size_rio(rios_t * rio,u_int32_t song_id,u_int8_t memory_unit)940 int return_file_size_rio(rios_t *rio, u_int32_t song_id, u_int8_t memory_unit) {
941 flist_rio_t *tmp;
942
943 if (rio == NULL)
944 return -1;
945
946 if (memory_unit >= MAX_MEM_UNITS) {
947 rio_log (rio, -2,
948 "return_file_size_rio: memory unit %02x out of range.\n",
949 memory_unit);
950 return -2;
951 }
952
953 /* find the file */
954 for (tmp = rio->info.memory[memory_unit].files ; tmp ; tmp = tmp->next)
955 if (tmp->num == song_id)
956 break;
957
958 if (tmp == NULL)
959 return -1;
960
961 return tmp->size;
962 }
963
964 /*
965 return_num_files_rio:
966
967 returns the number of files on a memory unit.
968 */
return_num_files_rio(rios_t * rio,u_int8_t memory_unit)969 int return_num_files_rio (rios_t *rio, u_int8_t memory_unit) {
970 if (rio == NULL)
971 return -EINVAL;
972
973 if (memory_unit >= MAX_MEM_UNITS) {
974 rio_log (rio, -2,
975 "return_num_files_rio: memory unit %02x out of range.\n",
976 memory_unit);
977 return -2;
978 }
979
980 return rio->info.memory[memory_unit].num_files;
981 }
982
983 /*
984 return_time_rio:
985
986 returns the sum of the duration of all tracks on a memory unit
987 */
return_time_rio(rios_t * rio,u_int8_t memory_unit)988 int return_time_rio (rios_t *rio, u_int8_t memory_unit) {
989 if (rio == NULL)
990 return -EINVAL;
991
992 if (memory_unit >= MAX_MEM_UNITS) {
993 rio_log (rio, -2, "return_time_rio: memory unit %02x out of range.\n",
994 memory_unit);
995 return -2;
996 }
997
998 return rio->info.memory[memory_unit].total_time;
999 }
1000
1001 /*
1002 Other Info -- This does not return file list
1003 */
return_info_rio(rios_t * rio)1004 rio_info_t *return_info_rio (rios_t *rio) {
1005 rio_info_t *new_info = NULL;
1006
1007 rio_log (rio, 0, "return_info_rio: function depricated. use get_info_rio instead.\n");
1008
1009 get_info_rio (rio, &new_info);
1010
1011 return new_info;
1012 }
1013
get_info_rio(rios_t * rio,rio_info_t ** info)1014 int get_info_rio (rios_t *rio, rio_info_t **info) {
1015 int i;
1016
1017 if (rio == NULL || info == NULL)
1018 return -EINVAL;
1019
1020 if (rio->info.memory[0].size == 0)
1021 return_intrn_info_rio (rio);
1022
1023 *info = calloc(1, sizeof (rio_info_t));
1024
1025 /* make a duplicate of rio's info */
1026 memcpy(*info, &rio->info, sizeof(rio_info_t));
1027
1028 for (i = 0 ; i < 2 ; i++)
1029 (*info)->memory[i].files = NULL;
1030
1031 return 0;
1032 }
1033
1034 /*
1035 set_progress_rio:
1036 */
set_progress_rio(rios_t * rio,void (* f)(int x,int X,void * ptr),void * ptr)1037 void set_progress_rio (rios_t *rio, void (*f)(int x, int X, void *ptr), void *ptr) {
1038 if (rio != NULL) {
1039 rio->progress_ptr = ptr;
1040 rio->progress = f;
1041 }
1042 }
1043
1044 /*
1045 return_conn_method_rio: return the driver librioutil is using (soon to be deprecated)
1046 */
return_conn_method_rio(void)1047 char *return_conn_method_rio (void) {
1048 return driver_method;
1049 }
1050
return_serial_number_rio(rios_t * rio,u_int8_t serial_number[16])1051 int return_serial_number_rio (rios_t *rio, u_int8_t serial_number[16]) {
1052 if (rio == NULL)
1053 return -EINVAL;
1054
1055 memmove (serial_number, rio->info.serial_number, 16);
1056
1057 return 0;
1058 }
1059
1060 /* locking/unlocking routines */
try_lock_rio(rios_t * rio)1061 int try_lock_rio (rios_t *rio) {
1062 if (rio == NULL)
1063 return -EINVAL;
1064
1065 if (rio->lock != 0) {
1066 rio_log (rio, -EBUSY, "librioutil/rio.c try_lock_rio: rio is being used by another thread.\n");
1067
1068 return -EBUSY;
1069 }
1070
1071 rio->lock = 1;
1072
1073 return 0;
1074 }
1075
unlock_rio(rios_t * rio)1076 void unlock_rio (rios_t *rio) {
1077 rio->lock = 0;
1078 }
1079