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