Source
...
Target
Commits (17)
  • Jeffrey Lee's avatar
    Rework USB driver makefile & cmhg files to avoid constant rebuilds of USBDriver.h · 0531a2c1
    Jeffrey Lee authored
    Detail:
      Limitations in the way CMHG was being told which message file to use meant that the makefile was constructed in a way that would automatically delete usbmodhead.h/.o after they were built, to protect against OHCIDriver or EHCIDriver causing the file to be built referencing the wrong messages file.
      However since each component uses a unique messages filename, and each component has its own CMHG file, there was absolutely no need for this - all that was needed was to update the CMHG files to reference the correct messages file directly.
      ROM builds are now a minute or two faster because of this, which is quite welcome since I can often find myself doing 30+ builds a day.
    Admin:
      Tested by building Tungsten ROM and diffing new modules against old; no differences detected.
      Not tagged.
    
    
    Version 0.49. Not tagged
    0531a2c1
  • Jeffrey Lee's avatar
    Fix USBDriver's handling of PointerV. Increase module version numbers/dates. · c5f29964
    Jeffrey Lee authored
    Detail:
      build/c/usbmouse - USBDriver's PointerReason_Request handler now correctly restores the IRQ state to that of the caller, instead of unconditionally enabling IRQs. It also correctly intercepts the vector instead of passing it on to other claimants.
      build/Version - This fake VersionNum file hasn't been touched in a long time, leading to some newer versions of the USB modules being released with version numbers identical to their predecessors. This has now been fixed, so that each module has had its version increased by 0.01 and date increased to that of the last (functional) change.
    Admin:
      Tested on rev C2 beagleboard
    
    
    Version 0.50. Tagged as 'NetBSD-0_50'
    c5f29964
  • Ben Avison's avatar
    Support for USB short packages · 7ca6fbdc
    Ben Avison authored
    Detail:
      * DeviceFSCallDevice_TransferInfo and notation of padded bytes
      * Added (updated) documentation
    Admin:
      Provided by Thomas Milius
    
    Version 0.51. Tagged as 'NetBSD-0_51'
    7ca6fbdc
  • Jeffrey Lee's avatar
    Update EHCI driver to NetBSD latest (as of 10/07/2010), improve DeviceFS interface · eb6607d0
    Jeffrey Lee authored
    Detail:
      EHCI driver update:
        dev/usb/c/ehci - Updated to latest NetBSD version, except for revisions 1.134 and 1.135 which are too invasive to merge in without updating the rest of the USB stack. This new version brings lots of bug fixes, and adds (untested on RISC OS) support for EHCI isochronous transfers.
        dev/usb/h/ehcivar - Updated to latest NetBSD version, except for the sc_bus splitting that was held back from the ehci.c update
        dev/usb/h/usb, dev/usb/h/usbdi, dev/usb/usbdivar - partial update to latest as required/possible
        dev/usb/c/usb_quirks, dev/usb/h/ehcireg, dev/usb/h/usb_mem, dev/usb/h/usb_quirks, dev/usb/h/usbhid, dev/usb/usbdevs, dev/usb/devlist2h.awk, dev/wscons/h/wsconsio, dev/wscons/h/wsmousevar - Updated to latest NetBSD versions
        dev/usb/c/usbroothub_subr, dev/usb/h/usbroothub_subr - New files brought in from NetBSD sources for use with new EHCI driver
        build/objehcidriver - Added usbroorhub_subr to EHCI driver
        dev/usb/h/usb_port - Added extra dummy functions as required by new EHCI driver
        dev/build/c/port - Added extra parameter to callout_init as required by new EHCI driver
      DeviceFS improvements:
        build/c/usbmodule - Added DeviceFSCallDevice_GetHandles2 as a replacement for Thomas Milius's backwards-incompatible GetHandles changes. Added DeviceFSCallDevice_GetSetOptions call to control RX padding and TX force-short-xfer features. These features can also be controlled at endpoint creation time by new fields in the filename. Also fixed packet padding to not fill the buffer with garbage or potentially crash when the padded area is more than one packet in length.
      New bus registration API:
        Changes made to the data structures that are shared between the modules means that new checks are needed to ensure USB modules with incompatible APIs are not used with one another.
        build/h/usbdivar - Since this seems to be the file containing the main structures that are shared, it now has a #define at the top indicating the first version of the USBDriver module that implemented the data structures within. This version number is used to check that the driver modules are compatible.
        build/cmhg/usbmodhead, build/h/usbdriver, build/c/usbmodule - Add a new SWI, USBDriver_Version, to return the version number of the USBDriver module. Used for both intra-stack API version checks and can be useful for external code that wants to query DeviceFS feature availability.
        build/c/usbmodule, build/c/ehcimodule, build/c/ohcimodule - Updated USBDriver_RegisterBus SWI and the code that calls it to pass the API version number (as defined in usbdivar.h) to USBDriver when attempting to reigster the bus. USBDriver then ensures the version matches that of itself, and if not refuses to allow the bus to register. EHCI & OHCI modules also check that USBDriver is new enough to implement this behaviour via the USBDriver_Version SWI.
      And finally:
        build/version - Incremented module version numbers.
        build/doc/usb - Updated with details of new features
    Admin:
      Tested in ROM softload on Iyonix & beagleboard. Beagleboard hub issues seem to be resolved, and there are no new bugs that I can see.
    
    
    Version 0.52. Tagged as 'NetBSD-0_52'
    eb6607d0
  • Jeffrey Lee's avatar
    Update hid.c, ums.c to latest (ish), update usbmouse.c, add TouchBook touchpad fix · f3df0153
    Jeffrey Lee authored
    Detail:
      dev/usb/c/hid, dev/usb/h/hid, dev/usb/c/ums - Updated to latest NetBSD versions (actually the version that was used for the recent core/EHCI update, so not 100% latest)
      build/c/usbmouse, dev/wscons/h/wsmousevar - Updated RISC OS USB mouse driver to be similar to the new NetBSD version. Also reformatted file to use tab char instead of inconsistent numbers of spaces for indentation.
      build/c/usbmouse, dev/usb/usbdevs - Added fix for broken TouchBook touchpad behaviour.
    Admin:
      Tested with various mice on a beagleboard, and with the TouchBook touchpad.
      We should now have support for the W axis of mice, but that code is untested since I don't have any suitable mice to hand.
    
    
    Version 0.53. Tagged as 'NetBSD-0_53'
    f3df0153
  • Steve Revill's avatar
    Minor bugfix and documentation improvements. · 68888ee8
    Steve Revill authored
    Detail:
      I have done some minor changes to the USB documenation in a few points
      and corrected a smaller bug inside the USB alias handling (used release
      instead interface).
    Author:
      Thomas Milius
    
    Version 0.54. Tagged as 'NetBSD-0_54'
    68888ee8
  • Steve Revill's avatar
    Revert previous commit as it has already been superceded. · 62f5d8e8
    Steve Revill authored
    Version 0.55. Tagged as 'NetBSD-0_55'
    62f5d8e8
  • Jeffrey Lee's avatar
    Fix a few USBDriver bugs · 3c10a2b1
    Jeffrey Lee authored
    Detail:
      build/c/usbdi - Fix compiler warning in usbd_clear_endpoint_stall()
      build/c/usbmodule - Fix detach_device() to deregister any pending attach callback for the detaching device. Fixes crash seen when inserting 16GB USB stick into EHCI port of rev C2 beagleboard (a current surge or something causes the stick to immediately disconnect then reconnect, but the disconnect occurs before the initial attach callback)
      build/c/usbmodule - Fix device_initialise() to use a timeout of 0 if no timeout was specified in the DeviceFS special field
      build/c/usbmodule - Fix the new read_cb() buffer padding logic to only pad up to totalcount instead of filling the entire buffer
    Admin:
      Tested on rev C2 beagleboard.
      This seems to fix the problems that were preventing Steffen Huber's USB CD code from working properly.
    
    
    Version 0.56. Tagged as 'NetBSD-0_56'
    3c10a2b1
  • Jeffrey Lee's avatar
    Fix modules so resources don't get included twice in ROM builds · 32bcd2b5
    Jeffrey Lee authored
    Detail:
      A couple of the USB modules were including their resources both in the Messages module and within themselves, leading to wasted ROM space
      build/OBJOHCIDriver, build/OBJUSBDriver - Tweaked makefiles so that ohcimsgs.o and usbmsgs.o only get built/linked for RAM builds
      build/c/usbmodule - Fix erroneous attempt to free non-registered resource files in ROM builds
      Version - Increased OHCIDriver & USBDriver version numbers
    Admin:
      Tested with Iyonix ROM softload. Saves approx 48k of ROM space.
      Fixes bug #265
    
    
    Version 0.57. Tagged as 'NetBSD-0_57'
    32bcd2b5
  • Ben Avison's avatar
    Build fix · 21c07dfd
    Ben Avison authored
    Detail:
      A couple of source files now have a dependency on an auto-generated
      header file, dev/usb/usbdevs.h. Normally you get away with this, because
      it's created during the export_hdrs phase. But if the first build you do
      on a freshly checked-out build tree includes a rom phase, then srcbuild
      cleans the component between the export_hdrs and rom phases, so the rom
      phase fails. Fixed by adding a couple of static dependencies to Makefile.
    Admin:
      Tested manually.
    
    Version 0.58. Tagged as 'NetBSD-0_58'
    21c07dfd
  • Jeffrey Lee's avatar
    Add the ability to build the USB drivers as HAL-compatible static libraries · 4ca937fd
    Jeffrey Lee authored
    Detail:
      build/Makefile, build/OBJEHCIDriver, build/OBJOHCIDriver, build/OBJUSBDriver - Modified makefiles to build the HAL libs during the export libs phase
      build/!MkHAL,fd7 - Handy script for building the HAL libs
      build/Hdr/usbhal - Header containing definitions for the assembler code. Also gets exported so that HALs know how much workspace to reserve.
      build/c/usbhal - HAL version of usbmodule.c & port.c. Also contains the keyboard scan code, adapted from the code in the Tungsten HAL.
      build/s/porthal - Assembler versions of some port.c routines that were easier to do in assembler than C
      build/s/halheap - OS_Heap code that's been adapted for use in the HAL. Could easily be changed into a standalone library instead of being part of the HAL USB libs. Supports memory-efficient allocation of aligned blocks.
      build/c/ehcihal - HAL version of ehcimodule.c. Currently only supports EHCI controllers exposed via HAL_USBControllerInfo (i.e. no PCI support)
      build/c/ehcimodule, build/c/ohcimodule, build/c/port - Moved riscos_irq_clear into port.c. Removed unused microtime() function.
      build/c/usbmouse - Strip out some debug-related code in non-debug builds
      build/Version - Updated version numbers
      dev/usb/c/ehci, dev/usb/h/ehcivar - Adapted to add support for the HAL build. Apart from the base changes, the code has also been tweaked to significantly reduce the amount of memory used at runtime by the HAL version of the driver.
      dev/usb/c/hid, dev/usb/c/uhub, dev/usb/c/usb, dev/usb/c/usb_quirks, dev/usb/c/usb_subr, dev/usb/c/usbdi, dev/usb/c/usbdi_util, dev/usb/c/usbroothub_subr - Changes to support HAL builds. Mainly disabling bits that won't work in the HAL or disabling bits for RISC OS in general if they weren't being used in the first place.
      dev/usb/c/ohci, dev/usb/h/ohcivar - Basic changes to support HAL builds. However HAL OHCI support is still incomplete.
      dev/usb/h/usb_port - Added support for the HAL build. Also tweaked logprintf definition to get rid of logprintf calls entirely in non-debug builds.
      dev/usb/h/usbdivar - Added support for the HAL build.
      dev/usb/h/usbhal - New header used by the HAL build. Gets included by every C file to ensure the compiler doesn't use sb, and contains structs/macros to allow access to the shared workspace.
    Admin:
      HAL & non-HAL builds tested on rev C2 BB, rev A2 BB-xM, rev C1 TouchBook.
      Non-HAL builds tested with Iyonix ROM softload.
      Needs latest Kernel source for OSEntries.h export.
    
    
    Version 0.59. Tagged as 'NetBSD-0_59'
    4ca937fd
  • Jeffrey Lee's avatar
    Update to work with zero page relocation. Remove ability to cancel transfers by pressing escape · ab69b3d9
    Jeffrey Lee authored
    Detail:
      build/c/port - Removed ability to cancel transfers by pressing escape. Too dangerous for things like mass storage devices, and the code won't work anyway for the common case of being in the wimp
      build/s/triggercbs - Try using OS_ReadSysInfo 6 to get IRQsema ptr before falling back on legacy address
      build/Version - Updated version numbers
    Admin:
      Tested on rev A2 BB-xM
    
    
    Version 0.60. Tagged as 'NetBSD-0_60'
    ab69b3d9
  • Jeffrey Lee's avatar
    Fix null pointer access in OHCIDriver · 6a444648
    Jeffrey Lee authored
    Detail:
      build/c/ohcimodule - Not all PCI_ReadInfo calls were checking for null pointers afterwards, leading to strncpy being called with a null source
      build/Version - Updated OCHIDriver version number
    Admin:
      Tested in Iyonix ROM softload
    
    
    Version 0.61. Tagged as 'NetBSD-0_61'
    6a444648
  • Jeffrey Lee's avatar
    Update HAL USB code for new HAL_KbdScanInterrupt behaviour. Fix data aborts... · 68f485b5
    Jeffrey Lee authored
    Update HAL USB code for new HAL_KbdScanInterrupt behaviour. Fix data aborts during keyboard scanning.
    
    Detail:
      build/c/usbhal, build/h/usbhal - Updated USBHAL_KbdScanInterrupt to behave the same way HAL_KbdScanInterrupt is now expected to behave.
      build/c/ehci, build/c/ohci - Fixed some root hub emulation code which was writing to a global structure before copying it into the destination buffer. Although this works fine in ROM modules it was causing data aborts in the USB HAL libraries due to lack of automatic RW data relocation by the compiler.
      build/Version - Updated version numbers
    Admin:
      Tested on rev C2 BB.
    
    
    Version 0.62. Tagged as 'NetBSD-0_62'
    68f485b5
  • Jeffrey Lee's avatar
    Fix memory overwrites in root hub emulation · d3628750
    Jeffrey Lee authored
    Detail:
      dev/usb/c/ehci, dev/usb/c/ohci - Fixed device descriptor and config descriptor reads writing outside the destination buffer if the buffer was small enough.
      build/Version - Incremented EHCI & OHCI version numbers & dates
    Admin:
      Tested in OMAP3 ROM & Iyonix ROM softload
    
    
    Version 0.63. Tagged as 'NetBSD-0_63'
    d3628750
  • Jeffrey Lee's avatar
    Improve scrollwheel handling · aa5a3fc0
    Jeffrey Lee authored
    Detail:
      build/c/usbmouse - Scrollwheel code now only sends scroll requests in a given direction if the window has an appropriate scroll bar.
      build/Version - Incremented USBDriver version number
    Admin:
      Tested in OMAP3 ROM
      Fixes issue reported on forums where it was possible to scroll filer windows horizontally if you used a mouse with a 'w' axis
    
    
    Version 0.64. Tagged as 'NetBSD-0_64'
    aa5a3fc0
  • Jeffrey Lee's avatar
    Add workaround for what looks like a bug in the DM37x EHCI controller · 2230ce20
    Jeffrey Lee authored
    Detail:
      dev/usb/c/ehci - Force all EHCI data buffers to be 512 byte aligned.
      This is a workaround for what I believe is a bug in the DM37x EHCI controller - It looks like if the last packet of a bulk in transfer is a short packet, and that packet crosses a page boundary, then the second half of the packet doesn't seem to be written out to the correct address in memory.
      Version - increased EHCI module version number
    Admin:
      Tested on rev A2 BB-xM
      Fixes issue reported on forums with unreliable USB ethernet:
      http://www.riscosopen.org/forum/fourms/5/topics/828#posts-9691
    
    
    Version 0.65. Tagged as 'NetBSD-0_65'
    2230ce20
