X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FUSB%2FMSC%2Fmain.c;h=94d258a6b5842cbbbda6838f433568fb3b0d2da7;hb=11dbd684e9a3d907d43d71a3145205f1a86992fb;hp=6d64b7bb7bb71d56734f1de826c233c34437dc6c;hpb=587ebbbb92ed0610562ca059121c263e1faa19dd;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/USB/MSC/main.c b/KernelLand/Modules/USB/MSC/main.c index 6d64b7bb..94d258a6 100644 --- a/KernelLand/Modules/USB/MSC/main.c +++ b/KernelLand/Modules/USB/MSC/main.c @@ -14,7 +14,7 @@ // === PROTOTYPES === int MSC_Initialise(char **Arguments); -void MSC_Cleanup(void); + int 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 @@ -43,22 +43,54 @@ int MSC_Initialise(char **Arguments) return 0; } -void MSC_Cleanup(void) +int MSC_Cleanup(void) { + return 0; } 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 - + tLVM_VolType *vt; + info = malloc( sizeof(*info) ); - USB_SetDeviceDataPtr(Dev, info); - - info->BlockCount = MSC_SCSI_GetSize(Dev, &info->BlockSize); + USB_SetDeviceDataPtr(Dev, info); - LVM_AddVolume(&gMSC_SCSI_VolType, "0", Dev, info->BlockSize, info->BlockCount); + // Get the class code (and hence what command set is in use) + Uint8 sc = (USB_GetInterfaceClass(Dev) & 0x00FF00) >> 8; + switch( sc ) + { + // SCSI Transparent Command Set + case 0x06: + info->BlockCount = MSC_SCSI_GetSize(Dev, &info->BlockSize); + vt = &gMSC_SCSI_VolType; + break; + // Unknown, prepare to chuck sad + default: + Log_Error("USB MSC", "Unknown sub-class 0x%02x", sc); + USB_SetDeviceDataPtr(Dev, NULL); + free(info); + return ; + } + + // Create device name from Vendor ID, Device ID and Serial Number + Uint16 vendor, devid; + char *serial_number; + USB_GetDeviceVendor(Dev, &vendor, &devid); + serial_number = USB_GetSerialNumber(Dev); + if( !serial_number ) { + // No serial number - this breaks spec, but it's easy to handle + Log_Warning("USB MSC", "Device does not have a serial number, using a random one"); + serial_number = malloc(4+8+1); + sprintf(serial_number, "rand%08x", rand()); + } + char name[4 + 4 + 1 + 4 + 1 + strlen(serial_number) + 1]; + sprintf(name, "usb-%04x:%04x-%s", vendor, devid, serial_number); + free(serial_number); + + // Pass the buck to LVM + LOG("Device '%s' has 0x%llx blocks of 0x%x bytes", name, info->BlockCount, info->BlockSize); + LVM_AddVolume(vt, name, Dev, info->BlockSize, info->BlockCount); } void MSC_DataIn(tUSBInterface *Dev, int EndPt, int Length, void *Data) @@ -66,6 +98,9 @@ void MSC_DataIn(tUSBInterface *Dev, int EndPt, int Length, void *Data) // Will this ever be needed? } +/** + * \brief Create a CBW structure + */ int MSC_int_CreateCBW(tMSC_CBW *Cbw, int bInput, size_t CmdLen, const void *CmdData, size_t DataLen) { if( CmdLen == 0 ) { @@ -79,10 +114,10 @@ int MSC_int_CreateCBW(tMSC_CBW *Cbw, int bInput, size_t CmdLen, const void *CmdD } Cbw->dCBWSignature = LittleEndian32(0x43425355); - Cbw->dCBWTag = giMSC_NextTag ++; + Cbw->dCBWTag = giMSC_NextTag ++; Cbw->dCBWDataTransferLength = LittleEndian32(DataLen); Cbw->bmCBWFlags = (bInput ? 0x80 : 0x00); - Cbw->bCBWLUN = 0; // TODO: Logical Unit Number (param from proto) + Cbw->bCBWLUN = 0; // TODO: Logical Unit Number (param from proto) Cbw->bCBWLength = CmdLen; memcpy(Cbw->CBWCB, CmdData, CmdLen); @@ -95,7 +130,6 @@ void MSC_SendData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t 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 ; @@ -104,10 +138,7 @@ void MSC_SendData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t 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); - } + USB_SendData(Dev, endpoint_out, DataLen, Data); // Read CSW USB_RecvData(Dev, endpoint_in, sizeof(csw), &csw); @@ -120,8 +151,7 @@ void MSC_RecvData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t 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 ; @@ -129,11 +159,8 @@ void MSC_RecvData(tUSBInterface *Dev, size_t CmdLen, const void *CmdData, size_t 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); - } + // TODO: use async version and wait for the transaction to complete + USB_RecvData(Dev, endpoint_in, DataLen, Data); // Read CSW USB_RecvData(Dev, endpoint_in, sizeof(csw), &csw);