mirror of
https://github.com/holub/mame
synced 2025-07-01 16:19:38 +03:00
ch376 updates [R. Belmont]
- Ignore non-8.3 compliant filenames when generating the directory since CH376 is super-tied to FAT12 semantics - Implement CHECK_EXIST command for BBC Micro - Implement undocumented command 0x16, also for BBC Micro - Fix status return from SET_USB_MODE
This commit is contained in:
parent
2077c7dca0
commit
488e60b3ab
@ -2,24 +2,25 @@
|
|||||||
// copyright-holders:R. Belmont
|
// copyright-holders:R. Belmont
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
|
||||||
ch376.h
|
ch376.cpp
|
||||||
|
|
||||||
"File manage and control chip CH376"
|
"File manage and control chip CH376"
|
||||||
https://www.mpja.com/download/ch376ds1.pdf
|
https://www.mpja.com/download/ch376ds1.pdf
|
||||||
|
https://github.com/djuseeq/Ch376msc/blob/master/src/CommDef.h
|
||||||
|
|
||||||
This is a module intended to offload USB and USB mass storage
|
This is a module intended to offload USB and USB mass storage
|
||||||
I/O from a small microcontroller or microprocessor.
|
I/O from a small microcontroller or microprocessor.
|
||||||
|
|
||||||
It has 3 host interfaces:
|
It has 3 host interfaces:
|
||||||
1) A regular 8-bit bus with 8 data lines, an address line,
|
1) A regular 8-bit bus with 8 data lines, an address line,
|
||||||
chip select, read enable, and write enable lines
|
chip select, read enable, and write enable lines
|
||||||
2) An SPI bus interface (SCS, SCK, MOSI, MISO lines)
|
2) An SPI bus interface (SCS, SCK, MOSI, MISO lines)
|
||||||
3) An asynchronous serial interface (TxD and RxD lines)
|
3) An asynchronous serial interface (TxD and RxD lines)
|
||||||
|
|
||||||
And 2 guest interfaces: USB 2.0 and a second 4-wire SPI bus for SD/MMC/TF cards.
|
And 2 guest interfaces: USB 2.0 and a second 4-wire SPI bus for SD/MMC/TF cards.
|
||||||
|
|
||||||
The module can give high level directory/open/close/read/write access to
|
The module can give high level directory/open/close/read/write access to
|
||||||
files on a FAT12, FAT16, or FAT32 filesystem.
|
files on a FAT12, FAT16, or FAT32 filesystem.
|
||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
@ -44,7 +45,11 @@ static constexpr u8 STATUS_USB_INT_DISK_WRITE = 0x1e;
|
|||||||
static constexpr u8 STATUS_USB_INT_DISK_ERR = 0x1f;
|
static constexpr u8 STATUS_USB_INT_DISK_ERR = 0x1f;
|
||||||
static constexpr u8 STATUS_ERR_MISS_FILE = 0x42;
|
static constexpr u8 STATUS_ERR_MISS_FILE = 0x42;
|
||||||
|
|
||||||
|
// despite the name, this isn't a command
|
||||||
|
static constexpr u8 CMD_RET_SUCCESS = 0x51;
|
||||||
|
|
||||||
static constexpr u8 CMD_GET_IC_VER = 0x01;
|
static constexpr u8 CMD_GET_IC_VER = 0x01;
|
||||||
|
static constexpr u8 CMD_CHECK_EXIST = 0x06;
|
||||||
static constexpr u8 CMD_GET_FILE_SIZE = 0x0c;
|
static constexpr u8 CMD_GET_FILE_SIZE = 0x0c;
|
||||||
static constexpr u8 CMD_SET_USB_MODE = 0x15;
|
static constexpr u8 CMD_SET_USB_MODE = 0x15;
|
||||||
static constexpr u8 CMD_GET_STATUS = 0x22;
|
static constexpr u8 CMD_GET_STATUS = 0x22;
|
||||||
@ -144,8 +149,18 @@ void ch376_device::write(offs_t offset, u8 data)
|
|||||||
m_last_command = data;
|
m_last_command = data;
|
||||||
switch (data)
|
switch (data)
|
||||||
{
|
{
|
||||||
|
case 0x16: // not a documented valid command, but apparently used by the BBC Micro software
|
||||||
|
m_dataBuffer[0] = m_int_status = STATUS_USB_INT_CONNECT;
|
||||||
|
m_dataPtr = 0;
|
||||||
|
m_dataLen = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_CHECK_EXIST:
|
||||||
|
m_state = STATE_CHECK_EXIST;
|
||||||
|
break;
|
||||||
|
|
||||||
case CMD_GET_IC_VER:
|
case CMD_GET_IC_VER:
|
||||||
m_dataBuffer[0] = 0x41; //
|
m_dataBuffer[0] = 0x41;
|
||||||
m_dataPtr = 0;
|
m_dataPtr = 0;
|
||||||
m_dataLen = 1;
|
m_dataLen = 1;
|
||||||
break;
|
break;
|
||||||
@ -187,13 +202,13 @@ void ch376_device::write(offs_t offset, u8 data)
|
|||||||
|
|
||||||
case CMD_FILE_OPEN:
|
case CMD_FILE_OPEN:
|
||||||
/*
|
/*
|
||||||
CH376 allows paths with a leading / or \ to indicate the root of the SD card.
|
CH376 allows paths with a leading / or \ to indicate the root of the SD card.
|
||||||
Directories are chained by an unusual method: start with the root dir (leading path separator),
|
Directories are chained by an unusual method: start with the root dir (leading path separator),
|
||||||
then open each subdirectory without a leading path separator, and finally open the file without
|
then open each subdirectory without a leading path separator, and finally open the file without
|
||||||
a leading path separator.
|
a leading path separator.
|
||||||
|
|
||||||
The BOOTI card ignores directories entirely, so the implmentation here is not tested with that
|
The BOOTI card ignores directories entirely, so the implmentation here is not tested with that
|
||||||
scenario but it should work.
|
scenario but it should work.
|
||||||
*/
|
*/
|
||||||
if (m_file_name[strlen(m_file_name) - 1] == '*')
|
if (m_file_name[strlen(m_file_name) - 1] == '*')
|
||||||
{
|
{
|
||||||
@ -258,7 +273,7 @@ void ch376_device::write(offs_t offset, u8 data)
|
|||||||
{
|
{
|
||||||
m_int_status = STATUS_USB_INT_DISK_READ;
|
m_int_status = STATUS_USB_INT_DISK_READ;
|
||||||
}
|
}
|
||||||
else // end of directory
|
else // end of directory
|
||||||
{
|
{
|
||||||
m_int_status = STATUS_ERR_MISS_FILE;
|
m_int_status = STATUS_ERR_MISS_FILE;
|
||||||
}
|
}
|
||||||
@ -327,8 +342,17 @@ void ch376_device::write(offs_t offset, u8 data)
|
|||||||
{
|
{
|
||||||
switch (m_state)
|
switch (m_state)
|
||||||
{
|
{
|
||||||
|
case STATE_CHECK_EXIST:
|
||||||
|
m_data = (data ^ 0xff);
|
||||||
|
m_state = STATE_IDLE;
|
||||||
|
break;
|
||||||
|
|
||||||
case STATE_USB_MODE_SET:
|
case STATE_USB_MODE_SET:
|
||||||
m_state = STATE_IDLE;
|
m_state = STATE_IDLE;
|
||||||
|
if ((data == 0x6) || (data == 0x7))
|
||||||
|
{
|
||||||
|
m_data = CMD_RET_SUCCESS;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_SET_FILE_NAME:
|
case STATE_SET_FILE_NAME:
|
||||||
@ -426,7 +450,7 @@ bool ch376_device::generateNextDirEntry()
|
|||||||
if (ourEntry->type == osd::directory::entry::entry_type::DIR)
|
if (ourEntry->type == osd::directory::entry::entry_type::DIR)
|
||||||
{
|
{
|
||||||
strncpy(reinterpret_cast<char *>(&m_dataBuffer[1]), ourEntry->name, 8);
|
strncpy(reinterpret_cast<char *>(&m_dataBuffer[1]), ourEntry->name, 8);
|
||||||
m_dataBuffer[0xc] = 0x10; // directory type
|
m_dataBuffer[0xc] = 0x10; // directory type
|
||||||
}
|
}
|
||||||
else if (ourEntry->type == osd::directory::entry::entry_type::FILE)
|
else if (ourEntry->type == osd::directory::entry::entry_type::FILE)
|
||||||
{
|
{
|
||||||
@ -440,6 +464,13 @@ bool ch376_device::generateNextDirEntry()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// is this an 8.3 filename? CH376 can only really cope with 8.3, so
|
||||||
|
// skip this entry and recurse to get the next one.
|
||||||
|
if (dotIdx > 8)
|
||||||
|
{
|
||||||
|
return generateNextDirEntry();
|
||||||
|
}
|
||||||
|
|
||||||
int baseLen = std::min(8, dotIdx);
|
int baseLen = std::min(8, dotIdx);
|
||||||
for (int idx = 0; idx < baseLen; idx++)
|
for (int idx = 0; idx < baseLen; idx++)
|
||||||
{
|
{
|
||||||
@ -465,7 +496,7 @@ bool ch376_device::generateNextDirEntry()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dataBuffer[0xc] = 0; // no attributes
|
m_dataBuffer[0xc] = 0; // no attributes
|
||||||
|
|
||||||
if (ourEntry->size >= u64(0x100000000))
|
if (ourEntry->size >= u64(0x100000000))
|
||||||
{
|
{
|
||||||
@ -482,7 +513,7 @@ bool ch376_device::generateNextDirEntry()
|
|||||||
m_dataBuffer[0x20] = ((ourEntry->size >> 24) & 0xff);
|
m_dataBuffer[0x20] = ((ourEntry->size >> 24) & 0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // not a file or directory, recurse and hope the next one's better
|
else // not a file or directory, recurse and hope the next one's better
|
||||||
{
|
{
|
||||||
return generateNextDirEntry();
|
return generateNextDirEntry();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user