**/Hdr/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
**/s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true **/s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
**/c/** gitlab-language=c linguist-language=c linguist-detectable=true **/c/** gitlab-language=c linguist-language=c linguist-detectable=true
**/h/** gitlab-language=c linguist-language=c linguist-detectable=true **/h/** gitlab-language=c linguist-language=c linguist-detectable=true
......
/* (0.49) /* (0.65)
* *
* This file is automatically maintained by srccommit, do not edit manually. * This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1. * Last processed by srccommit version: 1.1.
* *
*/ */
#define Module_MajorVersion_CMHG 0.49 #define Module_MajorVersion_CMHG 0.65
#define Module_MinorVersion_CMHG #define Module_MinorVersion_CMHG
#define Module_Date_CMHG 02 Oct 2009 #define Module_Date_CMHG 18 Dec 2011
#define Module_MajorVersion "0.49" #define Module_MajorVersion "0.65"
#define Module_Version 49 #define Module_Version 65
#define Module_MinorVersion "" #define Module_MinorVersion ""
#define Module_Date "02 Oct 2009" #define Module_Date "18 Dec 2011"
#define Module_ApplicationDate "02-Oct-09" #define Module_ApplicationDate "18-Dec-11"
#define Module_ComponentName "NetBSD" #define Module_ComponentName "NetBSD"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/USB/NetBSD" #define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/USB/NetBSD"
#define Module_FullVersion "0.49" #define Module_FullVersion "0.65"
#define Module_HelpVersion "0.49 (02 Oct 2009)" #define Module_HelpVersion "0.65 (18 Dec 2011)"
#define Module_LibraryVersionInfo "0:49" #define Module_LibraryVersionInfo "0:65"
| Copyright 2011 Castle Technology Ltd
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
Dir <Obey$Dir>
amu_machine export PHASE=hdrs COMPONENT=USBDriver THROWBACK=-throwback
amu_machine export PHASE=libs COMPONENT=USBDriver THROWBACK=-throwback
amu_machine export PHASE=hdrs COMPONENT=OHCIDriver THROWBACK=-throwback
amu_machine export PHASE=libs COMPONENT=OHCIDriver THROWBACK=-throwback
amu_machine export PHASE=hdrs COMPONENT=EHCIDriver THROWBACK=-throwback
amu_machine export PHASE=libs COMPONENT=EHCIDriver THROWBACK=-throwback
USB API
=======
This API details the programming interface through which device drivers
can communicate with devices via the USB bus.
Versions
--------
Version Date Author Change
0.93 18/7/2010 JL Updated for USBDriver 0.49
0.92 06/3/2010 TM Clear Stall/Transfer info added
0.91 11/4/2003 JWB Minor corrections.
0.90 10/4/2003 JWB Major modifications to reflect the capabilities
built into RISC OS 5 and the IYONIX pc. This
reflects a significant change in the manner in
which the USB driver is called, but does lead to
a significant simplification of the whole
process.
Where differences in the current implementations exist, these are noted.
Introduction
------------
Sections:
- DeviceFS interface
- DeviceFS calls
- Service calls
- Alias matching
- Commands
The Universal Serial Bus (USB) is a simple interconnect system widely
standardised and for which a large range of devices is available. For use
on RISCOS specific drivers will (always) need to be adapted or written.
It is useful, however, to provide a relatively simple programming interface(API) that will permit developers of device drivers to create
drivers that will operate on a variety of different USB host adaptor
cards within the RISCOS environment. This document describes such an
API which is compatible with both RISCOS 5 as shipped on the IYONIX pc,
and version 0.90 and later of Castle's 4 port USB podule.
No attempt is made to describe how to control devices over the USB bus
using USB protocols. It merely describes the low level interface through
which these commands may be issued in a manner that is not directly
dependant on the hardware providing the USB host interface.
The naming convention used for devices is USBxxnnn, where all device
names start USB, followed by 0 or more vendor specific characters (nn)
and a number (nnn) in the range 0 to 999.
The IYONIX pc uses "USBnnn" e.g. "USB2".
Castle's USB podule uses "USBDnnn" e.g. "USBD2".
Examples given in this document use "USBD" as the driver name.
DeviceFS interface
-----------------
Device specific drivers communicate with the low level USB host driver,
and thence the USB hardware and attached devices, via FileSwitch and
DeviceFS_CallDevice. Streams are opened to or from an endpoint using
special fields to define requirements.
The special field can have some or all of the following:
Value Meaning IYONIX? Podule?  
interface/N Interface to use. Defaults to the first suitable one. Yes Yes  
alternate/N Interface alternate to use. Defaults to the first suitable Yes Yes  
one.  
endpoint/N Desired endpoint. Defaults to the first suitable one. Yes Yes  
report/N Desired HID report. If specified,only this information will Yes No  
be made available.  
control The type of transfer required. Defaults to bulk, or what a Yes Yes  
isochronous specified endpoint requires. (Isochronous is not fully  
bulk supported at present.)  
interrupt/S  
nosync Synchronisation type. Only relevant to isochronous No No  
async transfers.  
adaptive  
sync/S  
data Only relevant to isochronous transfers. No No  
feedback  
implicit/S  
usbtimeout/N Command timeout in milliseconds. Default is no timeout. Yes No  
size/N The preferred stream buffer size to use. Some devices may Yes Yes  
benefit from a larger buffer than the default.  
nopad/S Disable the code that adds padding bytes to received data if 0.49+ No
it is shorter than the requested read size.
short/S Force a 'short packet' to be sent at the end of each transfer. 0.49+ No
Ordinarily short packets are only sent if the data is not a
multiple of the max packet size; however by specifiying the
'short' flag this will force a short packet to be sent even if
the data is an exact multiple. This is equivalent to the
USBD_FORCE_SHORT_XFER flag used by the core NetBSD code.
Numbers are converted using OS_ReadUnsigned so if the string starts with base_,
this base is used or if the string starts with & then it is hexadecimal. If
there is no prefix then it is decimal.
Two special fields have been added that are acted on by later versions of
DeviceFS. The same functionality is also available via an IOCTL call.
Value IOCTL Action IYONIX? Podule?  
Nosleep 4 true/false. Any DeviceFS stream, if opened with the special Yes No  
sleep/S field entry 'sleep' will issue OS_UpCall 6 when it would      
otherwise block thus allowing Taskwindows to continue      
multitasking. Default nosleep. (Note.. in currently    
available versions of DeviceFS, without this sleep    
ability, the same effect can be achieved by polling the    
buffer associated with the stream and only making such a    
'blocking' call if there is data (or space as relevant)    
in the buffer. If no data/space is available, then an    
UpCall 6 can be issued. (See later for details of a   
call to provide this information)    
timeout/N 5 Time in cs This will cause the stream to issue a timeout Yes No    
error if it sleeps for too long. The default is 0 meaning    
sleep for ever.    
Each USB device, when plugged in, is "enumerated" and a separate device is created within DeviceFS. Each time a device is "enumerated" it has a new device number created. Devices thus range from "USBD0" to "USBD999" (or "USB0" to "USB999") before starting at 0 again.
Examples:
To open an interrupt in connection to USBD3 endpoint 1 (which is an interrupt endpoint) from BASIC:
port% = OPENIN"devices#endpoint1:usbd3"
To open a bulk (by default) out connection to USB3 endpoint 2 from BASIC:
out% = OPENOUT"devices#endpoint2:usb3"
To open a bulk (by default) in connection from USBD3 endpoint 1 from BASIC:
in% = OPENIN"devices#endpoint1:usbd3"
DeviceFS_CallDevice
-------------------
Also: Fehler über Fehler in Dokumentation. Es gibt noch einen SWI der das Löschen eines
Endpunkts erlaubt (Aus Castles Quellcode).
R0 1<<31 + 5 Löscht die Stall Bedingung für einen Endpunkt sowohl per Request
als auch intern auf Hostseite.
R1 Device name eg "usbd"  
R2 Stream handle as returned by fileswitch.  
There are 4 extension calls into the DeviceFS driver which are passed directly to the USB driver and are shown in the table below.
Register Value Entry IYONIX? Podule?  
USB Control Request Yes Yes  
R0 1<<31 + 0 Send request to a device's default control pipe and  
return the reply.  
R1 Device name eg "usbd"  
R3 Byte 0 BmRequestType  
Byte 1 BRequest  
Bytes 2,3 WValue  
R4 Bytes 0,1 WIndex  
Bytes 2,3 WLength  
R5 Pointer to data buffer.  
R6 0 Return on command completion, command failure,  
or command timeout.  
Bit 0 = 1 Return after commencing the command with R7 containing  
the address of a pollable status byte. See  
below for details of return values  
Bit 1 = 1 On entry, R7 contains the address of a routine to be  
called on command completion. R8 will contain the  
value to be used for the R12 value when this is  
called. See below for details of this call.  
R7 Callback address if R6 bit 1 set.  
R8 Private word for Callback address in R7 if  
R6 bit 1 set.  
Check buffer space Yes Yes  
R0 1<<31 + 2 Interrogate the free space and data available in the  
buffer associated with a DeviceFS stream. (note:  
not all drivers will implement this, as the  
information can be directly discovered)  
R1 Device name eg "usbd"  
R2 Stream handle as returned by fileswitch.  
Returns:R3 Bytes available in buffer  
Returns:R4 Bytes free in buffer  
Return handles Yes Yes  
R0 1<<31 + 3 Return the buffer handle and DeviceFS stream  
handle for this stream  
R1 Device name eg "usbd"  
R2 Stream handle as returned by fileswitch.  
Returns:R3 Buffer handle  
Returns:R4 DeviceFS stream handle  
Get Location Yes No
R0 1<<31 + 4 Get Device Location on bus.  
R1 Device name eg "usbd"  
R3 Pointer to 6 byte block.  
Returns: Block filled in with 6 byte array: bus, port1, port2,  
port3, port4, port5. This indicates the physical  
location of the usb device. This provides a method  
of identifying the same device across reboots.  
Clear Stall Yes ???
R0 1<<31 + 5 Clears USB stall condition for requested pipe
R1 Device name eg "usbd"  
R2 Stream handle as returned by fileswitch.  
The following calls were added with USBDriver 0.49:
Transfer Info Yes No
R0 1<<31 + 6 Returns some information about actual/last transfer
for the requested stream  
R1 Device name eg "usbd"  
R2 USB Stream handle as returned by 'Return handles 2' in R5
Returns:R0 Bytes received/sent up to now.
Returns:R1 Total Bytes to transfer requested
Returns:R3 Transfer Status:
-1 - Transfer terminated with error
0 - Transfer in progress
1 - Transfer successfully completed
Returns:R4 After end of transfer number of Bytes with which
Buffer has been padded up to requested length in case
of receiving a short package.
Return handles 2 Yes No  
R0 1<<31 + 7 Return the buffer handle and DeviceFS stream  
handle for this stream  
R1 Device name eg "usbd"  
R2 Stream handle as returned by fileswitch.  
Returns:R3 Buffer handle  
Returns:R4 DeviceFS stream handle  
Returns:R5 USB Stream handle
Returns:R6 Device drivers handle for usage with DeviceFS_CallDevice
Get/Set options Yes No
R0 1<<31 + 8 Get/set current options
R1 Device name eg "usbd"  
R2 USB Stream handle as returned by 'Return handles 2' in R5
R3 EOR mask of bits to change (similar to OS_Byte)
R4 AND mask of bits to change (similar to OS_Byte)
Returns:R3 Previous flags value
Returns:R4 New flags value
Flags in version 0.49 of USBDriver are:
bit 0 - 'nopad' flag
bit 1 - 'short' flag
bits 2+ - reserved, reads return 0, writes ignored
Note that modifying flags is only guaranteed to work
correctly if no transfer is active for that stream
Note: The Check Buffer Space call has been added to enable users to code simple drivers in higher level languages such as BASIC. On RISC OS 4 and earlier, commands such as BGET of BPUT will not return if there is no data or space in the stream's buffer. With this call the user can only make such blocking calls when they wont be blocked.
Command completion status
-------------------------
(Podule only)
There are currently 2 defined status values detectable in the pollable byte.
0 command not completed.
1 command completed successfully.
2 command currently receiving a NAK.
3 command has received a STALL and finished.
4 command retrying.
5 command has received a USB timeout.
6 command is set inactive.
If a callback on completion is requested, the routine will be called back with registers set as follows:
R0 completion status as above
R12 set to the value passed through in R8 when the callback was requested
Your routine may be called within an interrupt service routine, so
care should be taken to ensure that non re-entrant SWIs are not
called, and that you spend the minimum time in your callback routine.
Service calls
-------------
There is 1 defined service call at present, Service_USB (0xD2). It has 3 variants, distinguished by the value in R0 on entry. It is issued by the hub controller within the driver, once it has successfully "enumerated" a device, to report the presence of a newly connected device. It can also be issued by other parties wishing to find what devices are available if they are unable to receive service calls (e.g are applications), or if they arrived after a device was connected.
Service_USB
Register Value Meaning
R1 0xD2 Service_USB service call number. R1 should be passed
onwards without claiming the call. The value in R0
determines the usage of this.
R2 name Name driver uses (reason codes 3 and 4) e.g. "USB"
R0 0 New device connected. Issued by the USB controller,
this call reports that a new device has been connected
and is available for use. R2 is a pointer to a structure
of type USBServiceCall. The format of this is specified
in the USBDevFS.txt header file . The current version
of this header file is 0.75 (8 March 2003). Access to
a device can be claimed by opening a file for that
device/endpoint. Please see the sample drivers for
an example of this.
R0 1 Report connected devices. Issued with R2 set to zero.
Each controller adds USBServiceAnswer pointers in a
linked list. If R2 = NULL, then the controller sets
R2 to point to a chunk of RMA containing a
USBServiceAnswer structure, with the link field set
to NULL. Subsequent devices are reported by scanning
the list of pointers until a NULL next pointer is found
and replacing the NULL with a pointer to a further
chunk of RMA, with its link pointer set to NULL. It
is the responsibility of the issuer of this service
call to free the memory chunks returned.
R0 2 Device has gone. (not used) R2 is a pointer to a
structure of type USBServiceCall, such as would
have been issued when the device was originally
announced using reason code 0 - New device connected.
This call announces the fact that the device is no
longer available for use. Note that this call is
not used. Since each USB device is a unique DeviceFS
device, the DeviceFS_DeviceDead service call will
provide this information.
R0 3 USB driver module starting.
R0 4 USB driver module dying.
SWIs
----
The USBDriver module provides one SWI suitable for use by USB device drivers:
SWI USBDriver_Version (0x54a45)
In: N/A
Out: R0 = USBDriver module version number, *100
This SWI is only available in USBDriver version 0.49 and above.
Aliases and Alias Matching
--------------------------
A powerful Alias matching system is employed to provide a system for locating and launching specific applications and tools when relevant USB devices become available.
Once a device is connected and "enumerated" several things happen:
- A device is created for it within DeviceFS.
- The USB_Connected service call is issued.
- An Alias is created for it with just vendor and product IDs in place.
- A check is made for a matching alias, and if found it is launched.
- If no alias was launched, a second Alias is created with additional
configuration information.
- A new check is made for an alias match.
The alias created is of the form USB$Device_LL_SS_TT_VVVV_PPPP_CC_II_RRRR_USBDnnn (or USBnnn)
Code Meaning Value at first check Value at second check  
LL class 00 class  
SS subclass 00 subclass  
TT protocol 00 protocol  
VVVV vendorID vendorID vendorID  
PPPP productID productID productID  
CC current -1 configuration  
configuration  
II interface -1 interface  
RRRR release number -1 product release number  
nnn device number usb device number usb device number  
When first created this is set to the number nnn. The second time around it has 3 numbers: nnn interface alternate. In the descriptions and examples below device USBDnnn is used. This is correct for the podule. IYONIX uses USBnnn.
Aliases are searched in accordance with the USB Common Class Specification (revision 1.0). This means that the following searches shall be done:
Alias@USBD$Device_*_*_*_V_P___R
Alias@USBD$Device_*_*_*_V_P___*
Alias@USBD$Device_L_S_T_V_*___*
Alias@USBD$Device_L_S_*_V_*___*
Alias@USBD$Device_L_S_T_*_*___*
Alias@USBD$Device_L_S_*_*_*___*
If a driver is found at that stage then it can participate in choosing the configuration for the driver. Otherwise the system software chooses an appropriate configuration and the search is proceeded using the following, taking each interface in turn, taking the class and subclass data from the interface descriptor:
Alias$@USBD$Device_*_*_*_V_P_C_I_R
Alias$@USBD$Device_*_*_*_V_P_C_I_*
Alias$@USBD$Device_L_S_T_V_*_*_*_*
Alias$@USBD$Device_L_S_*_V_*_*_*_*
Alias$@USBD$Device_L_S_T_*_*_*_*_*
Alias$@USBD$Device_L_S_*_*_*_*_*_*
If a match is made, the alias will be executed. This permits (e.g.) an obey file to be created containing lines such as:
Alias @USBDDevice____03F0_0417____ Do Path HPLJ1220
USBD%%0#usbtimeout10000;size16384:|mUSBDSetInterface %%0 0 1|m||%%*0
If "<USBD$Device_*_*_*_03F0_0417_*_*_*_*>" <> "" Then Do
@usbddevice____03F0_0417____ <USBD$Device_*_*_*_03F0_0417_*_*_*_*>
Note that though each command appears to take 2 or more lines, each is one line only.
The first line sets up an alias for a device (vendor)03F0 and (product)0417 (which is an HPLJ1220C printer) which will create a path variable "HPLJ1220:" and choose interface 0 alternate 1 as the desired interface to use. The second line will execute the alias if it is already set up when the obey file is run.
Commands
-------
Command Usage IYONIX? Podule?  
USBDBuses Displays a list of available USB buses Yes No  
USBBuses  
USBDDevices Displays a list of available USB devices Yes No  
USBDevices  
USBDDevInfo <n> Displays device information on device <n> Yes No  
USBdevInfo  
USBDConfInfo <n> Displays configuration information on device <n> Yes No  
USBConfInfo  
USBDSetConfig <n><m> Set configuration value for device <n> to Yes Yes  
USBSetConfig configuration <m>  
USBDSetInterface <n><m><p> Set device <n> to interface <m> Yes Yes  
USBSetInterface and alternate <p>  
USBDReset <n> Force device <n> to be reset and Yes No  
USBReset "enumerated" again.  
DeviceFS issues
---------------
This is for others intending to provide a DeviceFS interface to their USB cards.. When writing a DeviceFS driver the DeviceFS driver entry 0 (initialise) is missing a vital parameter on versions of DeviceFS prior to that shipped with RISC OS 4. The RISC OS 4(or 5) entry provides the fileswitch stream handle in R4. For earlier DeviceFS versions, this handle may be found as a 32 bit value at offset 44 from the pointer supplied in R2.
Licence:
--------
The USB stack (OHCIDriver and USBDriver modules) on the IYONIX pc is Copyright (C) Castle Technology Ltd except for those portions covered by the notice below:
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Lennart Augustsson (lennart@augustsson.net) at
* Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
; Copyright 2011 Castle Technology Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; HAL USB workspace structure
; This workspace shouldn't be poked directly by the HAL. The only reason
; it gets exported is to allow USBHAL_WS_Size to be read, to allow the
; correct amount of memory to be reserved in the HAL workspace at sb
; USBHAL_WorkspaceOffset should then be set to the offset of this memory
; Note: This must be kept in sync with the matching C struct in dev/usb/usbhal.h
^ 0
USBHAL_WS_Heap_Normal # 4 ; Heap structure for malloc & free
USBHAL_WS_Heap_NCNB # 4 ; Heap structure for malloc_contig & free_contig
USBHAL_WS_allbuses # 8 ; TAILQ of buses
USBHAL_WS_usbbus_no # 4 ; Next number to use
USBHAL_WS_monotonictime # 4 ; Centisecond counter equivalent to OS_ReadMonotonicTime
USBHAL_WS_callouts # 4 ; Head of callouts list
USBHAL_WS_irqsema # 4 ; nonzero when processing interrupts
USBHAL_WS_rediscover # 4 ; re_discover callout
USBHAL_WS_t_handles # 4 ; tsleep handle list
USBHAL_WS_t_locks # 4 ; tsleep lock list
USBHAL_WS_nhandles # 4 ; tsleep handle count
USBHAL_WS_kbdflags # 4 ; Sticky keyboard scan bits
USBHAL_WS_callbacks # 4 ; Array of callbacks
USBHAL_WS_nextcb # 4 ; Index of next callback to run
USBHAL_WS_numcb # 4 ; Number of callbacks
USBHAL_WS_Size # 0
END
...@@ -29,7 +29,7 @@ USBDIR = <Lib$Dir>.USB ...@@ -29,7 +29,7 @@ USBDIR = <Lib$Dir>.USB
CINCLUDES = -Itbox:,TCPIPLibs:,^.,OS: CINCLUDES = -Itbox:,TCPIPLibs:,^.,OS:
CDEFINES += ${CDEBUG} -DKERNEL -D_KERNEL -Dpaddr_t=int -D__P(A)=A -DKLD_MODULE -DDISABLE_PACKED CDEFINES += ${CDEBUG} -DKERNEL -D_KERNEL -Dpaddr_t=int -D__P(A)=A -DKLD_MODULE -DDISABLE_PACKED
CMHGINCLUDES = ${CINCLUDES} CMHGINCLUDES = ${CINCLUDES}
CMHGDEFINES = -DMSGLOC=${MSGLOC} ${CDEBUG} CMHGDEFINES = ${CDEBUG}
CFLAGS += -ff -wp -wc -zm -zps1 CFLAGS += -ff -wp -wc -zm -zps1
LDFLAGS = -LIST maps.${TARGET} -MAP -Xref -Symbols rm.sym${TARGET} LDFLAGS = -LIST maps.${TARGET} -MAP -Xref -Symbols rm.sym${TARGET}
...@@ -50,6 +50,7 @@ UNAME= "RISC_OS" ...@@ -50,6 +50,7 @@ UNAME= "RISC_OS"
clean: clean:
${WIPE} o ${WFLAGS} ${WIPE} o ${WFLAGS}
${WIPE} o_hal ${WFLAGS}
${WIPE} aif ${WFLAGS} ${WIPE} aif ${WFLAGS}
${WIPE} aof ${WFLAGS} ${WIPE} aof ${WFLAGS}
${WIPE} rm ${WFLAGS} ${WIPE} rm ${WFLAGS}
...@@ -69,13 +70,14 @@ all: o._dirs ...@@ -69,13 +70,14 @@ all: o._dirs
export: export_${PHASE} export: export_${PHASE}
export_libs: export_libs: ${USBDIR}.o.${COMPONENT}
@echo ${COMPONENT}: export complete (libs) @echo ${COMPONENT}: export complete (libs)
export_hdrs: ^.dev.usb.h.usbdevs export_hdrs: ^.dev.usb.h.usbdevs
${MKDIR} ${USBDIR}.dev.usb.h ${MKDIR} ${USBDIR}.dev.usb.h
${MKDIR} ${USBDIR}.h ${MKDIR} ${USBDIR}.h
${MKDIR} ${USBDIR}.sys.h ${MKDIR} ${USBDIR}.sys.h
${MKDIR} ${USBDIR}.Hdr
${CP} ^.dev.usb.h.usb ${USBDIR}.dev.usb.h.usb ${CPFLAGS} ${CP} ^.dev.usb.h.usb ${USBDIR}.dev.usb.h.usb ${CPFLAGS}
${CP} ^.dev.usb.h.usbdevs ${USBDIR}.dev.usb.h.usbdevs ${CPFLAGS} ${CP} ^.dev.usb.h.usbdevs ${USBDIR}.dev.usb.h.usbdevs ${CPFLAGS}
${CP} ^.dev.usb.h.usbdi ${USBDIR}.dev.usb.h.usbdi ${CPFLAGS} ${CP} ^.dev.usb.h.usbdi ${USBDIR}.dev.usb.h.usbdi ${CPFLAGS}
...@@ -83,6 +85,7 @@ export_hdrs: ^.dev.usb.h.usbdevs ...@@ -83,6 +85,7 @@ export_hdrs: ^.dev.usb.h.usbdevs
${CP} h.USBDevFS ${USBDIR}.h.USBDevFS ${CPFLAGS} ${CP} h.USBDevFS ${USBDIR}.h.USBDevFS ${CPFLAGS}
${CP} ^.sys.h.device ${USBDIR}.sys.h.device ${CPFLAGS} ${CP} ^.sys.h.device ${USBDIR}.sys.h.device ${CPFLAGS}
${CP} ^.VersionNum ${USBDIR}.NetBSDVersion ${CPFLAGS} ${CP} ^.VersionNum ${USBDIR}.NetBSDVersion ${CPFLAGS}
${CP} Hdr.usbhal ${USBDIR}.Hdr.usbhal ${CPFLAGS}
@echo ${COMPONENT}: export complete (hdrs) @echo ${COMPONENT}: export complete (hdrs)
resources: resources_${COMPONENT} resources: resources_${COMPONENT}
...@@ -105,6 +108,7 @@ resources_USBDriver: LocalRes:USBDriver ${DEVICELIST} ...@@ -105,6 +108,7 @@ resources_USBDriver: LocalRes:USBDriver ${DEVICELIST}
o._dirs: o._dirs:
${MKDIR} o ${MKDIR} o
${MKDIR} o_hal
${MKDIR} aif ${MKDIR} aif
${MKDIR} aof ${MKDIR} aof
${MKDIR} rm ${MKDIR} rm
...@@ -124,12 +128,8 @@ usbmodule.o usbkboard.o: usbmodhead.h ...@@ -124,12 +128,8 @@ usbmodule.o usbkboard.o: usbmodhead.h
Resources.<Locale>.USBDevs: bin.makedevs ^.dev.usb.h.usbdevs ^.dev.usb.h.usbdevs_data Resources.<Locale>.USBDevs: bin.makedevs ^.dev.usb.h.usbdevs ^.dev.usb.h.usbdevs_data
${RUN}bin.makedevs > Resources.<Locale>.USBDevs ${RUN}bin.makedevs > Resources.<Locale>.USBDevs
# Remove the usbmodhead after creating the SWI table because if OHCIDriver
# makes it then it has the wrong messages file in it
USBDriver.h: usbmodhead.h USBDriver.h: usbmodhead.h
${SED} -n "/define USBDriver_/p" h.usbmodhead > h.USBDriver ${SED} -n "/define USBDriver_/p" h.usbmodhead > h.USBDriver
${RM} h.usbmodhead
${RM} o.usbmodhead
bin.makedevs: c.makedevs ${CLIB} ${DIRS} bin.makedevs: c.makedevs ${CLIB} ${DIRS}
${MAKE} -f makedevs/mk COMPONENT=makedevs THROWBACK=${THROWBACK} ${MAKE} -f makedevs/mk COMPONENT=makedevs THROWBACK=${THROWBACK}
...@@ -143,6 +143,15 @@ ohcimsgs.o: Resources.<Locale>.OHCIMessages ...@@ -143,6 +143,15 @@ ohcimsgs.o: Resources.<Locale>.OHCIMessages
ehcimsgs.o: Resources.<Locale>.EHCIMessages ehcimsgs.o: Resources.<Locale>.EHCIMessages
resgen resource_files o.ehcimsgs Resources.<Locale>.EHCIMessages ${MSGLOC} resgen resource_files o.ehcimsgs Resources.<Locale>.EHCIMessages ${MSGLOC}
# HAL libraries:
.SUFFIXES: .o_hal
.c.o_hal:; ${CC} -APCS 3/nofp/noswst -wp -ff -DUSBHAL -c -depend !Depend -DKERNEL -D_KERNEL -Dpaddr_t=int -D__P(A)=A -DKLD_MODULE -DDISABLE_PACKED ${CINCLUDES} ${THROWBACK} -o $@ $<
.s.o_hal:; ${AS} ${ASFLAGS} -APCS 3/nofp/noswst -o $@ $<
${USBDIR}.o.${COMPONENT}: ${OBJS_HAL} ${DIRS}
${MKDIR} ${USBDIR}.o
${AR} ${ARFLAGS} ${USBDIR}.o.${COMPONENT} ${OBJS_HAL}
# RISC OS debug: # RISC OS debug:
aif.${COMPONENT}: ${RAM_OBJS} ${RAM_LIBS} ${CLIB} ${DIRS} aif.${COMPONENT}: ${RAM_OBJS} ${RAM_LIBS} ${CLIB} ${DIRS}
link -base 0 -aif -bin -d -o $@ ${RAM_OBJS} ${RAM_LIBS} ${CLIB} link -base 0 -aif -bin -d -o $@ ${RAM_OBJS} ${RAM_LIBS} ${CLIB}
...@@ -165,5 +174,7 @@ bbe-usb: bbe-generic ...@@ -165,5 +174,7 @@ bbe-usb: bbe-generic
${CP} rom_link_v.${TARGET} ${VERBATIMROMLINK} ${CPFLAGS} ${CP} rom_link_v.${TARGET} ${VERBATIMROMLINK} ${CPFLAGS}
BBE_Export_File ^.VersionNum BBE_Export_File ^.VersionNum
# Static dependencies:
o.makedevs o.usbmouse: ^.dev.usb.h.usbdevs
# Dynamic dependencies: # Dynamic dependencies:
...@@ -8,4 +8,10 @@ ehci.o \ ...@@ -8,4 +8,10 @@ ehci.o \
port.o \ port.o \
call_veneer.o \ call_veneer.o \
\ \
triggercbs.o triggercbs.o \
usbroothub_subr.o
OBJS_HAL = \
o_hal.ehci \
o_hal.usbroothub_subr \
o_hal.ehcihal
...@@ -4,5 +4,9 @@ ohcimodule.o \ ...@@ -4,5 +4,9 @@ ohcimodule.o \
ohci.o \ ohci.o \
port.o \ port.o \
call_veneer.o \ call_veneer.o \
triggercbs.o \ triggercbs.o
ohcimsgs.o
\ No newline at end of file RAM_OBJS = ${OBJS} ohcimsgs.o
OBJS_HAL = \
o_hal.ohci
...@@ -13,5 +13,17 @@ usbkboard.o \ ...@@ -13,5 +13,17 @@ usbkboard.o \
hid.o \ hid.o \
bufman.o \ bufman.o \
triggercbs.o \ triggercbs.o \
call_veneer.o \ call_veneer.o
usbmsgs.o
RAM_OBJS = ${OBJS} usbmsgs.o
OBJS_HAL = \
o_hal.usb \
o_hal.usbdi \
o_hal.usb_subr \
o_hal.usbdi_util \
o_hal.usb_quirks \
o_hal.uhub \
o_hal.porthal \
o_hal.halheap \
o_hal.usbhal
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
VersionNum file really,as a work around define them here so the CMHG VersionNum file really,as a work around define them here so the CMHG
file remains unaltered */ file remains unaltered */
#define OHCIDriverModule_Module_Date_CMHG 31 Dec 2005 #define OHCIDriverModule_Module_Date_CMHG 04 Dec 2011
#define OHCIDriverModule_MajorVersion_CMHG 0.29 #define OHCIDriverModule_MajorVersion_CMHG 0.37
#define EHCIDriverModule_Module_Date_CMHG 15 May 2005 #define EHCIDriverModule_Module_Date_CMHG 18 Dec 2011
#define EHCIDriverModule_MajorVersion_CMHG 0.14 #define EHCIDriverModule_MajorVersion_CMHG 0.21
#define USBDriverModule_Module_Date_CMHG 22 Feb 2006 #define USBDriverModule_Module_Date_CMHG 10 Dec 2011
#define USBDriverModule_MajorVersion_CMHG 0.47 #define USBDriverModule_MajorVersion_CMHG 0.55
/* Copyright 2011 Castle Technology Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* HAL version of ehcimodule.c */
#include <dev/usb/usbhal.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <machine/bus.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/ehcireg.h>
#include <dev/usb/ehcivar.h>
#include "Global/RISCOS.h"
#include "Global/Services.h"
#include "Global/HALEntries.h"
/* Have to avoid including stdio as there's a clash with the BSD stuff */
#define __stdio_h
#include "DebugLib/DebugLib.h"
#include "service.h"
#include "oslib/devicefs.h"
typedef struct
{
int type;
int flags;
void *hw;
int devno;
} usbinfo;
extern size_t HAL_USBControllerInfo(int idx,usbinfo *info,size_t size);
extern int HAL_IRQEnable(int device);
extern int HAL_IRQDisable(int device);
extern void HAL_IRQClear(int device);
extern device_ptr_t register_bus(device_ptr_t bus);
static void init_device(usbinfo *info,int idx)
{
ehci_softc_t *ehci = malloc(sizeof(ehci_softc_t));
memset(ehci,0,sizeof(ehci_softc_t));
sprintf(ehci->sc_bus.bdev.dv_xname,"EHCI%d",idx);
ehci->sc_irqdevno = info->devno;
ehci->sc_ncomp = 2;
/* Abuse iot & ioh members to store base addr & flags */
ehci->iot = (bus_space_tag_t) info->hw;
ehci->ioh = (bus_space_handle_t) info->flags;
ehci_init(ehci);
/* Enable IRQ */
HAL_IRQEnable(ehci->sc_irqdevno);
/* Register with USBDriver */
register_bus((device_ptr_t) ehci);
}
void USBHAL_EHCIDriver_Init(void)
{
/* Find and initialise all controllers. Note that this currently only
supports controllers exposed via HAL_USBControllerInfo */
int idx=0;
do {
usbinfo info;
size_t usbinfolen = HAL_USBControllerInfo(idx,&info,sizeof(info));
if((usbinfolen >= sizeof(info)) && (info.type == 1))
init_device(&info,idx);
else if(!usbinfolen)
return;
idx++;
} while(1);
}
int usbhal_ehci_do_intr(struct usbd_bus *bus,int irqdevno)
{
ehci_softc_t *sc = (ehci_softc_t *)bus;
if(irqdevno != sc->sc_irqdevno)
return 0;
int ret = ehci_intr(sc);
return ret;
}
void usbhal_ehci_shutdown(struct usbd_bus *bus)
{
ehci_softc_t *sc = (ehci_softc_t *)bus;
/* Disable IRQ */
HAL_IRQDisable(sc->sc_irqdevno);
/* Reset controller */
EOWRITE4(sc, EHCI_USBCMD, 0);
EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
EOREAD4(sc, EHCI_USBCMD);/* flush the command */
/* Wait a bit */
delay(1000);
/* Clear any lingering IRQ */
HAL_IRQClear(sc->sc_irqdevno);
}
/* #define these because I'm feeling lazy */
#define ehci_base ((volatile int *)iot)
#define registers_32bit (((int)ioh) & 8)
void bus_space_write_4 (bus_space_tag_t iot, bus_space_handle_t ioh, int o, int x)
{
ehci_base[o>>2] = x;
}
int bus_space_read_4 (bus_space_tag_t iot, bus_space_handle_t ioh, int o)
{
return ehci_base[o>>2];
}
void bus_space_write_2 (bus_space_tag_t iot, bus_space_handle_t ioh, int o, int x)
{
if (registers_32bit)
{
x &= 0xFFFF;
if (o&2)
ehci_base[o>>2]=(ehci_base[o>>2]&0xFFFF)|(x<<16);
else
ehci_base[o>>2]=(ehci_base[o>>2]&0xFFFF0000)|x;
}
else
((uint16_t*) ehci_base)[o>>1] = x;
}
int bus_space_read_2 (bus_space_tag_t iot, bus_space_handle_t ioh, int o)
{
if (registers_32bit)
{
if (o&2)
return ((uint32_t*)ehci_base)[o>>2]>>16;
else
return ((uint32_t*)ehci_base)[o>>2]&0xFFFF;
}
return ((uint16_t*) ehci_base)[o>>1];
}
void bus_space_write_1 (bus_space_tag_t iot, bus_space_handle_t ioh, int o, int x)
{
if (registers_32bit)
{
x &= 0xFF;
int t = ehci_base[o>>2];
t &= ~(0xFF<<((o&3)*8));
t |= x<<((o&3)*8);
ehci_base[o>>2] = t;
}
else
((uint8_t*) ehci_base)[o] = x;
}
int bus_space_read_1 (bus_space_tag_t iot, bus_space_handle_t ioh, int o)
{
if (registers_32bit)
return (((uint32_t*)ehci_base)[o/4]>>((o&3)*8))&0xff;
return ((uint8_t*) ehci_base)[o];
}
...@@ -65,7 +65,7 @@ void* private_word; ...@@ -65,7 +65,7 @@ void* private_word;
volatile int* ehci_base; volatile int* ehci_base;
ehci_softc_t ehci_soft; ehci_softc_t ehci_soft;
struct device * usb_soft; struct device * usb_soft = NULL;
extern int * init_veneer (void); extern int * init_veneer (void);
//extern void* resource_files (void); //extern void* resource_files (void);
#ifdef EHCI_DEBUG #ifdef EHCI_DEBUG
...@@ -142,23 +142,21 @@ int unhandled_irqs; ...@@ -142,23 +142,21 @@ int unhandled_irqs;
int registers_32bit=0; //(used with rhenium) int registers_32bit=0; //(used with rhenium)
#endif /* RHENIUM */ #endif /* RHENIUM */
_kernel_oserror* register_bus(void *in,struct device **out)
//_kernel_oserror* bus_register (_kernel_swi_regs* r, void* pw, void* h) {
//{ *out = NULL;
// /* register with the usbdriver module if it's already resident */ /* Check USBDriver is new enough */
// dprintf (("", "Registering with USB driver\n")); int version;
// _kernel_oserror *e = _swix(USBDriver_Version,_OUT(0),&version);
// memset (&ehci_soft, 0, sizeof ehci_soft); if(e)
// sprintf (ehci_soft.sc_bus.bdev.dv_xname, "EHCI%d", instance); return e;
// /* fix n companions */ if(version < RISCOS_USBDRIVER_API_VERSION)
// ehci_soft.sc_ncomp = 2; return (_kernel_oserror*)"\0\0\0\0USBDriver too old";
// ehci_init (&ehci_soft); /* Now attempt to register */
// e = _swix(USBDriver_RegisterBus, _INR(0,1)|_OUT(0),in,RISCOS_USBDRIVER_API_VERSION,out);
// _swix (USBDriver_RegisterBus, _IN(0)|_OUT(0), if(e) *out = NULL;
// &ehci_soft, &usb_soft); return e;
// }
// return NULL;
//}
_kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h) _kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h)
{ {
...@@ -172,16 +170,15 @@ _kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h) ...@@ -172,16 +170,15 @@ _kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h)
/* register with the usbdriver module if it's already resident */ /* register with the usbdriver module if it's already resident */
dprintf (("", "Registering with USB driver\n")); dprintf (("", "Registering with USB driver\n"));
e = register_bus(&ehci_soft, &usb_soft);
// memset (&ehci_soft, 0, sizeof ehci_soft); if (e)
// sprintf (ehci_soft.sc_bus.bdev.dv_xname, "EHCI%d", instance); {
// /* fix n companions */ dprintf (("", "Failed to register: %s\n", e->errmess));
// ehci_soft.sc_ncomp = 2; }
// ehci_init (&ehci_soft); else
{
_swix (USBDriver_RegisterBus, _IN(0)|_OUT(0), dprintf (("", "Registering with USB driver-done\n"));
&ehci_soft, &usb_soft); }
dprintf (("", "Registering with USB driver-done\n"));
// allow enough space for name, % and number, then space, and // allow enough space for name, % and number, then space, and
...@@ -203,19 +200,6 @@ _kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h) ...@@ -203,19 +200,6 @@ _kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h)
_kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) { _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) {
_kernel_oserror* e = 0; _kernel_oserror* e = 0;
#ifdef EHCI_DEBUG
// struct dev_struct {
// devicefs_device dev;
// int null;
// char name[32];
// }* dev = NULL;
#endif
callx_init (pw); callx_init (pw);
...@@ -348,27 +332,6 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) { ...@@ -348,27 +332,6 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) {
#ifdef EHCI_DEBUG #ifdef EHCI_DEBUG
usbdebug = ehcidebug = atoi (getenv ("ehcidebug")); usbdebug = ehcidebug = atoi (getenv ("ehcidebug"));
irq0 = gettime () / 1000; irq0 = gettime () / 1000;
// dev = calloc (sizeof *dev, 1);
// strcpy (dev->name, ehci_soft.sc_bus.bdev.dv_xname);
//
// dev->dev.name_offset = dev->name - (char*) dev;
// dev->dev.flags = 3;
// dev->dev.tx_flags = 0x8;
// dev->dev.tx_buffer_size = 0;
// dev->dev.rx_flags = 0x8;
// dev->dev.rx_buffer_size = 1024;
//
// e = _swix (DeviceFS_Register, _INR (0, 7) | _OUT(0),
// 4,
// dev,
// driver_entry,
// NULL,
// pw,
// NULL,
// INT_MAX, // XXX should be -1, but that doesn't seem to work
// INT_MAX,
// &irq_device);
#endif #endif
_swix (OS_ClaimDeviceVector, _INR(0,4), _swix (OS_ClaimDeviceVector, _INR(0,4),
...@@ -385,6 +348,7 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) { ...@@ -385,6 +348,7 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) {
memset (&ehci_soft, 0, sizeof ehci_soft); memset (&ehci_soft, 0, sizeof ehci_soft);
sprintf (ehci_soft.sc_bus.bdev.dv_xname, "EHCI%d", instance); sprintf (ehci_soft.sc_bus.bdev.dv_xname, "EHCI%d", instance);
ehci_soft.sc_irqdevno = device_number;
/* fix n companions */ /* fix n companions */
ehci_soft.sc_ncomp = 2; ehci_soft.sc_ncomp = 2;
...@@ -455,17 +419,16 @@ void module_services(int service_number, _kernel_swi_regs *r, void *pw) ...@@ -455,17 +419,16 @@ void module_services(int service_number, _kernel_swi_regs *r, void *pw)
case Service_USBDriver_Starting: case Service_USBDriver_Starting:
if (usb_soft == NULL) if (usb_soft == NULL)
{ {
dprintf (("", "Registering with USB driver from svcecall\n"));
_kernel_oserror *e = register_bus(&ehci_soft,&usb_soft);
if(e)
{
dprintf (("", "Registering with USB driver from svcecall\n")); dprintf (("", "Failed to register: %s\n", e->errmess));
_swix (USBDriver_RegisterBus, _IN(0)|_OUT(0), }
&ehci_soft, &usb_soft); else
dprintf (("", "Registering with USB driver from svcecall-done\n")); {
dprintf (("", "Registering with USB driver from svcecall-done\n"));
}
} }
break; break;
case Service_USBDriver_Dying: case Service_USBDriver_Dying:
...@@ -841,11 +804,6 @@ softintr (_kernel_swi_regs* r, void* pw) ...@@ -841,11 +804,6 @@ softintr (_kernel_swi_regs* r, void* pw)
return 1; return 1;
} }
void riscos_irqclear()
{
_swix(OS_Hardware, _IN(0)|_INR(8,9), device_number, 0, EntryNo_HAL_IRQClear);
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
//#ifdef EHCI_DEBUG //#ifdef EHCI_DEBUG
// //
......
...@@ -76,7 +76,7 @@ void* private_word; ...@@ -76,7 +76,7 @@ void* private_word;
volatile int* ohci_base; volatile int* ohci_base;
ohci_softc_t ohci_soft; ohci_softc_t ohci_soft;
struct device * usb_soft; struct device * usb_soft=NULL;
extern int * init_veneer (void); extern int * init_veneer (void);
extern void* resource_files (void); extern void* resource_files (void);
#ifdef OHCI_DEBUG #ifdef OHCI_DEBUG
...@@ -275,21 +275,26 @@ int do_ohci_perror(int port) ...@@ -275,21 +275,26 @@ int do_ohci_perror(int port)
#endif /* RHENIUM */ #endif /* RHENIUM */
//_kernel_oserror* bus_register (_kernel_swi_regs* r, void* pw, void* h) _kernel_oserror* register_bus(void *in,struct device **out)
//{ {
// /* register with the usbdriver module if it's already resident */ *out = NULL;
// dprintf (("", "Registering with USB driver\n")); /* Check USBDriver is new enough */
// _swix (USBDriver_RegisterBus, _IN(0)|_OUT(0), int version;
// &ohci_soft, &usb_soft); _kernel_oserror *e = _swix(USBDriver_Version,_OUT(0),&version);
// dprintf (("", "Registering with USB driver-done\n")); if(e)
// return e;
// return NULL; if(version < RISCOS_USBDRIVER_API_VERSION)
//} return (_kernel_oserror*)"\0\0\0\0USBDriver too old";
// /* Now attempt to register */
e = _swix(USBDriver_RegisterBus, _INR(0,1)|_OUT(0),in,RISCOS_USBDRIVER_API_VERSION,out);
if(e) *out = NULL;
return e;
}
_kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h) _kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h)
{ {
_kernel_oserror * e; _kernel_oserror * e;
char* v; char* v=NULL;
(void) r; (void) r;
(void) pw; (void) pw;
...@@ -315,9 +320,15 @@ _kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h) ...@@ -315,9 +320,15 @@ _kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h)
#endif /* RHENIUM */ #endif /* RHENIUM */
/* now we know the root hub info, register it with USBDriver */ /* now we know the root hub info, register it with USBDriver */
dprintf (("", "Init-Registering with USB driver\n")); dprintf (("", "Init-Registering with USB driver\n"));
_swix (USBDriver_RegisterBus, _IN(0)|_OUT(0), e = register_bus(&ohci_soft, &usb_soft);
&ohci_soft, &usb_soft); if (e)
dprintf (("", "Init-Registering with USB driver-done\n")); {
dprintf (("", "Failed to register: %s\n", e->errmess));
}
else
{
dprintf (("", "Init-Registering with USB driver-done\n"));
}
/* allow enough space for name, % and number, then space, and /* allow enough space for name, % and number, then space, and
another number */ another number */
...@@ -501,6 +512,7 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) { ...@@ -501,6 +512,7 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) {
memset (&ohci_soft, 0, sizeof ohci_soft); memset (&ohci_soft, 0, sizeof ohci_soft);
sprintf (ohci_soft.sc_bus.bdev.dv_xname, "OHCI%d", instance); sprintf (ohci_soft.sc_bus.bdev.dv_xname, "OHCI%d", instance);
ohci_soft.sc_irqdevno = device_number;
#ifdef RHENIUM #ifdef RHENIUM
...@@ -510,6 +522,7 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) { ...@@ -510,6 +522,7 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) {
{ {
#endif /* RHENIUM */ #endif /* RHENIUM */
_swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device); _swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device);
if (v == 0) v = (char *)" ";
strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor-1); strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor-1);
// [sizeof ohci_soft.sc_vendor - 1] = '\0'; // [sizeof ohci_soft.sc_vendor - 1] = '\0';
#ifdef RHENIUM #ifdef RHENIUM
...@@ -704,10 +717,16 @@ void module_services(int service_number, _kernel_swi_regs *r, void *pw) ...@@ -704,10 +717,16 @@ void module_services(int service_number, _kernel_swi_regs *r, void *pw)
{ {
if(ohci_soft.sc_vendor[0]!='\0') // (means svce_PCI has happened) if(ohci_soft.sc_vendor[0]!='\0') // (means svce_PCI has happened)
{ /* we're here in callback.. so foo we go */ { /* we're here in callback.. so foo we go */
dprintf (("", "Registering with USB driver from svcecall \n")); dprintf (("", "Registering with USB driver from svcecall\n"));
_swix (USBDriver_RegisterBus, _IN(0)|_OUT(0), _kernel_oserror *e = register_bus(&ohci_soft,&usb_soft);
&ohci_soft, &usb_soft); if(e)
dprintf (("", "Registering with USB driver from svcecall-done\n")); {
dprintf (("", "Failed to register: %s\n", e->errmess));
}
else
{
dprintf (("", "Registering with USB driver from svcecall-done\n"));
}
} }
} }
break; break;
...@@ -725,6 +744,7 @@ void module_services(int service_number, _kernel_swi_regs *r, void *pw) ...@@ -725,6 +744,7 @@ void module_services(int service_number, _kernel_swi_regs *r, void *pw)
{ {
#endif /* RHENIUM */ #endif /* RHENIUM */
_swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device); _swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device);
if (v == 0) v = (char *)" ";
strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor-1); strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor-1);
// [sizeof ohci_soft.sc_vendor - 1] = '\0'; // [sizeof ohci_soft.sc_vendor - 1] = '\0';
#ifdef RHENIUM #ifdef RHENIUM
...@@ -1035,8 +1055,3 @@ softintr (_kernel_swi_regs* r, void* pw) ...@@ -1035,8 +1055,3 @@ softintr (_kernel_swi_regs* r, void* pw)
ohci_softintr ((void*) r->r[0]); ohci_softintr ((void*) r->r[0]);
return 0; return 0;
} }
void riscos_irqclear()
{
_swix(OS_Hardware, _IN(0)|_INR(8,9), device_number, 0, EntryNo_HAL_IRQClear);
}
...@@ -12,6 +12,11 @@ ...@@ -12,6 +12,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* This is the module version of port.c
For the HAL version, see usbhal.c and porthal.s
*/
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
...@@ -122,14 +127,6 @@ delay (int d) ...@@ -122,14 +127,6 @@ delay (int d)
_swix (OS_Hardware, _IN(0)|_INR(8,9), d, 0, EntryNo_HAL_CounterDelay); _swix (OS_Hardware, _IN(0)|_INR(8,9), d, 0, EntryNo_HAL_CounterDelay);
} }
void
microtime(struct timeval *thetime)
{
uint64_t t = gettime ();
thetime->tv_sec = (unsigned long) (t / 1000000000);
thetime->tv_usec = (unsigned long) ((t / 1000) % 1000000);
}
void void
selrecord(struct proc *selector, struct selinfo *selinfo) selrecord(struct proc *selector, struct selinfo *selinfo)
{ {
...@@ -179,8 +176,9 @@ extern int private_word; ...@@ -179,8 +176,9 @@ extern int private_word;
extern void callout_veneer (void); extern void callout_veneer (void);
void void
callout_init (struct callout* c) callout_init (struct callout* c,int ignored)
{ {
(void)ignored;
#ifdef USB_DEBUG0 #ifdef USB_DEBUG0
if (usbdebug > 15) dprintf (("Port", "callout init %p\n", c)); if (usbdebug > 15) dprintf (("Port", "callout init %p\n", c));
#endif #endif
...@@ -287,26 +285,20 @@ int tsleep (void* ident, int priority, const char* wmesg, int timo, int noblock) ...@@ -287,26 +285,20 @@ int tsleep (void* ident, int priority, const char* wmesg, int timo, int noblock)
t_locks[i] = 0; t_locks[i] = 0;
/* wait until the lock is free */ /* wait until the lock is free */
int flags = 0;
_kernel_irqs_on (); _kernel_irqs_on ();
if (timo) { if (timo) {
do { do {
triggercbs (); triggercbs ();
t2 = gettime (); t2 = gettime ();
_swix (OS_ReadEscapeState, _OUT(_FLAGS), &flags);
} }
while ((t_locks[i] == 0) && (t2 < t1) && ((flags & _C) == 0)); while ((t_locks[i] == 0) && (t2 < t1));
} }
else else
{ {
while (t_locks[i] == 0 && (flags & _C) == 0) while (t_locks[i] == 0)
{ {
/* allow foreground process to function while we're waiting */
/* if (noblock) _swix (OS_UpCall, _INR(0,1), 6, &t_locks[i]);*/
/*// _swix (OS_UpCall, _INR(0,1), 6, &t_locks[i]);*/
triggercbs (); triggercbs ();
_swix (OS_ReadEscapeState, _OUT(_FLAGS), &flags);
} }
#ifdef USB_DEBUG0 #ifdef USB_DEBUG0
t2 = gettime (); t2 = gettime ();
...@@ -314,11 +306,6 @@ int tsleep (void* ident, int priority, const char* wmesg, int timo, int noblock) ...@@ -314,11 +306,6 @@ int tsleep (void* ident, int priority, const char* wmesg, int timo, int noblock)
} }
_kernel_irqs_off (); _kernel_irqs_off ();
if (flags & _C)
{
_kernel_osbyte (126, 0, 0);
}
t_handles[i] = 0; t_handles[i] = 0;
#ifdef USB_DEBUG0 #ifdef USB_DEBUG0
...@@ -469,3 +456,8 @@ void softintr_disestablish (void* p) ...@@ -469,3 +456,8 @@ void softintr_disestablish (void* p)
free (p); free (p);
} }
#endif #endif
void riscos_irqclear(int devno)
{
_swix(OS_Hardware, _IN(0)|_INR(8,9), devno, 0, EntryNo_HAL_IRQClear);
}
/* Copyright 2011 Castle Technology Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This file is the HAL equivalent of usbmodule.c, with a few routines from
port.c thrown in for good measure.
*/
#include <dev/usb/usbhal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "DebugLib/DebugLib.h"
#include "swis.h"
#include <sys/callout.h>
#include "sys/time.h"
#include "Global/HALEntries.h"
#include "dev/usb/usb.h"
#include "dev/usb/usbdi.h"
#include "dev/usb/usbdi_util.h"
#include "dev/usb/usbdivar.h"
#define MAX_TSLEEP_HANDLES 32 /* Should be plenty? */
#define MAX_CALLBACKS 16
//#define DEBUG_HAL
#ifdef DEBUG_HAL
#define hdprintf printf
#else
#define hdprintf(...) 0
#endif
extern void HALHeap_InitHeap(void *heap,uint32_t size);
extern uint32_t HAL_CounterRead(void);
extern uint32_t HAL_CounterPeriod(void);
extern int HAL_TimerDevice(int timer);
extern int HAL_IRQEnable(int device);
extern int HAL_IRQDisable(int device);
extern int HAL_IRQSource(void);
extern void HAL_IRQClear(int device);
extern void HAL_DebugTX(int c);
extern void panic (const char* str, ...);
/* this is defined in usb.c by the macro USB_DECLARE_DRIVER */
extern const struct cfattach usb_ca;
extern const struct cfattach uhub_uhub_ca;
extern struct usbd_bus *usb_getbus(device_ptr_t self);
extern int usbioctl(int devt, u_long cmd, void* data, int flag, void *p);
static void re_discover(void *param);
#if 0
/* Some heap validation code, since I got rid of the code in halheap.s */
void dumpheap(uint32_t *heap)
{
int s = splbio();
printf("heap @ %p:\nmag %x\nfree %x\nbase %x\nend %x\n",heap,heap[0],heap[1],heap[2],heap[3]);
uint32_t free = heap[1];
uint32_t next = 16;
if(free)
free += 4;
while(free)
{
if(free > next)
{
printf("allocs between %x and %x:\n",next,free);
do {
printf("%x: alloc size %x\n",next,heap[next>>2]);
if((heap[next>>2] > heap[2]) || (heap[next>>2]+next > heap[2]) || (heap[next>>2]&3) || !heap[next>>2])
{
printf("bad block, skipping rest\n");
break;
}
next += heap[next>>2];
} while(free>next);
if(free!=next)
printf("alloc mismatch! next=%x\n",next);
}
printf("%x: free size %x next %x\n",free,heap[(free+4)>>2],heap[free>>2]);
if(heap[(free+4)>>2] == heap[free>>2])
printf("consecutive free blocks!\n");
next = free+heap[(free+4)>>2];
if((heap[free>>2] & 3) || (heap[free>>2] >= heap[2]) || (heap[free>>2]+free >= heap[2]))
{
printf("bad next ptr\n");
do {} while(1);
}
if((heap[(free+4)>>2] & 3) || (heap[(free+4)>>2] >= heap[2]) || (heap[(free+4)>>2]+free >= heap[2]))
{
printf("bad size\n");
do {} while(1);
}
if(!heap[free>>2])
{
printf("end of free list\n");
break;
}
free = free+heap[free>>2];
if(free<next)
{
printf("next free is inside current?\n");
do {} while(1);
}
}
if(free > heap[2])
{
printf("free list extends beyond heap end\n");
}
if(next > heap[2])
{
printf("next ptr beyond heap end\n");
}
printf("end allocs:\n");
while(next < heap[2])
{
printf("%x: alloc size %x\n",next,heap[next>>2]);
if((heap[next>>2] > heap[2]) || (heap[next>>2]+next > heap[2]) || (heap[next>>2]&3) || !heap[next>>2])
{
printf("bad block, skipping rest\n");
break;
}
next += heap[next>>2];
}
printf("end\n");
splx(s);
}
#endif
/*
* Keyboard code
*/
#define NKEYCODE 6
struct ukbd_data {
uint8_t modifiers;
uint8_t reserved;
uint8_t keycode[NKEYCODE];
};
struct ukbd_softc {
USBBASEDEVICE sc_dev;
usbd_device_handle sc_udev;
usbd_interface_handle sc_iface; /* interface */
usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
int sc_ep_addr;
struct ukbd_data data;
};
void ukbd_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status ustatus)
{
struct ukbd_softc *sc = addr;
struct ukbd_data * data = &sc->data;
if (ustatus) {
hdprintf("ukbd_intr: status=%d\n", ustatus);
if (ustatus != USBD_CANCELLED)
{
usbd_clear_endpoint_stall_async(sc->sc_intrpipe);
}
return;
}
/* Minimal decoding, as per Tungsten HAL */
uint32_t result = HAL_KbdScan_Present;
if (data->modifiers & ((1<<0) | (1<<4)))
result |= HAL_KbdScan_Ctrl;
if (data->modifiers & ((1<<1) | (1<<5)))
result |= HAL_KbdScan_Shift;
for (int i = 0; i < NKEYCODE; ++i)
{
switch (data->keycode[i])
{
case 0x15: result |= HAL_KbdScan_R; break;
case 0x17: result |= HAL_KbdScan_T; break;
case 0x4c: result |= HAL_KbdScan_Delete; break;
case 0x4d: result |= HAL_KbdScan_End; break;
case 0x28: result |= HAL_KbdScan_Return; break;
}
}
result |= HAL_KbdScan_Complete;
int s = splbio();
USBHALWS->kbdflags |= result;
splx(s);
}
struct device* attach_keyboard (struct device* parent, void* aux)
{
struct ukbd_softc* softc;
struct usb_attach_arg *uaa = aux;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
/* First see if we match */
/* Check that this is a keyboard that speaks the boot protocol. */
if (uaa->iface == NULL)
{
return (UMATCH_NONE);
}
id = usbd_get_interface_descriptor(uaa->iface);
if (id == NULL ||
id->bInterfaceClass != UICLASS_HID ||
id->bInterfaceSubClass != UISUBCLASS_BOOT ||
id->bInterfaceProtocol != UIPROTO_BOOT_KEYBOARD)
{
return (UMATCH_NONE);
}
/* If so, allocate memory for the device and attach ourselves. */
softc = malloc (sizeof *softc);
if (softc == 0) {
return NULL;
}
memset(softc,0,sizeof(*softc));
strcpy (softc->sc_dev.dv_xname, "USBK");
softc->sc_dev.dv_cfdata = (void*) 4; // keyboard
softc->sc_udev = uaa->device;
softc->sc_iface = uaa->iface;
ed = usbd_interface2endpoint_descriptor(uaa->iface, 0);
if (ed == NULL) {
hdprintf("kbd: Could not read endpoint descriptor\n");
return NULL;
}
if (usbd_set_protocol(uaa->iface, 0)) {
hdprintf("kbd: Set protocol failed\n");
return NULL;
}
softc->sc_ep_addr = ed->bEndpointAddress;
hdprintf("USB keyboard enabled\n");
int s = splbio();
USBHALWS->kbdflags |= HAL_KbdScan_Present;
splx(s);
/* set idle rate to 0 */
usbd_set_idle (softc->sc_iface, 0, 0);
/* Set up interrupt pipe. */
usbd_open_pipe_intr(softc->sc_iface, softc->sc_ep_addr,
USBD_SHORT_XFER_OK, &softc->sc_intrpipe, softc,
&softc->data, sizeof(softc->data), ukbd_intr,
USBD_DEFAULT_INTERVAL);
return (struct device*) softc;
}
int detach_keyboard (struct device* kb)
{
struct ukbd_softc* sc = (struct ukbd_softc*) kb;
usbd_abort_pipe(sc->sc_intrpipe);
usbd_close_pipe(sc->sc_intrpipe);
free (kb);
return 0;
}
/*
* HAL interface bits
*/
void triggercbs (void)
{
int s = splbio();
if(!USBHALWS->irqsema)
{
/* Prevent recusrive callbacks */
USBHALWS->irqsema++;
/* Trigger all pending callbacks */
while(USBHALWS->numcb)
{
void (*cbfunc)(void *) = USBHALWS->callbacks[USBHALWS->nextcb].cbfunc;
void *param = USBHALWS->callbacks[USBHALWS->nextcb].param;
USBHALWS->numcb--;
USBHALWS->nextcb++;
hdprintf("cb %p %p\n",cbfunc,param);
if(cbfunc)
{
cbfunc(param);
splbio(); /* Make sure IRQs remain off */
}
}
USBHALWS->irqsema--;
}
splx(s);
}
void USBHAL_Init(void *heapbase,uint32_t heapsize,void *ncnbbase,uint32_t ncnbsize)
{
/* Init heaps so malloc/free will work */
USBHALWS->heap_normal = heapbase;
USBHALWS->heap_ncnb = ncnbbase;
HALHeap_InitHeap(USBHALWS->heap_normal,heapsize);
HALHeap_InitHeap(USBHALWS->heap_ncnb,ncnbsize);
/* Init rest of workspace */
TAILQ_INIT(&(USBHALWS->allbuses));
USBHALWS->usbbus_no = 1;
USBHALWS->monotonictime = 0;
USBHALWS->callouts = NULL;
USBHALWS->irqsema = 0;
USBHALWS->t_handles = malloc(MAX_TSLEEP_HANDLES*4);
USBHALWS->t_locks = malloc(MAX_TSLEEP_HANDLES*4);
USBHALWS->nhandles = 0;
USBHALWS->kbdflags = 0;
USBHALWS->callbacks = malloc(sizeof(usbhal_callback)*MAX_CALLBACKS);
USBHALWS->nextcb = 0;
USBHALWS->numcb = 0;
/* The centisecond timer will be running, but the interrupt won't. Enable it. */
HAL_IRQEnable(HAL_TimerDevice(0));
/* Start rediscover callout. Half second interval should do it. */
USBHALWS->rediscover = malloc(sizeof(struct callout));
callout_init(USBHALWS->rediscover,0);
callout_reset(USBHALWS->rediscover,500,re_discover,NULL);
}
uint32_t USBHAL_KbdScan(void)
{
/* Return sticky flags */
return USBHALWS->kbdflags;
}
int USBHAL_KbdScanInterrupt(int irq)
{
USBHALWS->irqsema++;
hdprintf("i%d\n",irq);
if(irq == HAL_TimerDevice(0))
{
/* Timer interrupt */
HAL_IRQClear(irq);
USBHALWS->monotonictime++;
while(USBHALWS->callouts && (USBHALWS->monotonictime >= USBHALWS->callouts->c_time))
{
/* Trigger callout */
void (*f)(void *) = USBHALWS->callouts->c_func;
void *v = USBHALWS->callouts->c_arg;
USBHALWS->callouts = USBHALWS->callouts->c_next;
hdprintf("co %p %p\n",f,v);
if(f)
{
f(v);
}
/* Make sure IRQs are still off */
splbio();
}
irq = -1;
}
else if(irq != -1)
{
/* Process controller IRQs */
struct device* dev;
TAILQ_FOREACH(dev, &USBHALWS->allbuses, dv_list)
{
struct usbd_bus *bus = usb_getbus(dev);
if(bus->methods->do_intr(bus,irq))
{
irq = -1;
goto done;
}
}
hdprintf("?\n");
}
done:
USBHALWS->irqsema--;
/* Trigger any pending callbacks */
triggercbs();
hdprintf("I\n");
return irq;
}
void USBHAL_Shutdown(void)
{
#if 0
dumpheap(USBHALWS->heap_normal);
dumpheap(USBHALWS->heap_ncnb);
#endif
callout_stop(USBHALWS->rediscover);
/* RISC OS calls this with interrupts off, but we probably want them on */
splx(0);
/* Shut down all host controllers */
struct device* dev;
TAILQ_FOREACH(dev, &USBHALWS->allbuses, dv_list)
{
/* Trigger any pending callbacks */
triggercbs();
(*usb_ca.ca_detach)(dev, 0);
/* Should we be doing this before or after? */
struct usbd_bus *bus = usb_getbus(dev);
bus->methods->shutdown(bus);
free (dev);
}
/* Trigger any pending callbacks */
triggercbs();
/* Now stop the timer IRQ */
HAL_IRQDisable(HAL_TimerDevice(0));
/* Done! */
/* TODO - Clear up memory allocations? */
splbio();
}
void USBHAL_AddCallback(void (*cbfunc)(void *),void *param)
{
int s = splbio();
if(USBHALWS->numcb == MAX_CALLBACKS)
panic("Ran out of callbacks!");
int idx = (USBHALWS->numcb+USBHALWS->nextcb) & (MAX_CALLBACKS-1);
USBHALWS->callbacks[idx].cbfunc = cbfunc;
USBHALWS->callbacks[idx].param = param;
USBHALWS->numcb++;
splx(s);
}
void USBHAL_RemoveCallback(void (*cbfunc)(void *),void *param)
{
int s = splbio();
for(int i=0;i<USBHALWS->numcb;i++)
{
int idx = (i+USBHALWS->nextcb) & (MAX_CALLBACKS-1);
if((USBHALWS->callbacks[idx].cbfunc == cbfunc) && (USBHALWS->callbacks[idx].param == param))
{
/* Do it the easy way */
USBHALWS->callbacks[idx].cbfunc = NULL;
splx(s);
return;
}
}
splx(s);
}
/*
* usbmodule.c routines:
*/
device_ptr_t register_bus(device_ptr_t bus)
{
device_ptr_t softc;
/* initialise device structure */
softc = malloc (usb_ca.ca_devsize);
if (softc == NULL) return NULL;
memset(softc,0,usb_ca.ca_devsize);
TAILQ_INSERT_TAIL (&(USBHALWS->allbuses), softc, dv_list);
hdprintf("adding bus %p using %p size %x\n", bus,softc,usb_ca.ca_devsize);
/* abuse the device structure a bit */
bus->dv_unit = softc->dv_unit = (USBHALWS->usbbus_no++);
/* set the flag to make it explore immediately */
softc->dv_cfdata = &(struct cfdata) { .cf_flags = 1 };;
strcpy (softc->dv_xname, "USBDriver");
(*usb_ca.ca_attach)(0, softc, bus);
return softc;
}
/*---------------------------------------------------------------------------*/
void deregister_bus (device_ptr_t bus)
{
hdprintf ("removing bus %p\n", bus);
(*usb_ca.ca_detach)(bus, 0);
hdprintf ("finished removing bus %p\n", bus);
TAILQ_REMOVE (&(USBHALWS->allbuses), (device_ptr_t) bus, dv_list);
free (bus);
}
/*---------------------------------------------------------------------------*/
struct device* get_softc (int unit)
{
struct device* dev;
TAILQ_FOREACH(dev, &(USBHALWS->allbuses), dv_list)
{
if (dev->dv_unit == ((unit >> 16) & 0xff))
return dev;
}
hdprintf ("couldn't find unit %x\n", unit);
return NULL;
}
/*---------------------------------------------------------------------------*/
extern void usb_discover (void*);
void discover_callback (void* sc)
{
struct usbd_bus* bus = sc;
struct device* dev;
hdprintf ("bus discover %p\n",bus);
TAILQ_FOREACH(dev, &USBHALWS->allbuses, dv_list)
{
/* XXX this is dodgy, because in the case where the OHCIDriver module
has removed its memory, 'bus' is no longer a valid pointer, and
could either cause an abort or accidentally contain a valid usbctl */
hdprintf("dev:%p uctl:%p \n",dev,bus->usbctl);
if (dev == (struct device*) bus->usbctl)
goto valid;
}
hdprintf ("bus %p has been removed\n",bus);
if(bus) bus->callbacks=0;
return;
valid:
/* This is a standard callx callback, so we want IRQs on */
splx(0);
hdprintf ("discovering %p\n",dev);
do {
usb_discover (bus->usbctl);
} while (--bus->callbacks);
hdprintf ("finished callbacks\n");
}
/*---------------------------------------------------------------------------*/
void usb_needs_explore_callback (void* h) {
struct usbd_bus* bus = h;
if (bus->callbacks>9) bus->callbacks=9;
if (bus->callbacks++ == 0)
{
hdprintf ("Adding explore callback on bus %p\n",h);
USBHAL_AddCallback (discover_callback, h);
}
else
hdprintf ("deferring callback on bus %p - %d callbacks queued\n",bus, bus->callbacks);
}
/*---------------------------------------------------------------------------*/
struct device* attach_hub (struct device* parent, void* aux)
{
struct device* softc;
struct usb_attach_arg* uaa = aux;
/* don't match generic */
if (uaa->usegeneric) return NULL;
hdprintf ("Trying match on usb hub\n");
/* First see if we match */
if ((*uhub_uhub_ca.ca_match) (0, 0, aux) == UMATCH_NONE)
{
hdprintf ("Failed to match\n");
return NULL;
}
/* If so, allocate memory for the device and attach ourselves. */
softc = malloc (uhub_uhub_ca.ca_devsize);
if (softc == 0) {
hdprintf ("Couldn't allocate memory for hub device\n");
return NULL;
}
memset (softc, 0, uhub_uhub_ca.ca_devsize);
strcpy (softc->dv_xname,"USBHub");
softc->dv_cfdata = (void*) 1; // hub
(*uhub_uhub_ca.ca_attach) (parent, softc, aux);
hdprintf ("Matched hub\n");
return softc;
}
/*---------------------------------------------------------------------------*/
int detach_hub (struct device* hub)
{
(*uhub_uhub_ca.ca_detach) (hub, 0);
free (hub);
return 0;
}
/*---------------------------------------------------------------------------*/
struct device* riscos_usb_attach
(
void* dev,
struct device* parent,
void* aux
) {
struct device* ret = attach_hub(parent,aux);
if(!ret)
ret = attach_keyboard(parent,aux);
return ret;
}
/*---------------------------------------------------------------------------*/
int config_detach (struct device* dev, int n)
{
hdprintf ("config detach %p, %d, type %d\n",
dev, n, (int) dev->dv_cfdata);
/* catch case of config_detach called from config_found above */
if (dev == (void*) 1)
{
return 0;
}
switch ((int) (dev->dv_cfdata))
{
case 1: return detach_hub (dev);
case 4: return detach_keyboard (dev);
}
// free (dev);
return 0;
}
/*---------------------------------------------------------------------------*/
void uhub_activate (void)
{}
/*---------------------------------------------------------------------------*/
void riscos_failed_device (void* p)
{
}
/*---------------------------------------------------------------------------*/
static void re_discover(void *param)
{
(void)param;
for (int i = 1; i < USBHALWS->usbbus_no; i++)
{
if (get_softc (i << 16) != NULL)
{
hdprintf("rediscover bus %d\n",i);
usbioctl (i << 16, USB_DISCOVER, 0, 0, 0);
}
}
callout_reset(USBHALWS->rediscover,500,re_discover,NULL);
}
/*
* port.c routines:
*/
extern uint64_t gettime (void);
uint64_t gettime (void)
{
uint32_t cs;
uint32_t ns_factor;
uint32_t max_count = HAL_CounterPeriod();
/* conversion to ns, assume counter is for 1 cs */
ns_factor = 10000000u / max_count;
cs = USBHALWS->monotonictime;
return (uint64_t) (max_count - HAL_CounterRead()) * ns_factor +
((uint64_t) cs) * 10000000 /* 1e7 */;
}
/*
* Callouts
*/
void
callout_init (struct callout* c,int ignored)
{
(void)ignored;
memset (c, 0, sizeof c);
}
void
callout_stop (struct callout *c) {
int s = splbio();
struct callout **c2 = &(USBHALWS->callouts);
while(*c2)
{
if(*c2 == c)
{
*c2 = c->c_next;
splx(s);
return;
}
c2 = &((*c2)->c_next);
}
splx(s);
}
void
callout_reset (struct callout *c, int i, void (*f)(void *), void *v) {
int s = splbio();
callout_stop(c);
if (i <= 0) i = 1;
c->c_arg = v;
c->c_func = f;
c->c_time = (((uint32_t)(i+9))/10u) + USBHALWS->monotonictime;
/* Find insertion pos */
struct callout **c2 = &(USBHALWS->callouts);
while((*c2) && ((*c2)->c_time < c->c_time))
c2 = &((*c2)->c_next);
c->c_next = *c2;
*c2 = c;
splx(s);
}
int tsleep (void* ident, int priority, const char* wmesg, int timo, int noblock)
{
int i;
int s = splbio();
uint64_t t0, t1, t2;
hdprintf(">ts %p\n",ident);
t1 = t0 = gettime();
t1 += ((uint64_t) timo) * 1000000;
for (i = 0; i < USBHALWS->nhandles && USBHALWS->t_handles[i] && USBHALWS->t_handles[i] != ident; ++i);
if (i == USBHALWS->nhandles) {
USBHALWS->nhandles = i + 1;
if (USBHALWS->nhandles >= MAX_TSLEEP_HANDLES)
{
panic ("run out of thread handles...");
}
}
USBHALWS->t_handles[i] = ident;
USBHALWS->t_locks[i] = 0;
/* wait until the lock is free */
/* TODO - May want to limit max wait to 5 seconds to ensure boot doesn't hang? */
splx(0);
if (timo) {
do {
triggercbs ();
t2 = gettime ();
}
while ((USBHALWS->t_locks[i] == 0) && (t2 < t1));
}
else
{
while (USBHALWS->t_locks[i] == 0)
{
triggercbs ();
}
}
splbio();
USBHALWS->t_handles[i] = 0;
hdprintf("<ts\n");
splx(s);
return 0;
}
int wakeup (void* ident) {
int i;
hdprintf("wu %p\n",ident);
/* Find the index of the handle passed */
for (i = 0; i < USBHALWS->nhandles && USBHALWS->t_handles[i] != ident; ++i);
/* unlock it */
if (USBHALWS->t_handles[i] == ident)
{
USBHALWS->t_locks[i] = 1;
USBHALWS->t_handles[i] =NULL; /* TODO - Could cause handle to be reused before tsleep is able to wake up? */
}
return 0;
}
void usbd_devinfo_vp(usbd_device_handle dev, char* v, size_t vl, char* p, size_t pl, int usedev)
{
#ifdef DEBUG_HAL
usb_device_descriptor_t *udd = &dev->ddesc;
snprintf(v, vl, "Vendor ID %04X", UGETW(udd->idVendor));
snprintf(p, pl, "Product ID %04X", UGETW(udd->idProduct));
#else
*v = *p = 0;
#endif
}
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* Changed 17.02.2010 TM DeviceFSCallDevice_TransferInfo and notation of padded bytes. */
#include "usbmodhead.h" #include "usbmodhead.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
...@@ -66,8 +67,11 @@ ...@@ -66,8 +67,11 @@
#define DeviceFSCallDevice_GetHandles 0x80000003 #define DeviceFSCallDevice_GetHandles 0x80000003
#define DeviceFSCallDevice_GetLocation 0x80000004 #define DeviceFSCallDevice_GetLocation 0x80000004
#define DeviceFSCallDevice_ClearStall 0x80000005 #define DeviceFSCallDevice_ClearStall 0x80000005
#define DeviceFSCallDevice_TransferInfo 0x80000006
#define DeviceFSCallDevice_GetHandles2 0x80000007
#define DeviceFSCallDevice_GetSetOptions 0x80000008
/* Was this used by the Castle podule at some time? - JL
#define DeviceFSCallDevice_GetConfig 0x80000001 #define DeviceFSCallDevice_GetConfig 0x80000001
#define DeviceFSCallDevice_SetConfig 0x80000002 #define DeviceFSCallDevice_SetConfig 0x80000002
#define DeviceFSCallDevice_GetAltInterface 0x80000003 #define DeviceFSCallDevice_GetAltInterface 0x80000003
...@@ -78,6 +82,7 @@ ...@@ -78,6 +82,7 @@
#define DeviceFSCallDevice_GetInterfaceDesc 0x80000008 #define DeviceFSCallDevice_GetInterfaceDesc 0x80000008
#define DeviceFSCallDevice_GetEndpointDesc 0x80000009 #define DeviceFSCallDevice_GetEndpointDesc 0x80000009
#define DeviceFSCallDevice_GetString 0x8000000a #define DeviceFSCallDevice_GetString 0x8000000a
*/
struct ugen_softc; struct ugen_softc;
...@@ -114,6 +119,11 @@ struct devstream { ...@@ -114,6 +119,11 @@ struct devstream {
int bandwidth; /* isochronous bandwidth */ int bandwidth; /* isochronous bandwidth */
int residue; int residue;
int dying; int dying;
int padded_bytes; /* only greater 0 in case of short packages */
int flags; /* Flags altered by the GetSetOptions call */
#define FLAG_NOPAD 1
#define FLAG_SHORT 2
#define FLAG_VALIDMASK 3 /* Which bits can be modified */
struct isoc_buffer * isoc; struct isoc_buffer * isoc;
}; };
...@@ -335,9 +345,9 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) ...@@ -335,9 +345,9 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw)
#else #else
/* if standalone then this happens in the service call handler */ /* if standalone then this happens in the service call handler */
e = messages_update (&mod_messages); e = messages_update (&mod_messages);
if (e) goto error0; if (e) return e;
e = messages_update (&usbdev_messages); e = messages_update (&usbdev_messages);
if (e) goto error1; if (e) goto error;
#endif #endif
#ifdef USB_DEBUG #ifdef USB_DEBUG
...@@ -358,12 +368,10 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) ...@@ -358,12 +368,10 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw)
return 0; return 0;
#ifndef STANDALONE #ifndef STANDALONE
error1: error:
_swix (MessageTrans_CloseFile, _IN(0), &mod_messages); _swix (MessageTrans_CloseFile, _IN(0), &mod_messages);
error0:
_swix (ResourceFS_DeregisterFiles, _IN (0), resource_files ());
#endif
return e; return e;
#endif
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
...@@ -439,7 +447,7 @@ _kernel_oserror* RegisterNewDevice(struct ugen_softc * softc,int no) ...@@ -439,7 +447,7 @@ _kernel_oserror* RegisterNewDevice(struct ugen_softc * softc,int no)
driver_entry, driver_entry,
softc, softc,
private_word, private_word,
"endpoint/Ninterface/Nalternate/Nreport/Ncontrol,isochronous,bulk,interrupt/Susbtimeout/Nsize/N", "endpoint/Ninterface/Nalternate/Nreport/Ncontrol,isochronous,bulk,interrupt/Susbtimeout/Nsize/Nnopad/Sshort/S",
#ifdef DEVICEFSISBROKEN #ifdef DEVICEFSISBROKEN
INT_MAX, // should be -1, but that doesn't seem to work INT_MAX, // should be -1, but that doesn't seem to work
INT_MAX, INT_MAX,
...@@ -1060,11 +1068,11 @@ static void deregister_bus (device_ptr_t bus) ...@@ -1060,11 +1068,11 @@ static void deregister_bus (device_ptr_t bus)
_kernel_oserror *module_swis(int swi_offset, _kernel_swi_regs *r, void *pw) _kernel_oserror *module_swis(int swi_offset, _kernel_swi_regs *r, void *pw)
{ {
switch (swi_offset) { switch (swi_offset) {
// case USBDriver_Register:
// break;
// case USBDriver_DeRegister:
// break;
case USBDriver_RegisterBus - USBDriver_00: case USBDriver_RegisterBus - USBDriver_00:
/* R1 now contains internal API version number
This check should be made more permissive when appropriate */
if(r->r[1] != RISCOS_USBDRIVER_API_VERSION)
return (_kernel_oserror *)"\0\0\0\0Incompatible USBDriver version";
r->r[0] = (int) register_bus ((device_ptr_t) r->r[0]); r->r[0] = (int) register_bus ((device_ptr_t) r->r[0]);
break; break;
...@@ -1088,6 +1096,9 @@ _kernel_oserror *module_swis(int swi_offset, _kernel_swi_regs *r, void *pw) ...@@ -1088,6 +1096,9 @@ _kernel_oserror *module_swis(int swi_offset, _kernel_swi_regs *r, void *pw)
usb_schedsoftintr (*(void**) (bus + 1)); usb_schedsoftintr (*(void**) (bus + 1));
} }
break; break;
case USBDriver_Version - USBDriver_00:
r->r[0] = Module_VersionNumber;
break;
default: default:
return error_BAD_SWI; return error_BAD_SWI;
} }
...@@ -1334,7 +1345,6 @@ int detach_hub (struct device* hub) ...@@ -1334,7 +1345,6 @@ int detach_hub (struct device* hub)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#ifdef OBSOLETE_SERVICE_CALLS #ifdef OBSOLETE_SERVICE_CALLS
/* returns non-zero if not handed */ /* returns non-zero if not handed */
char* service_call (usbd_device_handle dev, int unit, int link) char* service_call (usbd_device_handle dev, int unit, int link)
...@@ -1718,6 +1728,8 @@ int detach_device (struct device* dev, int d) ...@@ -1718,6 +1728,8 @@ int detach_device (struct device* dev, int d)
_swix (DeviceFS_Deregister, _IN(0), udev->sc_devfs); _swix (DeviceFS_Deregister, _IN(0), udev->sc_devfs);
dprintf (("", "deregistered driver %p\n", udev->sc_devfs)); dprintf (("", "deregistered driver %p\n", udev->sc_devfs));
} }
/* Cancel any pending callbacks attached to this device */
callx_remove_callback(announce_device,udev);
free (udev); free (udev);
return 0; return 0;
} }
...@@ -1953,6 +1965,8 @@ typedef struct device_valid { ...@@ -1953,6 +1965,8 @@ typedef struct device_valid {
uint32_t ep_type; uint32_t ep_type;
uint32_t timeout; uint32_t timeout;
uint32_t size; uint32_t size;
uint32_t nopad;
uint32_t shortflag;
} device_valid; } device_valid;
static void find_interface_and_endpoint static void find_interface_and_endpoint
...@@ -2073,7 +2087,10 @@ static _kernel_oserror* device_initialise ...@@ -2073,7 +2087,10 @@ static _kernel_oserror* device_initialise
str->report = valid->report; str->report = valid->report;
/* usb timeout, used for transfers */ /* usb timeout, used for transfers */
str->timeout = valid->timeout; str->timeout = (valid->timeout==0xdeaddead?0:valid->timeout);
/* New flags to work around deficencies in the DeviceFS interface */
str->flags = (valid->nopad?0:FLAG_NOPAD)|(valid->shortflag?0:FLAG_SHORT);
/* see if an interface was specified, if not then look for the interface /* see if an interface was specified, if not then look for the interface
with the endpoint specified */ with the endpoint specified */
...@@ -2301,7 +2318,7 @@ void start_write (struct devstream* str) ...@@ -2301,7 +2318,7 @@ void start_write (struct devstream* str)
{ {
#ifdef DMA_FROM_BUFFER #ifdef DMA_FROM_BUFFER
usbd_setup_xfer(str->xfer, str->pipe, str, usbd_setup_xfer(str->xfer, str->pipe, str,
(void*) r.r[2], r.r[3], USBD_NO_COPY, 500, write_cb); (void*) r.r[2], r.r[3], USBD_NO_COPY | (str->flags & FLAG_SHORT?USBD_FORCE_SHORT_XFER:0), 500, write_cb);
#else #else
usbd_setup_xfer( usbd_setup_xfer(
str->xfer, str->xfer,
...@@ -2309,7 +2326,7 @@ void start_write (struct devstream* str) ...@@ -2309,7 +2326,7 @@ void start_write (struct devstream* str)
str, str,
(void*) str->buffer_id, (void*) str->buffer_id,
r.r[2], r.r[2],
0, (str->flags & FLAG_SHORT?USBD_FORCE_SHORT_XFER:0),
str->timeout, str->timeout,
write_cb); write_cb);
...@@ -2357,47 +2374,39 @@ static void read_cb(usbd_xfer_handle xfer, usbd_private_handle priv, ...@@ -2357,47 +2374,39 @@ static void read_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
return; return;
} }
if((str->flags & FLAG_NOPAD) || (str->count == str->totalcount))
{
/* Whatever happened, we're finished */
return;
}
/* only start another transfer if we haven't finished the transfer and /* only start another transfer if we haven't finished the transfer and
this is not a interrupt endpoint (the BSD framework restarts this is not a interrupt endpoint (the BSD framework restarts
repeating transfers) */ repeating transfers) */
/* if we've got a number of bytes including a part packet, then /* if we've got a number of bytes including a part packet, then
transfer must have ended.. else.. try more */ transfer must have ended.. else.. try more */
// if(!xfer->pipe->repeat) if (xfer->actlen % UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize))
// {
// if(xfer->actlen < xfer->length)
// {
// char zero[ UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize)];
// memset (zero, 0, sizeof zero);
// /* fill up the rest of the request with garbage! */
// _kernel_swi_regs r;
// r.r[0] = BM_InsertBlock;
// r.r[1] = (int) str->buffer_id;
// r.r[2] = (int) zero;
// r.r[3] = str->totalcount - str->count;
// dprintf (("", "Fill insert %x bytes\n",r.r[3]));
// CallBufMan (&r);
// }
// else if (str->count != str->totalcount)
// {
// dprintf (("", "Starting read from callback\n"));
// start_read (str);
// }
// }
if ((xfer->actlen % UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize))
&& str->count != str->totalcount)
{ {
/* required due to DeviceFS concept. */
char zero[ UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize)]; char zero[ UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize)];
/* Note difference for later correction by application */
int remain = str->padded_bytes = str->totalcount - str->count;
memset (zero, 0, sizeof zero); memset (zero, 0, sizeof zero);
/* fill up the rest of the request with garbage! */ /* fill up the rest of the request with garbage! */
_kernel_swi_regs r; _kernel_swi_regs r;
r.r[0] = BM_InsertBlock; r.r[0] = BM_InsertBlock;
r.r[1] = (int) str->buffer_id; r.r[1] = (int) str->buffer_id;
r.r[2] = (int) zero; while(remain > 0)
r.r[3] = str->totalcount - str->count; {
CallBufMan (&r); r.r[2] = (int) zero;
r.r[3] = min(remain,UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize));
remain -= r.r[3];
CallBufMan (&r);
if(r.r[3])
break; /* Buffer was full - what do we do here? Try and insert the extra padding as more space becomes available? For now, just do what the old code did and give up */
}
} }
else if (str->count != str->totalcount && !xfer->pipe->repeat) else if (!xfer->pipe->repeat)
{ {
dprintf (("", "Starting read from callback\n")); dprintf (("", "Starting read from callback\n"));
start_read (str); start_read (str);
...@@ -2718,7 +2727,9 @@ _kernel_oserror* get_handles ...@@ -2718,7 +2727,9 @@ _kernel_oserror* get_handles
struct ugen_softc* udev, struct ugen_softc* udev,
int fs, int fs,
int* buf, int* buf,
int* dvfs int* dvfs,
struct devstream ** str,
devicefs_device** sc_devfs
) )
{ {
int devfs; int devfs;
...@@ -2732,6 +2743,8 @@ _kernel_oserror* get_handles ...@@ -2732,6 +2743,8 @@ _kernel_oserror* get_handles
{ {
if (dvfs) *dvfs = devfs; if (dvfs) *dvfs = devfs;
if (buf) *buf = udev->str[i]->buffer; if (buf) *buf = udev->str[i]->buffer;
if (str) *str=udev->str[i];
if (sc_devfs) *sc_devfs=udev->sc_devfs;
return NULL; return NULL;
} }
} }
...@@ -2798,6 +2811,53 @@ _kernel_oserror* clear_endpoint_stall ...@@ -2798,6 +2811,53 @@ _kernel_oserror* clear_endpoint_stall
return uerror (E_NoStream); return uerror (E_NoStream);
} }
_kernel_oserror* get_transfer_info
(
struct devstream* str,
int* count,
int* totalcount,
int* status,
int* padded_buffer_bytes
)
{
if (!str) {
return uerror (E_NoStream);
}
*count=str->count;
*totalcount=str->totalcount;
switch(str->xfer->status) {
case USBD_NORMAL_COMPLETION: {
*status=1;
}
break;
case USBD_IN_PROGRESS: {
*status=0;
}
break;
default: {
*status=-1;
}
}
*padded_buffer_bytes=str->padded_bytes;
return NULL;
}
_kernel_oserror* getset_options
(
struct devstream* str,
int* eor,
int* and
)
{
if (!str) {
return uerror (E_NoStream);
}
int new = ((str->flags & *and) ^ *eor) & FLAG_VALIDMASK;
*eor = str->flags;
str->flags = *and = new;
return NULL;
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
_kernel_oserror* driver (_kernel_swi_regs* r, void* pw) _kernel_oserror* driver (_kernel_swi_regs* r, void* pw)
...@@ -2848,6 +2908,7 @@ _kernel_oserror* driver (_kernel_swi_regs* r, void* pw) ...@@ -2848,6 +2908,7 @@ _kernel_oserror* driver (_kernel_swi_regs* r, void* pw)
break; break;
case DeviceFSCallDevice_RxWakeUp: case DeviceFSCallDevice_RxWakeUp:
str->count = 0; str->count = 0;
str->padded_bytes=0;
/* total length has always been passed in R3, although not documented */ /* total length has always been passed in R3, although not documented */
str->totalcount = r->r[3]; str->totalcount = r->r[3];
dprintf (("main", "wakeup read, resetting count to %d, totalcount to %d\n", dprintf (("main", "wakeup read, resetting count to %d, totalcount to %d\n",
...@@ -2963,7 +3024,7 @@ _kernel_oserror* driver (_kernel_swi_regs* r, void* pw) ...@@ -2963,7 +3024,7 @@ _kernel_oserror* driver (_kernel_swi_regs* r, void* pw)
return get_buffer_space (udev, r->r[2], r->r + 3, r->r + 4); return get_buffer_space (udev, r->r[2], r->r + 3, r->r + 4);
break; break;
case DeviceFSCallDevice_GetHandles: case DeviceFSCallDevice_GetHandles:
return get_handles (udev, r->r[2], r->r + 3, r->r + 4); return get_handles (udev, r->r[2], r->r + 3, r->r + 4, NULL, NULL);
break; break;
case DeviceFSCallDevice_GetLocation: case DeviceFSCallDevice_GetLocation:
return get_location (udev, (char*) r->r[3]); return get_location (udev, (char*) r->r[3]);
...@@ -2971,10 +3032,18 @@ _kernel_oserror* driver (_kernel_swi_regs* r, void* pw) ...@@ -2971,10 +3032,18 @@ _kernel_oserror* driver (_kernel_swi_regs* r, void* pw)
case DeviceFSCallDevice_ClearStall: case DeviceFSCallDevice_ClearStall:
return clear_endpoint_stall (udev, r->r[2]); return clear_endpoint_stall (udev, r->r[2]);
break; break;
case DeviceFSCallDevice_TransferInfo:
return get_transfer_info (str, r->r + 0, r->r + 1, r->r + 3, r->r + 4);
break;
case DeviceFSCallDevice_GetHandles2:
return get_handles (udev, r->r[2], r->r + 3, r->r + 4, (struct devstream **) ((int *) r->r + 5), (devicefs_device**) ((int *) r->r + 6));
break;
case DeviceFSCallDevice_GetSetOptions:
return getset_options (str, r->r + 3, r->r + 4);
break;
} }
return NULL; return NULL;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
...@@ -12,6 +12,37 @@ ...@@ -12,6 +12,37 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Lennart Augustsson (lennart@augustsson.net) at
* Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* mouse interface */ /* mouse interface */
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
...@@ -39,556 +70,728 @@ ...@@ -39,556 +70,728 @@
#include <dev/usb/usb_quirks.h> #include <dev/usb/usb_quirks.h>
#include <dev/usb/hid.h> #include <dev/usb/hid.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
#include "usbmouse.h" #include "usbmouse.h"
#include "wimplib.h" #include "wimplib.h"
#ifdef __riscos
#define printf logprintf
#define aprint_verbose logprintf
#define aprint_normal logprintf
#define aprint_error logprintf
#endif
#ifdef USB_DEBUG
#define DPRINTF(x) if (umsdebug) logprintf x
#define DPRINTFN(n,x) if (umsdebug>(n)) logprintf x
int umsdebug = 10;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
#endif
#ifdef __riscos
#define UMS_BUT(i) (i)
#else
#define UMS_BUT(i) ((i) == 1 || (i) == 2 ? 3 - (i) : i)
#endif
extern void ums_enable (void*); extern void ums_enable (void*);
extern void ums_disable (void*); extern void ums_disable (void*);
extern int umsdebug = 0;
extern struct messages mod_messages; extern struct messages mod_messages;
extern struct cfattach ums_ca; extern struct cfattach ums_ca;
static int relx = 0, rely = 0, relz = 0, morebuttons = 0; static int relx = 0, rely = 0, relz = 0, relw = 0, morebuttons = 0;
static bool enabled = false; static bool enabled = false;
#define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
#define MOUSE_FLAGS (HIO_RELATIVE)
void ums_intr (usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status); void ums_intr (usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status);
static int uhidev_maxrepid(void *buf, int len); static int uhidev_maxrepid(void *buf, int len);
#define MAX_BUTTONS 31 /* must not exceed size of sc_buttons */
struct ums_softc { struct ums_softc {
USBBASEDEVICE sc_dev; /* base device */ USBBASEDEVICE sc_dev; /* base device */
usbd_device_handle sc_udev; usbd_device_handle sc_udev;
usbd_interface_handle sc_iface; /* interface */ usbd_interface_handle sc_iface; /* interface */
usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
int sc_ep_addr; int sc_ep_addr;
u_char *sc_ibuf; u_char *sc_ibuf;
u_int8_t sc_iid; u_int8_t sc_iid;
int sc_isize; int sc_isize;
struct hid_location sc_loc_x, sc_loc_y, sc_loc_z; struct hid_location sc_loc_x, sc_loc_y, sc_loc_z, sc_loc_w;
struct hid_location *sc_loc_btn; struct hid_location *sc_loc_btn;
int sc_enabled; int sc_enabled;
int flags; /* device configuration */ int flags; /* device configuration */
#define UMS_Z 0x01 /* z direction available */ #define UMS_Z 0x01 /* z direction available */
#define UMS_SPUR_BUT_UP 0x02 /* spurious button up events */ #define UMS_SPUR_BUT_UP 0x02 /* spurious button up events */
#define UMS_REVZ 0x04 /* Z-axis is reversed */ #define UMS_REVZ 0x04 /* Z-axis is reversed */
#define UMS_W 0x08 /* w direction/tilt available */
#define UMS_ABS 0x10 /* absolute position, touchpanel */
#define UMS_NO_REPID 0x20 /* broken device that doesn't prefix the report ID */
int nbuttons; int nbuttons;
#define MAX_BUTTONS 31 /* chosen because sc_buttons is u_int32_t */
u_int32_t sc_buttons; /* mouse button status */ u_int32_t sc_buttons; /* mouse button status */
char sc_dying; char sc_dying;
/* list of ukbd softcs */ /* list of ukbd softcs */
TAILQ_ENTRY(ums_softc) link_ms; TAILQ_ENTRY(ums_softc) link_ms;
}; };
#define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
TAILQ_HEAD(umslist, ums_softc) allums = TAILQ_HEAD_INITIALIZER(allums); TAILQ_HEAD(umslist, ums_softc) allums = TAILQ_HEAD_INITIALIZER(allums);
extern void remove_all_mice (void) extern void remove_all_mice (void)
{ {
struct ums_softc* sc; struct ums_softc* sc;
TAILQ_FOREACH(sc, &allums, link_ms) TAILQ_FOREACH(sc, &allums, link_ms)
{ {
detach_mouse ((struct device*) sc); detach_mouse ((struct device*) sc);
} }
} }
static int match_mouse (struct usb_attach_arg *uaa) static int match_mouse (struct usb_attach_arg *uaa)
{ {
usb_interface_descriptor_t *id; usb_interface_descriptor_t *id;
int size, ret, nrepid, repid; int size, ret, nrepid, repid;
void *desc; void *desc;
usbd_status err; usbd_status err;
dprintf (("", "Trying ums attach\n")); dprintf (("", "Trying ums attach\n"));
if (uaa->iface == NULL) if (uaa->iface == NULL)
return (UMATCH_NONE); return (UMATCH_NONE);
id = usbd_get_interface_descriptor(uaa->iface); id = usbd_get_interface_descriptor(uaa->iface);
if (id == NULL || id->bInterfaceClass != UICLASS_HID) if (id == NULL || id->bInterfaceClass != UICLASS_HID)
{ {
dprintf (("", "failed class match: id == %p\n", id)); dprintf (("", "failed class match: id == %p\n", id));
return (UMATCH_NONE); return (UMATCH_NONE);
} }
err = usbd_read_report_desc(uaa->iface, &desc, &size, M_USBDEV); /*
if (err) * Some (older) Griffin PowerMate knobs may masquerade as a
{ * mouse, avoid treating them as such, they have only one axis.
dprintf (("", "failed to get report\n")); */
return (UMATCH_NONE); if (uaa->vendor == USB_VENDOR_GRIFFIN &&
} uaa->product == USB_PRODUCT_GRIFFIN_POWERMATE)
return (UMATCH_NONE);
nrepid = uhidev_maxrepid(desc, size);
err = usbd_read_report_desc(uaa->iface, &desc, &size, M_USBDEV);
if (err)
ret = UMATCH_NONE; {
for (repid = 0; repid <= nrepid; repid++) dprintf (("", "failed to get report\n"));
{ return (UMATCH_NONE);
if (hid_is_collection(desc, size, repid, }
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
{ nrepid = uhidev_maxrepid(desc, size);
ret = UMATCH_IFACECLASS;
}
} ret = UMATCH_NONE;
for (repid = 0; repid <= nrepid; repid++)
{
free(desc); if ((hid_is_collection(desc, size, repid,
dprintf (("", "ums attach returning: %d\n", ret)); HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
return (ret); || (hid_is_collection(desc, size, repid,
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_POINTER))))
{
ret = UMATCH_IFACECLASS;
}
}
free(desc);
dprintf (("", "ums attach returning: %d\n", ret));
return (ret);
} }
static void do_attach_mouse (struct ums_softc* sc, struct usb_attach_arg *uaa) static void do_attach_mouse (struct ums_softc* sc, struct usb_attach_arg *uaa)
{ {
usbd_interface_handle iface = uaa->iface; usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id; usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed; usb_endpoint_descriptor_t *ed;
int size; int size;
void *desc; void *desc;
usbd_status err; usbd_status err;
char devinfo[1024]; #ifdef USB_DEBUG
u_int32_t flags, quirks; char devinfo[1024];
int i, wheel, repid, nrepid; #endif
struct hid_location loc_btn; u_int32_t flags, quirks;
int i, repid, nrepid;
sc->sc_udev = uaa->device; int hl;
sc->sc_iface = iface; struct hid_location *zloc;
id = usbd_get_interface_descriptor(iface); struct hid_location loc_btn;
usbd_devinfo(uaa->device, 0, devinfo, sizeof devinfo);
USB_ATTACH_SETUP; sc->sc_udev = uaa->device;
dprintf(("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), sc->sc_iface = iface;
devinfo, id->bInterfaceClass, id->bInterfaceSubClass)); id = usbd_get_interface_descriptor(iface);
ed = usbd_interface2endpoint_descriptor(iface, 0); #ifdef USB_DEBUG
if (ed == NULL) { usbd_devinfo(uaa->device, 0, devinfo, sizeof devinfo);
logprintf("%s: could not read endpoint descriptor\n", USB_ATTACH_SETUP;
USBDEVNAME(sc->sc_dev)); dprintf(("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
USB_ATTACH_ERROR_RETURN; devinfo, id->bInterfaceClass, id->bInterfaceSubClass));
} #endif
ed = usbd_interface2endpoint_descriptor(iface, 0);
dprintf(("", "ums_attach: bLength=%d bDescriptorType=%d " if (ed == NULL) {
"bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" logprintf("%s: could not read endpoint descriptor\n",
" bInterval=%d\n", USBDEVNAME(sc->sc_dev));
ed->bLength, ed->bDescriptorType, USB_ATTACH_ERROR_RETURN;
ed->bEndpointAddress & UE_ADDR, }
UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",
ed->bmAttributes & UE_XFERTYPE, dprintf(("", "ums_attach: bLength=%d bDescriptorType=%d "
UGETW(ed->wMaxPacketSize), ed->bInterval)); "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
" bInterval=%d\n",
if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || ed->bLength, ed->bDescriptorType,
(ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { ed->bEndpointAddress & UE_ADDR,
logprintf("%s: unexpected endpoint\n", UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",
USBDEVNAME(sc->sc_dev)); ed->bmAttributes & UE_XFERTYPE,
USB_ATTACH_ERROR_RETURN; UGETW(ed->wMaxPacketSize), ed->bInterval));
}
if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN ||
quirks = usbd_get_quirks(uaa->device)->uq_flags; (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
if (quirks & UQ_MS_REVZ) logprintf("%s: unexpected endpoint\n",
sc->flags |= UMS_REVZ; USBDEVNAME(sc->sc_dev));
if (quirks & UQ_SPUR_BUT_UP) USB_ATTACH_ERROR_RETURN;
sc->flags |= UMS_SPUR_BUT_UP; }
err = usbd_read_report_desc(uaa->iface, &desc, &size, M_USBDEV); quirks = usbd_get_quirks(uaa->device)->uq_flags;
if (err) if (quirks & UQ_MS_REVZ)
USB_ATTACH_ERROR_RETURN; sc->flags |= UMS_REVZ;
if (quirks & UQ_SPUR_BUT_UP)
nrepid = uhidev_maxrepid(desc, size); sc->flags |= UMS_SPUR_BUT_UP;
for (repid = 0; repid <= nrepid; repid++) err = usbd_read_report_desc(uaa->iface, &desc, &size, M_USBDEV);
{ if (err)
if (hid_is_collection(desc, size, repid, USB_ATTACH_ERROR_RETURN;
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
{ nrepid = uhidev_maxrepid(desc, size);
sc->sc_iid = repid;
} for (repid = 0; repid <= nrepid; repid++)
} {
if ((hid_is_collection(desc, size, repid,
if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
sc->sc_iid, hid_input, &sc->sc_loc_x, &flags)) { || (hid_is_collection(desc, size, repid,
logprintf("%s: mouse has no X report\n", USBDEVNAME(sc->sc_dev)); HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_POINTER))))
USB_ATTACH_ERROR_RETURN; {
} sc->sc_iid = repid;
if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { }
logprintf("%s: X report 0x%04x not supported\n", }
USBDEVNAME(sc->sc_dev), flags);
USB_ATTACH_ERROR_RETURN; if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
} sc->sc_iid, hid_input, &sc->sc_loc_x, &flags)) {
aprint_error("\n%s: mouse has no X report\n",
if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), USBDEVNAME(sc->sc_dev));
sc->sc_iid, hid_input, &sc->sc_loc_y, &flags)) { USB_ATTACH_ERROR_RETURN;
logprintf("%s: mouse has no Y report\n", USBDEVNAME(sc->sc_dev)); }
USB_ATTACH_ERROR_RETURN; switch (flags & MOUSE_FLAGS_MASK) {
} case 0:
if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { sc->flags |= UMS_ABS;
logprintf("%s: Y report 0x%04x not supported\n", break;
USBDEVNAME(sc->sc_dev), flags); case HIO_RELATIVE:
USB_ATTACH_ERROR_RETURN; break;
} default:
aprint_error("\n%s: X report 0x%04x not supported\n",
/* Try to guess the Z activator: first check Z, then WHEEL. */ USBDEVNAME(sc->sc_dev), flags);
wheel = 0; USB_ATTACH_ERROR_RETURN;
if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), }
sc->sc_iid, hid_input, &sc->sc_loc_z, &flags) ||
(wheel = hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
HUG_WHEEL), sc->sc_iid, hid_input, &sc->sc_loc_y, &flags)) {
sc->sc_iid, hid_input, &sc->sc_loc_z, &flags)) != 0) { aprint_error("\n%s: mouse has no Y report\n",
if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { USBDEVNAME(sc->sc_dev));
sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */ USB_ATTACH_ERROR_RETURN;
} else { }
sc->flags |= UMS_Z; switch (flags & MOUSE_FLAGS_MASK) {
/* Wheels need the Z axis reversed. */ case 0:
if (wheel) sc->flags |= UMS_ABS;
sc->flags ^= UMS_REVZ; break;
} case HIO_RELATIVE:
} break;
default:
/* figure out the number of buttons */ aprint_error("\n%s: Y report 0x%04x not supported\n",
for (i = 1; i <= MAX_BUTTONS; i++) USBDEVNAME(sc->sc_dev), flags);
if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), USB_ATTACH_ERROR_RETURN;
sc->sc_iid, hid_input, &loc_btn, 0)) }
break;
sc->nbuttons = i - 1; /* Try the wheel first as the Z activator since it's tradition. */
sc->sc_loc_btn = malloc(sizeof(struct hid_location)*sc->nbuttons); hl = hid_locate(desc,
if (!sc->sc_loc_btn) { size,
logprintf("%s: no memory\n", USBDEVNAME(sc->sc_dev)); HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
USB_ATTACH_ERROR_RETURN; sc->sc_iid,
} hid_input,
&sc->sc_loc_z,
dprintf(("", "%s: %d buttons%s\n", USBDEVNAME(sc->sc_dev), &flags);
sc->nbuttons, sc->flags & UMS_Z ? " and Z dir." : ""));
zloc = &sc->sc_loc_z;
for (i = 1; i <= sc->nbuttons; i++) if (hl) {
hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), if ((flags & MOUSE_FLAGS_MASK) != HIO_RELATIVE) {
sc->sc_iid, hid_input, &sc->sc_loc_btn[i-1], 0); aprint_verbose("\n%s: Wheel report 0x%04x not "
"supported\n", USBDEVNAME(sc->sc_dev),
sc->sc_isize = hid_report_size(desc, size, hid_input, sc->sc_iid); flags);
sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
sc->sc_isize += (nrepid != 0); } else {
sc->sc_ibuf = malloc(sc->sc_isize); sc->flags |= UMS_Z;
if (sc->sc_ibuf == NULL) { /* Wheels need the Z axis reversed. */
logprintf("%s: no memory\n", USBDEVNAME(sc->sc_dev)); sc->flags ^= UMS_REVZ;
free(sc->sc_loc_btn); /* Put Z on the W coordinate */
USB_ATTACH_ERROR_RETURN; zloc = &sc->sc_loc_w;
} }
}
sc->sc_ep_addr = ed->bEndpointAddress;
free(desc); hl = hid_locate(desc,
size,
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
sc->sc_iid,
hid_input,
zloc,
&flags);
/*
* The horizontal component of the scrollball can also be given by
* Application Control Pan in the Consumer page, so if we didnt see
* any Z then check that.
*/
if (!hl) {
hl = hid_locate(desc,
size,
HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN),
sc->sc_iid,
hid_input,
zloc,
&flags);
}
if (hl) {
if ((flags & MOUSE_FLAGS_MASK) != HIO_RELATIVE) {
aprint_verbose("\n%s: Z report 0x%04x not supported\n",
USBDEVNAME(sc->sc_dev), flags);
zloc->size = 0; /* Bad Z coord, ignore it */
} else {
if (sc->flags & UMS_Z)
sc->flags |= UMS_W;
else
sc->flags |= UMS_Z;
}
}
/*
* The Microsoft Wireless Laser Mouse 6000 v2.0 reports a bad
* position for the wheel and wheel tilt controls -- should be
* in bytes 3 & 4 of the report. Fix this if necessary.
*/
if (uaa->vendor == USB_VENDOR_MICROSOFT &&
(uaa->product == USB_PRODUCT_MICROSOFT_24GHZ_XCVR10 ||
uaa->product == USB_PRODUCT_MICROSOFT_24GHZ_XCVR20)) {
if ((sc->flags & UMS_Z) && sc->sc_loc_z.pos == 0)
sc->sc_loc_z.pos = 24;
if ((sc->flags & UMS_W) && sc->sc_loc_w.pos == 0)
sc->sc_loc_w.pos = sc->sc_loc_z.pos + 8;
}
/* figure out the number of buttons */
for (i = 1; i <= MAX_BUTTONS; i++)
if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
sc->sc_iid, hid_input, &loc_btn, 0))
break;
sc->nbuttons = i - 1;
sc->sc_loc_btn = malloc(sizeof(struct hid_location)*sc->nbuttons);
if (!sc->sc_loc_btn) {
logprintf("%s: no memory\n", USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
aprint_normal(": %d button%s%s%s%s\n",
sc->nbuttons, sc->nbuttons == 1 ? "" : "s",
sc->flags & UMS_W ? ", W" : "",
sc->flags & UMS_Z ? " and Z dir" : "",
sc->flags & UMS_W ? "s" : "");
for (i = 1; i <= sc->nbuttons; i++)
hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
sc->sc_iid, hid_input,
&sc->sc_loc_btn[i-1], 0);
sc->sc_isize = hid_report_size(desc, size, hid_input, sc->sc_iid);
sc->sc_isize += (nrepid != 0);
sc->sc_ibuf = malloc(sc->sc_isize);
if (sc->sc_ibuf == NULL) {
logprintf("%s: no memory\n", USBDEVNAME(sc->sc_dev));
free(sc->sc_loc_btn);
USB_ATTACH_ERROR_RETURN;
}
sc->sc_ep_addr = ed->bEndpointAddress;
free(desc);
/*
* Deal with the broken behaviour of the touchpad of the TouchBook
* keyboard. Despite sending out a report descriptor containing
* multiple report IDs, the device fails to prepend the report ID to
* the reports it sends out for touchpad events. Furthermore the device
* refuses to switch to the Boot report protocol, for which the data it
* sends would actually be valid. So just flag that it's broken and
* that we shouldn't bother looking for a report ID.
*/
if((uaa->vendor == USB_VENDOR_ALWAYSINNOVATING) &&
(uaa->product == USB_PRODUCT_ALWAYSINNOVATING_USBKBDTPAD))
sc->flags |= UMS_NO_REPID;
#ifdef USB_DEBUG #ifdef USB_DEBUG
dprintf(("", "ums_attach: sc=%p\n", sc)); DPRINTF(("ums_attach: sc=%p flags=%x\n", sc, sc->flags));
dprintf(("", "ums_attach: X\t%d/%d\n", DPRINTF(("ums_attach: X\t%d/%d\n",
sc->sc_loc_x.pos, sc->sc_loc_x.size)); sc->sc_loc_x.pos, sc->sc_loc_x.size));
dprintf(("", "ums_attach: Y\t%d/%d\n", DPRINTF(("ums_attach: Y\t%d/%d\n",
sc->sc_loc_x.pos, sc->sc_loc_x.size)); sc->sc_loc_y.pos, sc->sc_loc_y.size));
if (sc->flags & UMS_Z) if (sc->flags & UMS_Z)
dprintf(("", "ums_attach: Z\t%d/%d\n", DPRINTF(("ums_attach: Z\t%d/%d\n",
sc->sc_loc_z.pos, sc->sc_loc_z.size)); sc->sc_loc_z.pos, sc->sc_loc_z.size));
for (i = 1; i <= sc->nbuttons; i++) { if (sc->flags & UMS_W)
dprintf(("", "ums_attach: B%d\t%d/%d\n", DPRINTF(("ums_attach: W\t%d/%d\n",
i, sc->sc_loc_btn[i-1].pos,sc->sc_loc_btn[i-1].size)); sc->sc_loc_w.pos, sc->sc_loc_w.size));
} for (i = 1; i <= sc->nbuttons; i++) {
dprintf(("", "ums_attach: size=%d, id=%d\n", sc->sc_isize, sc->sc_iid)); DPRINTF(("ums_attach: B%d\t%d/%d\n",
i, sc->sc_loc_btn[i-1].pos,sc->sc_loc_btn[i-1].size));
}
DPRINTF(("ums_attach: size=%d, id=%d\n", sc->sc_isize, sc->sc_iid));
#endif #endif
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
USBDEV(sc->sc_dev)); USBDEV(sc->sc_dev));
USB_ATTACH_SUCCESS_RETURN; USB_ATTACH_SUCCESS_RETURN;
} }
struct device* attach_mouse (struct device* parent, void* aux) struct device* attach_mouse (struct device* parent, void* aux)
{ {
struct device* softc; struct device* softc;
struct ums_softc* sc; struct ums_softc* sc;
dprintf (("", "Trying match on usb mouse\n")); dprintf (("", "Trying match on usb mouse\n"));
/* First see if we match */ /* First see if we match */
if (match_mouse (aux) == UMATCH_NONE) if (match_mouse (aux) == UMATCH_NONE)
{ {
dprintf (("", "Failed to match\n")); dprintf (("", "Failed to match\n"));
return NULL; return NULL;
} }
/* If so, allocate memory for the device and attach ourselves. */ /* If so, allocate memory for the device and attach ourselves. */
softc = malloc (sizeof *sc); softc = malloc (sizeof *sc);
if (softc == 0) { if (softc == 0) {
dprintf (("", "Couldn't allocate memory for mouse device\n")); dprintf (("", "Couldn't allocate memory for mouse device\n"));
return NULL; return NULL;
} }
memset (softc, 0, sizeof *sc); memset (softc, 0, sizeof *sc);
strcpy (softc->dv_xname, "USBMouse"Module_VersionString); strcpy (softc->dv_xname, "USBMouse"Module_VersionString);
softc->dv_cfdata = (void*) 3; // mouse softc->dv_cfdata = (void*) 3; // mouse
/* enable */ /* enable */
sc = (struct ums_softc*) softc; sc = (struct ums_softc*) softc;
do_attach_mouse (sc, aux); do_attach_mouse (sc, aux);
dprintf (("", "Matched mouse\n")); dprintf (("", "Matched mouse\n"));
sc->sc_enabled = 1; sc->sc_enabled = 1;
sc->sc_buttons = 0; sc->sc_buttons = 0;
/* set idle rate to 0 */ /* set idle rate to 0 */
usbd_set_idle (sc->sc_iface, 0, 0); usbd_set_idle (sc->sc_iface, 0, 0);
/* make sure we're using the report protocol */ /* make sure we're using the report protocol */
usbd_set_protocol(sc->sc_iface, 1); if(usbd_set_protocol(sc->sc_iface, 1)) {
dprintf(("", "Set protocol failed\n"));
return NULL;
}
int err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, int err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
sc->sc_ibuf, sc->sc_isize, ums_intr, USBD_DEFAULT_INTERVAL); USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc,
sc->sc_ibuf, sc->sc_isize, ums_intr, USBD_DEFAULT_INTERVAL);
if (err) {
dprintf(("", "ums_enable: usbd_open_pipe_intr failed, error=%d\n", if (err) {
err)); dprintf(("", "ums_enable: usbd_open_pipe_intr failed, error=%d\n",
sc->sc_enabled = 0; err));
} sc->sc_enabled = 0;
else }
_swix (OS_Pointer, _INR(0,1), 1, PointerDevice_USB); else
_swix (OS_Pointer, _INR(0,1), 1, PointerDevice_USB);
TAILQ_INSERT_TAIL (&allums, sc, link_ms);
TAILQ_INSERT_TAIL (&allums, sc, link_ms);
return softc;
return softc;
} }
int detach_mouse (struct device* ms) int detach_mouse (struct device* ms)
{ {
struct ums_softc* sc= (struct ums_softc*) ms; struct ums_softc* sc= (struct ums_softc*) ms;
if(!sc || !sc->sc_intrpipe) if(!sc || !sc->sc_intrpipe)
{ {
dprintf (("", "attempt to detach a NULL mouse 'sc'\n")); dprintf (("", "attempt to detach a NULL mouse 'sc'\n"));
return 0; return 0;
} }
dprintf (("", "detaching mouse, buttons = %x\n", sc->sc_buttons)); dprintf (("", "detaching mouse, buttons = %x\n", sc->sc_buttons));
usbd_abort_pipe(sc->sc_intrpipe); usbd_abort_pipe(sc->sc_intrpipe);
usbd_close_pipe(sc->sc_intrpipe); usbd_close_pipe(sc->sc_intrpipe);
dprintf (("", "aborted pipe\n")); dprintf (("", "aborted pipe\n"));
if (sc->sc_buttons & 1) { if (sc->sc_buttons & 1) {
dprintf (("", "releaseing 1\n")); dprintf (("", "releaseing 1\n"));
_swix (OS_CallAVector, _INR(0,1) | _IN(9), _swix (OS_CallAVector, _INR(0,1) | _IN(9),
KeyV_KeyUp, KeyNo_LeftMouse, KEYV); KeyV_KeyUp, KeyNo_LeftMouse, KEYV);
} }
if (sc->sc_buttons & 2) if (sc->sc_buttons & 2)
{ {
dprintf (("", "releaseing 2\n")); dprintf (("", "releaseing 2\n"));
_swix (OS_CallAVector, _INR(0,1) | _IN(9), _swix (OS_CallAVector, _INR(0,1) | _IN(9),
KeyV_KeyUp, KeyNo_RightMouse, KEYV); KeyV_KeyUp, KeyNo_RightMouse, KEYV);
} }
if (sc->sc_buttons & 4) if (sc->sc_buttons & 4)
{ {
dprintf (("", "releaseing 4\n")); dprintf (("", "releaseing 4\n"));
_swix (OS_CallAVector, _INR(0,1) | _IN(9), _swix (OS_CallAVector, _INR(0,1) | _IN(9),
KeyV_KeyUp, KeyNo_CentreMouse, KEYV); KeyV_KeyUp, KeyNo_CentreMouse, KEYV);
} }
TAILQ_REMOVE (&allums, sc, link_ms); TAILQ_REMOVE (&allums, sc, link_ms);
free(sc->sc_loc_btn); free(sc->sc_loc_btn);
free(sc->sc_ibuf); free(sc->sc_ibuf);
free (ms); free (ms);
dprintf (("", "mouse detached\n")); dprintf (("", "mouse detached\n"));
return 0; return 0;
} }
int pointerv (_kernel_swi_regs* r, void* pw) int pointerv (_kernel_swi_regs* r, void* pw)
{ {
_kernel_oserror* e; _kernel_oserror* e;
(void) pw; (void) pw;
switch (r->r[0]) { switch (r->r[0]) {
case PointerReason_Request: case PointerReason_Request:
if (r->r[1] == PointerDevice_USB) { if (r->r[1] == PointerDevice_USB) {
/* Turn off interrupts while updating */ /* Turn off interrupts while updating */
_kernel_irqs_off (); int irqs = _kernel_irqs_disabled();
r->r[2] = relx; if(!irqs)
r->r[3] = rely; _kernel_irqs_off ();
relx = rely = 0; r->r[2] = relx;
_kernel_irqs_on (); r->r[3] = rely;
} relx = rely = 0;
break; if(!irqs)
_kernel_irqs_on ();
return 0; /* PRM says we should intercept */
}
break;
#define RECORD "\x0\x0\x0\x0\x0\x0\x0\x0\x7USB Mouse" #define RECORD "\x0\x0\x0\x0\x0\x0\x0\x0\x7USB Mouse"
case PointerReason_Identify: case PointerReason_Identify:
{ {
struct pointer_device { struct pointer_device {
struct pointer_device *next; struct pointer_device *next;
uint32_t flags; uint32_t flags;
char typenname[32]; char typenname[32];
} *p; } *p;
e = _swix (OS_Module, _IN(0) | _IN(3) | _OUT(2), 6, e = _swix (OS_Module, _IN(0) | _IN(3) | _OUT(2), 6,
sizeof *p, &p); sizeof *p, &p);
if (!e) { if (!e) {
p->next = (struct pointer_device *) r->r[1]; p->next = (struct pointer_device *) r->r[1];
p->flags = 0; p->flags = 0;
p->typenname[0] = PointerDevice_USB; p->typenname[0] = PointerDevice_USB;
_swix (MessageTrans_Lookup, _INR(0,3), _swix (MessageTrans_Lookup, _INR(0,3),
&mod_messages, "Mouse:USB mouse", &p->typenname[1], 31); &mod_messages, "Mouse:USB mouse", &p->typenname[1], 31);
r->r[1] = (int) p; r->r[1] = (int) p;
} }
break; break;
} }
case PointerReason_Selected: case PointerReason_Selected:
if (r->r[1] == PointerDevice_USB) { if (r->r[1] == PointerDevice_USB) {
relx = 0; /* ensure the pointer doesnt jump */ relx = 0; /* ensure the pointer doesnt jump */
rely = 0; rely = 0;
relz = 0; relz = 0;
dprintf (("", "USB mouse enabled\n")); relw = 0;
enabled = true; dprintf (("", "USB mouse enabled\n"));
} else { enabled = true;
dprintf (("", "USB mouse disabled\n")); } else {
enabled = false; dprintf (("", "USB mouse disabled\n"));
} enabled = false;
break; }
} break;
}
return 1;
return 1;
} }
static _kernel_oserror *zscroll_handler static _kernel_oserror *zscroll_handler(_kernel_swi_regs *r, void *pw, void *h)
(
_kernel_swi_regs * r,
void * pw,
void * h
)
{ {
int b[64]; int b[10];
(void) r; (void) r;
(void) pw; (void) pw;
(void) h; (void) h;
_swix (Wimp_GetPointerInfo, _IN(1), b); _swix (Wimp_GetPointerInfo, _IN(1), b);
b[0] = b[3]; b[0] = b[3];
if(relz && !_swix (Wimp_GetWindowState, _IN(1), b)) // valid window handle if((relz || relw) && (b[0] != -1) && !_swix (Wimp_GetWindowState, _IN(1), b)) // valid window handle
{ {
/* does it do scroll requests? */ /* does it do scroll requests? */
if (b[8] & ((1<<8)|(1<<9))) if (b[8] & ((1<<8)|(1<<9)))
{ {
b[8] = 0; /* Only scroll if scrollbars are present */
b[9] = relz > 0? -1: 1; if(b[8] & (1<<31))
relz*=5; // a bit more movement... {
while (relz != 0) /* New format window flags word */
{ if(!(b[8] & (1<<28)))
relz += relz > 0? -1: 1; relz = 0;
_swix (Wimp_SendMessage, _INR(0,2), 10, b, b[0]); if(!(b[8] & (1<<30)))
} relw = 0;
} }
else else
{ // give it to a wimpscroll module {
/* Old format window flags word */
if(!(b[8] & (1<<2)))
relz = 0;
if(!(b[8] & (1<<3)))
relw = 0;
}
relz*=5; // a bit more movement...
relw*=5;
while(relz || relw)
{
b[8] = (relw?(relw > 0? -1: 1):0);
b[9] = (relz?(relz > 0? -1: 1):0);
relw += b[8];
relz += b[9];
_swix (Wimp_SendMessage, _INR(0,2), 10, b, b[0]);
}
}
else
{ // give it to a wimpscroll module
#define PointerReason_WheelChange 9 #define PointerReason_WheelChange 9
_swix (OS_CallAVector, _INR(0,3) | _IN(9), _swix (OS_CallAVector, _INR(0,3) | _IN(9),
PointerReason_WheelChange, // wheel change reason PointerReason_WheelChange, // wheel change reason
relz, // main wheel value relz, // main wheel value
morebuttons, // any additional buttons morebuttons, // any additional buttons
0, // extra wheel (not supp yet) relw, // extra wheel
PointerV); PointerV);
relz=0; relz=0;
} relw=0;
} }
return NULL; }
return NULL;
} }
void ums_intr void ums_intr
( (
usbd_xfer_handle xfer, usbd_xfer_handle xfer,
usbd_private_handle addr, usbd_private_handle addr,
usbd_status status usbd_status status
) )
{ {
struct ums_softc *sc = addr; struct ums_softc *sc = addr;
u_char *ibuf = sc->sc_ibuf; u_char *ibuf = sc->sc_ibuf;
int dx, dy, dz, i, b = 0; int dx, dy, dz, dw;
uint8_t change; u_int32_t buttons = 0;
int i, flags;
if (status == USBD_CANCELLED) uint8_t change;
return;
flags = WSMOUSE_INPUT_DELTA; /* equals 0 */
if (status) {
dprintf(("", "ums_intr: status=%d\n", status)); if (status == USBD_CANCELLED)
usbd_clear_endpoint_stall_async(sc->sc_intrpipe); return;
return;
} if (status) {
dprintf(("", "ums_intr: status=%d\n", status));
/* only respond to our report, and skip the report number */ usbd_clear_endpoint_stall_async(sc->sc_intrpipe);
if (sc->sc_iid && *ibuf++ != sc->sc_iid) return;
return; }
dx = (u_int) hid_get_data(ibuf, &sc->sc_loc_x); /* only respond to our report, and skip the report number */
dy = -(u_int) hid_get_data(ibuf, &sc->sc_loc_y); if (sc->sc_iid && !(sc->flags & UMS_NO_REPID) && *ibuf++ != sc->sc_iid)
dz = (u_int) hid_get_data(ibuf, &sc->sc_loc_z); return;
if (sc->flags & UMS_REVZ)
dz = -dz; dx = hid_get_data(ibuf, &sc->sc_loc_x);
relx += dx; if (sc->flags & UMS_ABS) {
rely += dy; flags |= (WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
relz += dz; dy = hid_get_data(ibuf, &sc->sc_loc_y);
for (i = 0; i < sc->nbuttons; i++) } else
if (hid_get_data(ibuf, &sc->sc_loc_btn[i])) dy = -hid_get_data(ibuf, &sc->sc_loc_y);
b |= (1 << i); dz = hid_get_data(ibuf, &sc->sc_loc_z);
dw = hid_get_data(ibuf, &sc->sc_loc_w);
if (enabled)
{ if (sc->flags & UMS_REVZ)
_swix(OS_CallAVector, _INR(0,3) | _IN(9), dz = -dz;
PointerReason_Report, PointerDevice_USB, for (i = 0; i < sc->nbuttons; i++)
dx, dy, if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
PointerV); buttons |= (1 << UMS_BUT(i));
if (relz != 0)
{ relx += dx;
morebuttons = b>>3; rely += dy;
callx_add_callback (zscroll_handler, 0); relz += dz;
} relw += dw;
}
if (enabled)
{
if(dx || dy)
{
_swix(OS_CallAVector, _INR(0,3) | _IN(9),
PointerReason_Report, PointerDevice_USB,
dx, dy,
PointerV);
}
if (relz || relw)
{
morebuttons = buttons>>3;
callx_add_callback (zscroll_handler, 0);
}
}
#ifdef USB_DEBUG #ifdef USB_DEBUG
if (umsdebug > 5) dprintf(("", if (umsdebug > 5) dprintf(("",
"data.relx = %d, data.rely = %d, relx = %d, rely = %d, buttons = %x\n", "data.relx = %d, data.rely = %d, relx = %d, rely = %d, buttons = %x\n",
dx, dy, relx, rely, b)); dx, dy, relx, rely, buttons));
#endif #endif
if ((change = sc->sc_buttons ^ b) != 0) { if ((change = sc->sc_buttons ^ buttons) != 0) {
sc->sc_buttons = b; sc->sc_buttons = buttons;
#ifdef USB_DEBUG #ifdef USB_DEBUG
if (umsdebug > 5) dprintf (("", "change = %x, enabled = %d\n", change, if (umsdebug > 5) dprintf (("", "change = %x, enabled = %d\n", change,
enabled)); enabled));
#endif #endif
if (enabled) { if (enabled) {
if (change & 1) _swix (OS_CallAVector, _INR(0,1) | _IN(9), if (change & 1) _swix (OS_CallAVector, _INR(0,1) | _IN(9),
(b & 1)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_LeftMouse, KEYV); (buttons & 1)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_LeftMouse, KEYV);
if (change & 2) _swix (OS_CallAVector, _INR(0,1) | _IN(9), if (change & 2) _swix (OS_CallAVector, _INR(0,1) | _IN(9),
(b & 2)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_RightMouse, KEYV); (buttons & 2)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_RightMouse, KEYV);
if (change & 4) _swix (OS_CallAVector, _INR(0,1) | _IN(9), if (change & 4) _swix (OS_CallAVector, _INR(0,1) | _IN(9),
(b & 4)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_CentreMouse, KEYV); (buttons & 4)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_CentreMouse, KEYV);
/* make the next button replicate menu */ /* make the next button replicate menu */
if (change & 8) _swix (OS_CallAVector, _INR(0,1) | _IN(9), if (change & 8) _swix (OS_CallAVector, _INR(0,1) | _IN(9),
(b & 8)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_CentreMouse, KEYV); (buttons & 8)? KeyV_KeyDown: KeyV_KeyUp, KeyNo_CentreMouse, KEYV);
} }
} }
} }
int wsmousedevprint (void * v, const char * c) int wsmousedevprint (void * v, const char * c)
{ {
(void) v; (void) v;
(void) c; (void) c;
return 0; return 0;
} }
int int
...@@ -601,8 +804,10 @@ uhidev_maxrepid(void *buf, int len) ...@@ -601,8 +804,10 @@ uhidev_maxrepid(void *buf, int len)
maxid = -1; maxid = -1;
h.report_ID = 0; h.report_ID = 0;
for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); ) for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); )
{
if (h.report_ID > maxid) if (h.report_ID > maxid)
maxid = h.report_ID; maxid = h.report_ID;
}
hid_end_parse(d); hid_end_parse(d);
return (maxid); return (maxid);
} }
...@@ -29,9 +29,7 @@ help-string: EHCIDriver EHCIDriverModule_MajorVersion_CMHG ...@@ -29,9 +29,7 @@ help-string: EHCIDriver EHCIDriverModule_MajorVersion_CMHG
date-string: EHCIDriverModule_Module_Date_CMHG date-string: EHCIDriverModule_Module_Date_CMHG
#define HELPFILE(M) "Resources:$." #M international-help-file: "Resources:$.Resources.EHCIDriver.Messages"
#define XHELPFILE(M) HELPFILE(M)
international-help-file: XHELPFILE(MSGLOC)
#ifdef EHCI_DEBUG #ifdef EHCI_DEBUG
command-keyword-table: module_commands command-keyword-table: module_commands
......
...@@ -32,9 +32,7 @@ help-string: OHCIDriver OHCIDriverModule_MajorVersion_CMHG ...@@ -32,9 +32,7 @@ help-string: OHCIDriver OHCIDriverModule_MajorVersion_CMHG
date-string: OHCIDriverModule_Module_Date_CMHG date-string: OHCIDriverModule_Module_Date_CMHG
#define HELPFILE(M) "Resources:$." #M international-help-file: "Resources:$.Resources.OHCIDriver.Messages"
#define XHELPFILE(M) HELPFILE(M)
international-help-file: XHELPFILE(MSGLOC)
#ifdef OHCI_DEBUG #ifdef OHCI_DEBUG
command-keyword-table: module_commands command-keyword-table: module_commands
......
...@@ -31,9 +31,7 @@ help-string: USBDriver USBDriverModule_MajorVersion_CMHG ...@@ -31,9 +31,7 @@ help-string: USBDriver USBDriverModule_MajorVersion_CMHG
date-string: USBDriverModule_Module_Date_CMHG date-string: USBDriverModule_Module_Date_CMHG
#define HELPFILE(M) "Resources:$." #M international-help-file: "Resources:$.Resources.USBDriver.Messages"
#define XHELPFILE(M) HELPFILE(M)
international-help-file: XHELPFILE(MSGLOC)
command-keyword-table: module_commands command-keyword-table: module_commands
...@@ -80,43 +78,8 @@ swi-decoding-table: USBDriver, ...@@ -80,43 +78,8 @@ swi-decoding-table: USBDriver,
DeRegisterBus, DeRegisterBus,
InsertTransfer, InsertTransfer,
TransferComplete, TransferComplete,
ScheduleSoftInterrupt ScheduleSoftInterrupt,
; IOCtl, Version
; OpenPipe,
; ClosePipe,
; Transfer,
; AllocXfer,
; FreeXfer,
; SetupXfer,
; SetupDefaultXfer,
; SetupIsocXfer,
; GetXferStatus,
; Interface2EndpointDescriptor,
; AbortPipe,
; ClearEndpointStall,
; ClearEndpointStallAsync,
; EndpointCount,
; Interface2DeviceHandle,
; Device2InterfaceHandle,
; Pipe2DeviceHandle,
; AllocBuffer,
; Freebuffer,
; GetBuffer,
; SyncTransfer,
; OpenPipeIntr,
; DoRequest,
; DoRequestAsync,
; DoRequestFlags,
; GetInterfaceDescriptor,
; GetConfigDescriptor,
; SetInterface,
; FillDeviceInfo,
; GetInterfaceAltindex,
; FindIdesc,
; FindEdesc,
; DevInfo,
; GetEndpointDescriptor,
; ReloadDeviceDesc
generic-veneers: driver_entry/driver generic-veneers: driver_entry/driver
......