2 * Acess2 USB Stack Mass Storage Driver
3 * - By John Hodge (thePowersGang)
9 #define VERSION VER2(0,1)
13 #include "msc_proto.h"
16 int MSC_Initialise(char **Arguments);
17 void MSC_Cleanup(void);
18 void MSC_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t DescriptorsLen);
19 void MSC_DataIn(tUSBInterface *Dev, int EndPt, int Length, void *Data);
20 // --- Internal Helpers
21 int MSC_int_CreateCBW(tMSC_CBW *Cbw, int bInput, size_t CmdLen, const void *CmdData, size_t DataLen);
22 void MSC_SendData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t DataLen, const void *Data);
23 void MSC_RecvData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t DataLen, void *Data);
26 MODULE_DEFINE(0, VERSION, USB_MSC, MSC_Initialise, MSC_Cleanup, "USB_Core", NULL);
27 tUSBDriver gMSC_Driver_BulkOnly = {
28 .Name = "MSC_BulkOnly",
29 .Match = {.Class = {0x080050, 0xFF00FF}},
30 .Connected = MSC_DeviceConnected,
40 int MSC_Initialise(char **Arguments)
42 USB_RegisterDriver( &gMSC_Driver_BulkOnly );
46 void MSC_Cleanup(void)
50 void MSC_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t DescriptorsLen)
53 // TODO: Get the class code (and hence what command set is in use)
54 // TODO: Get the maximum packet size too
56 info = malloc( sizeof(*info) );
57 USB_SetDeviceDataPtr(Dev, info);
59 info->BlockCount = MSC_SCSI_GetSize(Dev, &info->BlockSize);
61 LOG("Device has 0x%llx blocks of 0x%x bytes",
62 info->BlockCount, info->BlockSize);
63 // TODO: Get serial number
64 LVM_AddVolume(&gMSC_SCSI_VolType, "usb0", Dev, info->BlockSize, info->BlockCount);
67 void MSC_DataIn(tUSBInterface *Dev, int EndPt, int Length, void *Data)
69 // Will this ever be needed?
72 int MSC_int_CreateCBW(tMSC_CBW *Cbw, int bInput, size_t CmdLen, const void *CmdData, size_t DataLen)
75 Log_Error("MSC", "Zero length commands are invalid");
80 Log_Error("MSC", "Command data >16 bytes (%i)", CmdLen);
84 Cbw->dCBWSignature = LittleEndian32(0x43425355);
85 Cbw->dCBWTag = giMSC_NextTag ++;
86 Cbw->dCBWDataTransferLength = LittleEndian32(DataLen);
87 Cbw->bmCBWFlags = (bInput ? 0x80 : 0x00);
88 Cbw->bCBWLUN = 0; // TODO: Logical Unit Number (param from proto)
89 Cbw->bCBWLength = CmdLen;
90 memcpy(Cbw->CBWCB, CmdData, CmdLen);
95 void MSC_SendData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t DataLen, const void *Data)
99 const int endpoint_out = 2;
100 const int endpoint_in = 1;
101 const int max_packet_size = 64;
103 if( MSC_int_CreateCBW(&cbw, 0, CmdLen, CmdData, DataLen) )
107 USB_SendData(Dev, endpoint_out, sizeof(cbw), &cbw);
110 for( size_t ofs = 0; ofs < DataLen; ofs += max_packet_size )
112 USB_SendData(Dev, endpoint_out, MIN(max_packet_size, DataLen - ofs), Data + ofs);
116 USB_RecvData(Dev, endpoint_in, sizeof(csw), &csw);
117 // TODO: Validate CSW
120 void MSC_RecvData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t DataLen, void *Data)
124 const int endpoint_out = 2;
125 const int endpoint_in = 1;
126 const int max_packet_size = 64;
128 if( MSC_int_CreateCBW(&cbw, 1, CmdLen, CmdData, DataLen) )
133 USB_SendData(Dev, endpoint_out, sizeof(cbw), &cbw);
136 for( size_t ofs = 0; ofs < DataLen; ofs += max_packet_size )
138 LOG("Read bytes 0x%x+0x%x", ofs, MIN(max_packet_size, DataLen - ofs));
139 // TODO: use async version and wait for the transaction to complete
140 USB_RecvData(Dev, endpoint_in, MIN(max_packet_size, DataLen - ofs), Data + ofs);
145 USB_RecvData(Dev, endpoint_in, sizeof(csw), &csw);
146 // TODO: Validate CSW