Modules/USB - Added prototype mass storage driver
authorJohn Hodge <[email protected]>
Sat, 19 May 2012 13:52:03 +0000 (21:52 +0800)
committerJohn Hodge <[email protected]>
Sat, 19 May 2012 13:52:03 +0000 (21:52 +0800)
BuildConf/x86/default.mk
KernelLand/Modules/USB/MSC/Makefile [new file with mode: 0644]
KernelLand/Modules/USB/MSC/common.h [new file with mode: 0644]
KernelLand/Modules/USB/MSC/main.c [new file with mode: 0644]
KernelLand/Modules/USB/MSC/msc_proto.h [new file with mode: 0644]
KernelLand/Modules/USB/MSC/scsi.c [new file with mode: 0644]
KernelLand/Modules/USB/MSC/scsi.h [new file with mode: 0644]

index 51bb9fc..274e559 100644 (file)
@@ -11,5 +11,5 @@ MODULES += x86/ISADMA x86/VGAText
 
 MODULES += USB/Core USB/UHCI
 #USB/OHCI
-MODULES += USB/HID
+MODULES += USB/HID USB/MSC
 #MODULES += Interfaces/UDI
diff --git a/KernelLand/Modules/USB/MSC/Makefile b/KernelLand/Modules/USB/MSC/Makefile
new file mode 100644 (file)
index 0000000..bb53fc9
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Acess2 USB MSC Driver
+#
+
+OBJ = main.o scsi.o
+CPPFLAGS = -I../Core/include
+NAME = MSC
+
+-include ../Makefile.tpl
+
diff --git a/KernelLand/Modules/USB/MSC/common.h b/KernelLand/Modules/USB/MSC/common.h
new file mode 100644 (file)
index 0000000..f459080
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Acess2 USB Stack Mass Storage Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * common.h
+ * - Common header
+ */
+#ifndef _MSC__COMMON_H_
+#define _MSC__COMMON_H_
+
+#include <usb_core.h>
+#include <Storage/LVM/include/lvm.h>
+
+typedef struct sMSCInfo        tMSCInfo;
+
+struct sMSCInfo
+{
+       Uint64  BlockCount;
+       size_t  BlockSize;
+};
+
+extern void    MSC_SendData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t DataLen, const void *Data);
+extern void    MSC_RecvData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t DataLen, void *Data);
+
+extern tLVM_VolType    gMSC_SCSI_VolType;
+extern Uint64 MSC_SCSI_GetSize(tUSBInterface *Dev, size_t *BlockSize);
+#endif
+
diff --git a/KernelLand/Modules/USB/MSC/main.c b/KernelLand/Modules/USB/MSC/main.c
new file mode 100644 (file)
index 0000000..6d64b7b
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Acess2 USB Stack Mass Storage Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Driver Core
+ */
+#define DEBUG  1
+#define VERSION        VER2(0,1)
+#include <acess.h>
+#include <modules.h>
+#include "common.h"
+#include "msc_proto.h"
+
+// === PROTOTYPES ===
+ int   MSC_Initialise(char **Arguments);
+void   MSC_Cleanup(void);
+void   MSC_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t DescriptorsLen);
+void   MSC_DataIn(tUSBInterface *Dev, int EndPt, int Length, void *Data);
+// --- Internal Helpers
+ int   MSC_int_CreateCBW(tMSC_CBW *Cbw, int bInput, size_t CmdLen, const void *CmdData, size_t DataLen);
+void   MSC_SendData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t DataLen, const void *Data);
+void   MSC_RecvData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t DataLen, void *Data);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, USB_MSC, MSC_Initialise, MSC_Cleanup, "USB_Core", NULL);
+tUSBDriver     gMSC_Driver_BulkOnly = {
+       .Name = "MSC_BulkOnly",
+       .Match = {.Class = {0x080050, 0xFF00FF}},
+       .Connected = MSC_DeviceConnected,
+       .MaxEndpoints = 2,
+       .Endpoints = {
+               {0x82, MSC_DataIn},
+               {0x02, NULL},
+               }
+       };
+int giMSC_NextTag;
+
+// === CODE ===
+int MSC_Initialise(char **Arguments)
+{
+       USB_RegisterDriver( &gMSC_Driver_BulkOnly );
+       return 0;
+}
+
+void MSC_Cleanup(void)
+{
+}
+
+void MSC_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t DescriptorsLen)
+{
+       tMSCInfo        *info;
+       // TODO: Get the class code (and hence what command set is in use)
+       // TODO: Get the maximum packet size too
+
+       info = malloc( sizeof(*info) );
+       USB_SetDeviceDataPtr(Dev, info);        
+
+       info->BlockCount = MSC_SCSI_GetSize(Dev, &info->BlockSize);
+       
+       LVM_AddVolume(&gMSC_SCSI_VolType, "0", Dev, info->BlockSize, info->BlockCount);
+}
+
+void MSC_DataIn(tUSBInterface *Dev, int EndPt, int Length, void *Data)
+{
+       // Will this ever be needed?
+}
+
+int MSC_int_CreateCBW(tMSC_CBW *Cbw, int bInput, size_t CmdLen, const void *CmdData, size_t DataLen)
+{
+       if( CmdLen == 0 ) {
+               Log_Error("MSC", "Zero length commands are invalid");
+               return -1;
+       }
+       
+       if( CmdLen > 16 ) {
+               Log_Error("MSC", "Command data >16 bytes (%i)", CmdLen);
+               return -1;
+       }
+       
+       Cbw->dCBWSignature = LittleEndian32(0x43425355);
+       Cbw->dCBWTag = giMSC_NextTag ++;
+       Cbw->dCBWDataTransferLength = LittleEndian32(DataLen);
+       Cbw->bmCBWFlags = (bInput ? 0x80 : 0x00);
+       Cbw->bCBWLUN = 0;       // TODO: Logical Unit Number (param from proto)
+       Cbw->bCBWLength = CmdLen;
+       memcpy(Cbw->CBWCB, CmdData, CmdLen);
+       
+       return 0;
+}
+
+void MSC_SendData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t DataLen, const void *Data)
+{
+       tMSC_CBW        cbw;
+       tMSC_CSW        csw;
+       const int       endpoint_out = 2;
+       const int       endpoint_in = 1;
+       const int       max_packet_size = 64;
+       
+       if( MSC_int_CreateCBW(&cbw, 0, CmdLen, CmdData, DataLen) )
+               return ;
+       
+       // Send CBW
+       USB_SendData(Dev, endpoint_out, sizeof(cbw), &cbw);
+       
+       // Send Data
+       for( size_t ofs = 0; ofs < DataLen; ofs += max_packet_size )
+       {
+               USB_SendData(Dev, endpoint_out, MIN(max_packet_size, DataLen - ofs), Data + ofs);
+       }
+       
+       // Read CSW
+       USB_RecvData(Dev, endpoint_in, sizeof(csw), &csw);
+       // TODO: Validate CSW
+}
+
+void MSC_RecvData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t DataLen, void *Data)
+{
+       tMSC_CBW        cbw;
+       tMSC_CSW        csw;
+       const int       endpoint_out = 2;
+       const int       endpoint_in = 1;
+       const int       max_packet_size = 64;
+       
+       if( MSC_int_CreateCBW(&cbw, 1, CmdLen, CmdData, DataLen) )
+               return ;
+       
+       // Send CBW
+       USB_SendData(Dev, endpoint_out, sizeof(cbw), &cbw);
+       
+       // Read Data
+       for( size_t ofs = 0; ofs < DataLen; ofs += max_packet_size )
+       {
+               // TODO: use async version and wait for the transaction to complete
+               USB_RecvData(Dev, endpoint_in, MIN(max_packet_size, DataLen - ofs), Data + ofs);
+       }
+       
+       // Read CSW
+       USB_RecvData(Dev, endpoint_in, sizeof(csw), &csw);
+       // TODO: Validate CSW
+}
+
diff --git a/KernelLand/Modules/USB/MSC/msc_proto.h b/KernelLand/Modules/USB/MSC/msc_proto.h
new file mode 100644 (file)
index 0000000..913822f
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Acess2 USB Stack Mass Storage Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Driver Core
+ */
+#ifndef _MSC__MSC_PROTO_H_
+#define _MSC__MSC_PROTO_H_
+
+typedef struct sMSC_CBW        tMSC_CBW;
+typedef struct sMSC_CSW        tMSC_CSW;
+
+struct sMSC_CBW
+{
+       Uint32  dCBWSignature;  // = 0x43425355
+       Uint32  dCBWTag;
+       Uint32  dCBWDataTransferLength;
+       Uint8   bmCBWFlags;
+       Uint8   bCBWLUN;
+       Uint8   bCBWLength;
+       Uint8   CBWCB[16];
+};
+
+struct sMSC_CSW
+{
+       Uint32  dCSWSignature;  // = 0x53425355
+       Uint32  dCSWTag;
+       Uint32  dCSWDataResidue;
+       Uint8   dCSWStatus;
+};
+
+#endif
diff --git a/KernelLand/Modules/USB/MSC/scsi.c b/KernelLand/Modules/USB/MSC/scsi.c
new file mode 100644 (file)
index 0000000..c4220d8
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Acess2 USB Stack Mass Storage Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * scsi.c
+ * - "SCSI Transparent Command Set" handling code
+ */
+#define DEBUG  0
+#include "common.h"
+#include "scsi.h"
+
+// === PROTOTYPES ===
+Uint64 MSC_SCSI_GetSize(tUSBInterface *Dev, size_t *BlockSize);
+int    MSC_SCSI_ReadData(void *Ptr, Uint64 Block, size_t Count, void *Dest);
+int    MSC_SCSI_WriteData(void *Ptr, Uint64 Block, size_t Count, const void *Dest);
+
+// === GLOBALS ===
+tLVM_VolType   gMSC_SCSI_VolType = {
+       .Name = "USB-MSC-SCSI",
+       .Read = MSC_SCSI_ReadData,
+       .Write = MSC_SCSI_WriteData
+       };
+
+// === CODE ===
+Uint64 MSC_SCSI_GetSize(tUSBInterface *Dev, size_t *BlockSize)
+{
+       struct sSCSI_Cmd_ReadCapacity16 cmd;
+       struct sSCSI_Ret_ReadCapacity16 ret;
+       
+       cmd.Op   = 0x9E;
+       cmd.Svc  = 0x10;
+       cmd.LBA  = BigEndian64( 0 );
+       cmd.AllocationLength = BigEndian32(sizeof(ret));
+       cmd.Flags   = 0;
+       cmd.Control = 0;
+
+       ret.BlockSize = 0;
+       ret.BlockCount = 0;     
+       MSC_RecvData(Dev, sizeof(cmd), &cmd, sizeof(ret), &ret);
+       
+       *BlockSize = BigEndian32(ret.BlockSize);
+       return BigEndian64(ret.BlockCount);
+}
+
+int MSC_SCSI_ReadData(void *Ptr, Uint64 Block, size_t Count, void *Dest)
+{
+       tUSBInterface   *Dev = Ptr;
+       tMSCInfo        *info = USB_GetDeviceDataPtr(Dev);
+       struct sSCSI_Cmd_Read16 cmd;
+
+       // TODO: Bounds checking?
+       
+       cmd.Op     = 0x88;
+       cmd.Flags  = 0;
+       cmd.LBA    = BigEndian64(Block);
+       cmd.Length = BigEndian32(Count);
+       cmd.GroupNumber = 0;
+       cmd.Control = 0;
+       
+       MSC_RecvData(Dev, sizeof(cmd), &cmd, Count*info->BlockSize, Dest);
+       // TODO: Error check    
+
+       return Count;
+}
+
+int MSC_SCSI_WriteData(void *Ptr, Uint64 Block, size_t Count, const void *Data)
+{
+       Log_Warning("MSC_SCSI", "TODO: Impliment MSC_SCSI_WriteData");
+       return 0;
+}
+
diff --git a/KernelLand/Modules/USB/MSC/scsi.h b/KernelLand/Modules/USB/MSC/scsi.h
new file mode 100644 (file)
index 0000000..4795989
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Acess2 USB Stack Mass Storage Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * scsi.h
+ * - "SCSI Transparent Command Set" handling code
+ */
+#ifndef _MSC__SCSI_H_
+#define _MSC__SCSI_H_
+
+// NOTE: All commands are big-endian
+
+struct sSCSI_Cmd_ReadCapacity16
+{
+       Uint8   Op;     // 0x9E
+       Uint8   Svc;    // 0x10
+       Uint64  LBA;    //
+       Uint32  AllocationLength;
+       Uint8   Flags;
+       Uint8   Control;
+} PACKED;
+
+struct sSCSI_Ret_ReadCapacity16
+{
+       Uint64  BlockCount;
+       Uint32  BlockSize;
+       Uint8   Flags;
+       Uint8   _resvd[32-13];
+} PACKED;
+
+struct sSCSI_Cmd_Read16
+{
+       Uint8   Op;     // 0x88
+       Uint8   Flags;
+       Uint64  LBA;
+       Uint32  Length;
+       Uint8   GroupNumber;
+       Uint8   Control;
+} PACKED;
+
+#endif
+

UCC git Repository :: git.ucc.asn.au