From 3e39f3e998538521830c10da09fe14c7a7dc66bd Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 28 Nov 2011 21:13:48 +0800 Subject: [PATCH] Modules/USB - Cleaning up protocol code, working on device API --- Modules/USB/Core/Makefile | 2 +- Modules/USB/Core/hub.c | 44 +++++-- Modules/USB/Core/include/usb_core.h | 4 + Modules/USB/Core/include/usb_hub.h | 3 +- Modules/USB/Core/usb.c | 173 +-------------------------- Modules/USB/Core/usb.h | 4 +- Modules/USB/Core/usb_lowlevel.c | 178 ++++++++++++++++++++++++++++ Modules/USB/Core/usb_lowlevel.h | 15 +++ Modules/USB/Core/usb_proto.h | 5 + 9 files changed, 243 insertions(+), 185 deletions(-) create mode 100644 Modules/USB/Core/usb_lowlevel.c create mode 100644 Modules/USB/Core/usb_lowlevel.h diff --git a/Modules/USB/Core/Makefile b/Modules/USB/Core/Makefile index 7e8c30d9..6ef0f03b 100644 --- a/Modules/USB/Core/Makefile +++ b/Modules/USB/Core/Makefile @@ -1,7 +1,7 @@ # # -OBJ = main.o usb.o +OBJ = main.o usb.o usb_lowlevel.o CPPFLAGS = -Iinclude NAME = Core diff --git a/Modules/USB/Core/hub.c b/Modules/USB/Core/hub.c index 552ab96e..22fed9dd 100644 --- a/Modules/USB/Core/hub.c +++ b/Modules/USB/Core/hub.c @@ -20,6 +20,14 @@ struct sHubDescriptor Uint8 DeviceRemovable[MAX_PORTS]; }; +struct sHubInfo +{ + tUSBHub *HubPtr; + int PowerOnDelay; // in ms + int nPorts; + Uint8 DeviceRemovable[]; +} + // === PROTOTYPES === void Hub_Connected(tUSBInterface *Dev); void Hub_Disconnected(tUSBInterface *Dev); @@ -40,33 +48,42 @@ tUSBDriver gUSBHub_Driver = { // === CODE === void Hub_Connected(tUSBInterface *Dev) { - struct sHubDescriptor *hub_desc; - - hub_desc = malloc(sizeof(*hub_desc)); - if(!hub_desc) { + struct sHubDescriptor hub_desc; + struct sHubInfo *info; + + // Read hub descriptor + USB_ReadDescriptor(Dev, 0x29, 0, sizeof(*hub_desc), hub_desc); + + // Allocate infomation structure + info = malloc(sizeof(*info) + (hub_desc.NbrPorts+7)/8); + if(!info) { Log_Error("USBHub", "malloc() failed"); return ; } - USB_SetDeviceDataPtr(Dev, hub_desc); + USB_SetDeviceDataPtr(Dev, info); - USB_ReadDescriptor(Dev, 0, 0x29, 0, sizeof(hub_desc), hub_desc); + // Fill data + info->nPorts = hub_desc.NbrPorts; + info->PowerOnDelay = hub_desc.PwrOn2PwrGood * 2; + memcpy(info->DeviceRemovable, hub_desc.DeviceRemovable, (hub_desc.NbrPorts+7)/8); + // Register + info->HubPtr = USB_RegisterHub(Dev, info->nPorts); // Register poll on endpoint - USB_PollEndpoint(Dev, 1); - - USB_RegisterHub(Dev, hub_desc->NbrPorts); + USB_StartPollingEndpoint(Dev, 1); } void Hub_Disconnected(tUSBInterface *Dev) { + USB_RemoveHub(Dev); } void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data) { Uint8 *status = Data; - struct sHubDescriptor *info = USB_GetDeviceDataPtr(Dev); + struct sHubInfo *info = USB_GetDeviceDataPtr(Dev); int i; - for( i = 0; i < info->NbrPorts; i += 8, status ++ ) + for( i = 0; i < info->nPorts; i += 8, status ++ ) { if( i/8 >= Length ) break; if( *status == 0 ) continue; @@ -80,7 +97,10 @@ void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data) void Hub_int_HandleChange(tUSBInterface *Dev, int Port) { Uint16 status[2]; // Status, Change - // Get change status + + // Get port status USB_Request(Dev, 0, 0xA3, 0, 0, Port, 4, status); + + // Handle connections / disconnections } diff --git a/Modules/USB/Core/include/usb_core.h b/Modules/USB/Core/include/usb_core.h index 2a8ce9d8..104d0e3d 100644 --- a/Modules/USB/Core/include/usb_core.h +++ b/Modules/USB/Core/include/usb_core.h @@ -50,7 +50,11 @@ struct sUSBDriver extern void *USB_GetDeviceDataPtr(tUSBInterface *Dev); extern void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr); +extern void USB_StartPollingEndpoint(tUSBInterface *Dev, int Endpoint); +extern void USB_ReadDescriptor(tUSBInterface *Dev, int Type, int Index, int Length, void *Data); +// TODO: Async extern void USB_SendData(tUSBInterface *Dev, int Endpoint, int Length, void *Data); +extern void USB_RecvData(tUSBInterface *Dev, int Endpoint, int Length, void *Data); #endif diff --git a/Modules/USB/Core/include/usb_hub.h b/Modules/USB/Core/include/usb_hub.h index 42fbeabc..6b32d49c 100644 --- a/Modules/USB/Core/include/usb_hub.h +++ b/Modules/USB/Core/include/usb_hub.h @@ -17,7 +17,8 @@ typedef struct sUSBHub tUSBHub; * * Used by the hub class initialisation routine. */ -extern tUSBHub USB_RegisterHub(tUSBInterface *Device, int nPorts); +extern tUSBHub *USB_RegisterHub(tUSBInterface *Device, int nPorts); +extern void USB_RemoveHub(tUSBHub *Hub); extern void USB_DeviceConnected(tUSBHub *Hub, int Port); extern void USB_DeviceDisconnected(tUSBHub *Hub, int Port); diff --git a/Modules/USB/Core/usb.c b/Modules/USB/Core/usb.c index f090f634..ca86a2b4 100644 --- a/Modules/USB/Core/usb.c +++ b/Modules/USB/Core/usb.c @@ -1,6 +1,9 @@ /* * Acess 2 USB Stack - * USB Packet Control + * - By John Hodge (thePowersGang) + * + * usb.c + * - USB Packet Control */ #define DEBUG 1 #include @@ -8,6 +11,7 @@ #include #include "usb.h" #include "usb_proto.h" +#include "usb_lowlevel.h" // === IMPORTS === extern tUSBHost *gUSB_Hosts; @@ -21,11 +25,6 @@ void USB_DeviceDisconnected(tUSBHub *Hub, int Port); void *USB_GetDeviceDataPtr(tUSBInterface *Dev); void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr); int USB_int_AllocateAddress(tUSBHost *Host); - int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address); - int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest); -char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index); - - int _UTF16to8(Uint16 *Input, int InputLen, char *Dest); // === CODE === tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts) @@ -233,165 +232,3 @@ void USB_int_DeallocateAddress(tUSBHost *Host, int Address) Host->AddressBitmap[Address/8] &= ~(1 << (Address%8)); } -void *USB_int_Request(tUSBHost *Host, int Addr, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data) -{ - void *hdl; - // TODO: Sanity check (and check that Type is valid) - struct sDeviceRequest req; - req.ReqType = Type; - req.Request = Req; - req.Value = LittleEndian16( Val ); - req.Index = LittleEndian16( Indx ); - req.Length = LittleEndian16( Len ); - - hdl = Host->HostDef->SendSETUP(Host->Ptr, Addr, EndPt, 0, NULL, &req, sizeof(req)); - - // TODO: Data toggle? - // TODO: Correct sequence? (Some OUT requests need an IN) - if( Type & 0x80 ) - { - hdl = Host->HostDef->SendIN(Host->Ptr, Addr, EndPt, 0, NULL, Data, Len); - while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 ) - Time_Delay(1); - } - else - { - hdl = Host->HostDef->SendOUT(Host->Ptr, Addr, EndPt, 0, NULL, Data, Len); - } - return hdl; -} - -int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address) -{ - void *hdl; - struct sDeviceRequest req; - req.ReqType = 0; // bmRequestType - req.Request = 5; // SET_ADDRESS - // TODO: Endian - req.Value = LittleEndian16( Address & 0x7F ); // wValue - req.Index = LittleEndian16( 0 ); // wIndex - req.Length = LittleEndian16( 0 ); // wLength - - // Addr 0:0, Data Toggle = 0, no interrupt - hdl = Host->HostDef->SendSETUP(Host->Ptr, 0, 0, 0, NULL, &req, sizeof(req)); - if(!hdl) - return 1; - - hdl = Host->HostDef->SendIN(Host->Ptr, 0, 0, 0, NULL, NULL, 0); - - while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 ) - Time_Delay(1); - - return 0; -} - -int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest) -{ - const int ciMaxPacketSize = 0x400; - struct sDeviceRequest req; - int bToggle = 0; - void *final; - - req.ReqType = 0x80; - req.Request = 6; // GET_DESCRIPTOR - req.Value = LittleEndian16( ((Type & 0xFF) << 8) | (Index & 0xFF) ); - req.Index = LittleEndian16( 0 ); // TODO: Language ID - req.Length = LittleEndian16( Length ); - - Dev->Host->HostDef->SendSETUP( - Dev->Host->Ptr, Dev->Address, Endpoint, - 0, NULL, - &req, sizeof(req) - ); - - bToggle = 1; - while( Length > ciMaxPacketSize ) - { - Dev->Host->HostDef->SendIN( - Dev->Host->Ptr, Dev->Address, Endpoint, - bToggle, NULL, - Dest, ciMaxPacketSize - ); - bToggle = !bToggle; - Length -= ciMaxPacketSize; - } - - final = Dev->Host->HostDef->SendIN( - Dev->Host->Ptr, Dev->Address, Endpoint, - bToggle, INVLPTR, - Dest, Length - ); - - while( Dev->Host->HostDef->IsOpComplete(Dev->Host->Ptr, final) == 0 ) - Time_Delay(1); - - return 0; -} - -char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index) -{ - struct sDescriptor_String str; - int src_len, new_len; - char *ret; - - USB_int_ReadDescriptor(Dev, Endpoint, 3, Index, sizeof(str), &str); -// if(str.Length > sizeof(str)) { -// // IMPOSSIBLE! -// Log_Error("USB", "String is %i bytes, which is over prealloc size (%i)", -// str.Length, sizeof(str) -// ); -// } - src_len = (str.Length - 2) / sizeof(str.Data[0]); - - new_len = _UTF16to8(str.Data, src_len, NULL); - ret = malloc( new_len + 1 ); - _UTF16to8(str.Data, src_len, ret); - ret[new_len] = 0; - return ret; -} - -int _UTF16to8(Uint16 *Input, int InputLen, char *Dest) -{ - int str_len, cp_len; - Uint32 saved_bits = 0; - str_len = 0; - for( int i = 0; i < InputLen; i ++) - { - Uint32 cp; - Uint16 val = Input[i]; - if( val >= 0xD800 && val <= 0xDBFF ) - { - // Multibyte - Leading - if(i + 1 > InputLen) { - cp = '?'; - } - else { - saved_bits = (val - 0xD800) << 10; - saved_bits += 0x10000; - continue ; - } - } - else if( val >= 0xDC00 && val <= 0xDFFF ) - { - if( !saved_bits ) { - cp = '?'; - } - else { - saved_bits |= (val - 0xDC00); - cp = saved_bits; - } - } - else - cp = val; - - cp_len = WriteUTF8((Uint8*)Dest, cp); - if(Dest) - Dest += cp_len; - str_len += cp_len; - - saved_bits = 0; - } - - return str_len; -} - diff --git a/Modules/USB/Core/usb.h b/Modules/USB/Core/usb.h index 9f4384d9..8759ee1d 100644 --- a/Modules/USB/Core/usb.h +++ b/Modules/USB/Core/usb.h @@ -34,9 +34,7 @@ struct sUSBEndpoint int PollingPeriod; // In 1ms intervals int MaxPacketSize; // In bytes - char Direction; // 1 Polled Input, 0 Output - - Uint8 Type; // Same as sDescriptor_Endpoint.Type + Uint8 Type; // Same as sUSBDriver.Endpoints.Type }; /** diff --git a/Modules/USB/Core/usb_lowlevel.c b/Modules/USB/Core/usb_lowlevel.c new file mode 100644 index 00000000..7cde67ff --- /dev/null +++ b/Modules/USB/Core/usb_lowlevel.c @@ -0,0 +1,178 @@ +/* + * Acess 2 USB Stack + * - By John Hodge (thePowersGang) + * + * usb_lowlevel.c + * - Low Level IO + */ +#define DEBUG 1 +#include +#include "usb.h" +#include "usb_proto.h" +#include "usb_lowlevel.h" + +// === PROTOTYPES === + int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address); + int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest); +char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index); + int _UTF16to8(Uint16 *Input, int InputLen, char *Dest); + +// === CODE === +void *USB_int_Request(tUSBHost *Host, int Addr, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data) +{ + void *hdl; + // TODO: Sanity check (and check that Type is valid) + struct sDeviceRequest req; + req.ReqType = Type; + req.Request = Req; + req.Value = LittleEndian16( Val ); + req.Index = LittleEndian16( Indx ); + req.Length = LittleEndian16( Len ); + + hdl = Host->HostDef->SendSETUP(Host->Ptr, Addr, EndPt, 0, NULL, &req, sizeof(req)); + + // TODO: Data toggle? + // TODO: Multi-packet transfers + if( Type & 0x80 ) + { + void *hdl2; + + hdl = Host->HostDef->SendIN(Host->Ptr, Addr, EndPt, 0, NULL, Data, Len); + + hdl2 = Host->HostDef->SendOUT(Host->Ptr, Addr, EndPt, 0, NULL, NULL, 0); + while( Host->HostDef->IsOpComplete(Host->Ptr, hdl2) == 0 ) + Time_Delay(1); + } + else + { + void *hdl2; + + if( Len > 0 ) + hdl = Host->HostDef->SendOUT(Host->Ptr, Addr, EndPt, 0, NULL, Data, Len); + else + hdl = NULL; + + // Status phase (DataToggle=1) + hdl2 = Host->HostDef->SendIN(Host->Ptr, Addr, EndPt, 1, NULL, NULL, 0); + while( Host->HostDef->IsOpComplete(Host->Ptr, hdl2) == 0 ) + Time_Delay(1); + } + return hdl; +} + +int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address) +{ + USB_int_Request(Host, 0, 0, 0x00, 5, Address & 0x7F, 0, 0, NULL); + return 0; +} + +int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest) +{ + const int ciMaxPacketSize = 0x400; + struct sDeviceRequest req; + int bToggle = 0; + void *final; + + req.ReqType = 0x80; + req.Request = 6; // GET_DESCRIPTOR + req.Value = LittleEndian16( ((Type & 0xFF) << 8) | (Index & 0xFF) ); + req.Index = LittleEndian16( 0 ); // TODO: Language ID + req.Length = LittleEndian16( Length ); + + Dev->Host->HostDef->SendSETUP( + Dev->Host->Ptr, Dev->Address, Endpoint, + 0, NULL, + &req, sizeof(req) + ); + + bToggle = 1; + while( Length > ciMaxPacketSize ) + { + Dev->Host->HostDef->SendIN( + Dev->Host->Ptr, Dev->Address, Endpoint, + bToggle, NULL, + Dest, ciMaxPacketSize + ); + bToggle = !bToggle; + Length -= ciMaxPacketSize; + } + + final = Dev->Host->HostDef->SendIN( + Dev->Host->Ptr, Dev->Address, Endpoint, + bToggle, INVLPTR, + Dest, Length + ); + + while( Dev->Host->HostDef->IsOpComplete(Dev->Host->Ptr, final) == 0 ) + Time_Delay(1); + + return 0; +} + +char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index) +{ + struct sDescriptor_String str; + int src_len, new_len; + char *ret; + + USB_int_ReadDescriptor(Dev, Endpoint, 3, Index, sizeof(str), &str); +// if(str.Length > sizeof(str)) { +// // IMPOSSIBLE! +// Log_Error("USB", "String is %i bytes, which is over prealloc size (%i)", +// str.Length, sizeof(str) +// ); +// } + src_len = (str.Length - 2) / sizeof(str.Data[0]); + + new_len = _UTF16to8(str.Data, src_len, NULL); + ret = malloc( new_len + 1 ); + _UTF16to8(str.Data, src_len, ret); + ret[new_len] = 0; + return ret; +} + +int _UTF16to8(Uint16 *Input, int InputLen, char *Dest) +{ + int str_len, cp_len; + Uint32 saved_bits = 0; + str_len = 0; + for( int i = 0; i < InputLen; i ++) + { + Uint32 cp; + Uint16 val = Input[i]; + if( val >= 0xD800 && val <= 0xDBFF ) + { + // Multibyte - Leading + if(i + 1 > InputLen) { + cp = '?'; + } + else { + saved_bits = (val - 0xD800) << 10; + saved_bits += 0x10000; + continue ; + } + } + else if( val >= 0xDC00 && val <= 0xDFFF ) + { + if( !saved_bits ) { + cp = '?'; + } + else { + saved_bits |= (val - 0xDC00); + cp = saved_bits; + } + } + else + cp = val; + + cp_len = WriteUTF8((Uint8*)Dest, cp); + if(Dest) + Dest += cp_len; + str_len += cp_len; + + saved_bits = 0; + } + + return str_len; +} + diff --git a/Modules/USB/Core/usb_lowlevel.h b/Modules/USB/Core/usb_lowlevel.h new file mode 100644 index 00000000..903dd2e7 --- /dev/null +++ b/Modules/USB/Core/usb_lowlevel.h @@ -0,0 +1,15 @@ +/** + * Acess2 USB Stack + * - By John Hodge (thePowersGang) + * + * usb_lowlevel.h + * - Low-Level USB IO Functions + */ +#ifndef _USB_LOWLEVEL_H_ +#define _USB_LOWLEVEL_H_ + +extern int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address); +extern int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest); +extern char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index); + +#endif diff --git a/Modules/USB/Core/usb_proto.h b/Modules/USB/Core/usb_proto.h index 2ac2781f..5641dd24 100644 --- a/Modules/USB/Core/usb_proto.h +++ b/Modules/USB/Core/usb_proto.h @@ -1,4 +1,9 @@ /** + * Acess2 USB Stack + * - By John Hodge (thePowersGang) + * + * usb_proto.h + * - USB Core Protocol Definitions */ #ifndef _USB_PROTO_H_ #define _USB_PROTO_H_ -- 2.20.1