/* Copyright (C) 2000 Andy Sherwood (enigmax@home.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // Most of this object is self-explanitory... // Rio500.h : Declaration of the CRio500 #ifndef __RIO500_H_ #define __RIO500_H_ #include "resource.h" // main symbols #include "Rio500RemixCP.h" #include // Some constants we use again and again... const unsigned RIO_TEXTGRAPHICSHEIGHT = 16; const unsigned RIO_TEXTGRAPHICSWIDTH = 768; const unsigned RIO_BITMAPSIZE = 1536; const unsigned RIO_BLOCKSIZE = 0x4000; const unsigned RIO_BIGBLOCKSIZE = 0x10000; const unsigned RIO_HUGEBLOCKSIZE = 0x100000; ///////////////////////////////////////////////////////////////////////////// // CRio500 class ATL_NO_VTABLE CRio500 : public CComObjectRootEx, public CComCoClass, public IConnectionPointContainerImpl, public ISupportErrorInfo, public IDispatchImpl, public CProxy_IRio500Events< CRio500 > { enum RIO_DIRECTION { DIR_IN, DIR_OUT }; enum RIO_REQUEST { REQ_FIRMWARE = 0x40, REQ_NOP = 0x42, REQ_QUERY_OFFSET_LAST_WRITE = 0x43, REQ_READ_FROM_USB = 0x45, REQ_WRITE_TO_USB = 0x46, REQ_START_USB_COMM = 0x47, REQ_END_USB_COMM = 0x48, REQ_SET_WRITE_ADDRESS = 0x4C, REQ_RIO_FORMAT_DEVICE = 0x4D, REQ_QUERY_FOLDER_BLOCK = 0x4E, REQ_MYSTERY = 0x4F, REQ_QUERY_FREE_MEM = 0x50, REQ_SEND_FOLDER_LOCATION = 0x56, REQ_END_FOLDER_TRANSFERS = 0x58, REQ_QUERY_NUM_FOLDER_BLOCKS = 0x59 }; enum RIO_STATUS { RSTATUS_ERROR = 0, RSTATUS_OK = 1 }; // Inner class exception object we throw around (pun intended). Sets extended error info class CLocalException { public: CLocalException(HRESULT hr, LPCOLESTR wszError) : m_hr(hr) { AtlReportError(__uuidof(Rio500), wszError, __uuidof(IRio500), hr); } inline HRESULT GetErrorCode() { return m_hr; } protected: HRESULT m_hr; }; // Rio structures... struct SRioBitmapData { WORD wNumBlocks; BYTE Image[RIO_BITMAPSIZE]; }; struct SRioSongEntry { WORD wOffset; WORD wDunno1; DWORD dwLength; WORD wDunno2; WORD wDunno3; DWORD dwMP3Sig; DWORD dwTime; SRioBitmapData Bitmap; char szName1[362]; char szName2[128]; }; struct SRioFolderEntry { WORD wOffset; WORD wDunno1; WORD wFirstFreeEntryOfs; WORD wDunno2; DWORD dwDunno3; DWORD dwDunno4; DWORD dwTime; SRioBitmapData Bitmap; char szName1[362]; char szName2[128]; }; struct SRioMemStatus { WORD wDunno1; WORD wBlockSize; WORD wNumBlocks; WORD wFirstFreeBlock; WORD wNumUnusedBlocks; DWORD dwDunno2; DWORD dwDunno3; }; struct SRioFolderLocation { WORD wOffset; WORD wBytes; WORD wFolderNum; }; // STL collections we'll be using.. typedef std::vector SONGENTRYLIST; typedef std::vector FOLDERENTRYLIST; public: CRio500(); ~CRio500(); DECLARE_REGISTRY_RESOURCEID(IDR_RIO500) DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct(); BEGIN_COM_MAP(CRio500) COM_INTERFACE_ENTRY(IRio500) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ISupportErrorInfo) COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer) END_COM_MAP() BEGIN_CONNECTION_POINT_MAP(CRio500) CONNECTION_POINT_ENTRY(DIID__IRio500Events) END_CONNECTION_POINT_MAP() // ISupportsErrorInfo STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid); // IRio500 public: STDMETHOD(Open)(); STDMETHOD(Close)(); STDMETHOD(get_ExtFlash)(/*[out, retval]*/ long *pVal); STDMETHOD(get_AvailableMemory)(/*[in]*/ long lFlash, /*[out, retval]*/ long *pVal); STDMETHOD(get_FirmwareVersion)(/*[out, retval]*/ long *pVal); STDMETHOD(Format)(/*[in]*/ long lFlash); STDMETHOD(AddFolder)(/*[in]*/ BSTR bsName, /*[in]*/ long lFlash); STDMETHOD(AddFolderEx)(/*[in]*/ IFolder* pFolder, /*[in]*/ long lFlash); STDMETHOD(RenameFolder)(/*[in]*/ long lFolderNum, /*[in]*/ BSTR bsNewName); STDMETHOD(DeleteFolder)(/*[in]*/ long lFolderNum, /*[in]*/ long lFlash); STDMETHOD(get_Folders)( /*[in]*/ long lFlash, /*[out, retval]*/ IFolders** ppFolders); STDMETHOD(AddSong)(/*[in]*/ long lFolder, /*[in]*/ BSTR bsName, /*[in]*/ BSTR bsSongFileName, /*[in]*/ long lFlash); STDMETHOD(AddSongEx)(/*[in]*/ ISong* pSong, /*[in]*/ long lFlash); STDMETHOD(RenameSong)(/*[in]*/ long lFolderNum, /*[in]*/ long lSongNum, /*[in]*/ BSTR bsNewName, /*[in]*/ long lFlash); STDMETHOD(DeleteSong)(/*[in]*/ long lFolderNum, /*[in]*/ long lSongNum, /*[in]*/ long lFlash); STDMETHOD(SwapSong)(/*[in]*/ long lFolderNum, /*[in]*/ long lSongNum1, /*[in]*/ long lSongNum2, /*[in]*/ long lFlash); STDMETHOD(get_Songs)(/*[in]*/ long lFlash, /*[in]*/ long lFolderNum, /*[out, retval]*/ ISongs** ppSongs); STDMETHOD(get_FontName)(/*[out, retval]*/ BSTR *pVal); STDMETHOD(put_FontName)(/*[in]*/ BSTR newVal); STDMETHOD(get_FontSize)(/*[out, retval]*/ long *pVal); STDMETHOD(put_FontSize)(/*[in]*/ long newVal); STDMETHOD(GetSong)(/*[in]*/ long lFolderNum, /*[in]*/ long lSongNum, /*[in]*/ BSTR bsSongFileName, /*[in]*/ long lFlash); // Protected methods protected: inline bool IsDriverOpened() { return m_hRio500 != INVALID_HANDLE_VALUE; } // In the order they were written... all of the protected methods of this object... int OpenDriver(); int OpenDriverRaw(); void CloseDriver(); bool StartComm(); bool EndComm(); DWORD SendCommand(RIO_REQUEST Req, WORD wValue, WORD wIndex); bool IORequest(RIO_DIRECTION Dir, RIO_REQUEST Req, WORD wValue, WORD wIndex, DWORD dwLen, void* pData); bool BuildTextBitmapInVariant(BSTR bsText, _variant_t& vDest, WORD& wBlocks); bool BuildTextBitmap(BSTR bsText, BYTE* pBitmapData, WORD& wBlocks); bool IsFirstFolder(long lFlash); FOLDERENTRYLIST ReadFolderEntries(long lFlash); bool BuildFolderEntry(IFolder* pFolder, SRioFolderEntry& NewFolder); bool AllocateEmptyFolderBlock(DWORD dwNumFolders, long lFlash); void ClearBlock(BYTE *pBlock); bool SendWriteCommand(DWORD dwAddress, DWORD dwNumBlocks, long lFlash); DWORD BulkWrite(void* pBlock, DWORD dwNumBytes); bool WriteFolderEntries(FOLDERENTRYLIST& Folders, long lFlash); bool SendFolderLocation(DWORD dwOffset, DWORD dwFolderNum, long lFlash); bool SendReadCommand(DWORD dwAddress, DWORD dwNumBlocks, long lFlash); DWORD BulkRead(void* pBlock, DWORD dwNumBytes); SONGENTRYLIST ReadSongEntries(SRioFolderEntry& Folder, DWORD dwFolderNum, long lFlash); bool WriteSongEntries(DWORD dwFolderNum, CRio500::SONGENTRYLIST& Songs, long lFlash); inline void NOP() { SendCommand(REQ_NOP, 0x0000, 0x00); } bool MP3ReadWord(DWORD* fhp, HANDLE hFile); DWORD GetFrameHeader(HANDLE hFile); DWORD IsFrameHeader(DWORD fh); bool MP3ReadByte(DWORD* fhp, HANDLE hFile); bool MP3ReadBlock (DWORD fh, HANDLE hFile); int SearchForFrameHeader (DWORD *fhp, HANDLE hFile); // Protected member variables protected: HANDLE m_hRio500; HANDLE m_hRio500Read; HANDLE m_hRio500Write; _bstr_t m_bsFontName; long m_lFontSize; }; #endif //__RIO500_H_