📄 rio500.java
字号:
private static final int ROOT_FOLDER_ADDRESS = 0xff00;
/**
* This class is a base class that wraps a data buffer;
* subclasses expose the fields in that data.
*/
static public class Data
{
// keep all internals package-private
final byte data [];
final int off;
final Rio500 rio;
Data (Rio500 dev, byte buf []) { rio = dev; data = buf; off = 0; }
Data (Rio500 dev, byte buf [], int o) { rio = dev; data = buf; off = o; }
final int getU8 (int index)
{
return data [index] & 0xff;
}
final int getU16 (int index)
{
int retval;
index += off;
retval = 0xff & data [index++];
retval |= 0xff00 & (data [index] << 8);
return retval;
}
final int getU32 (int index)
{
int temp;
index += off;
temp = 0x0ff & data [3 + index];
temp <<= 8; temp |= 0x0ff & data [2 + index];
temp <<= 8; temp |= 0x0ff & data [1 + index];
temp <<= 8; temp |= 0x0ff & data [0 + index];
return temp;
}
final String getString (int start, int count)
{
try {
int end;
start += off;
for (end = start; count > 0 && data [end] != 0; end++)
count--;
// NOTE: this constructor doesn't exist
// in some embedded profiles
return new String (data, start, end - start, "8859_1");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException ("8859_1"); // "can't happen"
}
}
}
/** Exposes the fields of a memory status record. */
final static public class MemoryStatus extends Data
{
MemoryStatus (Rio500 dev, byte buf []) { super (dev, buf); }
// 2 bytes ?
public int getBlockSize () { return getU16 (2); }
public int getBlockCount () { return getU16 (4); }
public int getFirstFreeBlock () { return getU16 (6); }
public int getNumUnusedBlocks () { return getU16 (8); }
// 4 bytes ?
// 4 bytes ?
}
/** Exposes the fields desribing a folder. */
final static public class FolderEntry extends Data
{
private boolean external;
private int folderNumber;
FolderEntry (Rio500 dev, boolean e, int folder, Data d, int off)
{
super (dev, d.data, d.off + off);
external = e;
folderNumber = folder;
}
public int getFolderNumber () { return folderNumber; }
public int getOffset () { return getU16 (0); }
// 2 bytes ? /2
public int getFirstFreeEntryOffset () { return getU16 (4); }
// 2 bytes ? /6
// 4 bytes ? /8
// 4 bytes ? /12
public int getTime () { return getU16 (16); }
// Bitmap /20
public String getName1 () { return getString (1558, 362); }
public String getName2 () { return getString (1920, 128); }
// song entries are eight per block (like folders)
public int getSongCount ()
{ return getFirstFreeEntryOffset () / SONG_ENTRY_SIZE; }
public SongEntry [] getSongs ()
throws IOException
{
int temp = getFirstFreeEntryOffset ();
// a lot of these calculations feel quite odd
// they're from the c code
int blocks = temp / BLOCKSIZE;
int count = 8 * blocks;
temp %= BLOCKSIZE;
if (temp > 0)
blocks++;
count += temp / SONG_ENTRY_SIZE;
byte data [] = new byte [blocks * BLOCKSIZE];
SongEntry retval [] = new SongEntry [count];
int address = getFolderNumber ();
address <<= 8;
address |= 0x0ff;
address &= 0xfff;
rio.read (external, address, data, 0, data.length);
address = 0;
for (int i = 0; i < retval.length; i++) {
retval [i] = new SongEntry (this, data, address);
address += SONG_ENTRY_SIZE;
}
return retval;
}
/** Returns true if the folder is on a removable memory card */
public boolean isExternal () { return external; }
// upload song
// download song
// delete song
// rename song
}
/**
* Represents the information known about each song.
*/
static final public class SongEntry extends Data
{
private FolderEntry folder;
SongEntry (FolderEntry f, byte buf [], int off)
{ super (f.rio, buf, off); folder = f; }
public int getOffset () { return getU16 (0); }
// 2 bytes ?/2
public int getLength () { return getU32 (4); }
// 2 bytes ?/8
// 2 bytes ?/10
public int getMP3Sig () { return getU32 (12); }
public int getTime () { return getU32 (16); }
// Bitmap/20
public String getName1 () { return getString (1558, 362); }
public String getName2 () { return getString (1920, 128); }
// for debug
public void dump ()
{
}
FolderEntry getFolder () { return folder; }
// long getSize () { return 0; }
// int getNumber () { return 0; }
}
/*
static final class Bitmap extends Data
{
// 2 bytes == #blocks
// 1536 bytes == bits
}
static final public class FolderLocation extends Data
{
// 2 bytes offset
// 2 bytes bytes
// 2 bytes folder num
}
// FOLDER OPS:
// add folder
// rename folder
// delete folder
// [get folder location]
// format
// set report func
// destroy content
// get content
// font operations
*/
/*==================================================================*/
// read and write chunks of memory starting at a given block
private void read (boolean external, int address, byte buf [], int off, int len)
throws IOException
{
int val;
int card = external ? 1 : 0;
if ((len % BLOCKSIZE) != 0)
throw new IllegalArgumentException ();
if ((val = get (RIO_SET_READ_PTR, address, card)) == 0
|| (val = get (RIO_SET_READ_LEN,
len / IO_SIZE_BIG,
len % IO_SIZE_BIG)) == 0)
throw new IOException ("rio read");
// value of the READ command appears to be bytecount (len).
socket.getInputStream ().read (buf, off, len);
}
private void write (int address, byte buf [], int off, int len)
throws IOException
{
int val;
if ((len % BLOCKSIZE) != 0)
throw new IllegalArgumentException ();
if ((val = get (RIO_UNKNOWN_4C, address, 0)) == 0
|| (val = get (RIO_UNKNOWN_4F, address, 0)) == 0
|| (val = get (RIO_WRITE,
len / IO_SIZE_BIG,
len % IO_SIZE_BIG)) == 0)
throw new IOException ("rio write");
socket.getOutputStream ().write (buf, off, len);
}
/*==================================================================*/
// sends 32 bits with request code; receives 32 bits back
// 0 indicates failure
private int get (byte req, int value, int index)
throws IOException
{
synchronized (msg) {
return new Data (this, rioRead (req, value, index, 4)).getU32 (0);
}
}
// synchronize on 'msg' before calling this
private byte [] rioRead (byte req, int value, int index, int length)
throws IOException
{
msg.setRequestType ((byte) (ControlMessage.DIR_TO_HOST
| ControlMessage.RECIPIENT_DEVICE
| ControlMessage.TYPE_VENDOR));
msg.setRequest (req);
msg.setValue ((short)value);
msg.setIndex ((short)index);
msg.setLength (length);
socket.getDevice ().control (msg);
return msg.getBuffer ();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -