diff --git a/CREDITS b/CREDITS index bde0c83..25c68bb 100644 --- a/CREDITS +++ b/CREDITS @@ -14,3 +14,6 @@ Spanish keymap (taken from Circle) Joshua Otto Providing support for framebuffers where pitch != width * bytes per pixel USB MIDI device class support + +Paolo Franchetti +Suggesting improvements for the HID class device support and testing diff --git a/README.md b/README.md index c95b3d2..f2cbf3a 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,9 @@ Another option (NDEBUG) can be defined in Rules.mk to build the release version. Building -------- -Building is normally done on PC Linux. If building for the Raspberry Pi 1 you need a [toolchain](http://elinux.org/Rpi_Software#ARM) for the ARM1176JZF core. For Raspberry Pi 2/3 you need a toolchain with Cortex-A7/-A53 support. A toolchain, which works for all of these, can be downloaded [here](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads). USPi has been tested with the version *6-2017-q1-update* from this website. You can also build USPi on the Raspberry Pi itself on Raspbian. +> For AArch64 support go to the end of this file. + +Building is normally done on PC Linux. If building for the Raspberry Pi 1 you need a [toolchain](http://elinux.org/Rpi_Software#ARM) for the ARM1176JZF core. For Raspberry Pi 2/3 you need a toolchain with Cortex-A7/-A53 support. A toolchain, which works for all of these, can be downloaded [here](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads). USPi has been tested with the version *7-2018-q2-update* from this website. You can also build USPi on the Raspberry Pi itself on Raspbian. First edit the file *Rules.mk* and set the Raspberry Pi version (*RASPPI*, 1, 2 or 3) and the *PREFIX* of your toolchain commands. Alternatively you can create a *Config.mk* file (which is ignored by git) and set the Raspberry Pi version and the *PREFIX* variable to the prefix of your compiler like this (don't forget the dash at the end): diff --git a/Rules.mk b/Rules.mk index 59cd759..daa4454 100644 --- a/Rules.mk +++ b/Rules.mk @@ -42,10 +42,13 @@ AR = $(PREFIX)ar ifeq ($(strip $(AARCH64)),0) ifeq ($(strip $(RASPPI)),1) ARCH ?= -march=armv6j -mtune=arm1176jzf-s -mfloat-abi=hard +TARGET ?= kernel else ifeq ($(strip $(RASPPI)),2) ARCH ?= -march=armv7-a -mtune=cortex-a7 -mfloat-abi=hard +TARGET ?= kernel7 else ARCH ?= -march=armv8-a -mtune=cortex-a53 -mfloat-abi=hard +TARGET ?= kernel8-32 endif else ARCH ?= -march=armv8-a -mtune=cortex-a53 -mlittle-endian -mcmodel=small -DAARCH64=1 @@ -58,10 +61,23 @@ CFLAGS += $(ARCH) -Wall -Wno-psabi -fsigned-char -fno-builtin -nostdinc -nostdli -std=gnu99 -undef -DRASPPI=$(RASPPI) -I $(USPIHOME)/include $(OPTIMIZE) #-DNDEBUG %.o: %.S - $(AS) $(AFLAGS) -c -o $@ $< + @echo " AS $@" + @$(AS) $(AFLAGS) -c -o $@ $< %.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< + @echo " CC $@" + @$(CC) $(CFLAGS) -c -o $@ $< + +$(TARGET).img: $(OBJS) $(LIBS) + @echo " LD $(TARGET).elf" + @$(LD) -o $(TARGET).elf -Map $(TARGET).map -T $(USPIHOME)/env/uspienv.ld \ + $(USPIHOME)/env/lib/startup.o $(OBJS) $(LIBS) + @echo " DUMP $(TARGET).lst" + @$(PREFIX)objdump -D $(TARGET).elf > $(TARGET).lst + @echo " COPY $(TARGET).img" + @$(PREFIX)objcopy $(TARGET).elf -O binary $(TARGET).img + @echo -n " WC $(TARGET).img => " + @wc -c < $(TARGET).img clean: rm -f *.o *.a *.elf *.lst *.img *.cir *.map *~ $(EXTRACLEAN) diff --git a/env/include/uspienv/armv6mmu.h b/env/include/uspienv/armv6mmu.h index c4584ba..b436322 100644 --- a/env/include/uspienv/armv6mmu.h +++ b/env/include/uspienv/armv6mmu.h @@ -2,7 +2,7 @@ // armv6mmu.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014-2015 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -66,6 +66,11 @@ typedef struct TARMV6MMU_LEVEL1_SECTION_DESCRIPTOR // subpages disabled } PACKED TARMV6MMU_LEVEL1_SECTION_DESCRIPTOR; +#define ARMV6MMUL1SECTION_NORMAL 0x0040E // outer and inner write back, no write allocate +#define ARMV6MMUL1SECTION_NORMAL_XN 0x0041E // + execute never +#define ARMV6MMUL1SECTION_DEVICE 0x10416 // shared device +#define ARMV6MMUL1SECTION_COHERENT 0x10412 // strongly ordered + #define ARMV6MMUL1SECTIONBASE(addr) (((addr) >> 20) & 0xFFF) #define ARMV6MMUL1SECTIONPTR(base) ((void *) ((base) << 20)) diff --git a/env/include/uspienv/memory.h b/env/include/uspienv/memory.h index 1dfd181..c47128e 100644 --- a/env/include/uspienv/memory.h +++ b/env/include/uspienv/memory.h @@ -2,7 +2,7 @@ // memory.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014-2015 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -32,8 +32,7 @@ typedef struct TMemorySystem boolean m_bEnableMMU; u32 m_nMemSize; - TPageTable *m_pPageTable0Default; - TPageTable *m_pPageTable1; + TPageTable *m_pPageTable; } TMemorySystem; diff --git a/env/include/uspienv/pagetable.h b/env/include/uspienv/pagetable.h index 69d05f4..7dd0924 100644 --- a/env/include/uspienv/pagetable.h +++ b/env/include/uspienv/pagetable.h @@ -2,7 +2,7 @@ // pagetable.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014-2015 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -20,7 +20,6 @@ #ifndef _uspienv_pagetable_h #define _uspienv_pagetable_h -#include #include #ifdef __cplusplus @@ -29,17 +28,11 @@ extern "C" { typedef struct TPageTable { - boolean m_bTableAllocated; - TARMV6MMU_LEVEL1_SECTION_DESCRIPTOR *m_pTable; + u32 *m_pTable; } TPageTable; -// 4GB shared device -void PageTable (TPageTable *pThis); - -// 0..nMemSize: normal, -// nMemSize..512MB: shared device (1024MB on Raspberry Pi 2) -void PageTable2 (TPageTable *pThis, u32 nMemSize); +void PageTable (TPageTable *pThis, u32 nMemSize); void _PageTable (TPageTable *pThis); diff --git a/env/include/uspienv/sysconfig.h b/env/include/uspienv/sysconfig.h index bdc3350..c60ee41 100644 --- a/env/include/uspienv/sysconfig.h +++ b/env/include/uspienv/sysconfig.h @@ -2,7 +2,7 @@ // sysconfig.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014-2016 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -52,7 +52,7 @@ // system options #if RASPPI == 1 // valid on Raspberry Pi 1 only //#define ARM_DISABLE_MMU -#define ARM_STRICT_ALIGNMENT +//#define ARM_STRICT_ALIGNMENT #define GPU_L2_CACHE_ENABLED #else #define CORES 4 // must be a power of 2 diff --git a/env/lib/Makefile b/env/lib/Makefile index f964128..9f78429 100644 --- a/env/lib/Makefile +++ b/env/lib/Makefile @@ -2,7 +2,7 @@ # Makefile # # USPi - An USB driver for Raspberry Pi written in C -# Copyright (C) 2014-2015 R. Stange +# Copyright (C) 2014-2018 R. Stange # # 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 @@ -33,7 +33,12 @@ all: startup.o libuspienv.a startup.o: startup.S libuspienv.a: $(OBJS) - rm -f $@ - $(AR) cr $@ $(OBJS) + @echo " AR $@" + @rm -f $@ + @$(AR) cr $@ $(OBJS) include $(USPIHOME)/Rules.mk + +ifneq ($(strip $(AARCH64)),0) +$(error AARCH64 is not supported in lib/env/) +endif diff --git a/env/lib/memory.c b/env/lib/memory.c index ef23920..589aa17 100644 --- a/env/lib/memory.c +++ b/env/lib/memory.c @@ -2,7 +2,7 @@ // memory.c // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014-2015 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -31,17 +31,15 @@ | ARM_CONTROL_L1_INSTRUCTION_CACHE \ | ARM_CONTROL_BRANCH_PREDICTION \ | ARM_CONTROL_EXTENDED_PAGE_TABLE) - -#define TTBCR_SPLIT 3 #else #define MMU_MODE ( ARM_CONTROL_MMU \ | ARM_CONTROL_L1_CACHE \ | ARM_CONTROL_L1_INSTRUCTION_CACHE \ | ARM_CONTROL_BRANCH_PREDICTION) - -#define TTBCR_SPLIT 2 #endif +#define TTBCR_SPLIT 0 + void MemorySystemEnableMMU (TMemorySystem *pThis); void MemorySystem (TMemorySystem *pThis, boolean bEnableMMU) @@ -50,8 +48,7 @@ void MemorySystem (TMemorySystem *pThis, boolean bEnableMMU) pThis->m_bEnableMMU = bEnableMMU; pThis->m_nMemSize = 0; - pThis->m_pPageTable0Default = 0; - pThis->m_pPageTable1 = 0; + pThis->m_pPageTable = 0; TBcmPropertyTags Tags; BcmPropertyTags (&Tags); @@ -69,13 +66,9 @@ void MemorySystem (TMemorySystem *pThis, boolean bEnableMMU) if (pThis->m_bEnableMMU) { - pThis->m_pPageTable0Default = (TPageTable *) malloc (sizeof (TPageTable)); - assert (pThis->m_pPageTable0Default != 0); - PageTable2 (pThis->m_pPageTable0Default, pThis->m_nMemSize); - - pThis->m_pPageTable1 = (TPageTable *) malloc (sizeof (TPageTable)); - assert (pThis->m_pPageTable1 != 0); - PageTable (pThis->m_pPageTable1); + pThis->m_pPageTable = (TPageTable *) malloc (sizeof (TPageTable)); + assert (pThis->m_pPageTable != 0); + PageTable (pThis->m_pPageTable, pThis->m_nMemSize); MemorySystemEnableMMU (pThis); } @@ -99,13 +92,9 @@ void _MemorySystem (TMemorySystem *pThis) asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0) : "memory"); } - _PageTable (pThis->m_pPageTable1); - free (pThis->m_pPageTable1); - pThis->m_pPageTable1 = 0; - - _PageTable (pThis->m_pPageTable0Default); - free (pThis->m_pPageTable0Default); - pThis->m_pPageTable0Default = 0; + _PageTable (pThis->m_pPageTable); + free (pThis->m_pPageTable); + pThis->m_pPageTable = 0; } u32 MemorySystemGetMemSize (TMemorySystem *pThis) @@ -138,16 +127,11 @@ void MemorySystemEnableMMU (TMemorySystem *pThis) asm volatile ("mcr p15, 0, %0, c2, c0, 2" : : "r" (TTBCR_SPLIT)); // set TTBR0 - assert (pThis->m_pPageTable0Default != 0); - asm volatile ("mcr p15, 0, %0, c2, c0, 0" : : "r" (PageTableGetBaseAddress (pThis->m_pPageTable0Default))); + assert (pThis->m_pPageTable != 0); + asm volatile ("mcr p15, 0, %0, c2, c0, 0" : : "r" (PageTableGetBaseAddress (pThis->m_pPageTable))); - // set TTBR1 - assert (pThis->m_pPageTable1 != 0); - asm volatile ("mcr p15, 0, %0, c2, c0, 1" : : "r" (PageTableGetBaseAddress (pThis->m_pPageTable1))); - // set Domain Access Control register (Domain 0 and 1 to client) - asm volatile ("mcr p15, 0, %0, c3, c0, 0" : : "r" ( DOMAIN_CLIENT << 0 - | DOMAIN_CLIENT << 2)); + asm volatile ("mcr p15, 0, %0, c3, c0, 0" : : "r" (DOMAIN_CLIENT << 0)); InvalidateDataCache (); FlushPrefetchBuffer (); diff --git a/env/lib/pagetable.c b/env/lib/pagetable.c index a79fbcd..234a2e8 100644 --- a/env/lib/pagetable.c +++ b/env/lib/pagetable.c @@ -2,7 +2,7 @@ // pagetable.c // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014-2016 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -18,120 +18,53 @@ // along with this program. If not, see . // #include -#include +#include #include #include -#include #include #if RASPPI == 1 -#define SDRAM_SIZE_MBYTE 512 - #define TTBR_MODE ( ARM_TTBR_INNER_CACHEABLE \ | ARM_TTBR_OUTER_NON_CACHEABLE) #else -#define SDRAM_SIZE_MBYTE 1024 - #define TTBR_MODE ( ARM_TTBR_INNER_WRITE_BACK \ | ARM_TTBR_OUTER_WRITE_BACK) #endif -void PageTable (TPageTable *pThis) +void PageTable (TPageTable *pThis, u32 nMemSize) { assert (pThis != 0); - pThis->m_bTableAllocated = FALSE; - pThis->m_pTable = (TARMV6MMU_LEVEL1_SECTION_DESCRIPTOR *) MEM_PAGE_TABLE1; + pThis->m_pTable = (u32 *) MEM_PAGE_TABLE1; assert (((u32) pThis->m_pTable & 0x3FFF) == 0); for (unsigned nEntry = 0; nEntry < 4096; nEntry++) { u32 nBaseAddress = MEGABYTE * nEntry; - - TARMV6MMU_LEVEL1_SECTION_DESCRIPTOR *pEntry = &pThis->m_pTable[nEntry]; - // shared device - pEntry->Value10 = 2; - pEntry->BBit = 1; - pEntry->CBit = 0; - pEntry->XNBit = 0; - pEntry->Domain = 0; - pEntry->IMPBit = 0; - pEntry->AP = AP_SYSTEM_ACCESS; - pEntry->TEX = 0; - pEntry->APXBit = APX_RW_ACCESS; - pEntry->SBit = 1; - pEntry->NGBit = 0; - pEntry->Value0 = 0; - pEntry->SBZ = 0; - pEntry->Base = ARMV6MMUL1SECTIONBASE (nBaseAddress); - - if (nEntry >= SDRAM_SIZE_MBYTE) +#if RASPPI == 3 + if (nBaseAddress == MEM_COHERENT_REGION) { - pEntry->XNBit = 1; + pThis->m_pTable[nEntry] = ARMV6MMUL1SECTION_COHERENT | nBaseAddress; } - } - - CleanDataCache (); - DataSyncBarrier (); -} - -void PageTable2 (TPageTable *pThis, u32 nMemSize) -{ - assert (pThis != 0); - - pThis->m_bTableAllocated = TRUE; - pThis->m_pTable = (TARMV6MMU_LEVEL1_SECTION_DESCRIPTOR *) palloc (); - - assert (pThis->m_pTable != 0); - assert (((u32) pThis->m_pTable & 0xFFF) == 0); - - for (unsigned nEntry = 0; nEntry < SDRAM_SIZE_MBYTE; nEntry++) - { - u32 nBaseAddress = MEGABYTE * nEntry; - - TARMV6MMU_LEVEL1_SECTION_DESCRIPTOR *pEntry = &pThis->m_pTable[nEntry]; - - // outer and inner write back, no write allocate - pEntry->Value10 = 2; - pEntry->BBit = 1; - pEntry->CBit = 1; - pEntry->XNBit = 0; - pEntry->Domain = 0; - pEntry->IMPBit = 0; - pEntry->AP = AP_SYSTEM_ACCESS; - pEntry->TEX = 0; - pEntry->APXBit = APX_RW_ACCESS; - pEntry->SBit = 0; - pEntry->NGBit = 0; - pEntry->Value0 = 0; - pEntry->SBZ = 0; - pEntry->Base = ARMV6MMUL1SECTIONBASE (nBaseAddress); - - extern u8 _etext; - if (nBaseAddress >= (u32) &_etext) + else +#endif + if (nBaseAddress < nMemSize) { - pEntry->XNBit = 1; - - if (nBaseAddress >= nMemSize) + extern u8 _etext; + if (nBaseAddress < (u32) &_etext) { - // shared device - pEntry->BBit = 1; - pEntry->CBit = 0; - pEntry->TEX = 0; - pEntry->SBit = 1; + pThis->m_pTable[nEntry] = ARMV6MMUL1SECTION_NORMAL | nBaseAddress; } -#if RASPPI == 3 - else if (nBaseAddress == MEM_COHERENT_REGION) + else { - // strongly ordered - pEntry->BBit = 0; - pEntry->CBit = 0; - pEntry->TEX = 0; - pEntry->SBit = 1; + pThis->m_pTable[nEntry] = ARMV6MMUL1SECTION_NORMAL_XN | nBaseAddress; } -#endif + } + else + { + pThis->m_pTable[nEntry] = ARMV6MMUL1SECTION_DEVICE | nBaseAddress; } } @@ -141,13 +74,6 @@ void PageTable2 (TPageTable *pThis, u32 nMemSize) void _PageTable (TPageTable *pThis) { - assert (pThis != 0); - - if (pThis->m_bTableAllocated) - { - pfree (pThis->m_pTable); - pThis->m_pTable = 0; - } } u32 PageTableGetBaseAddress (TPageTable *pThis) diff --git a/include/uspi.h b/include/uspi.h index cb440b9..ad1c404 100644 --- a/include/uspi.h +++ b/include/uspi.h @@ -4,7 +4,7 @@ // Services provided by the USPi library // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -26,6 +26,16 @@ extern "C" { #endif +// +// Version information +// + +#define USPI_NAME "USPi library" + +#define USPI_MAJOR_VERSION 2 +#define USPI_MINOR_VERSION 0 +#define USPI_VERSION_STRING "2.00" + // // USPi initialization // @@ -48,6 +58,9 @@ void USPiKeyboardRegisterKeyPressedHandler (TUSPiKeyPressedHandler *pKeyPressedH typedef void TUSPiShutdownHandler (void); void USPiKeyboardRegisterShutdownHandler (TUSPiShutdownHandler *pShutdownHandler); +// Call this frequently from your application main loop to allow updating the keyboard LEDs. +void USPiKeyboardUpdateLEDs (void); + // "raw mode" (if this handler is registered the others are ignored) // The raw handler is called when the keyboard sends a status report (on status change and/or continously). typedef void TUSPiKeyStatusHandlerRaw (unsigned char ucModifiers, @@ -64,6 +77,12 @@ void USPiKeyboardRegisterKeyStatusHandlerRaw (TUSPiKeyStatusHandlerRaw *pKeyStat #define ALTGR (1 << 6) #define RWIN (1 << 7) +// Set the keyboard LEDs in "raw mode" +void USPiKeyboardSetLEDs (unsigned char ucLEDMask); +#define LED_NUM_LOCK (1 << 0) +#define LED_CAPS_LOCK (1 << 1) +#define LED_SCROLL_LOCK (1 << 2) + // // Mouse device // @@ -82,16 +101,6 @@ void USPiMouseRegisterStatusHandler (TUSPiMouseStatusHandler *pStatusHandler); #define MOUSE_BUTTON2 (1 << 1) #define MOUSE_BUTTON3 (1 << 2) -// ucModifiers (bit is set if modifier key is pressed) -#define LCTRL (1 << 0) -#define LSHIFT (1 << 1) -#define ALT (1 << 2) -#define LWIN (1 << 3) -#define RCTRL (1 << 4) -#define RSHIFT (1 << 5) -#define ALTGR (1 << 6) -#define RWIN (1 << 7) - // // Mass storage device // @@ -126,6 +135,9 @@ int USPiEthernetAvailable (void); void USPiGetMACAddress (unsigned char Buffer[6]); +// returns != 0 if link is up +int USPiEthernetIsLinkUp (void); + // returns 0 on failure int USPiSendFrame (const void *pBuffer, unsigned nLength); diff --git a/include/uspi/dwhcidevice.h b/include/uspi/dwhcidevice.h index 97d5cf8..dc40c9c 100644 --- a/include/uspi/dwhcidevice.h +++ b/include/uspi/dwhcidevice.h @@ -2,7 +2,7 @@ // dwhcidevice.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -17,8 +17,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . // -#ifndef _dwhcidevice_h -#define _dwhcidevice_h +#ifndef _uspi_dwhcidevice_h +#define _uspi_dwhcidevice_h #include #include @@ -40,7 +40,7 @@ typedef struct TDWHCIDevice unsigned m_nChannels; volatile unsigned m_nChannelAllocated; // one bit per channel, set if allocated - TDWHCITransferStageData *m_pStageData[DWHCI_MAX_CHANNELS]; + TDWHCITransferStageData m_StageData[DWHCI_MAX_CHANNELS]; volatile boolean m_bWaiting; diff --git a/include/uspi/dwhcixferstagedata.h b/include/uspi/dwhcixferstagedata.h index 663ea10..50f6c25 100644 --- a/include/uspi/dwhcixferstagedata.h +++ b/include/uspi/dwhcixferstagedata.h @@ -2,7 +2,7 @@ // dwhcixferstagedata.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -17,7 +17,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . // -#ifndef _uspi__dwhcixferstagedata_h +#ifndef _uspi_dwhcixferstagedata_h #define _uspi_dwhcixferstagedata_h #include @@ -25,6 +25,10 @@ #include #include #include +#include +#include +#include +#include #include #ifdef __cplusplus @@ -56,10 +60,18 @@ typedef struct TDWHCITransferStageData unsigned m_nSubState; u32 m_nTransactionStatus; - u32 *m_pTempBuffer; + u32 m_TempBuffer ALIGN (4); // DMA buffer void *m_pBufferPointer; - TDWHCIFrameScheduler *m_pFrameScheduler; + boolean m_bFrameSchedulerUsed; + union + { + TDWHCIFrameScheduler Base; + TDWHCIFrameSchedulerPeriodic Periodic; + TDWHCIFrameSchedulerNonPeriodic NonPeriodic; + TDWHCIFrameSchedulerNoSplit NoSplit; + } + m_FrameScheduler; } TDWHCITransferStageData; diff --git a/include/uspi/lan7800.h b/include/uspi/lan7800.h index 3965064..73a2414 100644 --- a/include/uspi/lan7800.h +++ b/include/uspi/lan7800.h @@ -20,6 +20,7 @@ #ifndef _uspi_lan7800_h #define _uspi_lan7800_h +#include #include #include #include @@ -29,7 +30,7 @@ typedef struct TLAN7800Device { - TUSBDevice m_USBDevice; + TUSBFunction m_USBFunction; TUSBEndpoint *m_pEndpointBulkIn; TUSBEndpoint *m_pEndpointBulkOut; @@ -40,10 +41,10 @@ typedef struct TLAN7800Device } TLAN7800Device; -void LAN7800Device (TLAN7800Device *pThis, TUSBDevice *pDevice); +void LAN7800Device (TLAN7800Device *pThis, TUSBFunction *pFunction); void _LAN7800Device (TLAN7800Device *pThis); -boolean LAN7800DeviceConfigure (TUSBDevice *pUSBDevice); +boolean LAN7800DeviceConfigure (TUSBFunction *pUSBFunction); TMACAddress *LAN7800DeviceGetMACAddress (TLAN7800Device *pThis); diff --git a/include/uspi/smsc951x.h b/include/uspi/smsc951x.h index 2fa4fb2..56a39c4 100644 --- a/include/uspi/smsc951x.h +++ b/include/uspi/smsc951x.h @@ -2,7 +2,7 @@ // smsc951x.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -20,7 +20,7 @@ #ifndef _uspi_smsc951x_h #define _uspi_smsc951x_h -#include +#include #include #include #include @@ -30,7 +30,7 @@ typedef struct TSMSC951xDevice { - TUSBDevice m_USBDevice; + TUSBFunction m_USBFunction; TUSBEndpoint *m_pEndpointBulkIn; TUSBEndpoint *m_pEndpointBulkOut; @@ -41,10 +41,10 @@ typedef struct TSMSC951xDevice } TSMSC951xDevice; -void SMSC951xDevice (TSMSC951xDevice *pThis, TUSBDevice *pDevice); +void SMSC951xDevice (TSMSC951xDevice *pThis, TUSBFunction *pFunction); void _SMSC951xDevice (TSMSC951xDevice *pThis); -boolean SMSC951xDeviceConfigure (TUSBDevice *pUSBDevice); +boolean SMSC951xDeviceConfigure (TUSBFunction *pUSBFunction); TMACAddress *SMSC951xDeviceGetMACAddress (TSMSC951xDevice *pThis); @@ -53,7 +53,14 @@ boolean SMSC951xDeviceSendFrame (TSMSC951xDevice *pThis, const void *pBuffer, un // pBuffer must have size FRAME_BUFFER_SIZE boolean SMSC951xDeviceReceiveFrame (TSMSC951xDevice *pThis, void *pBuffer, unsigned *pResultLength); +// returns TRUE if PHY link is up +boolean SMSC951xDeviceIsLinkUp (TSMSC951xDevice *pThis); + // private: +boolean SMSC951xDevicePHYWrite (TSMSC951xDevice *pThis, u8 uchIndex, u16 usValue); +boolean SMSC951xDevicePHYRead (TSMSC951xDevice *pThis, u8 uchIndex, u16 *pValue); +boolean SMSC951xDevicePHYWaitNotBusy (TSMSC951xDevice *pThis); + boolean SMSC951xDeviceWriteReg (TSMSC951xDevice *pThis, u32 nIndex, u32 nValue); boolean SMSC951xDeviceReadReg (TSMSC951xDevice *pThis, u32 nIndex, u32 *pValue); diff --git a/include/uspi/usbconfigparser.h b/include/uspi/usbconfigparser.h index 798b4b9..a91c156 100644 --- a/include/uspi/usbconfigparser.h +++ b/include/uspi/usbconfigparser.h @@ -33,18 +33,22 @@ typedef struct TUSBConfigurationParser unsigned m_nBufLen; boolean m_bValid; const TUSBDescriptor *m_pEndPosition; - const TUSBDescriptor *m_pCurrentPosition; + const TUSBDescriptor *m_pNextPosition; + const TUSBDescriptor *m_pCurrentDescriptor; const TUSBDescriptor *m_pErrorPosition; } TUSBConfigurationParser; void USBConfigurationParser (TUSBConfigurationParser *pThis, const void *pBuffer, unsigned nBufLen); +void USBConfigurationParserCopy (TUSBConfigurationParser *pThis, TUSBConfigurationParser *pParser); void _USBConfigurationParser (TUSBConfigurationParser *pThis); boolean USBConfigurationParserIsValid (TUSBConfigurationParser *pThis); const TUSBDescriptor *USBConfigurationParserGetDescriptor (TUSBConfigurationParser *pThis, u8 ucType); // returns 0 if not found +const TUSBDescriptor *USBConfigurationParserGetCurrentDescriptor (TUSBConfigurationParser *pThis); + void USBConfigurationParserError (TUSBConfigurationParser *pThis, const char *pSource); #ifdef __cplusplus diff --git a/include/uspi/usbdevice.h b/include/uspi/usbdevice.h index 8b56ed9..eb63c0d 100644 --- a/include/uspi/usbdevice.h +++ b/include/uspi/usbdevice.h @@ -2,7 +2,7 @@ // usbdevice.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -30,11 +31,12 @@ extern "C" { #endif +#define USBDEV_MAX_FUNCTIONS 10 + typedef enum // do not change this order { DeviceNameVendor, DeviceNameDevice, - DeviceNameInterface, DeviceNameUnknown } TDeviceNameSelector; @@ -44,14 +46,13 @@ struct TUSBEndpoint; typedef struct TUSBDevice { - boolean (*Configure) (struct TUSBDevice *pThis); - struct TDWHCIDevice *m_pHost; u8 m_ucAddress; TUSBSpeed m_Speed; struct TUSBEndpoint *m_pEndpoint0; + boolean m_bSplitTransfer; u8 m_ucHubAddress; u8 m_ucHubPortNumber; @@ -62,21 +63,25 @@ typedef struct TUSBDevice TUSBString m_ManufacturerString; TUSBString m_ProductString; + + TUSBFunction *m_pFunction[USBDEV_MAX_FUNCTIONS]; } TUSBDevice; -void USBDevice (TUSBDevice *pThis, struct TDWHCIDevice *pHost, TUSBSpeed Speed, u8 ucHubAddress, u8 ucHubPortNumber); -void USBDeviceCopy (TUSBDevice *pThis, TUSBDevice *pDevice); +void USBDevice (TUSBDevice *pThis, struct TDWHCIDevice *pHost, TUSBSpeed Speed, + boolean bSplitTransfer, u8 ucHubAddress, u8 ucHubPortNumber); void _USBDevice (TUSBDevice *pThis); boolean USBDeviceInitialize (TUSBDevice *pThis); // onto address state (phase 1) boolean USBDeviceConfigure (TUSBDevice *pThis); // onto configured state (phase 2) TString *USBDeviceGetName (TUSBDevice *pThis, TDeviceNameSelector Selector); // string deleted by caller +TString *USBDeviceGetNames (TUSBDevice *pThis); // string deleted by caller u8 USBDeviceGetAddress (TUSBDevice *pThis); TUSBSpeed USBDeviceGetSpeed (TUSBDevice *pThis); +boolean USBDeviceIsSplit (TUSBDevice *pThis); u8 USBDeviceGetHubAddress (TUSBDevice *pThis); u8 USBDeviceGetHubPortNumber (TUSBDevice *pThis); @@ -90,6 +95,8 @@ const TUSBConfigurationDescriptor *USBDeviceGetConfigurationDescriptor (TUSBDevi const TUSBDescriptor *USBDeviceGetDescriptor (TUSBDevice *pThis, u8 ucType); // returns 0 if not found void USBDeviceConfigurationError (TUSBDevice *pThis, const char *pSource); +void USBDeviceLogWrite (TUSBDevice *pThis, unsigned Severity, const char *pMessage, ...); + #ifdef __cplusplus } #endif diff --git a/include/uspi/usbdevicefactory.h b/include/uspi/usbdevicefactory.h index 6127021..bc42377 100644 --- a/include/uspi/usbdevicefactory.h +++ b/include/uspi/usbdevicefactory.h @@ -2,7 +2,7 @@ // usbdevicefactory.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -20,9 +20,9 @@ #ifndef _uspi_usbdevicefactory_h #define _uspi_usbdevicefactory_h -#include +#include #include -TUSBDevice *USBDeviceFactoryGetDevice (TUSBDevice *pParent); +TUSBFunction *USBDeviceFactoryGetDevice (TUSBFunction *pParent, TString *pName); #endif diff --git a/include/uspi/usbfunction.h b/include/uspi/usbfunction.h new file mode 100644 index 0000000..8387510 --- /dev/null +++ b/include/uspi/usbfunction.h @@ -0,0 +1,70 @@ +// +// usbfunction.h +// +// USPi - An USB driver for Raspberry Pi written in C +// Copyright (C) 2018 R. Stange +// +// 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 3 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, see . +// +#ifndef _uspi_usbfunction_h +#define _uspi_usbfunction_h + +#include +#include +#include +#include + +struct TUSBDevice; +struct TDWHCIDevice; +struct TUSBEndpoint; + +typedef struct TUSBFunction +{ + boolean (*Configure) (struct TUSBFunction *pThis); + + struct TUSBDevice *m_pDevice; + + TUSBConfigurationParser *m_pConfigParser; + + TUSBInterfaceDescriptor *m_pInterfaceDesc; +} +TUSBFunction; + +void USBFunction (TUSBFunction *pThis, struct TUSBDevice *pDevice, TUSBConfigurationParser *pConfigParser); +void USBFunctionCopy (TUSBFunction *pThis, TUSBFunction *pFunction); // copy constructor +void _USBFunction (TUSBFunction *pThis); + +boolean USBFunctionConfigure (TUSBFunction *pThis); + +TString *USBFunctionGetInterfaceName (TUSBFunction *pThis); // string deleted by caller +u8 USBFunctionGetNumEndpoints (TUSBFunction *pThis); + +struct TUSBDevice *USBFunctionGetDevice (TUSBFunction *pThis); +struct TUSBEndpoint *USBFunctionGetEndpoint0 (TUSBFunction *pThis); +struct TDWHCIDevice *USBFunctionGetHost (TUSBFunction *pThis); + +// get next sub descriptor of ucType from interface descriptor +const TUSBDescriptor *USBFunctionGetDescriptor (TUSBFunction *pThis, u8 ucType); // returns 0 if not found +void USBFunctionConfigurationError (TUSBFunction *pThis, const char *pSource); + +// select a specific USB interface, called in constructor of derived class, +// if device has been detected by vendor/product ID +boolean USBFunctionSelectInterfaceByClass (TUSBFunction *pThis, u8 uchClass, u8 uchSubClass, u8 uchProtocol); + +u8 USBFunctionGetInterfaceNumber (TUSBFunction *pThis); +u8 USBFunctionGetInterfaceClass (TUSBFunction *pThis); +u8 USBFunctionGetInterfaceSubClass (TUSBFunction *pThis); +u8 USBFunctionGetInterfaceProtocol (TUSBFunction *pThis); + +#endif diff --git a/include/uspi/usbgamepad.h b/include/uspi/usbgamepad.h index 57ebcf9..03124f3 100644 --- a/include/uspi/usbgamepad.h +++ b/include/uspi/usbgamepad.h @@ -2,7 +2,7 @@ // usbgamepad.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // Copyright (C) 2014 M. Maccaferri // // This program is free software: you can redistribute it and/or modify @@ -18,10 +18,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . // -#ifndef _usbgamepad_h -#define _usbgamepad_h +#ifndef _uspi_usbgamepad_h +#define _uspi_usbgamepad_h -#include +#include #include #include #include @@ -30,12 +30,9 @@ typedef struct TUSBGamePadDevice { - TUSBDevice m_USBDevice; + TUSBFunction m_USBFunction; unsigned m_nDeviceIndex; - u8 m_ucInterfaceNumber; - u8 m_ucAlternateSetting; - TUSBEndpoint *m_pEndpointIn; TUSBEndpoint *m_pEndpointOut; @@ -45,16 +42,16 @@ typedef struct TUSBGamePadDevice u16 m_usReportDescriptorLength; u8 *m_pHIDReportDescriptor; - TUSBRequest *m_pURB; + TUSBRequest m_URB; u8 *m_pReportBuffer; u16 m_nReportSize; } TUSBGamePadDevice; -void USBGamePadDevice (TUSBGamePadDevice *pThis, TUSBDevice *pDevice); +void USBGamePadDevice (TUSBGamePadDevice *pThis, TUSBFunction *pFunction); void _CUSBGamePadDevice (TUSBGamePadDevice *pThis); -boolean USBGamePadDeviceConfigure (TUSBDevice *pUSBDevice); +boolean USBGamePadDeviceConfigure (TUSBFunction *pUSBFunction); void USBGamePadDeviceGetReport (TUSBGamePadDevice *pThis); void USBGamePadDeviceRegisterStatusHandler (TUSBGamePadDevice *pThis, TGamePadStatusHandler *pStatusHandler); diff --git a/include/uspi/usbkeyboard.h b/include/uspi/usbkeyboard.h index e06871c..d899601 100644 --- a/include/uspi/usbkeyboard.h +++ b/include/uspi/usbkeyboard.h @@ -2,7 +2,7 @@ // usbkeyboard.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -17,10 +17,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . // -#ifndef _usbkeyboard_h -#define _usbkeyboard_h +#ifndef _uspi_usbkeyboard_h +#define _uspi_usbkeyboard_h -#include +#include #include #include #include @@ -38,10 +38,7 @@ typedef void TKeyStatusHandlerRaw (unsigned char ucModifiers, // see usbhid.h typedef struct TUSBKeyboardDevice { - TUSBDevice m_USBDevice; - - u8 m_ucInterfaceNumber; - u8 m_ucAlternateSetting; + TUSBFunction m_USBFunction; TUSBEndpoint *m_pReportEndpoint; @@ -50,27 +47,33 @@ typedef struct TUSBKeyboardDevice TShutdownHandler *m_pShutdownHandler; TKeyStatusHandlerRaw *m_pKeyStatusHandlerRaw; - TUSBRequest *m_pURB; + TUSBRequest m_URB; u8 *m_pReportBuffer; u8 m_ucLastPhyCode; unsigned m_hTimer; TKeyMap m_KeyMap; + + u8 m_ucLastLEDStatus; } TUSBKeyboardDevice; -void USBKeyboardDevice (TUSBKeyboardDevice *pThis, TUSBDevice *pDevice); +void USBKeyboardDevice (TUSBKeyboardDevice *pThis, TUSBFunction *pFunction); void _CUSBKeyboardDevice (TUSBKeyboardDevice *pThis); -boolean USBKeyboardDeviceConfigure (TUSBDevice *pUSBDevice); +boolean USBKeyboardDeviceConfigure (TUSBFunction *pUSBFunction); // cooked mode void USBKeyboardDeviceRegisterKeyPressedHandler (TUSBKeyboardDevice *pThis, TKeyPressedHandler *pKeyPressedHandler); void USBKeyboardDeviceRegisterSelectConsoleHandler (TUSBKeyboardDevice *pThis, TSelectConsoleHandler *pSelectConsoleHandler); void USBKeyboardDeviceRegisterShutdownHandler (TUSBKeyboardDevice *pThis, TShutdownHandler *pShutdownHandler); +void USBKeyboardDeviceUpdateLEDs (TUSBKeyboardDevice *pThis); + // raw mode (if this handler is registered the others are ignored) void USBKeyboardDeviceRegisterKeyStatusHandlerRaw (TUSBKeyboardDevice *pThis, TKeyStatusHandlerRaw *pKeyStatusHandlerRaw); +void USBKeyboardDeviceSetLEDs (TUSBKeyboardDevice *pThis, u8 ucLEDMask); + #endif diff --git a/include/uspi/usbmassdevice.h b/include/uspi/usbmassdevice.h index 847587b..c3a6f0b 100644 --- a/include/uspi/usbmassdevice.h +++ b/include/uspi/usbmassdevice.h @@ -2,7 +2,7 @@ // usbmassdevice.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -20,7 +20,7 @@ #ifndef _uspi_usbmassdevice_h #define _uspi_usbmassdevice_h -#include +#include #include #include @@ -36,7 +36,7 @@ extern "C" { typedef struct TUSBBulkOnlyMassStorageDevice { - TUSBDevice m_USBDevice; + TUSBFunction m_USBFunction; TUSBEndpoint *m_pEndpointIn; TUSBEndpoint *m_pEndpointOut; @@ -47,10 +47,10 @@ typedef struct TUSBBulkOnlyMassStorageDevice } TUSBBulkOnlyMassStorageDevice; -void USBBulkOnlyMassStorageDevice (TUSBBulkOnlyMassStorageDevice *pThis, TUSBDevice *pDevice); +void USBBulkOnlyMassStorageDevice (TUSBBulkOnlyMassStorageDevice *pThis, TUSBFunction *pFunction); void _USBBulkOnlyMassStorageDevice (TUSBBulkOnlyMassStorageDevice *pThis); -boolean USBBulkOnlyMassStorageDeviceConfigure (TUSBDevice *pUSBDevice); +boolean USBBulkOnlyMassStorageDeviceConfigure (TUSBFunction *pUSBFunction); int USBBulkOnlyMassStorageDeviceRead (TUSBBulkOnlyMassStorageDevice *pThis, void *pBuffer, unsigned nCount); int USBBulkOnlyMassStorageDeviceWrite (TUSBBulkOnlyMassStorageDevice *pThis, const void *pBuffer, unsigned nCount); diff --git a/include/uspi/usbmidi.h b/include/uspi/usbmidi.h index d1520f8..5a7ab79 100644 --- a/include/uspi/usbmidi.h +++ b/include/uspi/usbmidi.h @@ -2,7 +2,7 @@ // usbmidi.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2016 R. Stange +// Copyright (C) 2016-2018 R. Stange // Copyright (C) 2016 J. Otto // // This program is free software: you can redistribute it and/or modify @@ -18,10 +18,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . // -#ifndef _usbmidi_h -#define _usbmidi_h +#ifndef _uspi_usbmidi_h +#define _uspi_usbmidi_h -#include +#include #include #include #include @@ -30,22 +30,22 @@ typedef void TMIDIPacketHandler(unsigned nCable, unsigned nLength, u8 *pPacket); typedef struct TUSBMIDIDevice { - TUSBDevice m_USBDevice; + TUSBFunction m_USBFunction; TUSBEndpoint *m_pEndpointIn; TMIDIPacketHandler *m_pPacketHandler; - TUSBRequest *m_pURB; + TUSBRequest m_URB; u16 m_usBufferSize; u8 *m_pPacketBuffer; } TUSBMIDIDevice; -void USBMIDIDevice (TUSBMIDIDevice *pThis, TUSBDevice *pDevice); +void USBMIDIDevice (TUSBMIDIDevice *pThis, TUSBFunction *pFunction); void _CUSBMIDIDevice (TUSBMIDIDevice *pThis); -boolean USBMIDIDeviceConfigure (TUSBDevice *pUSBDevice); +boolean USBMIDIDeviceConfigure (TUSBFunction *pUSBFunction); void USBMIDIDeviceRegisterPacketHandler (TUSBMIDIDevice *pThis, TMIDIPacketHandler *pPacketHandler); diff --git a/include/uspi/usbmouse.h b/include/uspi/usbmouse.h index a9353f4..e05b27f 100644 --- a/include/uspi/usbmouse.h +++ b/include/uspi/usbmouse.h @@ -2,7 +2,7 @@ // usbmouse.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -17,10 +17,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . // -#ifndef _usbmouse_h -#define _usbmouse_h +#ifndef _uspi_usbmouse_h +#define _uspi_usbmouse_h -#include +#include #include #include #include @@ -31,24 +31,24 @@ typedef void TMouseStatusHandler (unsigned nButtons, int nDisplacementX, int nDi typedef struct TUSBMouseDevice { - TUSBDevice m_USBDevice; - - u8 m_ucInterfaceNumber; - u8 m_ucAlternateSetting; + TUSBFunction m_USBFunction; TUSBEndpoint *m_pReportEndpoint; TMouseStatusHandler *m_pStatusHandler; - TUSBRequest *m_pURB; + u16 m_usReportDescriptorLength; + u8 *m_pHIDReportDescriptor; + + TUSBRequest m_URB; u8 *m_pReportBuffer; } TUSBMouseDevice; -void USBMouseDevice (TUSBMouseDevice *pThis, TUSBDevice *pDevice); +void USBMouseDevice (TUSBMouseDevice *pThis, TUSBFunction *pFunction); void _CUSBMouseDevice (TUSBMouseDevice *pThis); -boolean USBMouseDeviceConfigure (TUSBDevice *pUSBDevice); +boolean USBMouseDeviceConfigure (TUSBFunction *pUSBFunction); void USBMouseDeviceRegisterStatusHandler (TUSBMouseDevice *pThis, TMouseStatusHandler *pStatusHandler); diff --git a/include/uspi/usbstandardhub.h b/include/uspi/usbstandardhub.h index 54813c6..71b9448 100644 --- a/include/uspi/usbstandardhub.h +++ b/include/uspi/usbstandardhub.h @@ -2,7 +2,7 @@ // usbstandardhub.h // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -17,12 +17,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . // -#ifndef _usbstandardhub_h -#define _usbstandardhub_h +#ifndef _uspi_usbstandardhub_h +#define _uspi_usbstandardhub_h #include #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ extern "C" { typedef struct TUSBStandardHub { - TUSBDevice m_USBDevice; + TUSBFunction m_USBFunction; TUSBHubDescriptor *m_pHubDesc; @@ -43,13 +43,11 @@ typedef struct TUSBStandardHub } TUSBStandardHub; -void USBStandardHub (TUSBStandardHub *pThis, TUSBDevice *pDevice); +void USBStandardHub (TUSBStandardHub *pThis, TUSBFunction *pFunction); void _USBStandardHub (TUSBStandardHub *pThis); boolean USBStandardHubInitialize (TUSBStandardHub *pThis); -boolean USBStandardHubConfigure (TUSBDevice *pUSBDevice); - -TString *USBStandardHubGetDeviceNames (TUSBDevice *pDevice); +boolean USBStandardHubConfigure (TUSBFunction *pUSBFunction); #ifdef __cplusplus } diff --git a/lib/Makefile b/lib/Makefile index 7dccc73..8b4c76f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -21,14 +21,15 @@ OBJS = uspilibrary.o \ dwhcidevice.o dwhciregister.o dwhcixferstagedata.o \ usbconfigparser.o usbdevice.o usbdevicefactory.o usbendpoint.o usbrequest.o usbstandardhub.o \ - devicenameservice.o macaddress.o smsc951x.o lan7800.o string.o util.o \ + devicenameservice.o macaddress.o usbfunction.o smsc951x.o lan7800.o string.o util.o \ usbmassdevice.o \ dwhciframeschednper.o dwhciframeschedper.o keymap.o usbkeyboard.o \ dwhcirootport.o usbmouse.o \ dwhciframeschednsplit.o usbgamepad.o synchronize.o usbstring.o usbmidi.o libuspi.a: $(OBJS) - rm -f libuspi.a - $(AR) cr libuspi.a $(OBJS) + @echo " AR $@" + @rm -f $@ + @$(AR) cr $@ $(OBJS) include ../Rules.mk diff --git a/lib/dwhcidevice.c b/lib/dwhcidevice.c index 06a0179..6bf33b7 100644 --- a/lib/dwhcidevice.c +++ b/lib/dwhcidevice.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #define ARM_IRQ_USB 9 // for ConnectInterrupt() @@ -97,11 +98,6 @@ void DWHCIDevice (TDWHCIDevice *pThis) pThis->m_nChannelAllocated = 0; pThis->m_bWaiting = FALSE; DWHCIRootPort (&pThis->m_RootPort, pThis); - - for (unsigned nChannel = 0; nChannel < DWHCI_MAX_CHANNELS; nChannel++) - { - pThis->m_pStageData[nChannel] = 0; - } } void _DWHCIDevice (TDWHCIDevice *pThis) @@ -232,17 +228,16 @@ int DWHCIDeviceControlMessage (TDWHCIDevice *pThis, TUSBEndpoint *pEndpoint, { assert (pThis != 0); - TSetupData *pSetup = (TSetupData *) malloc (sizeof (TSetupData)); - assert (pSetup != 0); + TSetupData SetupData ALIGN (4); // DMA buffer - pSetup->bmRequestType = ucRequestType; - pSetup->bRequest = ucRequest; - pSetup->wValue = usValue; - pSetup->wIndex = usIndex; - pSetup->wLength = usDataSize; + SetupData.bmRequestType = ucRequestType; + SetupData.bRequest = ucRequest; + SetupData.wValue = usValue; + SetupData.wIndex = usIndex; + SetupData.wLength = usDataSize; TUSBRequest URB; - USBRequest (&URB, pEndpoint, pData, usDataSize, pSetup); + USBRequest (&URB, pEndpoint, pData, usDataSize, &SetupData); int nResult = -1; @@ -251,8 +246,6 @@ int DWHCIDeviceControlMessage (TDWHCIDevice *pThis, TUSBEndpoint *pEndpoint, nResult = USBRequestGetResultLength (&URB); } - free (pSetup); - _USBRequest (&URB); return nResult; @@ -749,14 +742,9 @@ boolean DWHCIDeviceTransferStageAsync (TDWHCIDevice *pThis, TUSBRequest *pURB, b { return FALSE; } - - TDWHCITransferStageData *pStageData = - (TDWHCITransferStageData *) malloc (sizeof (TDWHCITransferStageData)); - assert (pStageData != 0); - DWHCITransferStageData (pStageData, nChannel, pURB, bIn, bStatusStage); - assert (pThis->m_pStageData[nChannel] == 0); - pThis->m_pStageData[nChannel] = pStageData; + TDWHCITransferStageData *pStageData = &pThis->m_StageData[nChannel]; + DWHCITransferStageData (pStageData, nChannel, pURB, bIn, bStatusStage); DWHCIDeviceEnableChannelInterrupt (pThis, nChannel); @@ -771,10 +759,7 @@ boolean DWHCIDeviceTransferStageAsync (TDWHCIDevice *pThis, TUSBRequest *pURB, b DWHCIDeviceDisableChannelInterrupt (pThis, nChannel); _DWHCITransferStageData (pStageData); - free (pStageData); - pThis->m_pStageData[nChannel] = 0; - DWHCIDeviceFreeChannel (pThis, nChannel); return FALSE; @@ -955,8 +940,7 @@ void DWHCIDeviceChannelInterruptHandler (TDWHCIDevice *pThis, unsigned nChannel) { assert (pThis != 0); - TDWHCITransferStageData *pStageData = pThis->m_pStageData[nChannel]; - assert (pStageData != 0); + TDWHCITransferStageData *pStageData = &pThis->m_StageData[nChannel]; TDWHCIFrameScheduler *pFrameScheduler = DWHCITransferStageDataGetFrameScheduler (pStageData); TUSBRequest *pURB = DWHCITransferStageDataGetURB (pStageData); assert (pURB != 0); @@ -1039,8 +1023,6 @@ void DWHCIDeviceChannelInterruptHandler (TDWHCIDevice *pThis, unsigned nChannel) DWHCIDeviceDisableChannelInterrupt (pThis, nChannel); _DWHCITransferStageData (pStageData); - free (pStageData); - pThis->m_pStageData[nChannel] = 0; DWHCIDeviceFreeChannel (pThis, nChannel); @@ -1060,8 +1042,6 @@ void DWHCIDeviceChannelInterruptHandler (TDWHCIDevice *pThis, unsigned nChannel) DWHCIDeviceDisableChannelInterrupt (pThis, nChannel); _DWHCITransferStageData (pStageData); - free (pStageData); - pThis->m_pStageData[nChannel] = 0; DWHCIDeviceFreeChannel (pThis, nChannel); @@ -1093,8 +1073,6 @@ void DWHCIDeviceChannelInterruptHandler (TDWHCIDevice *pThis, unsigned nChannel) DWHCIDeviceDisableChannelInterrupt (pThis, nChannel); _DWHCITransferStageData (pStageData); - free (pStageData); - pThis->m_pStageData[nChannel] = 0; DWHCIDeviceFreeChannel (pThis, nChannel); @@ -1120,8 +1098,6 @@ void DWHCIDeviceChannelInterruptHandler (TDWHCIDevice *pThis, unsigned nChannel) DWHCIDeviceDisableChannelInterrupt (pThis, nChannel); _DWHCITransferStageData (pStageData); - free (pStageData); - pThis->m_pStageData[nChannel] = 0; DWHCIDeviceFreeChannel (pThis, nChannel); @@ -1158,8 +1134,6 @@ void DWHCIDeviceChannelInterruptHandler (TDWHCIDevice *pThis, unsigned nChannel) USBRequestSetStatus (pURB, 1); _DWHCITransferStageData (pStageData); - free (pStageData); - pThis->m_pStageData[nChannel] = 0; DWHCIDeviceFreeChannel (pThis, nChannel); diff --git a/lib/dwhcirootport.c b/lib/dwhcirootport.c index 257151a..fb9ce30 100644 --- a/lib/dwhcirootport.c +++ b/lib/dwhcirootport.c @@ -2,7 +2,7 @@ // dwhcirootport.cpp // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -67,7 +67,7 @@ boolean DWHCIRootPortInitialize (TDWHCIRootPort *pThis) assert (pThis->m_pDevice == 0); pThis->m_pDevice = (TUSBDevice *) malloc (sizeof (TUSBDevice)); assert (pThis->m_pDevice != 0); - USBDevice (pThis->m_pDevice, pThis->m_pHost, Speed, 0, 1); + USBDevice (pThis->m_pDevice, pThis->m_pHost, Speed, FALSE, 0, 1); if (!USBDeviceInitialize (pThis->m_pDevice)) { @@ -78,39 +78,10 @@ boolean DWHCIRootPortInitialize (TDWHCIRootPort *pThis) return FALSE; } - TString *pNames = USBStandardHubGetDeviceNames (pThis->m_pDevice); - assert (pNames != 0); - - LogWrite (FromDWHCIRoot, LOG_NOTICE, "Device %s found", StringGet (pNames)); - - _String (pNames); - free (pNames); - - // now create specific device from default device - TUSBDevice *pChild = USBDeviceFactoryGetDevice (pThis->m_pDevice); - if (pChild != 0) + if (!USBDeviceConfigure (pThis->m_pDevice)) { - _USBDevice (pThis->m_pDevice); // delete default device - free (pThis->m_pDevice); - pThis->m_pDevice = pChild; // assign specific device - - if (!(*pThis->m_pDevice->Configure) (pThis->m_pDevice)) - { - LogWrite (FromDWHCIRoot, LOG_ERROR, "Cannot configure device"); + LogWrite (FromDWHCIRoot, LOG_ERROR, "Cannot configure device"); - _USBDevice (pThis->m_pDevice); - free (pThis->m_pDevice); - pThis->m_pDevice = 0; - - return FALSE; - } - - LogWrite (FromDWHCIRoot, LOG_DEBUG, "Device configured"); - } - else - { - LogWrite (FromDWHCIRoot, LOG_NOTICE, "Device is not supported"); - _USBDevice (pThis->m_pDevice); free (pThis->m_pDevice); pThis->m_pDevice = 0; @@ -118,6 +89,8 @@ boolean DWHCIRootPortInitialize (TDWHCIRootPort *pThis) return FALSE; } + LogWrite (FromDWHCIRoot, LOG_DEBUG, "Device configured"); + // check for over-current if (DWHCIDeviceOvercurrentDetected (pThis->m_pHost)) { diff --git a/lib/dwhcixferstagedata.c b/lib/dwhcixferstagedata.c index 6ac7ccf..74cbe29 100644 --- a/lib/dwhcixferstagedata.c +++ b/lib/dwhcixferstagedata.c @@ -18,9 +18,6 @@ // along with this program. If not, see . // #include -#include -#include -#include #include #include #include @@ -38,8 +35,7 @@ void DWHCITransferStageData (TDWHCITransferStageData *pThis, unsigned nChannel, pThis->m_nState = 0; pThis->m_nSubState = 0; pThis->m_nTransactionStatus = 0; - pThis->m_pTempBuffer = 0; - pThis->m_pFrameScheduler = 0; + pThis->m_bFrameSchedulerUsed = FALSE; assert (pThis->m_pURB != 0); @@ -90,10 +86,7 @@ void DWHCITransferStageData (TDWHCITransferStageData *pThis, unsigned nChannel, } else { - assert (pThis->m_pTempBuffer == 0); - pThis->m_pTempBuffer = (u32 *) malloc (sizeof (u32)); - assert (pThis->m_pTempBuffer != 0); - pThis->m_pBufferPointer = pThis->m_pTempBuffer; + pThis->m_pBufferPointer = &pThis->m_TempBuffer; pThis->m_nTransferSize = 0; pThis->m_nBytesPerTransaction = 0; @@ -108,25 +101,24 @@ void DWHCITransferStageData (TDWHCITransferStageData *pThis, unsigned nChannel, { if (DWHCITransferStageDataIsPeriodic (pThis)) { - pThis->m_pFrameScheduler = (TDWHCIFrameScheduler *) malloc (sizeof (TDWHCIFrameSchedulerPeriodic)); - DWHCIFrameSchedulerPeriodic ((TDWHCIFrameSchedulerPeriodic *) pThis->m_pFrameScheduler); + DWHCIFrameSchedulerPeriodic (&pThis->m_FrameScheduler.Periodic); } else { - pThis->m_pFrameScheduler = (TDWHCIFrameScheduler *) malloc (sizeof (TDWHCIFrameSchedulerNonPeriodic)); - DWHCIFrameSchedulerNonPeriodic ((TDWHCIFrameSchedulerNonPeriodic *) pThis->m_pFrameScheduler); + DWHCIFrameSchedulerNonPeriodic (&pThis->m_FrameScheduler.NonPeriodic); } - assert (pThis->m_pFrameScheduler != 0); + pThis->m_bFrameSchedulerUsed = TRUE; } else { if ( USBDeviceGetHubAddress (pThis->m_pDevice) == 0 && pThis->m_Speed != USBSpeedHigh) { - pThis->m_pFrameScheduler = (TDWHCIFrameScheduler *) malloc (sizeof (TDWHCIFrameSchedulerNoSplit)); - DWHCIFrameSchedulerNoSplit ((TDWHCIFrameSchedulerNoSplit *) pThis->m_pFrameScheduler, DWHCITransferStageDataIsPeriodic (pThis)); - assert (pThis->m_pFrameScheduler != 0); + DWHCIFrameSchedulerNoSplit (&pThis->m_FrameScheduler.NoSplit, + DWHCITransferStageDataIsPeriodic (pThis)); + + pThis->m_bFrameSchedulerUsed = TRUE; } } } @@ -135,21 +127,13 @@ void _DWHCITransferStageData (TDWHCITransferStageData *pThis) { assert (pThis != 0); - if (pThis->m_pFrameScheduler != 0) + if (pThis->m_bFrameSchedulerUsed) { - pThis->m_pFrameScheduler->_DWHCIFrameScheduler (pThis->m_pFrameScheduler); - free (pThis->m_pFrameScheduler); - pThis->m_pFrameScheduler = 0; + pThis->m_FrameScheduler.Base._DWHCIFrameScheduler (&pThis->m_FrameScheduler.Base); } pThis->m_pBufferPointer = 0; - if (pThis->m_pTempBuffer != 0) - { - free (pThis->m_pTempBuffer); - pThis->m_pTempBuffer = 0; - } - pThis->m_pEndpoint = 0; pThis->m_pDevice = 0; pThis->m_pURB = 0; @@ -412,8 +396,7 @@ u8 DWHCITransferStageDataGetHubPortAddress (TDWHCITransferStageData *pThis) u8 DWHCITransferStageDataGetSplitPosition (TDWHCITransferStageData *pThis) { - assert (pThis != 0); - assert (pThis->m_nTransferSize <= 188); // TODO + // only important for isochronous transfers return DWHCI_HOST_CHAN_SPLIT_CTRL_ALL; } @@ -469,5 +452,10 @@ TUSBRequest *DWHCITransferStageDataGetURB (TDWHCITransferStageData *pThis) TDWHCIFrameScheduler *DWHCITransferStageDataGetFrameScheduler (TDWHCITransferStageData *pThis) { assert (pThis != 0); - return pThis->m_pFrameScheduler; + if (!pThis->m_bFrameSchedulerUsed) + { + return 0; + } + + return &pThis->m_FrameScheduler.Base; } diff --git a/lib/lan7800.c b/lib/lan7800.c index 7752043..66535eb 100644 --- a/lib/lan7800.c +++ b/lib/lan7800.c @@ -243,12 +243,12 @@ static const char FromLAN7800[] = "lan7800"; // starting at 10, to be sure to not collide with smsc951x driver static unsigned s_nDeviceNumber = 10; -void LAN7800Device (TLAN7800Device *pThis, TUSBDevice *pDevice) +void LAN7800Device (TLAN7800Device *pThis, TUSBFunction *pFunction) { assert (pThis != 0); - USBDeviceCopy (&pThis->m_USBDevice, pDevice); - pThis->m_USBDevice.Configure = LAN7800DeviceConfigure; + USBFunctionCopy (&pThis->m_USBFunction, pFunction); + pThis->m_USBFunction.Configure = LAN7800DeviceConfigure; pThis->m_pEndpointBulkIn = 0; pThis->m_pEndpointBulkOut = 0; @@ -282,40 +282,25 @@ void _LAN7800Device (TLAN7800Device *pThis) pThis->m_pEndpointBulkIn = 0; } - _USBDevice (&pThis->m_USBDevice); + _USBFunction (&pThis->m_USBFunction); } -boolean LAN7800DeviceConfigure (TUSBDevice *pUSBDevice) +boolean LAN7800DeviceConfigure (TUSBFunction *pUSBFunction) { - TLAN7800Device *pThis = (TLAN7800Device *) pUSBDevice; + TLAN7800Device *pThis = (TLAN7800Device *) pUSBFunction; assert (pThis != 0); // check USB configuration - const TUSBConfigurationDescriptor *pConfigDesc = - (TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION); - if ( pConfigDesc == 0 - || pConfigDesc->bNumInterfaces != 1) + if (USBFunctionGetNumEndpoints (&pThis->m_USBFunction) != 3) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromLAN7800); - - return FALSE; - } - - const TUSBInterfaceDescriptor *pInterfaceDesc = - (TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE); - if ( pInterfaceDesc == 0 - || pInterfaceDesc->bInterfaceNumber != 0x00 - || pInterfaceDesc->bAlternateSetting != 0x00 - || pInterfaceDesc->bNumEndpoints != 3) - { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromLAN7800); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromLAN7800); return FALSE; } const TUSBEndpointDescriptor *pEndpointDesc; - while ((pEndpointDesc = (TUSBEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT)) != 0) + while ((pEndpointDesc = (TUSBEndpointDescriptor *) USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_ENDPOINT)) != 0) { if ((pEndpointDesc->bmAttributes & 0x3F) == 0x02) // Bulk { @@ -323,27 +308,27 @@ boolean LAN7800DeviceConfigure (TUSBDevice *pUSBDevice) { if (pThis->m_pEndpointBulkIn != 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromLAN7800); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromLAN7800); return FALSE; } pThis->m_pEndpointBulkIn = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint)); assert (pThis->m_pEndpointBulkIn); - USBEndpoint2 (pThis->m_pEndpointBulkIn, &pThis->m_USBDevice, pEndpointDesc); + USBEndpoint2 (pThis->m_pEndpointBulkIn, USBFunctionGetDevice (&pThis->m_USBFunction), pEndpointDesc); } else // Output { if (pThis->m_pEndpointBulkOut != 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromLAN7800); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromLAN7800); return FALSE; } pThis->m_pEndpointBulkOut = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint)); assert (pThis->m_pEndpointBulkOut); - USBEndpoint2 (pThis->m_pEndpointBulkOut, &pThis->m_USBDevice, pEndpointDesc); + USBEndpoint2 (pThis->m_pEndpointBulkOut, USBFunctionGetDevice (&pThis->m_USBFunction), pEndpointDesc); } } } @@ -351,14 +336,14 @@ boolean LAN7800DeviceConfigure (TUSBDevice *pUSBDevice) if ( pThis->m_pEndpointBulkIn == 0 || pThis->m_pEndpointBulkOut == 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromLAN7800); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromLAN7800); return FALSE; } - if (!USBDeviceConfigure (&pThis->m_USBDevice)) + if (!USBFunctionConfigure (&pThis->m_USBFunction)) { - LogWrite (FromLAN7800, LOG_ERROR, "Cannot set configuration"); + LogWrite (FromLAN7800, LOG_ERROR, "Cannot set interface"); return FALSE; } @@ -512,7 +497,7 @@ boolean LAN7800DeviceSendFrame (TLAN7800Device *pThis, const void *pBuffer, unsi *(u32 *) &pThis->m_pTxBuffer[4] = 0; assert (pThis->m_pEndpointBulkOut != 0); - return DWHCIDeviceTransfer (USBDeviceGetHost (&pThis->m_USBDevice), pThis->m_pEndpointBulkOut, + return DWHCIDeviceTransfer (USBFunctionGetHost (&pThis->m_USBFunction), pThis->m_pEndpointBulkOut, pThis->m_pTxBuffer, nLength+TX_HEADER_SIZE) >= 0; } @@ -525,7 +510,7 @@ boolean LAN7800DeviceReceiveFrame (TLAN7800Device *pThis, void *pBuffer, unsigne TUSBRequest URB; USBRequest (&URB, pThis->m_pEndpointBulkIn, pBuffer, FRAME_BUFFER_SIZE, 0); - if (!DWHCIDeviceSubmitBlockingRequest (USBDeviceGetHost (&pThis->m_USBDevice), &URB)) + if (!DWHCIDeviceSubmitBlockingRequest (USBFunctionGetHost (&pThis->m_USBFunction), &URB)) { _USBRequest (&URB); @@ -752,8 +737,8 @@ boolean LAN7800DeviceWriteReg (TLAN7800Device *pThis, u32 nIndex, u32 nValue) { assert (pThis != 0); - if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + if (DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), REQUEST_OUT | REQUEST_VENDOR, WRITE_REGISTER, 0, nIndex, &nValue, sizeof nValue) < 0) { @@ -769,8 +754,8 @@ boolean LAN7800DeviceReadReg (TLAN7800Device *pThis, u32 nIndex, u32 *pValue) { assert (pThis != 0); - if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + if (DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), REQUEST_IN | REQUEST_VENDOR, READ_REGISTER, 0, nIndex, pValue, sizeof *pValue) != (int) sizeof *pValue) { diff --git a/lib/smsc951x.c b/lib/smsc951x.c index 22543b0..a9f330e 100644 --- a/lib/smsc951x.c +++ b/lib/smsc951x.c @@ -9,7 +9,7 @@ // See the file lib/README for details! // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014-2016 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -30,6 +30,7 @@ #include #include #include +#include // USB vendor requests #define WRITE_REGISTER 0xA0 @@ -131,12 +132,12 @@ void SMSC951xDeviceDumpReg (TSMSC951xDevice *pThis, const char *pName, u32 nInde void SMSC951xDeviceDumpRegs (TSMSC951xDevice *pThis); #endif -void SMSC951xDevice (TSMSC951xDevice *pThis, TUSBDevice *pDevice) +void SMSC951xDevice (TSMSC951xDevice *pThis, TUSBFunction *pDevice) { assert (pThis != 0); - USBDeviceCopy (&pThis->m_USBDevice, pDevice); - pThis->m_USBDevice.Configure = SMSC951xDeviceConfigure; + USBFunctionCopy (&pThis->m_USBFunction, pDevice); + pThis->m_USBFunction.Configure = SMSC951xDeviceConfigure; pThis->m_pEndpointBulkIn = 0; pThis->m_pEndpointBulkOut = 0; @@ -170,12 +171,12 @@ void _SMSC951xDevice (TSMSC951xDevice *pThis) pThis->m_pEndpointBulkIn = 0; } - _USBDevice (&pThis->m_USBDevice); + _USBFunction (&pThis->m_USBFunction); } -boolean SMSC951xDeviceConfigure (TUSBDevice *pUSBDevice) +boolean SMSC951xDeviceConfigure (TUSBFunction *pUSBFunction) { - TSMSC951xDevice *pThis = (TSMSC951xDevice *) pUSBDevice; + TSMSC951xDevice *pThis = (TSMSC951xDevice *) pUSBFunction; assert (pThis != 0); u8 MACAddress[MAC_ADDRESS_SIZE]; @@ -194,26 +195,9 @@ boolean SMSC951xDeviceConfigure (TUSBDevice *pUSBDevice) MACAddressFormat (&pThis->m_MACAddress, &MACString); LogWrite (FromSMSC951x, LOG_DEBUG, "MAC address is %s", StringGet (&MACString)); - const TUSBConfigurationDescriptor *pConfigDesc = - (TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION); - if ( pConfigDesc == 0 - || pConfigDesc->bNumInterfaces != 1) - { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromSMSC951x); - - _String (&MACString); - - return FALSE; - } - - const TUSBInterfaceDescriptor *pInterfaceDesc = - (TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE); - if ( pInterfaceDesc == 0 - || pInterfaceDesc->bInterfaceNumber != 0x00 - || pInterfaceDesc->bAlternateSetting != 0x00 - || pInterfaceDesc->bNumEndpoints != 3) + if (USBFunctionGetNumEndpoints (&pThis->m_USBFunction) != 3) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromSMSC951x); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromSMSC951x); _String (&MACString); @@ -221,7 +205,7 @@ boolean SMSC951xDeviceConfigure (TUSBDevice *pUSBDevice) } const TUSBEndpointDescriptor *pEndpointDesc; - while ((pEndpointDesc = (TUSBEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT)) != 0) + while ((pEndpointDesc = (TUSBEndpointDescriptor *) USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_ENDPOINT)) != 0) { if ((pEndpointDesc->bmAttributes & 0x3F) == 0x02) // Bulk { @@ -229,7 +213,7 @@ boolean SMSC951xDeviceConfigure (TUSBDevice *pUSBDevice) { if (pThis->m_pEndpointBulkIn != 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromSMSC951x); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromSMSC951x); _String (&MACString); @@ -238,13 +222,13 @@ boolean SMSC951xDeviceConfigure (TUSBDevice *pUSBDevice) pThis->m_pEndpointBulkIn = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint)); assert (pThis->m_pEndpointBulkIn); - USBEndpoint2 (pThis->m_pEndpointBulkIn, &pThis->m_USBDevice, pEndpointDesc); + USBEndpoint2 (pThis->m_pEndpointBulkIn, USBFunctionGetDevice (&pThis->m_USBFunction), pEndpointDesc); } else // Output { if (pThis->m_pEndpointBulkOut != 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromSMSC951x); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromSMSC951x); _String (&MACString); @@ -253,7 +237,7 @@ boolean SMSC951xDeviceConfigure (TUSBDevice *pUSBDevice) pThis->m_pEndpointBulkOut = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint)); assert (pThis->m_pEndpointBulkOut); - USBEndpoint2 (pThis->m_pEndpointBulkOut, &pThis->m_USBDevice, pEndpointDesc); + USBEndpoint2 (pThis->m_pEndpointBulkOut, USBFunctionGetDevice (&pThis->m_USBFunction), pEndpointDesc); } } } @@ -261,16 +245,16 @@ boolean SMSC951xDeviceConfigure (TUSBDevice *pUSBDevice) if ( pThis->m_pEndpointBulkIn == 0 || pThis->m_pEndpointBulkOut == 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromSMSC951x); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromSMSC951x); _String (&MACString); return FALSE; } - if (!USBDeviceConfigure (&pThis->m_USBDevice)) + if (!USBFunctionConfigure (&pThis->m_USBFunction)) { - LogWrite (FromSMSC951x, LOG_ERROR, "Cannot set configuration"); + LogWrite (FromSMSC951x, LOG_ERROR, "Cannot set interface"); _String (&MACString); @@ -311,8 +295,6 @@ boolean SMSC951xDeviceConfigure (TUSBDevice *pUSBDevice) return FALSE; } - // TODO: check if PHY is up (wait for it) - TString DeviceName; String (&DeviceName); StringFormat (&DeviceName, "eth%u", s_nDeviceNumber++); @@ -348,7 +330,7 @@ boolean SMSC951xDeviceSendFrame (TSMSC951xDevice *pThis, const void *pBuffer, un *(u32 *) &pThis->m_pTxBuffer[4] = nLength; assert (pThis->m_pEndpointBulkOut != 0); - return DWHCIDeviceTransfer (USBDeviceGetHost (&pThis->m_USBDevice), pThis->m_pEndpointBulkOut, pThis->m_pTxBuffer, nLength+8) >= 0; + return DWHCIDeviceTransfer (USBFunctionGetHost (&pThis->m_USBFunction), pThis->m_pEndpointBulkOut, pThis->m_pTxBuffer, nLength+8) >= 0; } boolean SMSC951xDeviceReceiveFrame (TSMSC951xDevice *pThis, void *pBuffer, unsigned *pResultLength) @@ -360,7 +342,7 @@ boolean SMSC951xDeviceReceiveFrame (TSMSC951xDevice *pThis, void *pBuffer, unsig TUSBRequest URB; USBRequest (&URB, pThis->m_pEndpointBulkIn, pBuffer, FRAME_BUFFER_SIZE, 0); - if (!DWHCIDeviceSubmitBlockingRequest (USBDeviceGetHost (&pThis->m_USBDevice), &URB)) + if (!DWHCIDeviceSubmitBlockingRequest (USBFunctionGetHost (&pThis->m_USBFunction), &URB)) { _USBRequest (&URB); @@ -408,12 +390,95 @@ boolean SMSC951xDeviceReceiveFrame (TSMSC951xDevice *pThis, void *pBuffer, unsig return TRUE; } +boolean SMSC951xDeviceIsLinkUp (TSMSC951xDevice *pThis) +{ + assert (pThis != 0); + + u16 usPHYModeStatus; + if (!SMSC951xDevicePHYRead (pThis, 0x01, &usPHYModeStatus)) + { + return FALSE; + } + + return usPHYModeStatus & (1 << 2) ? TRUE : FALSE; +} + +boolean SMSC951xDevicePHYWrite (TSMSC951xDevice *pThis, u8 uchIndex, u16 usValue) +{ + assert (pThis != 0); + assert (uchIndex <= 31); + + if ( !SMSC951xDevicePHYWaitNotBusy (pThis) + || !SMSC951xDeviceWriteReg (pThis, MII_DATA, usValue)) + { + return FALSE; + } + + u32 nMIIAddress = (PHY_ID_INTERNAL << 11) | ((u32) uchIndex << 6); + if (!SMSC951xDeviceWriteReg (pThis, MII_ADDR, nMIIAddress | MII_WRITE | MII_BUSY)) + { + return FALSE; + } + + return SMSC951xDevicePHYWaitNotBusy (pThis); +} + +boolean SMSC951xDevicePHYRead (TSMSC951xDevice *pThis, u8 uchIndex, u16 *pValue) +{ + assert (pThis != 0); + assert (uchIndex <= 31); + + if (!SMSC951xDevicePHYWaitNotBusy (pThis)) + { + return FALSE; + } + + u32 nMIIAddress = (PHY_ID_INTERNAL << 11) | ((u32) uchIndex << 6); + u32 nValue; + if ( !SMSC951xDeviceWriteReg (pThis, MII_ADDR, nMIIAddress | MII_BUSY) + || !SMSC951xDevicePHYWaitNotBusy (pThis) + || !SMSC951xDeviceReadReg (pThis, MII_DATA, &nValue)) + { + return FALSE; + } + + assert (pValue != 0); + *pValue = nValue & 0xFFFF; + + return TRUE; +} + +boolean SMSC951xDevicePHYWaitNotBusy (TSMSC951xDevice *pThis) +{ + assert (pThis != 0); + + unsigned nTries = 1000; + u32 nValue; + do + { + MsDelay (1); + + if (--nTries == 0) + { + return FALSE; + } + + if (!SMSC951xDeviceReadReg (pThis, MII_ADDR, &nValue)) + { + return FALSE; + } + } + while (nValue & MII_BUSY); + + return TRUE; +} + boolean SMSC951xDeviceWriteReg (TSMSC951xDevice *pThis, u32 nIndex, u32 nValue) { assert (pThis != 0); - return DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + return DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), REQUEST_OUT | REQUEST_VENDOR, WRITE_REGISTER, 0, nIndex, &nValue, sizeof nValue) >= 0; } @@ -422,8 +487,8 @@ boolean SMSC951xDeviceReadReg (TSMSC951xDevice *pThis, u32 nIndex, u32 *pValue) { assert (pThis != 0); - return DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + return DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), REQUEST_IN | REQUEST_VENDOR, READ_REGISTER, 0, nIndex, pValue, sizeof *pValue) == (int) sizeof *pValue; } diff --git a/lib/usbconfigparser.c b/lib/usbconfigparser.c index c3007df..56e4d4f 100644 --- a/lib/usbconfigparser.c +++ b/lib/usbconfigparser.c @@ -30,7 +30,8 @@ void USBConfigurationParser (TUSBConfigurationParser *pThis, const void *pBuffer pThis->m_nBufLen = nBufLen; pThis->m_bValid = FALSE; pThis->m_pEndPosition = SKIP_BYTES (pThis->m_pBuffer, nBufLen); - pThis->m_pCurrentPosition = pThis->m_pBuffer; + pThis->m_pNextPosition = pThis->m_pBuffer; + pThis->m_pCurrentDescriptor = 0; pThis->m_pErrorPosition = pThis->m_pBuffer; assert (pThis->m_pBuffer != 0); @@ -124,6 +125,20 @@ void USBConfigurationParser (TUSBConfigurationParser *pThis, const void *pBuffer pThis->m_bValid = TRUE; } +void USBConfigurationParserCopy (TUSBConfigurationParser *pThis, TUSBConfigurationParser *pParser) +{ + assert (pThis != 0); + assert (pParser != 0); + + pThis->m_pBuffer = pParser->m_pBuffer; + pThis->m_nBufLen = pParser->m_nBufLen; + pThis->m_bValid = pParser->m_bValid; + pThis->m_pEndPosition = pParser->m_pEndPosition; + pThis->m_pNextPosition = pParser->m_pNextPosition; + pThis->m_pCurrentDescriptor = pParser->m_pCurrentDescriptor; + pThis->m_pErrorPosition = pParser->m_pErrorPosition; +} + void _USBConfigurationParser (TUSBConfigurationParser *pThis) { assert (pThis != 0); @@ -143,12 +158,12 @@ const TUSBDescriptor *USBConfigurationParserGetDescriptor (TUSBConfigurationPars const TUSBDescriptor *pResult = 0; - while (pThis->m_pCurrentPosition < pThis->m_pEndPosition) + while (pThis->m_pNextPosition < pThis->m_pEndPosition) { - u8 ucDescLen = pThis->m_pCurrentPosition->Header.bLength; - u8 ucDescType = pThis->m_pCurrentPosition->Header.bDescriptorType; + u8 ucDescLen = pThis->m_pNextPosition->Header.bLength; + u8 ucDescType = pThis->m_pNextPosition->Header.bDescriptorType; - TUSBDescriptor *pDescEnd = SKIP_BYTES (pThis->m_pCurrentPosition, ucDescLen); + TUSBDescriptor *pDescEnd = SKIP_BYTES (pThis->m_pNextPosition, ucDescLen); assert (pDescEnd <= pThis->m_pEndPosition); if ( ucType == DESCRIPTOR_ENDPOINT @@ -159,12 +174,12 @@ const TUSBDescriptor *USBConfigurationParserGetDescriptor (TUSBConfigurationPars if (ucDescType == ucType) { - pResult = pThis->m_pCurrentPosition; - pThis->m_pCurrentPosition = pDescEnd; + pResult = pThis->m_pNextPosition; + pThis->m_pNextPosition = pDescEnd; break; } - pThis->m_pCurrentPosition = pDescEnd; + pThis->m_pNextPosition = pDescEnd; } if (pResult != 0) @@ -172,9 +187,18 @@ const TUSBDescriptor *USBConfigurationParserGetDescriptor (TUSBConfigurationPars pThis->m_pErrorPosition = pResult; } + pThis->m_pCurrentDescriptor = pResult; + return pResult; } +const TUSBDescriptor *USBConfigurationParserGetCurrentDescriptor (TUSBConfigurationParser *pThis) +{ + assert (pThis->m_bValid); + assert (pThis->m_pCurrentDescriptor != 0); + + return pThis->m_pCurrentDescriptor; +} void USBConfigurationParserError (TUSBConfigurationParser *pThis, const char *pSource) { diff --git a/lib/usbdevice.c b/lib/usbdevice.c index 17ed3f7..abc9fac 100644 --- a/lib/usbdevice.c +++ b/lib/usbdevice.c @@ -2,7 +2,7 @@ // usbdevice.c // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -20,8 +20,10 @@ #include #include #include +#include #include #include +#include #include #define MAX_CONFIG_DESC_SIZE 512 // best guess @@ -39,16 +41,16 @@ static const char FromDevice[] = "usbdev"; static u8 s_ucNextAddress = USB_FIRST_DEDICATED_ADDRESS; -void USBDevice (TUSBDevice *pThis, struct TDWHCIDevice *pHost, TUSBSpeed Speed, u8 ucHubAddress, u8 ucHubPortNumber) +void USBDevice (TUSBDevice *pThis, struct TDWHCIDevice *pHost, TUSBSpeed Speed, + boolean bSplitTransfer, u8 ucHubAddress, u8 ucHubPortNumber) { assert (pThis != 0); - pThis->Configure = USBDeviceConfigure; - pThis->m_pHost = pHost; pThis->m_ucAddress = USB_DEFAULT_ADDRESS; pThis->m_Speed = Speed; pThis->m_pEndpoint0 = 0; + pThis->m_bSplitTransfer = bSplitTransfer; pThis->m_ucHubAddress = ucHubAddress; pThis->m_ucHubPortNumber = ucHubPortNumber; pThis->m_pDeviceDesc = 0; @@ -66,64 +68,26 @@ void USBDevice (TUSBDevice *pThis, struct TDWHCIDevice *pHost, TUSBSpeed Speed, USBString (&pThis->m_ManufacturerString, pThis); USBString (&pThis->m_ProductString, pThis); + + for (unsigned nFunction = 0; nFunction < USBDEV_MAX_FUNCTIONS; nFunction++) + { + pThis->m_pFunction[nFunction] = 0; + } } -void USBDeviceCopy (TUSBDevice *pThis, TUSBDevice *pDevice) +void _USBDevice (TUSBDevice *pThis) { assert (pThis != 0); - assert (pDevice != 0); - - pThis->Configure = pDevice->Configure; - - pThis->m_pEndpoint0 = 0; - pThis->m_pDeviceDesc = 0; - pThis->m_pConfigDesc = 0; - pThis->m_pConfigParser = 0; - - pThis->m_pHost = pDevice->m_pHost; - pThis->m_ucAddress = pDevice->m_ucAddress; - pThis->m_Speed = pDevice->m_Speed; - pThis->m_ucHubAddress = pDevice->m_ucHubAddress; - pThis->m_ucHubPortNumber = pDevice->m_ucHubPortNumber; - - USBStringCopy (&pThis->m_ManufacturerString, &pDevice->m_ManufacturerString); - USBStringCopy (&pThis->m_ProductString, &pDevice->m_ProductString); - - pThis->m_pEndpoint0 = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint)); - assert (pThis->m_pEndpoint0 != 0); - USBEndpointCopy (pThis->m_pEndpoint0, pDevice->m_pEndpoint0, pThis); - - if (pDevice->m_pDeviceDesc != 0) + for (unsigned nFunction = 0; nFunction < USBDEV_MAX_FUNCTIONS; nFunction++) { - pThis->m_pDeviceDesc = (TUSBDeviceDescriptor *) malloc (sizeof (TUSBDeviceDescriptor)); - assert (pThis->m_pDeviceDesc != 0); - - memcpy (pThis->m_pDeviceDesc, pDevice->m_pDeviceDesc, sizeof (TUSBDeviceDescriptor)); - } - - if (pDevice->m_pConfigDesc != 0) - { - unsigned nTotalLength = pDevice->m_pConfigDesc->wTotalLength; - assert (nTotalLength <= MAX_CONFIG_DESC_SIZE); - - pThis->m_pConfigDesc = (TUSBConfigurationDescriptor *) malloc (nTotalLength); - assert (pThis->m_pConfigDesc != 0); - - memcpy (pThis->m_pConfigDesc, pDevice->m_pConfigDesc, nTotalLength); - - if (pDevice->m_pConfigParser != 0) + if (pThis->m_pFunction[nFunction] != 0) { - pThis->m_pConfigParser = (TUSBConfigurationParser *) malloc (sizeof (TUSBConfigurationParser)); - assert (pThis->m_pConfigParser != 0); - USBConfigurationParser (pThis->m_pConfigParser, pThis->m_pConfigDesc, nTotalLength); + _USBFunction (pThis->m_pFunction[nFunction]); + free (pThis->m_pFunction[nFunction]); + pThis->m_pFunction[nFunction] = 0; } } -} - -void _USBDevice (TUSBDevice *pThis) -{ - assert (pThis != 0); if (pThis->m_pConfigParser != 0) { @@ -151,8 +115,6 @@ void _USBDevice (TUSBDevice *pThis) pThis->m_pEndpoint0 = 0; } - pThis->Configure = 0; - pThis->m_pHost = 0; _USBString (&pThis->m_ProductString); @@ -176,7 +138,7 @@ boolean USBDeviceInitialize (TUSBDevice *pThis) pThis->m_pDeviceDesc, USB_DEFAULT_MAX_PACKET_SIZE, REQUEST_IN) != USB_DEFAULT_MAX_PACKET_SIZE) { - LogWrite (FromDevice, LOG_ERROR, "Cannot get device descriptor (short)"); + USBDeviceLogWrite (pThis, LOG_ERROR, "Cannot get device descriptor (short)"); free (pThis->m_pDeviceDesc); pThis->m_pDeviceDesc = 0; @@ -187,7 +149,7 @@ boolean USBDeviceInitialize (TUSBDevice *pThis) if ( pThis->m_pDeviceDesc->bLength != sizeof *pThis->m_pDeviceDesc || pThis->m_pDeviceDesc->bDescriptorType != DESCRIPTOR_DEVICE) { - LogWrite (FromDevice, LOG_ERROR, "Invalid device descriptor"); + USBDeviceLogWrite (pThis, LOG_ERROR, "Invalid device descriptor"); free (pThis->m_pDeviceDesc); pThis->m_pDeviceDesc = 0; @@ -202,7 +164,7 @@ boolean USBDeviceInitialize (TUSBDevice *pThis) pThis->m_pDeviceDesc, sizeof *pThis->m_pDeviceDesc, REQUEST_IN) != (int) sizeof *pThis->m_pDeviceDesc) { - LogWrite (FromDevice, LOG_ERROR, "Cannot get device descriptor"); + USBDeviceLogWrite (pThis, LOG_ERROR, "Cannot get device descriptor"); free (pThis->m_pDeviceDesc); pThis->m_pDeviceDesc = 0; @@ -217,15 +179,14 @@ boolean USBDeviceInitialize (TUSBDevice *pThis) u8 ucAddress = s_ucNextAddress++; if (ucAddress > USB_MAX_ADDRESS) { - LogWrite (FromDevice, LOG_ERROR, "Too many devices"); + USBDeviceLogWrite (pThis, LOG_ERROR, "Too many devices"); return FALSE; } if (!DWHCIDeviceSetAddress (pThis->m_pHost, pThis->m_pEndpoint0, ucAddress)) { - LogWrite (FromDevice, LOG_ERROR, - "Cannot set address %u", (unsigned) ucAddress); + USBDeviceLogWrite (pThis, LOG_ERROR, "Cannot set address %u", (unsigned) ucAddress); return FALSE; } @@ -259,7 +220,7 @@ boolean USBDeviceInitialize (TUSBDevice *pThis) pThis->m_pConfigDesc, sizeof *pThis->m_pConfigDesc, REQUEST_IN) != (int) sizeof *pThis->m_pConfigDesc) { - LogWrite (FromDevice, LOG_ERROR, "Cannot get configuration descriptor (short)"); + USBDeviceLogWrite (pThis, LOG_ERROR, "Cannot get configuration descriptor (short)"); free (pThis->m_pConfigDesc); pThis->m_pConfigDesc = 0; @@ -271,7 +232,7 @@ boolean USBDeviceInitialize (TUSBDevice *pThis) || pThis->m_pConfigDesc->bDescriptorType != DESCRIPTOR_CONFIGURATION || pThis->m_pConfigDesc->wTotalLength > MAX_CONFIG_DESC_SIZE) { - LogWrite (FromDevice, LOG_ERROR, "Invalid configuration descriptor"); + USBDeviceLogWrite (pThis, LOG_ERROR, "Invalid configuration descriptor"); free (pThis->m_pConfigDesc); pThis->m_pConfigDesc = 0; @@ -291,7 +252,7 @@ boolean USBDeviceInitialize (TUSBDevice *pThis) pThis->m_pConfigDesc, nTotalLength, REQUEST_IN) != (int) nTotalLength) { - LogWrite (FromDevice, LOG_ERROR, "Cannot get configuration descriptor"); + USBDeviceLogWrite (pThis, LOG_ERROR, "Cannot get configuration descriptor"); free (pThis->m_pConfigDesc); pThis->m_pConfigDesc = 0; @@ -315,6 +276,95 @@ boolean USBDeviceInitialize (TUSBDevice *pThis) return FALSE; } + TString *pNames = USBDeviceGetNames (pThis); + assert (pNames != 0); + USBDeviceLogWrite (pThis, LOG_NOTICE, "Device %s found", StringGet (pNames)); + _String (pNames); + free (pNames); + + unsigned nFunction = 0; + u8 ucInterfaceNumber = 0; + + TUSBInterfaceDescriptor *pInterfaceDesc; + while ((pInterfaceDesc = (TUSBInterfaceDescriptor *) USBConfigurationParserGetDescriptor (pThis->m_pConfigParser, DESCRIPTOR_INTERFACE)) != 0) + { + if (pInterfaceDesc->bInterfaceNumber > ucInterfaceNumber) + { + ucInterfaceNumber = pInterfaceDesc->bInterfaceNumber; + } + + if (pInterfaceDesc->bInterfaceNumber != ucInterfaceNumber) + { + USBDeviceLogWrite (pThis, LOG_DEBUG, "Alternate setting %u ignored", + (unsigned) pInterfaceDesc->bAlternateSetting); + + continue; + } + + assert (pThis->m_pConfigParser != 0); + assert (pThis->m_pFunction[nFunction] == 0); + pThis->m_pFunction[nFunction] = (TUSBFunction *) malloc (sizeof (TUSBFunction)); + assert (pThis->m_pFunction[nFunction] != 0); + USBFunction (pThis->m_pFunction[nFunction], pThis, pThis->m_pConfigParser); + + TUSBFunction *pChild = 0; + + if (nFunction == 0) + { + pChild = USBDeviceFactoryGetDevice (pThis->m_pFunction[nFunction], USBDeviceGetName (pThis, DeviceNameVendor)); + if (pChild == 0) + { + pChild = USBDeviceFactoryGetDevice (pThis->m_pFunction[nFunction], USBDeviceGetName (pThis, DeviceNameDevice)); + } + } + + if (pChild == 0) + { + TString *pName = USBFunctionGetInterfaceName (pThis->m_pFunction[nFunction]); + assert (pName != 0); + if (StringCompare (pName, "unknown") != 0) + { + USBDeviceLogWrite (pThis, LOG_NOTICE, "Interface %s found", StringGet (pName)); + + pChild = USBDeviceFactoryGetDevice (pThis->m_pFunction[nFunction], pName); + } + else + { + _String (pName); + free (pName); + } + } + + _USBFunction (pThis->m_pFunction[nFunction]); + free (pThis->m_pFunction[nFunction]); + pThis->m_pFunction[nFunction] = 0; + + if (pChild == 0) + { + USBDeviceLogWrite (pThis, LOG_WARNING, "Function is not supported"); + + continue; + } + + pThis->m_pFunction[nFunction] = pChild; + + if (++nFunction == USBDEV_MAX_FUNCTIONS) + { + USBDeviceLogWrite (pThis, LOG_WARNING, "Too many functions per device"); + + break; + } + + ucInterfaceNumber++; + } + + if (nFunction == 0) + { + USBDeviceLogWrite (pThis, LOG_WARNING, "Device has no supported function"); + + return FALSE; + } + return TRUE; } @@ -332,13 +382,34 @@ boolean USBDeviceConfigure (TUSBDevice *pThis) if (!DWHCIDeviceSetConfiguration (pThis->m_pHost, pThis->m_pEndpoint0, pThis->m_pConfigDesc->bConfigurationValue)) { - LogWrite (FromDevice, LOG_ERROR, "Cannot set configuration (%u)", + USBDeviceLogWrite (pThis, LOG_ERROR, "Cannot set configuration (%u)", (unsigned) pThis->m_pConfigDesc->bConfigurationValue); return FALSE; } - return TRUE; + boolean bResult = FALSE; + + for (unsigned nFunction = 0; nFunction < USBDEV_MAX_FUNCTIONS; nFunction++) + { + if (pThis->m_pFunction[nFunction] != 0) + { + if (!(*pThis->m_pFunction[nFunction]->Configure) (pThis->m_pFunction[nFunction])) + { + //LogWrite (LOG_ERROR, "Cannot configure device"); + + _USBFunction (pThis->m_pFunction[nFunction]); + free (pThis->m_pFunction[nFunction]); + pThis->m_pFunction[nFunction] = 0; + } + else + { + bResult = TRUE; + } + } + } + + return bResult; } TString *USBDeviceGetName (TUSBDevice *pThis, TDeviceNameSelector Selector) @@ -371,21 +442,6 @@ TString *USBDeviceGetName (TUSBDevice *pThis, TDeviceNameSelector Selector) (unsigned) pThis->m_pDeviceDesc->bDeviceProtocol); break; - case DeviceNameInterface: { - TConfigurationHeader *pConfig = (TConfigurationHeader *) pThis->m_pConfigDesc; - assert (pConfig != 0); - if ( pConfig->Configuration.wTotalLength < sizeof *pConfig - || pConfig->Interface.bInterfaceClass == 0 - || pConfig->Interface.bInterfaceClass == 0xFF) - { - goto unknown; - } - StringFormat (pString, "int%x-%x-%x", - (unsigned) pConfig->Interface.bInterfaceClass, - (unsigned) pConfig->Interface.bInterfaceSubClass, - (unsigned) pConfig->Interface.bInterfaceProtocol); - } break; - default: assert (0); unknown: @@ -396,6 +452,41 @@ TString *USBDeviceGetName (TUSBDevice *pThis, TDeviceNameSelector Selector) return pString; } +TString *USBDeviceGetNames (TUSBDevice *pThis) +{ + assert (pThis != 0); + + TString *pResult = malloc (sizeof (TString)); + assert (pResult != 0); + String (pResult); + + for (unsigned nSelector = DeviceNameVendor; nSelector < DeviceNameUnknown; nSelector++) + { + TString *pName = USBDeviceGetName (pThis, (TDeviceNameSelector) nSelector); + assert (pName != 0); + + if (StringCompare (pName, "unknown") != 0) + { + if (StringGetLength (pResult) > 0) + { + StringAppend (pResult, ", "); + } + + StringAppend (pResult, StringGet (pName)); + } + + _String (pName); + free (pName); + } + + if (StringGetLength (pResult) == 0) + { + StringSet (pResult, "unknown"); + } + + return pResult; +} + u8 USBDeviceGetAddress (TUSBDevice *pThis) { assert (pThis != 0); @@ -408,6 +499,12 @@ TUSBSpeed USBDeviceGetSpeed (TUSBDevice *pThis) return pThis->m_Speed; } +boolean USBDeviceIsSplit (TUSBDevice *pThis) +{ + assert (pThis != 0); + return pThis->m_bSplitTransfer; +} + u8 USBDeviceGetHubAddress (TUSBDevice *pThis) { assert (pThis != 0); @@ -469,5 +566,30 @@ void USBDeviceSetAddress (TUSBDevice *pThis, u8 ucAddress) assert (ucAddress <= USB_MAX_ADDRESS); pThis->m_ucAddress = ucAddress; - //LogWrite (FromDevice, LOG_DEBUG, "Device address set to %u", (unsigned) pThis->m_ucAddress); + //USBDeviceLogWrite (pThis, LOG_DEBUG, "Device address set to %u", (unsigned) pThis->m_ucAddress); +} + +void USBDeviceLogWrite (TUSBDevice *pThis, unsigned Severity, const char *pMessage, ...) +{ + assert (pThis != 0); + assert (pMessage != 0); + + TString Source; + String (&Source); + StringFormat (&Source, "%s%u-%u", FromDevice, (unsigned) pThis->m_ucHubAddress, + (unsigned) pThis->m_ucHubPortNumber); + + va_list var; + va_start (var, pMessage); + + TString Message; + String (&Message); + StringFormatV (&Message, pMessage, var); + + LogWrite (StringGet (&Source), Severity, StringGet (&Message)); + + va_end (var); + + _String (&Message); + _String (&Source); } diff --git a/lib/usbdevicefactory.c b/lib/usbdevicefactory.c index 1f0d13c..39f9aea 100644 --- a/lib/usbdevicefactory.c +++ b/lib/usbdevicefactory.c @@ -31,93 +31,75 @@ #include #include -TUSBDevice *GetDevice (TUSBDevice *pParent, TString *pName); - -TUSBDevice *USBDeviceFactoryGetDevice (TUSBDevice *pParent) -{ - assert (pParent != 0); - - TUSBDevice *pResult; - if ( (pResult = GetDevice (pParent, USBDeviceGetName (pParent, DeviceNameVendor))) == 0 - && (pResult = GetDevice (pParent, USBDeviceGetName (pParent, DeviceNameDevice))) == 0 - && (pResult = GetDevice (pParent, USBDeviceGetName (pParent, DeviceNameInterface))) == 0) - { - return 0; - } - - assert (pResult != 0); - - return pResult; -} - -TUSBDevice *GetDevice (TUSBDevice *pParent, TString *pName) +TUSBFunction *USBDeviceFactoryGetDevice (TUSBFunction *pParent, TString *pName) { assert (pParent != 0); assert (pName != 0); - TUSBDevice *pResult = 0; + TUSBFunction *pResult = 0; - if (StringCompare (pName, "dev9-0-2") == 0) + if ( StringCompare (pName, "int9-0-2") == 0 + || StringCompare (pName, "int9-0-0") == 0) { TUSBStandardHub *pDevice = (TUSBStandardHub *) malloc (sizeof (TUSBStandardHub)); assert (pDevice != 0); USBStandardHub (pDevice, pParent); - pResult = (TUSBDevice *) pDevice; + pResult = (TUSBFunction *) pDevice; } else if (StringCompare (pName, "int8-6-50") == 0) { TUSBBulkOnlyMassStorageDevice *pDevice = (TUSBBulkOnlyMassStorageDevice *) malloc (sizeof (TUSBBulkOnlyMassStorageDevice)); assert (pDevice != 0); USBBulkOnlyMassStorageDevice (pDevice, pParent); - pResult = (TUSBDevice *) pDevice; + pResult = (TUSBFunction *) pDevice; } else if (StringCompare (pName, "int3-1-1") == 0) { TUSBKeyboardDevice *pDevice = (TUSBKeyboardDevice *) malloc (sizeof (TUSBKeyboardDevice)); assert (pDevice != 0); USBKeyboardDevice (pDevice, pParent); - pResult = (TUSBDevice *) pDevice; + pResult = (TUSBFunction *) pDevice; } else if (StringCompare (pName, "int3-1-2") == 0) { TUSBMouseDevice *pDevice = (TUSBMouseDevice *) malloc (sizeof (TUSBMouseDevice)); assert (pDevice != 0); USBMouseDevice (pDevice, pParent); - pResult = (TUSBDevice *) pDevice; + pResult = (TUSBFunction *) pDevice; } else if (StringCompare (pName, "ven424-ec00") == 0) { TSMSC951xDevice *pDevice = (TSMSC951xDevice *) malloc (sizeof (TSMSC951xDevice)); assert (pDevice != 0); SMSC951xDevice (pDevice, pParent); - pResult = (TUSBDevice *) pDevice; + pResult = (TUSBFunction *) pDevice; } else if (StringCompare (pName, "ven424-7800") == 0) { TLAN7800Device *pDevice = (TLAN7800Device *) malloc (sizeof (TLAN7800Device)); assert (pDevice != 0); LAN7800Device (pDevice, pParent); - pResult = (TUSBDevice *) pDevice; + pResult = (TUSBFunction *) pDevice; } else if (StringCompare (pName, "int3-0-0") == 0) { TUSBGamePadDevice *pDevice = (TUSBGamePadDevice *) malloc (sizeof (TUSBGamePadDevice)); assert (pDevice != 0); USBGamePadDevice (pDevice, pParent); - pResult = (TUSBDevice *) pDevice; + pResult = (TUSBFunction *) pDevice; } else if (StringCompare (pName, "int1-3-0") == 0) { TUSBMIDIDevice *pDevice = (TUSBMIDIDevice *) malloc (sizeof (TUSBMIDIDevice)); assert (pDevice != 0); USBMIDIDevice (pDevice, pParent); - pResult = (TUSBDevice *)pDevice; + pResult = (TUSBFunction *)pDevice; } // new devices follow if (pResult != 0) { - LogWrite ("usbdev", LOG_NOTICE, "Using device %s", StringGet (pName)); + LogWrite ("usbdev", LOG_NOTICE, "Using device/interface %s", StringGet (pName)); } _String (pName); diff --git a/lib/usbfunction.c b/lib/usbfunction.c new file mode 100644 index 0000000..ea386a9 --- /dev/null +++ b/lib/usbfunction.c @@ -0,0 +1,217 @@ +// +// usbfunction.c +// +// USPi - An USB driver for Raspberry Pi written in C +// Copyright (C) 2018 R. Stange +// +// 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 3 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, see . +// +#include +#include +#include +#include +#include +#include + +static const char FromUSBFunction[] = "usbfct"; + +void USBFunction (TUSBFunction *pThis, TUSBDevice *pDevice, TUSBConfigurationParser *pConfigParser) +{ + assert (pThis != 0); + + pThis->Configure = 0; + + pThis->m_pDevice = pDevice; + assert (pThis->m_pDevice != 0); + + pThis->m_pConfigParser = (TUSBConfigurationParser *) malloc (sizeof (TUSBConfigurationParser)); + assert (pThis->m_pConfigParser != 0); + assert (pConfigParser != 0); + USBConfigurationParserCopy (pThis->m_pConfigParser, pConfigParser); + + pThis->m_pInterfaceDesc = (TUSBInterfaceDescriptor *) USBConfigurationParserGetCurrentDescriptor (pThis->m_pConfigParser); + assert (pThis->m_pInterfaceDesc != 0); +} + +void USBFunctionCopy (TUSBFunction *pThis, TUSBFunction *pFunction) +{ + assert (pThis != 0); + assert (pFunction != 0); + + pThis->Configure = pFunction->Configure; + + pThis->m_pDevice = pFunction->m_pDevice; + assert (pThis->m_pDevice != 0); + + pThis->m_pConfigParser = (TUSBConfigurationParser *) malloc (sizeof (TUSBConfigurationParser)); + assert (pThis->m_pConfigParser != 0); + assert (pFunction->m_pConfigParser != 0); + USBConfigurationParserCopy (pThis->m_pConfigParser, pFunction->m_pConfigParser); + + pThis->m_pInterfaceDesc = (TUSBInterfaceDescriptor *) USBConfigurationParserGetCurrentDescriptor (pThis->m_pConfigParser); + assert (pThis->m_pInterfaceDesc != 0); +} + +void _USBFunction (TUSBFunction *pThis) +{ + assert (pThis != 0); + + pThis->m_pInterfaceDesc = 0; + + _USBConfigurationParser (pThis->m_pConfigParser); + free (pThis->m_pConfigParser); + pThis->m_pConfigParser = 0; + + pThis->m_pDevice = 0; + + pThis->Configure = 0; +} + +boolean USBFunctionConfigure (TUSBFunction *pThis) +{ + assert (pThis != 0); + + assert (pThis->m_pInterfaceDesc != 0); + if (pThis->m_pInterfaceDesc->bAlternateSetting != 0) + { + if (DWHCIDeviceControlMessage (USBFunctionGetHost (pThis), USBFunctionGetEndpoint0 (pThis), + REQUEST_OUT | REQUEST_TO_INTERFACE, SET_INTERFACE, + pThis->m_pInterfaceDesc->bAlternateSetting, + pThis->m_pInterfaceDesc->bInterfaceNumber, 0, 0) < 0) + { + LogWrite (FromUSBFunction, LOG_ERROR, "Cannot set interface"); + + return FALSE; + } + } + + return TRUE; +} + +TString *USBFunctionGetInterfaceName (TUSBFunction *pThis) +{ + assert (pThis != 0); + + TString *pString = (TString *) malloc (sizeof (TString)); + assert (pString != 0); + String2 (pString, "unknown"); + + if ( pThis->m_pInterfaceDesc != 0 + && pThis->m_pInterfaceDesc->bInterfaceClass != 0x00 + && pThis->m_pInterfaceDesc->bInterfaceClass != 0xFF) + { + StringFormat (pString, "int%x-%x-%x", + (unsigned) pThis->m_pInterfaceDesc->bInterfaceClass, + (unsigned) pThis->m_pInterfaceDesc->bInterfaceSubClass, + (unsigned) pThis->m_pInterfaceDesc->bInterfaceProtocol); + } + + return pString; +} + +u8 USBFunctionGetNumEndpoints (TUSBFunction *pThis) +{ + assert (pThis != 0); + assert (pThis->m_pInterfaceDesc != 0); + return pThis->m_pInterfaceDesc->bNumEndpoints; +} + +TUSBDevice *USBFunctionGetDevice (TUSBFunction *pThis) +{ + assert (pThis != 0); + assert (pThis->m_pDevice != 0); + return pThis->m_pDevice; +} + +TUSBEndpoint *USBFunctionGetEndpoint0 (TUSBFunction *pThis) +{ + assert (pThis != 0); + assert (pThis->m_pDevice != 0); + return USBDeviceGetEndpoint0 (pThis->m_pDevice); +} + +TDWHCIDevice *USBFunctionGetHost (TUSBFunction *pThis) +{ + assert (pThis != 0); + assert (pThis->m_pDevice != 0); + return USBDeviceGetHost (pThis->m_pDevice); +} + +const TUSBDescriptor *USBFunctionGetDescriptor (TUSBFunction *pThis, u8 ucType) +{ + assert (pThis != 0); + assert (pThis->m_pConfigParser != 0); + return USBConfigurationParserGetDescriptor (pThis->m_pConfigParser, ucType); +} + +void USBFunctionConfigurationError (TUSBFunction *pThis, const char *pSource) +{ + assert (pThis != 0); + assert (pThis->m_pConfigParser != 0); + assert (pSource != 0); + USBConfigurationParserError (pThis->m_pConfigParser, pSource); +} + +boolean USBFunctionSelectInterfaceByClass (TUSBFunction *pThis, u8 uchClass, u8 uchSubClass, u8 uchProtocol) +{ + assert (pThis != 0); + assert (pThis->m_pInterfaceDesc != 0); + assert (pThis->m_pConfigParser != 0); + assert (pThis->m_pDevice != 0); + + do + { + if ( pThis->m_pInterfaceDesc->bInterfaceClass == uchClass + && pThis->m_pInterfaceDesc->bInterfaceSubClass == uchSubClass + && pThis->m_pInterfaceDesc->bInterfaceProtocol == uchProtocol) + { + return TRUE; + } + + // skip to next interface in interface enumeration in class CDevice + USBDeviceGetDescriptor (pThis->m_pDevice, DESCRIPTOR_INTERFACE); + } + while ((pThis->m_pInterfaceDesc = (TUSBInterfaceDescriptor *) + USBConfigurationParserGetDescriptor (pThis->m_pConfigParser, DESCRIPTOR_INTERFACE)) != 0); + + return FALSE; +} + +u8 USBFunctionGetInterfaceNumber (TUSBFunction *pThis) +{ + assert (pThis != 0); + assert (pThis->m_pInterfaceDesc != 0); + return pThis->m_pInterfaceDesc->bInterfaceNumber; +} + +u8 USBFunctionGetInterfaceClass (TUSBFunction *pThis) +{ + assert (pThis != 0); + assert (pThis->m_pInterfaceDesc != 0); + return pThis->m_pInterfaceDesc->bInterfaceClass; +} + +u8 USBFunctionGetInterfaceSubClass (TUSBFunction *pThis) +{ + assert (pThis != 0); + assert (pThis->m_pInterfaceDesc != 0); + return pThis->m_pInterfaceDesc->bInterfaceSubClass; +} + +u8 USBFunctionGetInterfaceProtocol (TUSBFunction *pThis) +{ + assert (pThis != 0); + assert (pThis->m_pInterfaceDesc != 0); + return pThis->m_pInterfaceDesc->bInterfaceProtocol; +} diff --git a/lib/usbgamepad.c b/lib/usbgamepad.c index b8e4200..ddb6d2e 100644 --- a/lib/usbgamepad.c +++ b/lib/usbgamepad.c @@ -2,7 +2,7 @@ // usbgamepad.c // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // Copyright (C) 2014 M. Maccaferri // // This program is free software: you can redistribute it and/or modify @@ -81,17 +81,16 @@ static boolean USBGamePadDeviceStartRequest (TUSBGamePadDevice *pThis); static void USBGamePadDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pContext); static void USBGamePadDevicePS3Configure (TUSBGamePadDevice *pThis); -void USBGamePadDevice (TUSBGamePadDevice *pThis, TUSBDevice *pDevice) +void USBGamePadDevice (TUSBGamePadDevice *pThis, TUSBFunction *pDevice) { assert (pThis != 0); - USBDeviceCopy (&pThis->m_USBDevice, pDevice); - pThis->m_USBDevice.Configure = USBGamePadDeviceConfigure; + USBFunctionCopy (&pThis->m_USBFunction, pDevice); + pThis->m_USBFunction.Configure = USBGamePadDeviceConfigure; pThis->m_pEndpointIn = 0; pThis->m_pEndpointOut = 0; pThis->m_pStatusHandler = 0; - pThis->m_pURB = 0; pThis->m_pHIDReportDescriptor = 0; pThis->m_usReportDescriptorLength = 0; pThis->m_nReportSize = 0; @@ -144,7 +143,7 @@ void _CUSBGamePadDevice (TUSBGamePadDevice *pThis) pThis->m_pEndpointOut = 0; } - _USBDevice (&pThis->m_USBDevice); + _USBFunction (&pThis->m_USBFunction); } static u32 BitGetUnsigned(void *buffer, u32 offset, u32 length) @@ -334,48 +333,29 @@ static void USBGamePadDeviceDecodeReport(TUSBGamePadDevice *pThis) pThis->m_nReportSize = (offset + 7) / 8; } -boolean USBGamePadDeviceConfigure (TUSBDevice *pUSBDevice) +boolean USBGamePadDeviceConfigure (TUSBFunction *pUSBFunction) { - TUSBGamePadDevice *pThis = (TUSBGamePadDevice *) pUSBDevice; + TUSBGamePadDevice *pThis = (TUSBGamePadDevice *) pUSBFunction; assert (pThis != 0); - TUSBConfigurationDescriptor *pConfDesc = - (TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION); - if ( pConfDesc == 0 - || pConfDesc->bNumInterfaces < 1) + if (USBFunctionGetNumEndpoints (&pThis->m_USBFunction) < 1) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBPad); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUSBPad); return FALSE; } - TUSBInterfaceDescriptor *pInterfaceDesc = - (TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE); - if ( pInterfaceDesc == 0 - || pInterfaceDesc->bNumEndpoints < 1 - || pInterfaceDesc->bInterfaceClass != 0x03 // HID Class - || pInterfaceDesc->bInterfaceSubClass != 0x00 // Boot Interface Subclass - || pInterfaceDesc->bInterfaceProtocol != 0x00) // GamePad - { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBPad); - - return FALSE; - } - - pThis->m_ucInterfaceNumber = pInterfaceDesc->bInterfaceNumber; - pThis->m_ucAlternateSetting = pInterfaceDesc->bAlternateSetting; - - TUSBHIDDescriptor *pHIDDesc = (TUSBHIDDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_HID); + TUSBHIDDescriptor *pHIDDesc = (TUSBHIDDescriptor *) USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_HID); if ( pHIDDesc == 0 || pHIDDesc->wReportDescriptorLength == 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBPad); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUSBPad); return FALSE; } const TUSBEndpointDescriptor *pEndpointDesc; - while ((pEndpointDesc = (TUSBEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT)) != 0) + while ((pEndpointDesc = (TUSBEndpointDescriptor *) USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_ENDPOINT)) != 0) { if ((pEndpointDesc->bmAttributes & 0x3F) == 0x03) // Interrupt { @@ -383,34 +363,34 @@ boolean USBGamePadDeviceConfigure (TUSBDevice *pUSBDevice) { if (pThis->m_pEndpointIn != 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBPad); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUSBPad); return FALSE; } pThis->m_pEndpointIn = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint)); assert (pThis->m_pEndpointIn != 0); - USBEndpoint2 (pThis->m_pEndpointIn, &pThis->m_USBDevice, pEndpointDesc); + USBEndpoint2 (pThis->m_pEndpointIn, USBFunctionGetDevice (&pThis->m_USBFunction), pEndpointDesc); } else // Output { if (pThis->m_pEndpointOut != 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBPad); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUSBPad); return FALSE; } pThis->m_pEndpointOut = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint)); assert (pThis->m_pEndpointOut != 0); - USBEndpoint2 (pThis->m_pEndpointOut, &pThis->m_USBDevice, pEndpointDesc); + USBEndpoint2 (pThis->m_pEndpointOut, USBFunctionGetDevice (&pThis->m_USBFunction), pEndpointDesc); } } } if (pThis->m_pEndpointIn == 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBPad); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUSBPad); return FALSE; } @@ -419,11 +399,11 @@ boolean USBGamePadDeviceConfigure (TUSBDevice *pUSBDevice) pThis->m_pHIDReportDescriptor = (unsigned char *) malloc(pHIDDesc->wReportDescriptorLength); assert (pThis->m_pHIDReportDescriptor != 0); - if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + if (DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), REQUEST_IN | REQUEST_TO_INTERFACE, GET_DESCRIPTOR, (pHIDDesc->bReportDescriptorType << 8) | DESCRIPTOR_INDEX_DEFAULT, - pThis->m_ucInterfaceNumber, + USBFunctionGetInterfaceNumber (&pThis->m_USBFunction), pThis->m_pHIDReportDescriptor, pHIDDesc->wReportDescriptorLength) != pHIDDesc->wReportDescriptorLength) { @@ -436,31 +416,25 @@ boolean USBGamePadDeviceConfigure (TUSBDevice *pUSBDevice) pThis->m_pReportBuffer[0] = 0; USBGamePadDeviceDecodeReport (pThis); - if (!USBDeviceConfigure (&pThis->m_USBDevice)) - { - LogWrite (FromUSBPad, LOG_ERROR, "Cannot set configuration"); - - return FALSE; - } + // ignoring unsupported HID interface + if ( pThis->m_State.naxes == 0 + && pThis->m_State.nhats == 0 + && pThis->m_State.nbuttons == 0) + { + return FALSE; + } - if (pThis->m_ucAlternateSetting != 0) + if (!USBFunctionConfigure (&pThis->m_USBFunction)) { - if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), - REQUEST_OUT | REQUEST_TO_INTERFACE, SET_INTERFACE, - pThis->m_ucAlternateSetting, - pThis->m_ucInterfaceNumber, 0, 0) < 0) - { - LogWrite (FromUSBPad, LOG_ERROR, "Cannot set interface"); + LogWrite (FromUSBPad, LOG_ERROR, "Cannot set interface"); - return FALSE; - } + return FALSE; } pThis->m_nDeviceIndex = s_nDeviceNumber++; - if ( pUSBDevice->m_pDeviceDesc->idVendor == 0x054c - && pUSBDevice->m_pDeviceDesc->idProduct == 0x0268) + if ( USBFunctionGetDevice (pUSBFunction)->m_pDeviceDesc->idVendor == 0x054c + && USBFunctionGetDevice (pUSBFunction)->m_pDeviceDesc->idProduct == 0x0268) { USBGamePadDevicePS3Configure (pThis); } @@ -489,13 +463,10 @@ boolean USBGamePadDeviceStartRequest (TUSBGamePadDevice *pThis) assert (pThis->m_pEndpointIn != 0); assert (pThis->m_pReportBuffer != 0); - assert (pThis->m_pURB == 0); - pThis->m_pURB = malloc (sizeof (TUSBRequest)); - assert (pThis->m_pURB != 0); - USBRequest (pThis->m_pURB, pThis->m_pEndpointIn, pThis->m_pReportBuffer, pThis->m_nReportSize, 0); - USBRequestSetCompletionRoutine (pThis->m_pURB, USBGamePadDeviceCompletionRoutine, 0, pThis); + USBRequest (&pThis->m_URB, pThis->m_pEndpointIn, pThis->m_pReportBuffer, pThis->m_nReportSize, 0); + USBRequestSetCompletionRoutine (&pThis->m_URB, USBGamePadDeviceCompletionRoutine, 0, pThis); - return DWHCIDeviceSubmitAsyncRequest (USBDeviceGetHost (&pThis->m_USBDevice), pThis->m_pURB); + return DWHCIDeviceSubmitAsyncRequest (USBFunctionGetHost (&pThis->m_USBFunction), &pThis->m_URB); } void USBGamePadDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pContext) @@ -504,7 +475,7 @@ void USBGamePadDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *p assert (pThis != 0); assert (pURB != 0); - assert (pThis->m_pURB == pURB); + assert (&pThis->m_URB == pURB); if ( USBRequestGetStatus (pURB) != 0 && USBRequestGetResultLength (pURB) > 0) @@ -517,20 +488,18 @@ void USBGamePadDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *p } } - _USBRequest (pThis->m_pURB); - free (pThis->m_pURB); - pThis->m_pURB = 0; + _USBRequest (&pThis->m_URB); USBGamePadDeviceStartRequest (pThis); } void USBGamePadDeviceGetReport (TUSBGamePadDevice *pThis) { - if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + if (DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), REQUEST_IN | REQUEST_CLASS | REQUEST_TO_INTERFACE, GET_REPORT, (REPORT_TYPE_INPUT << 8) | 0x00, - pThis->m_ucInterfaceNumber, + USBFunctionGetInterfaceNumber (&pThis->m_USBFunction), pThis->m_pReportBuffer, pThis->m_nReportSize) > 0) { USBGamePadDeviceDecodeReport (pThis); @@ -567,19 +536,19 @@ void USBGamePadDevicePS3Configure (TUSBGamePadDevice *pThis) pThis->m_pReportBuffer[1] = 0x0c; pThis->m_pReportBuffer[2] = 0x00; pThis->m_pReportBuffer[3] = 0x00; - DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_INTERFACE, SET_REPORT, (REPORT_TYPE_FEATURE << 8) | 0xf4, - pThis->m_ucInterfaceNumber, + USBFunctionGetInterfaceNumber (&pThis->m_USBFunction), pThis->m_pReportBuffer, 4); /* Turn on LED */ writeBuf[9] |= (u8)(leds[pThis->m_nDeviceIndex] << 1); - DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_INTERFACE, SET_REPORT, (REPORT_TYPE_OUTPUT << 8) | 0x01, - pThis->m_ucInterfaceNumber, + USBFunctionGetInterfaceNumber (&pThis->m_USBFunction), writeBuf, 48); } diff --git a/lib/usbkeyboard.c b/lib/usbkeyboard.c index 2fe06bb..0ce5ab7 100644 --- a/lib/usbkeyboard.c +++ b/lib/usbkeyboard.c @@ -2,7 +2,7 @@ // usbkeyboard.c // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014-2016 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -45,22 +45,22 @@ static u8 USBKeyboardDeviceGetKeyCode (TUSBKeyboardDevice *pThis); static void USBKeyboardDeviceTimerHandler (unsigned hTimer, void *pParam, void *pContext); #endif -void USBKeyboardDevice (TUSBKeyboardDevice *pThis, TUSBDevice *pDevice) +void USBKeyboardDevice (TUSBKeyboardDevice *pThis, TUSBFunction *pDevice) { assert (pThis != 0); - USBDeviceCopy (&pThis->m_USBDevice, pDevice); - pThis->m_USBDevice.Configure = USBKeyboardDeviceConfigure; + USBFunctionCopy (&pThis->m_USBFunction, pDevice); + pThis->m_USBFunction.Configure = USBKeyboardDeviceConfigure; pThis->m_pReportEndpoint = 0; pThis->m_pKeyPressedHandler = 0; pThis->m_pSelectConsoleHandler = 0; pThis->m_pShutdownHandler = 0; pThis->m_pKeyStatusHandlerRaw = 0; - pThis->m_pURB = 0; pThis->m_pReportBuffer = 0; pThis->m_ucLastPhyCode = 0; pThis->m_hTimer = 0; + pThis->m_ucLastLEDStatus = 0; KeyMap (&pThis->m_KeyMap); @@ -86,42 +86,26 @@ void _CUSBKeyboardDevice (TUSBKeyboardDevice *pThis) } _KeyMap (&pThis->m_KeyMap); - _USBDevice (&pThis->m_USBDevice); + _USBFunction (&pThis->m_USBFunction); } -boolean USBKeyboardDeviceConfigure (TUSBDevice *pUSBDevice) +boolean USBKeyboardDeviceConfigure (TUSBFunction *pUSBFunction) { - TUSBKeyboardDevice *pThis = (TUSBKeyboardDevice *) pUSBDevice; + TUSBKeyboardDevice *pThis = (TUSBKeyboardDevice *) pUSBFunction; assert (pThis != 0); - TUSBConfigurationDescriptor *pConfDesc = - (TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION); - if ( pConfDesc == 0 - || pConfDesc->bNumInterfaces < 1) + if (USBFunctionGetNumEndpoints (&pThis->m_USBFunction) < 1) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBKbd); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUSBKbd); return FALSE; } - TUSBInterfaceDescriptor *pInterfaceDesc; - while ((pInterfaceDesc = (TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE)) != 0) + TUSBEndpointDescriptor *pEndpointDesc; + while ((pEndpointDesc = (TUSBEndpointDescriptor *) + USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_ENDPOINT)) != 0) { - if ( pInterfaceDesc->bNumEndpoints < 1 - || pInterfaceDesc->bInterfaceClass != 0x03 // HID Class - || pInterfaceDesc->bInterfaceSubClass != 0x01 // Boot Interface Subclass - || pInterfaceDesc->bInterfaceProtocol != 0x01) // Keyboard - { - continue; - } - - pThis->m_ucInterfaceNumber = pInterfaceDesc->bInterfaceNumber; - pThis->m_ucAlternateSetting = pInterfaceDesc->bAlternateSetting; - - TUSBEndpointDescriptor *pEndpointDesc = - (TUSBEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT); - if ( pEndpointDesc == 0 - || (pEndpointDesc->bEndpointAddress & 0x80) != 0x80 // Input EP + if ( (pEndpointDesc->bEndpointAddress & 0x80) != 0x80 // Input EP || (pEndpointDesc->bmAttributes & 0x3F) != 0x03) // Interrupt EP { continue; @@ -130,44 +114,30 @@ boolean USBKeyboardDeviceConfigure (TUSBDevice *pUSBDevice) assert (pThis->m_pReportEndpoint == 0); pThis->m_pReportEndpoint = malloc (sizeof (TUSBEndpoint)); assert (pThis->m_pReportEndpoint != 0); - USBEndpoint2 (pThis->m_pReportEndpoint, &pThis->m_USBDevice, pEndpointDesc); + USBEndpoint2 (pThis->m_pReportEndpoint, USBFunctionGetDevice (&pThis->m_USBFunction), pEndpointDesc); break; } if (pThis->m_pReportEndpoint == 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBKbd); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUSBKbd); return FALSE; } - if (!USBDeviceConfigure (&pThis->m_USBDevice)) + if (!USBFunctionConfigure (&pThis->m_USBFunction)) { - LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set configuration"); + LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set interface"); return FALSE; } - if (pThis->m_ucAlternateSetting != 0) - { - if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), - REQUEST_OUT | REQUEST_TO_INTERFACE, SET_INTERFACE, - pThis->m_ucAlternateSetting, - pThis->m_ucInterfaceNumber, 0, 0) < 0) - { - LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set interface"); - - return FALSE; - } - } - - if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + if (DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_INTERFACE, SET_PROTOCOL, BOOT_PROTOCOL, - pThis->m_ucInterfaceNumber, 0, 0) < 0) + USBFunctionGetInterfaceNumber (&pThis->m_USBFunction), 0, 0) < 0) { LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set boot protocol"); @@ -175,17 +145,7 @@ boolean USBKeyboardDeviceConfigure (TUSBDevice *pUSBDevice) } // setting the LED status forces some keyboard adapters to work - u8 LEDs[1] ALIGN(4) = {0}; // DMA buffer - if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), - REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_INTERFACE, - SET_REPORT, (REPORT_TYPE_OUTPUT << 8) | 0, - pThis->m_ucInterfaceNumber, LEDs, sizeof LEDs) < 0) - { - LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set LEDs"); - - return FALSE; - } + USBKeyboardDeviceSetLEDs (pThis, pThis->m_ucLastLEDStatus); TString DeviceName; String (&DeviceName); @@ -218,6 +178,18 @@ void USBKeyboardDeviceRegisterShutdownHandler (TUSBKeyboardDevice *pThis, TShutd pThis->m_pShutdownHandler = pShutdownHandler; } +void USBKeyboardDeviceUpdateLEDs (TUSBKeyboardDevice *pThis) +{ + assert (pThis != 0); + u8 ucLEDStatus = KeyMapGetLEDStatus (&pThis->m_KeyMap); + if (ucLEDStatus != pThis->m_ucLastLEDStatus) + { + USBKeyboardDeviceSetLEDs (pThis, ucLEDStatus); + + pThis->m_ucLastLEDStatus = ucLEDStatus; + } +} + void USBKeyboardDeviceRegisterKeyStatusHandlerRaw (TUSBKeyboardDevice *pThis, TKeyStatusHandlerRaw *pKeyStatusHandlerRaw) { assert (pThis != 0); @@ -225,6 +197,23 @@ void USBKeyboardDeviceRegisterKeyStatusHandlerRaw (TUSBKeyboardDevice *pThis, TK pThis->m_pKeyStatusHandlerRaw = pKeyStatusHandlerRaw; } +void USBKeyboardDeviceSetLEDs (TUSBKeyboardDevice *pThis, u8 ucLEDMask) +{ + assert (pThis != 0); + + u8 LEDs[1] ALIGN(4) = {ucLEDMask}; // DMA buffer + + if (DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), + REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_INTERFACE, + SET_REPORT, (REPORT_TYPE_OUTPUT << 8) | 0, + USBFunctionGetInterfaceNumber (&pThis->m_USBFunction), + LEDs, sizeof LEDs) < 0) + { + LogWrite (FromUSBKbd, LOG_WARNING, "Cannot set LEDs"); + } +} + void USBKeyboardDeviceGenerateKeyEvent (TUSBKeyboardDevice *pThis, u8 ucPhyCode) { assert (pThis != 0); @@ -290,13 +279,10 @@ boolean USBKeyboardDeviceStartRequest (TUSBKeyboardDevice *pThis) assert (pThis->m_pReportEndpoint != 0); assert (pThis->m_pReportBuffer != 0); - assert (pThis->m_pURB == 0); - pThis->m_pURB = malloc (sizeof (TUSBRequest)); - assert (pThis->m_pURB != 0); - USBRequest (pThis->m_pURB, pThis->m_pReportEndpoint, pThis->m_pReportBuffer, BOOT_REPORT_SIZE, 0); - USBRequestSetCompletionRoutine (pThis->m_pURB, USBKeyboardDeviceCompletionRoutine, 0, pThis); + USBRequest (&pThis->m_URB, pThis->m_pReportEndpoint, pThis->m_pReportBuffer, BOOT_REPORT_SIZE, 0); + USBRequestSetCompletionRoutine (&pThis->m_URB, USBKeyboardDeviceCompletionRoutine, 0, pThis); - return DWHCIDeviceSubmitAsyncRequest (USBDeviceGetHost (&pThis->m_USBDevice), pThis->m_pURB); + return DWHCIDeviceSubmitAsyncRequest (USBFunctionGetHost (&pThis->m_USBFunction), &pThis->m_URB); } void USBKeyboardDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pContext) @@ -305,7 +291,7 @@ void USBKeyboardDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void * assert (pThis != 0); assert (pURB != 0); - assert (pThis->m_pURB == pURB); + assert (&pThis->m_URB == pURB); if ( USBRequestGetStatus (pURB) != 0 && USBRequestGetResultLength (pURB) == BOOT_REPORT_SIZE) @@ -348,9 +334,7 @@ void USBKeyboardDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void * } } - _USBRequest (pThis->m_pURB); - free (pThis->m_pURB); - pThis->m_pURB = 0; + _USBRequest (&pThis->m_URB); USBKeyboardDeviceStartRequest (pThis); } diff --git a/lib/usbmassdevice.c b/lib/usbmassdevice.c index 705720b..4ca5fa4 100644 --- a/lib/usbmassdevice.c +++ b/lib/usbmassdevice.c @@ -2,7 +2,7 @@ // usbmassdevice.c // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -195,12 +195,12 @@ int USBBulkOnlyMassStorageDeviceCommand (TUSBBulkOnlyMassStorageDevice *pThis, void *pBuffer, unsigned nBufLen, boolean bIn); int USBBulkOnlyMassStorageDeviceReset (TUSBBulkOnlyMassStorageDevice *pThis); -void USBBulkOnlyMassStorageDevice (TUSBBulkOnlyMassStorageDevice *pThis, TUSBDevice *pDevice) +void USBBulkOnlyMassStorageDevice (TUSBBulkOnlyMassStorageDevice *pThis, TUSBFunction *pDevice) { assert (pThis != 0); - USBDeviceCopy (&pThis->m_USBDevice, pDevice); - pThis->m_USBDevice.Configure = USBBulkOnlyMassStorageDeviceConfigure; + USBFunctionCopy (&pThis->m_USBFunction, pDevice); + pThis->m_USBFunction.Configure = USBBulkOnlyMassStorageDeviceConfigure; pThis->m_pEndpointIn = 0; pThis->m_pEndpointOut = 0; @@ -227,41 +227,23 @@ void _USBBulkOnlyMassStorageDevice (TUSBBulkOnlyMassStorageDevice *pThis) pThis->m_pEndpointIn = 0; } - _USBDevice (&pThis->m_USBDevice); + _USBFunction (&pThis->m_USBFunction); } -boolean USBBulkOnlyMassStorageDeviceConfigure (TUSBDevice *pUSBDevice) +boolean USBBulkOnlyMassStorageDeviceConfigure (TUSBFunction *pUSBFunction) { - TUSBBulkOnlyMassStorageDevice *pThis = (TUSBBulkOnlyMassStorageDevice *) pUSBDevice; + TUSBBulkOnlyMassStorageDevice *pThis = (TUSBBulkOnlyMassStorageDevice *) pUSBFunction; assert (pThis != 0); - TUSBConfigurationDescriptor *pConfDesc = - (TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION); - if ( pConfDesc == 0 - || pConfDesc->bNumInterfaces < 1) + if (USBFunctionGetNumEndpoints (&pThis->m_USBFunction) < 2) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUmsd); - - return FALSE; - } - - TUSBInterfaceDescriptor *pInterfaceDesc = - (TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE); - if ( pInterfaceDesc == 0 - || pInterfaceDesc->bInterfaceNumber != 0x00 - || pInterfaceDesc->bAlternateSetting != 0x00 - || pInterfaceDesc->bNumEndpoints < 2 - || pInterfaceDesc->bInterfaceClass != 0x08 // Mass Storage Class - || pInterfaceDesc->bInterfaceSubClass != 0x06 // SCSI Transparent Command Set - || pInterfaceDesc->bInterfaceProtocol != 0x50) // Bulk-Only Transport - { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUmsd); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUmsd); return FALSE; } const TUSBEndpointDescriptor *pEndpointDesc; - while ((pEndpointDesc = (TUSBEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT)) != 0) + while ((pEndpointDesc = (TUSBEndpointDescriptor *) USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_ENDPOINT)) != 0) { if ((pEndpointDesc->bmAttributes & 0x3F) == 0x02) // Bulk { @@ -269,27 +251,27 @@ boolean USBBulkOnlyMassStorageDeviceConfigure (TUSBDevice *pUSBDevice) { if (pThis->m_pEndpointIn != 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUmsd); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUmsd); return FALSE; } pThis->m_pEndpointIn = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint)); assert (pThis->m_pEndpointIn != 0); - USBEndpoint2 (pThis->m_pEndpointIn, &pThis->m_USBDevice, pEndpointDesc); + USBEndpoint2 (pThis->m_pEndpointIn, USBFunctionGetDevice (&pThis->m_USBFunction), pEndpointDesc); } else // Output { if (pThis->m_pEndpointOut != 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUmsd); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUmsd); return FALSE; } pThis->m_pEndpointOut = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint)); assert (pThis->m_pEndpointOut != 0); - USBEndpoint2 (pThis->m_pEndpointOut, &pThis->m_USBDevice, pEndpointDesc); + USBEndpoint2 (pThis->m_pEndpointOut, USBFunctionGetDevice (&pThis->m_USBFunction), pEndpointDesc); } } } @@ -297,14 +279,14 @@ boolean USBBulkOnlyMassStorageDeviceConfigure (TUSBDevice *pUSBDevice) if ( pThis->m_pEndpointIn == 0 || pThis->m_pEndpointOut == 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUmsd); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUmsd); return FALSE; } - if (!USBDeviceConfigure (&pThis->m_USBDevice)) + if (!USBFunctionConfigure (&pThis->m_USBFunction)) { - LogWrite (FromUmsd, LOG_ERROR, "Cannot set configuration"); + LogWrite (FromUmsd, LOG_ERROR, "Cannot set interface"); return FALSE; } @@ -600,7 +582,7 @@ int USBBulkOnlyMassStorageDeviceCommand (TUSBBulkOnlyMassStorageDevice *pThis, memcpy (CBW.CBWCB, pCmdBlk, nCmdBlkLen); - TUSBHostController *pHost = USBDeviceGetHost (&pThis->m_USBDevice); + TUSBHostController *pHost = USBFunctionGetHost (&pThis->m_USBFunction); assert (pHost != 0); if (DWHCIDeviceTransfer (pHost, pThis->m_pEndpointOut, &CBW, sizeof CBW) < 0) @@ -665,24 +647,24 @@ int USBBulkOnlyMassStorageDeviceReset (TUSBBulkOnlyMassStorageDevice *pThis) { assert (pThis != 0); - TUSBHostController *pHost = USBDeviceGetHost (&pThis->m_USBDevice); + TUSBHostController *pHost = USBFunctionGetHost (&pThis->m_USBFunction); assert (pHost != 0); - if (DWHCIDeviceControlMessage (pHost, USBDeviceGetEndpoint0 (&pThis->m_USBDevice), 0x21, 0xFF, 0, 0x00, 0, 0) < 0) + if (DWHCIDeviceControlMessage (pHost, USBFunctionGetEndpoint0 (&pThis->m_USBFunction), 0x21, 0xFF, 0, 0x00, 0, 0) < 0) { LogWrite (FromUmsd, LOG_DEBUG, "Cannot reset device"); return -1; } - if (DWHCIDeviceControlMessage (pHost, USBDeviceGetEndpoint0 (&pThis->m_USBDevice), 0x02, 1, 0, 1, 0, 0) < 0) + if (DWHCIDeviceControlMessage (pHost, USBFunctionGetEndpoint0 (&pThis->m_USBFunction), 0x02, 1, 0, 1, 0, 0) < 0) { LogWrite (FromUmsd, LOG_DEBUG, "Cannot clear halt on endpoint 1"); return -1; } - if (DWHCIDeviceControlMessage (pHost, USBDeviceGetEndpoint0 (&pThis->m_USBDevice), 0x02, 1, 0, 2, 0, 0) < 0) + if (DWHCIDeviceControlMessage (pHost, USBFunctionGetEndpoint0 (&pThis->m_USBFunction), 0x02, 1, 0, 2, 0, 0) < 0) { LogWrite (FromUmsd, LOG_DEBUG, "Cannot clear halt on endpoint 2"); diff --git a/lib/usbmidi.c b/lib/usbmidi.c index cde6873..2cda1c9 100644 --- a/lib/usbmidi.c +++ b/lib/usbmidi.c @@ -2,7 +2,7 @@ // usbmidi.c // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2016 R. Stange +// Copyright (C) 2016-2018 R. Stange // Copyright (C) 2016 J. Otto // // This program is free software: you can redistribute it and/or modify @@ -41,16 +41,15 @@ static const unsigned cin_to_length[] = { #define EVENT_PACKET_SIZE 4 -void USBMIDIDevice (TUSBMIDIDevice *pThis, TUSBDevice *pDevice) +void USBMIDIDevice (TUSBMIDIDevice *pThis, TUSBFunction *pDevice) { assert (pThis != 0); - USBDeviceCopy (&pThis->m_USBDevice, pDevice); - pThis->m_USBDevice.Configure = USBMIDIDeviceConfigure; + USBFunctionCopy (&pThis->m_USBFunction, pDevice); + pThis->m_USBFunction.Configure = USBMIDIDeviceConfigure; pThis->m_pEndpointIn = 0; pThis->m_pPacketHandler = 0; - pThis->m_pURB = 0; pThis->m_pPacketBuffer = 0; } @@ -71,83 +70,68 @@ void _CUSBMIDIDevice (TUSBMIDIDevice *pThis) pThis->m_pEndpointIn = 0; } - _USBDevice (&pThis->m_USBDevice); + _USBFunction (&pThis->m_USBFunction); } -boolean USBMIDIDeviceConfigure (TUSBDevice *pUSBDevice) +boolean USBMIDIDeviceConfigure (TUSBFunction *pUSBFunction) { - TUSBMIDIDevice *pThis = (TUSBMIDIDevice *)pUSBDevice; + TUSBMIDIDevice *pThis = (TUSBMIDIDevice *)pUSBFunction; assert (pThis != 0); - TUSBConfigurationDescriptor *pConfDesc = - (TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION); - if ( pConfDesc == 0 - || pConfDesc->bNumInterfaces < 1) + if (USBFunctionGetNumEndpoints (&pThis->m_USBFunction) < 1) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromMIDI); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromMIDI); return FALSE; } - TUSBInterfaceDescriptor *pInterfaceDesc; - while ((pInterfaceDesc = (TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE)) != 0) + // Our strategy for now is simple: we'll take the first MIDI streaming + // bulk-in endpoint on this interface we can find. To distinguish + // between the MIDI streaming bulk-in endpoints we want (which carry + // actual MIDI data streams) and 'transfer bulk data' endpoints (which + // are used to implement features like Downloadable Samples that we + // don't care about), we'll look for an immediately-accompanying + // class-specific endpoint descriptor. + TUSBAudioEndpointDescriptor *pEndpointDesc; + while ((pEndpointDesc = (TUSBAudioEndpointDescriptor *) USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_ENDPOINT)) != 0) { - if ( pInterfaceDesc->bNumEndpoints == 0 - || pInterfaceDesc->bInterfaceClass != 0x01 // Audio class - || pInterfaceDesc->bInterfaceSubClass != 0x03 // MIDI streaming - || pInterfaceDesc->bInterfaceProtocol != 0x00) // unused, must be 0 + if ( (pEndpointDesc->bEndpointAddress & 0x80) != 0x80 // Input EP + || (pEndpointDesc->bmAttributes & 0x3F) != 0x02) // Bulk EP { continue; } - // Our strategy for now is simple: we'll take the first MIDI streaming - // bulk-in endpoint on this interface we can find. To distinguish - // between the MIDI streaming bulk-in endpoints we want (which carry - // actual MIDI data streams) and 'transfer bulk data' endpoints (which - // are used to implement features like Downloadable Samples that we - // don't care about), we'll look for an immediately-accompanying - // class-specific endpoint descriptor. - TUSBAudioEndpointDescriptor *pEndpointDesc; - while ((pEndpointDesc = (TUSBAudioEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT)) != 0) + TUSBMIDIStreamingEndpointDescriptor *pMIDIDesc = + (TUSBMIDIStreamingEndpointDescriptor *) USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_CS_ENDPOINT); + if ( pMIDIDesc == 0 + || (u8 *)pEndpointDesc + pEndpointDesc->bLength != (u8 *)pMIDIDesc) { - if ( (pEndpointDesc->bEndpointAddress & 0x80) != 0x80 // Input EP - || (pEndpointDesc->bmAttributes & 0x3F) != 0x02) // Bulk EP - { - continue; - } - - TUSBMIDIStreamingEndpointDescriptor *pMIDIDesc = - (TUSBMIDIStreamingEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CS_ENDPOINT); - if ( pMIDIDesc == 0 - || (u8 *)pEndpointDesc + pEndpointDesc->bLength != (u8 *)pMIDIDesc) - { - continue; - } + continue; + } - assert (pThis->m_pEndpointIn == 0); - pThis->m_pEndpointIn = malloc (sizeof (TUSBEndpoint)); - assert (pThis->m_pEndpointIn != 0); + assert (pThis->m_pEndpointIn == 0); + pThis->m_pEndpointIn = malloc (sizeof (TUSBEndpoint)); + assert (pThis->m_pEndpointIn != 0); - pThis->m_usBufferSize = pEndpointDesc->wMaxPacketSize; - pThis->m_usBufferSize -= pEndpointDesc->wMaxPacketSize % EVENT_PACKET_SIZE; - assert (pThis->m_pPacketBuffer == 0); - pThis->m_pPacketBuffer = malloc (pThis->m_usBufferSize); - assert (pThis->m_pPacketBuffer != 0); + pThis->m_usBufferSize = pEndpointDesc->wMaxPacketSize; + pThis->m_usBufferSize -= pEndpointDesc->wMaxPacketSize % EVENT_PACKET_SIZE; + assert (pThis->m_pPacketBuffer == 0); + pThis->m_pPacketBuffer = malloc (pThis->m_usBufferSize); + assert (pThis->m_pPacketBuffer != 0); - USBEndpoint2 (pThis->m_pEndpointIn, &pThis->m_USBDevice, (TUSBEndpointDescriptor *) pEndpointDesc); - } + USBEndpoint2 (pThis->m_pEndpointIn, USBFunctionGetDevice (&pThis->m_USBFunction), (TUSBEndpointDescriptor *) pEndpointDesc); } if (pThis->m_pEndpointIn == 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromMIDI); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromMIDI); return FALSE; } - if (!USBDeviceConfigure (&pThis->m_USBDevice)) + if (!USBFunctionConfigure (&pThis->m_USBFunction)) { - LogWrite (FromMIDI, LOG_ERROR, "Cannot set configuration"); + LogWrite (FromMIDI, LOG_ERROR, "Cannot set interface"); return FALSE; } @@ -176,13 +160,10 @@ boolean USBMIDIDeviceStartRequest (TUSBMIDIDevice *pThis) assert (pThis->m_pEndpointIn != 0); assert (pThis->m_pPacketBuffer != 0); - assert (pThis->m_pURB == 0); - pThis->m_pURB = malloc (sizeof (TUSBRequest)); - assert (pThis->m_pURB != 0); - USBRequest (pThis->m_pURB, pThis->m_pEndpointIn, pThis->m_pPacketBuffer, pThis->m_usBufferSize, 0); - USBRequestSetCompletionRoutine (pThis->m_pURB, USBMIDIDeviceCompletionRoutine, 0, pThis); + USBRequest (&pThis->m_URB, pThis->m_pEndpointIn, pThis->m_pPacketBuffer, pThis->m_usBufferSize, 0); + USBRequestSetCompletionRoutine (&pThis->m_URB, USBMIDIDeviceCompletionRoutine, 0, pThis); - return DWHCIDeviceSubmitAsyncRequest (USBDeviceGetHost (&pThis->m_USBDevice), pThis->m_pURB); + return DWHCIDeviceSubmitAsyncRequest (USBFunctionGetHost (&pThis->m_USBFunction), &pThis->m_URB); } void USBMIDIDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pContext) @@ -191,7 +172,7 @@ void USBMIDIDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pCon assert (pThis != 0); assert (pURB != 0); - assert (pThis->m_pURB == pURB); + assert (&pThis->m_URB == pURB); if ( USBRequestGetStatus (pURB) != 0 && USBRequestGetResultLength (pURB) % EVENT_PACKET_SIZE == 0) @@ -216,9 +197,7 @@ void USBMIDIDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pCon } } - _USBRequest (pThis->m_pURB); - free (pThis->m_pURB); - pThis->m_pURB = 0; + _USBRequest (&pThis->m_URB); USBMIDIDeviceStartRequest (pThis); } diff --git a/lib/usbmouse.c b/lib/usbmouse.c index 43f53fe..d84bdbe 100644 --- a/lib/usbmouse.c +++ b/lib/usbmouse.c @@ -2,7 +2,7 @@ // usbmouse.c // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -27,31 +27,38 @@ static unsigned s_nDeviceNumber = 1; -static const char FromUSBKbd[] = "umouse"; +static const char FromUSBMouse[] = "umouse"; static boolean USBMouseDeviceStartRequest (TUSBMouseDevice *pThis); static void USBMouseDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pContext); -void USBMouseDevice (TUSBMouseDevice *pThis, TUSBDevice *pDevice) +void USBMouseDevice (TUSBMouseDevice *pThis, TUSBFunction *pDevice) { assert (pThis != 0); - USBDeviceCopy (&pThis->m_USBDevice, pDevice); - pThis->m_USBDevice.Configure = USBMouseDeviceConfigure; + USBFunctionCopy (&pThis->m_USBFunction, pDevice); + pThis->m_USBFunction.Configure = USBMouseDeviceConfigure; pThis->m_pReportEndpoint = 0; pThis->m_pStatusHandler = 0; - pThis->m_pURB = 0; pThis->m_pReportBuffer = 0; pThis->m_pReportBuffer = malloc (MOUSE_BOOT_REPORT_SIZE); assert (pThis->m_pReportBuffer != 0); + + pThis->m_pHIDReportDescriptor = 0; } void _CUSBMouseDevice (TUSBMouseDevice *pThis) { assert (pThis != 0); + if (pThis->m_pHIDReportDescriptor != 0) + { + free (pThis->m_pHIDReportDescriptor); + pThis->m_pHIDReportDescriptor = 0; + } + if (pThis->m_pReportBuffer != 0) { free (pThis->m_pReportBuffer); @@ -65,42 +72,36 @@ void _CUSBMouseDevice (TUSBMouseDevice *pThis) pThis->m_pReportEndpoint = 0; } - _USBDevice (&pThis->m_USBDevice); + _USBFunction (&pThis->m_USBFunction); } -boolean USBMouseDeviceConfigure (TUSBDevice *pUSBDevice) +boolean USBMouseDeviceConfigure (TUSBFunction *pUSBFunction) { - TUSBMouseDevice *pThis = (TUSBMouseDevice *) pUSBDevice; + TUSBMouseDevice *pThis = (TUSBMouseDevice *) pUSBFunction; assert (pThis != 0); - TUSBConfigurationDescriptor *pConfDesc = - (TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION); - if ( pConfDesc == 0 - || pConfDesc->bNumInterfaces < 1) + if (USBFunctionGetNumEndpoints (&pThis->m_USBFunction) < 1) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBKbd); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUSBMouse); return FALSE; } - TUSBInterfaceDescriptor *pInterfaceDesc; - while ((pInterfaceDesc = (TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE)) != 0) + TUSBHIDDescriptor *pHIDDesc = (TUSBHIDDescriptor *) + USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_HID); + if ( pHIDDesc == 0 + || pHIDDesc->wReportDescriptorLength == 0) { - if ( pInterfaceDesc->bNumEndpoints < 1 - || pInterfaceDesc->bInterfaceClass != 0x03 // HID Class - || pInterfaceDesc->bInterfaceSubClass != 0x01 // Boot Interface Subclass - || pInterfaceDesc->bInterfaceProtocol != 0x02) // Mouse - { - continue; - } + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUSBMouse); - pThis->m_ucInterfaceNumber = pInterfaceDesc->bInterfaceNumber; - pThis->m_ucAlternateSetting = pInterfaceDesc->bAlternateSetting; + return FALSE; + } - TUSBEndpointDescriptor *pEndpointDesc = - (TUSBEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT); - if ( pEndpointDesc == 0 - || (pEndpointDesc->bEndpointAddress & 0x80) != 0x80 // Input EP + TUSBEndpointDescriptor *pEndpointDesc; + while ((pEndpointDesc = (TUSBEndpointDescriptor *) + USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_ENDPOINT)) != 0) + { + if ( (pEndpointDesc->bEndpointAddress & 0x80) != 0x80 // Input EP || (pEndpointDesc->bmAttributes & 0x3F) != 0x03) // Interrupt EP { continue; @@ -109,46 +110,50 @@ boolean USBMouseDeviceConfigure (TUSBDevice *pUSBDevice) assert (pThis->m_pReportEndpoint == 0); pThis->m_pReportEndpoint = malloc (sizeof (TUSBEndpoint)); assert (pThis->m_pReportEndpoint != 0); - USBEndpoint2 (pThis->m_pReportEndpoint, &pThis->m_USBDevice, pEndpointDesc); + USBEndpoint2 (pThis->m_pReportEndpoint, USBFunctionGetDevice (&pThis->m_USBFunction), pEndpointDesc); break; } if (pThis->m_pReportEndpoint == 0) { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBKbd); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromUSBMouse); return FALSE; } - if (!USBDeviceConfigure (&pThis->m_USBDevice)) + pThis->m_usReportDescriptorLength = pHIDDesc->wReportDescriptorLength; + pThis->m_pHIDReportDescriptor = (u8 *) malloc (pThis->m_usReportDescriptorLength); + assert (pThis->m_pHIDReportDescriptor != 0); + + if (DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), + REQUEST_IN | REQUEST_TO_INTERFACE, GET_DESCRIPTOR, + (pHIDDesc->bReportDescriptorType << 8) | DESCRIPTOR_INDEX_DEFAULT, + USBFunctionGetInterfaceNumber (&pThis->m_USBFunction), + pThis->m_pHIDReportDescriptor, pThis->m_usReportDescriptorLength) + != pThis->m_usReportDescriptorLength) { - LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set configuration"); + LogWrite (FromUSBMouse, LOG_ERROR, "Cannot get HID report descriptor"); return FALSE; } + //DebugHexdump (pThis->m_pHIDReportDescriptor, pThis->m_usReportDescriptorLength, FromUSBMouse); - if (pThis->m_ucAlternateSetting != 0) + if (!USBFunctionConfigure (&pThis->m_USBFunction)) { - if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), - REQUEST_OUT | REQUEST_TO_INTERFACE, SET_INTERFACE, - pThis->m_ucAlternateSetting, - pThis->m_ucInterfaceNumber, 0, 0) < 0) - { - LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set interface"); + LogWrite (FromUSBMouse, LOG_ERROR, "Cannot set interface"); - return FALSE; - } + return FALSE; } - if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice), - USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + if (DWHCIDeviceControlMessage (USBFunctionGetHost (&pThis->m_USBFunction), + USBFunctionGetEndpoint0 (&pThis->m_USBFunction), REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_INTERFACE, SET_PROTOCOL, BOOT_PROTOCOL, - pThis->m_ucInterfaceNumber, 0, 0) < 0) + USBFunctionGetInterfaceNumber (&pThis->m_USBFunction), 0, 0) < 0) { - LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set boot protocol"); + LogWrite (FromUSBMouse, LOG_ERROR, "Cannot set boot protocol"); return FALSE; } @@ -177,13 +182,10 @@ boolean USBMouseDeviceStartRequest (TUSBMouseDevice *pThis) assert (pThis->m_pReportEndpoint != 0); assert (pThis->m_pReportBuffer != 0); - assert (pThis->m_pURB == 0); - pThis->m_pURB = malloc (sizeof (TUSBRequest)); - assert (pThis->m_pURB != 0); - USBRequest (pThis->m_pURB, pThis->m_pReportEndpoint, pThis->m_pReportBuffer, MOUSE_BOOT_REPORT_SIZE, 0); - USBRequestSetCompletionRoutine (pThis->m_pURB, USBMouseDeviceCompletionRoutine, 0, pThis); + USBRequest (&pThis->m_URB, pThis->m_pReportEndpoint, pThis->m_pReportBuffer, MOUSE_BOOT_REPORT_SIZE, 0); + USBRequestSetCompletionRoutine (&pThis->m_URB, USBMouseDeviceCompletionRoutine, 0, pThis); - return DWHCIDeviceSubmitAsyncRequest (USBDeviceGetHost (&pThis->m_USBDevice), pThis->m_pURB); + return DWHCIDeviceSubmitAsyncRequest (USBFunctionGetHost (&pThis->m_USBFunction), &pThis->m_URB); } void USBMouseDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pContext) @@ -192,7 +194,7 @@ void USBMouseDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pCo assert (pThis != 0); assert (pURB != 0); - assert (pThis->m_pURB == pURB); + assert (&pThis->m_URB == pURB); if ( USBRequestGetStatus (pURB) != 0 && USBRequestGetResultLength (pURB) == MOUSE_BOOT_REPORT_SIZE @@ -204,9 +206,7 @@ void USBMouseDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pCo uspi_char2int ((char) pThis->m_pReportBuffer[2])); } - _USBRequest (pThis->m_pURB); - free (pThis->m_pURB); - pThis->m_pURB = 0; + _USBRequest (&pThis->m_URB); USBMouseDeviceStartRequest (pThis); } diff --git a/lib/usbstandardhub.c b/lib/usbstandardhub.c index 719fdde..633da4d 100644 --- a/lib/usbstandardhub.c +++ b/lib/usbstandardhub.c @@ -2,7 +2,7 @@ // usbstandardhub.c // // USPi - An USB driver for Raspberry Pi written in C -// Copyright (C) 2014 R. Stange +// Copyright (C) 2014-2018 R. Stange // // 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 @@ -27,12 +27,12 @@ boolean USBStandardHubEnumeratePorts (TUSBStandardHub *pThis); static const char FromHub[] = "usbhub"; -void USBStandardHub (TUSBStandardHub *pThis, TUSBDevice *pDevice) +void USBStandardHub (TUSBStandardHub *pThis, TUSBFunction *pDevice) { assert (pThis != 0); - USBDeviceCopy (&pThis->m_USBDevice, pDevice); - pThis->m_USBDevice.Configure = USBStandardHubConfigure; + USBFunctionCopy (&pThis->m_USBFunction, pDevice); + pThis->m_USBFunction.Configure = USBStandardHubConfigure; pThis->m_pHubDesc = 0; pThis->m_nPorts = 0; @@ -72,110 +72,47 @@ void _USBStandardHub (TUSBStandardHub *pThis) pThis->m_pHubDesc = 0; } - _USBDevice (&pThis->m_USBDevice); + _USBFunction (&pThis->m_USBFunction); } -boolean USBStandardHubInitialize (TUSBStandardHub *pThis) +boolean USBStandardHubConfigure (TUSBFunction *pUSBFunction) { + TUSBStandardHub *pThis = (TUSBStandardHub *) pUSBFunction; assert (pThis != 0); - return USBDeviceInitialize (&pThis->m_USBDevice); -} - -boolean USBStandardHubConfigure (TUSBDevice *pUSBDevice) -{ - TUSBStandardHub *pThis = (TUSBStandardHub *) pUSBDevice; - assert (pThis != 0); - - const TUSBDeviceDescriptor *pDeviceDesc = USBDeviceGetDeviceDescriptor (&pThis->m_USBDevice); - assert (pDeviceDesc != 0); - if ( pDeviceDesc->bDeviceClass != USB_DEVICE_CLASS_HUB - || pDeviceDesc->bDeviceSubClass != 0 - || pDeviceDesc->bDeviceProtocol != 2 // hub with multiple TTs - || pDeviceDesc->bNumConfigurations != 1) + if (USBFunctionGetNumEndpoints (&pThis->m_USBFunction) != 1) { - LogWrite (FromHub, LOG_ERROR, "Unsupported hub (proto %u)", - (unsigned) pDeviceDesc->bDeviceProtocol); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromHub); return FALSE; } - const TUSBConfigurationDescriptor *pConfigDesc = - (TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION); - if ( pConfigDesc == 0 - || pConfigDesc->bNumInterfaces != 1) + const TUSBEndpointDescriptor *pEndpointDesc = + (TUSBEndpointDescriptor *) USBFunctionGetDescriptor (&pThis->m_USBFunction, DESCRIPTOR_ENDPOINT); + if ( pEndpointDesc == 0 + || (pEndpointDesc->bEndpointAddress & 0x80) != 0x80 // input EP + || (pEndpointDesc->bmAttributes & 0x3F) != 0x03) // interrupt EP { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromHub); + USBFunctionConfigurationError (&pThis->m_USBFunction, FromHub); return FALSE; } - const TUSBInterfaceDescriptor *pInterfaceDesc; - while ((pInterfaceDesc = (TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE)) != 0) + if (!USBFunctionConfigure (&pThis->m_USBFunction)) { - if ( pInterfaceDesc->bInterfaceClass != USB_DEVICE_CLASS_HUB - || pInterfaceDesc->bInterfaceSubClass != 0 - || pInterfaceDesc->bInterfaceProtocol != 2) - { - continue; - } - - if (pInterfaceDesc->bNumEndpoints != 1) - { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromHub); - - return FALSE; - } - - const TUSBEndpointDescriptor *pEndpointDesc = - (TUSBEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT); - if ( pEndpointDesc == 0 - || (pEndpointDesc->bEndpointAddress & 0x80) != 0x80 // input EP - || (pEndpointDesc->bmAttributes & 0x3F) != 0x03) // interrupt EP - { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromHub); - - return FALSE; - } - - break; - } - - if (pInterfaceDesc == 0) - { - USBDeviceConfigurationError (&pThis->m_USBDevice, FromHub); - - return FALSE; - } - - if (!USBDeviceConfigure (&pThis->m_USBDevice)) - { - LogWrite (FromHub, LOG_ERROR, "Cannot set configuration"); + LogWrite (FromHub, LOG_ERROR, "Cannot set interface"); return FALSE; } - TUSBHostController *pHost = USBDeviceGetHost (&pThis->m_USBDevice); + TUSBHostController *pHost = USBFunctionGetHost (&pThis->m_USBFunction); assert (pHost != 0); - if (pInterfaceDesc->bAlternateSetting != 0) - { - if (DWHCIDeviceControlMessage (pHost, USBDeviceGetEndpoint0 (&pThis->m_USBDevice), - REQUEST_OUT | REQUEST_TO_INTERFACE, SET_INTERFACE, - pInterfaceDesc->bAlternateSetting, - pInterfaceDesc->bInterfaceNumber, 0, 0) < 0) - { - LogWrite (FromHub, LOG_ERROR, "Cannot set interface"); - - return FALSE; - } - } - assert (pThis->m_pHubDesc == 0); pThis->m_pHubDesc = (TUSBHubDescriptor *) malloc (sizeof (TUSBHubDescriptor)); assert (pThis->m_pHubDesc != 0); - if (DWHCIDeviceGetDescriptor (pHost, USBDeviceGetEndpoint0 (&pThis->m_USBDevice), + if (DWHCIDeviceGetDescriptor (pHost, USBFunctionGetEndpoint0 (&pThis->m_USBFunction), DESCRIPTOR_HUB, DESCRIPTOR_INDEX_DEFAULT, pThis->m_pHubDesc, sizeof *pThis->m_pHubDesc, REQUEST_IN | REQUEST_CLASS) @@ -218,10 +155,10 @@ boolean USBStandardHubEnumeratePorts (TUSBStandardHub *pThis) { assert (pThis != 0); - TUSBHostController *pHost = USBDeviceGetHost (&pThis->m_USBDevice); + TUSBHostController *pHost = USBFunctionGetHost (&pThis->m_USBFunction); assert (pHost != 0); - TUSBEndpoint *pEndpoint0 = USBDeviceGetEndpoint0 (&pThis->m_USBDevice); + TUSBEndpoint *pEndpoint0 = USBFunctionGetEndpoint0 (&pThis->m_USBFunction); assert (pEndpoint0 != 0); assert (pThis->m_nPorts > 0); @@ -318,11 +255,29 @@ boolean USBStandardHubEnumeratePorts (TUSBStandardHub *pThis) Speed = USBSpeedFull; } + TUSBDevice *pHubDevice = USBFunctionGetDevice (&pThis->m_USBFunction); + assert (pHubDevice != 0); + + boolean bSplit = USBDeviceIsSplit (pHubDevice); + u8 ucHubAddress = USBDeviceGetHubAddress (pHubDevice); + u8 ucHubPortNumber = USBDeviceGetHubPortNumber (pHubDevice); + + // Is this the first high-speed hub with a non-high-speed device following in chain? + if ( !bSplit + && USBDeviceGetSpeed (pHubDevice) == USBSpeedHigh + && Speed < USBSpeedHigh) + { + // Then enable split transfers with this hub port as translator. + bSplit = TRUE; + ucHubAddress = USBDeviceGetAddress (pHubDevice); + ucHubPortNumber = nPort+1; + } + // first create default device assert (pThis->m_pDevice[nPort] == 0); pThis->m_pDevice[nPort] = malloc (sizeof (TUSBDevice)); assert (pThis->m_pDevice[nPort] != 0); - USBDevice (pThis->m_pDevice[nPort], pHost, Speed, USBDeviceGetAddress (&pThis->m_USBDevice), nPort+1); + USBDevice (pThis->m_pDevice[nPort], pHost, Speed, bSplit, ucHubAddress, ucHubPortNumber); if (!USBDeviceInitialize (pThis->m_pDevice[nPort])) { @@ -332,14 +287,6 @@ boolean USBStandardHubEnumeratePorts (TUSBStandardHub *pThis) continue; } - - TString *pNames = USBStandardHubGetDeviceNames (pThis->m_pDevice[nPort]); - assert (pNames != 0); - - LogWrite (FromHub, LOG_NOTICE, "Port %u: Device %s found", nPort+1, StringGet (pNames)); - - _String (pNames); - free (pNames); } // now configure devices @@ -350,31 +297,18 @@ boolean USBStandardHubEnumeratePorts (TUSBStandardHub *pThis) continue; } - // now create specific device from default device - TUSBDevice *pChild = USBDeviceFactoryGetDevice (pThis->m_pDevice[nPort]); - if (pChild != 0) + if (!USBDeviceConfigure (pThis->m_pDevice[nPort])) { - _USBDevice (pThis->m_pDevice[nPort]); // delete default device - free (pThis->m_pDevice[nPort]); - pThis->m_pDevice[nPort] = pChild; // assign specific device - - if (!(*pThis->m_pDevice[nPort]->Configure) (pThis->m_pDevice[nPort])) - { - LogWrite (FromHub, LOG_ERROR, "Port %u: Cannot configure device", nPort+1); + LogWrite (FromHub, LOG_ERROR, "Port %u: Cannot configure device", nPort+1); - continue; - } - - LogWrite (FromHub, LOG_DEBUG, "Port %u: Device configured", nPort+1); - } - else - { - LogWrite (FromHub, LOG_NOTICE, "Port %u: Device is not supported", nPort+1); - _USBDevice (pThis->m_pDevice[nPort]); free (pThis->m_pDevice[nPort]); pThis->m_pDevice[nPort] = 0; + + continue; } + + LogWrite (FromHub, LOG_DEBUG, "Port %u: Device configured", nPort+1); } // again check for over-current @@ -436,38 +370,3 @@ boolean USBStandardHubEnumeratePorts (TUSBStandardHub *pThis) return bResult; } - -TString *USBStandardHubGetDeviceNames (TUSBDevice *pDevice) -{ - assert (pDevice != 0); - - TString *pResult = (TString *) malloc (sizeof (TString)); - assert (pResult != 0); - String (pResult); - - for (unsigned nSelector = DeviceNameVendor; nSelector < DeviceNameUnknown; nSelector++) - { - TString *pName = USBDeviceGetName (pDevice, (TDeviceNameSelector) nSelector); - assert (pName != 0); - - if (StringCompare (pName, "unknown") != 0) - { - if (StringGetLength (pResult) > 0) - { - StringAppend (pResult, ", "); - } - - StringAppend (pResult, StringGet (pName)); - } - - _String (pName); - free (pName); - } - - if (StringGetLength (pResult) == 0) - { - StringSet (pResult, "unknown"); - } - - return pResult; -} diff --git a/lib/uspilibrary.c b/lib/uspilibrary.c index 605beb8..05b5c71 100644 --- a/lib/uspilibrary.c +++ b/lib/uspilibrary.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -31,6 +31,8 @@ static TUSPiLibrary *s_pLibrary = 0; int USPiInitialize (void) { + LogWrite (FromUSPi, LOG_DEBUG, "Initializing " USPI_NAME " " USPI_VERSION_STRING); + assert (s_pLibrary == 0); s_pLibrary = (TUSPiLibrary *) malloc (sizeof (TUSPiLibrary)); assert (s_pLibrary != 0); @@ -86,7 +88,7 @@ int USPiInitialize (void) _String (&DeviceName); } - LogWrite (FromUSPi, LOG_DEBUG, "USPi library successfully initialized"); + LogWrite (FromUSPi, LOG_DEBUG, USPI_NAME " successfully initialized"); return 1; } @@ -111,6 +113,13 @@ void USPiKeyboardRegisterShutdownHandler (TUSPiShutdownHandler *pShutdownHandler USBKeyboardDeviceRegisterShutdownHandler (s_pLibrary->pUKBD1, pShutdownHandler); } +void USPiKeyboardUpdateLEDs (void) +{ + assert (s_pLibrary != 0); + assert (s_pLibrary->pUKBD1 != 0); + USBKeyboardDeviceUpdateLEDs (s_pLibrary->pUKBD1); +} + void USPiKeyboardRegisterKeyStatusHandlerRaw (TKeyStatusHandlerRaw *pKeyStatusHandlerRaw) { assert (s_pLibrary != 0); @@ -118,6 +127,13 @@ void USPiKeyboardRegisterKeyStatusHandlerRaw (TKeyStatusHandlerRaw *pKeyStatusHa USBKeyboardDeviceRegisterKeyStatusHandlerRaw (s_pLibrary->pUKBD1, pKeyStatusHandlerRaw); } +void USPiKeyboardSetLEDs (unsigned char ucLEDMask) +{ + assert (s_pLibrary != 0); + assert (s_pLibrary->pUKBD1 != 0); + USBKeyboardDeviceSetLEDs (s_pLibrary->pUKBD1, ucLEDMask); +} + int USPiMouseAvailable (void) { assert (s_pLibrary != 0); @@ -221,6 +237,19 @@ void USPiGetMACAddress (unsigned char Buffer[6]) MACAddressCopyTo (pMACAddress, Buffer); } +int USPiEthernetIsLinkUp (void) +{ + assert (s_pLibrary != 0); + + if (s_pLibrary->pEth10 != 0) + { + return LAN7800DeviceIsLinkUp (s_pLibrary->pEth10) ? 1 : 0; + } + + assert (s_pLibrary->pEth0 != 0); + return SMSC951xDeviceIsLinkUp (s_pLibrary->pEth0) ? 1 : 0; +} + int USPiSendFrame (const void *pBuffer, unsigned nLength) { assert (s_pLibrary != 0); @@ -309,28 +338,28 @@ int USPiDeviceGetInformation (unsigned nClass, unsigned nDeviceIndex, TUSPiDevic { assert (s_pLibrary != 0); - TUSBDevice *pUSBDevice = 0; + TUSBFunction *pUSBFunction = 0; switch (nClass) { case KEYBOARD_CLASS: if (nDeviceIndex == 0) { - pUSBDevice = (TUSBDevice *) s_pLibrary->pUKBD1; + pUSBFunction = (TUSBFunction *) s_pLibrary->pUKBD1; } break; case MOUSE_CLASS: if (nDeviceIndex == 0) { - pUSBDevice = (TUSBDevice *) s_pLibrary->pUMouse1; + pUSBFunction = (TUSBFunction *) s_pLibrary->pUMouse1; } break; case STORAGE_CLASS: if (nDeviceIndex < MAX_DEVICES) { - pUSBDevice = (TUSBDevice *) s_pLibrary->pUMSD[nDeviceIndex]; + pUSBFunction = (TUSBFunction *) s_pLibrary->pUMSD[nDeviceIndex]; } break; @@ -339,11 +368,11 @@ int USPiDeviceGetInformation (unsigned nClass, unsigned nDeviceIndex, TUSPiDevic { if (s_pLibrary->pEth10 != 0) { - pUSBDevice = (TUSBDevice *) s_pLibrary->pEth10; + pUSBFunction = (TUSBFunction *) s_pLibrary->pEth10; } else { - pUSBDevice = (TUSBDevice *) s_pLibrary->pEth0; + pUSBFunction = (TUSBFunction *) s_pLibrary->pEth0; } } break; @@ -351,14 +380,14 @@ int USPiDeviceGetInformation (unsigned nClass, unsigned nDeviceIndex, TUSPiDevic case GAMEPAD_CLASS: if (nDeviceIndex < MAX_DEVICES) { - pUSBDevice = (TUSBDevice *) s_pLibrary->pUPAD[nDeviceIndex]; + pUSBFunction = (TUSBFunction *) s_pLibrary->pUPAD[nDeviceIndex]; } break; case MIDI_CLASS: if (nDeviceIndex == 0) { - pUSBDevice = (TUSBDevice *) s_pLibrary->pMIDI1; + pUSBFunction = (TUSBFunction *) s_pLibrary->pMIDI1; } break; @@ -366,11 +395,14 @@ int USPiDeviceGetInformation (unsigned nClass, unsigned nDeviceIndex, TUSPiDevic break; } - if (pUSBDevice == 0) + if (pUSBFunction == 0) { return 0; } + TUSBDevice *pUSBDevice = USBFunctionGetDevice (pUSBFunction); + assert (pUSBDevice != 0); + const TUSBDeviceDescriptor *pDesc = USBDeviceGetDeviceDescriptor (pUSBDevice); assert (pDesc != 0); diff --git a/sample/Rules.mk b/sample/Rules.mk index 00e7d41..c3f604a 100644 --- a/sample/Rules.mk +++ b/sample/Rules.mk @@ -6,7 +6,7 @@ # which is Copyright (c) 2012 David Welch dwelch@dwelch.com # # USPi - An USB driver for Raspberry Pi written in C -# Copyright (C) 2014 R. Stange +# Copyright (C) 2014-2018 R. Stange # # 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 @@ -28,10 +28,8 @@ endif CFLAGS += -I $(USPIHOME)/env/include -kernel.img: $(OBJS) $(LIBS) - $(LD) -o kernel.elf -Map kernel.map -T $(USPIHOME)/env/uspienv.ld $(USPIHOME)/env/lib/startup.o $(OBJS) $(LIBS) - $(PREFIX)objdump -D kernel.elf > kernel.lst - $(PREFIX)objcopy kernel.elf -O binary kernel.img - wc -c kernel.img - include $(USPIHOME)/Rules.mk + +ifneq ($(strip $(AARCH64)),0) +$(error AARCH64 is not supported in sample/) +endif diff --git a/sample/ethernet/main.c b/sample/ethernet/main.c index b21223f..6583a18 100644 --- a/sample/ethernet/main.c +++ b/sample/ethernet/main.c @@ -79,6 +79,20 @@ int main (void) u8 OwnMACAddress[MAC_ADDRESS_SIZE]; USPiGetMACAddress (OwnMACAddress); + unsigned nTimeout = 0; + while (!USPiEthernetIsLinkUp ()) + { + MsDelay (100); + + if (++nTimeout < 40) + { + continue; + } + nTimeout = 0; + + LogWrite (FromSample, LOG_NOTICE, "Link is down"); + } + while (1) { u8 Buffer[USPI_FRAME_BUFFER_SIZE]; diff --git a/sample/keyboard/main.c b/sample/keyboard/main.c index a9b3052..d5b53fb 100644 --- a/sample/keyboard/main.c +++ b/sample/keyboard/main.c @@ -45,6 +45,8 @@ int main (void) // just wait and turn the rotor for (unsigned nCount = 0; 1; nCount++) { + USPiKeyboardUpdateLEDs (); + ScreenDeviceRotor (USPiEnvGetScreen (), 0, nCount); } diff --git a/sample/mouse/Makefile b/sample/mouse/Makefile new file mode 100644 index 0000000..9a5e9ba --- /dev/null +++ b/sample/mouse/Makefile @@ -0,0 +1,12 @@ +# +# Makefile +# + +USPIHOME = ../.. + +OBJS = main.o + +LIBS = $(USPIHOME)/lib/libuspi.a \ + $(USPIHOME)/env/lib/libuspienv.a + +include ../Rules.mk diff --git a/sample/mouse/main.c b/sample/mouse/main.c new file mode 100644 index 0000000..98b884b --- /dev/null +++ b/sample/mouse/main.c @@ -0,0 +1,56 @@ +// +// main.c +// +#include +#include +#include +#include + +static const char FromSample[] = "sample"; + +static void MouseStatusHandler (unsigned nButtons, int nDisplacementX, int nDisplacementY) +{ + LogWrite (FromSample, LOG_NOTICE, "Buttons %c%c%c, X %d, Y %d", + nButtons & MOUSE_BUTTON1 ? 'L' : '-', + nButtons & MOUSE_BUTTON3 ? 'M' : '-', + nButtons & MOUSE_BUTTON2 ? 'R' : '-', + nDisplacementX, nDisplacementY); +} + +int main (void) +{ + if (!USPiEnvInitialize ()) + { + return EXIT_HALT; + } + + if (!USPiInitialize ()) + { + LogWrite (FromSample, LOG_ERROR, "Cannot initialize USPi"); + + USPiEnvClose (); + + return EXIT_HALT; + } + + if (!USPiMouseAvailable ()) + { + LogWrite (FromSample, LOG_ERROR, "Mouse not found"); + + USPiEnvClose (); + + return EXIT_HALT; + } + + USPiMouseRegisterStatusHandler (MouseStatusHandler); + + LogWrite (FromSample, LOG_NOTICE, "Move your mouse!"); + + // just wait and turn the rotor + for (unsigned nCount = 0; 1; nCount++) + { + ScreenDeviceRotor (USPiEnvGetScreen (), 0, nCount); + } + + return EXIT_HALT; +}