Initial commit
This commit is contained in:
		
							
								
								
									
										55
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| # WinAVR cross-compiler toolchain is used here | ||||
| CC = avr-gcc | ||||
| OBJCOPY = avr-objcopy | ||||
| DUDE = avrdude | ||||
| MICRONUCLEUS = sudo micronucleus | ||||
|  | ||||
| # If you are not using ATtiny2313 and the USBtiny programmer,  | ||||
| # update the lines below to match your configuration | ||||
| CFLAGS = -Wall -Os -Iusbdrv -I. -mmcu=attiny85 -DF_CPU=16500000 | ||||
| OBJFLAGS = -j .text -j .data -O ihex | ||||
| DUDEFLAGS = -p attiny85 -c usbtiny -v | ||||
| MICRONUCLEUSFLAGS = --run | ||||
|  | ||||
| # Object files for the firmware (usbdrv/oddebug.o not strictly needed I think) | ||||
| OBJECTS = usbdrv/usbdrv.o usbdrv/oddebug.o usbdrv/usbdrvasm.o main.o | ||||
|  | ||||
| ## Command-line client | ||||
| #CMDLINE = usbtest.exe | ||||
|  | ||||
| # By default, build the firmware and command-line client, but do not flash | ||||
| all: main.hex | ||||
|  | ||||
| # With this, you can flash the firmware by just typing "make flash" on command-line | ||||
| flash: main.hex | ||||
| 	micronucleus --run main.hex | ||||
| #   $(MICRONUCLEUS) $(MICRONUCLEUSFLAGS) $< | ||||
| #	$(DUDE) $(DUDEFLAGS) -U flash:w:$< | ||||
|  | ||||
| # One-liner to compile the command-line client from usbtest.c | ||||
| #$(CMDLINE): usbtest.c | ||||
| #	gcc -I ./libusb/include -L ./libusb/lib/gcc -O -Wall usbtest.c -o usbtest.exe -lusb | ||||
|  | ||||
| # Housekeeping if you want it | ||||
| clean: | ||||
| 	$(RM) *.o *.hex *.elf usbdrv/*.o | ||||
|  | ||||
| # From .elf file to .hex | ||||
| %.hex: %.elf | ||||
| 	$(OBJCOPY) $(OBJFLAGS) $< $@ | ||||
|  | ||||
| # Main.elf requires additional objects to the firmware, not just main.o | ||||
| main.elf: $(OBJECTS) | ||||
| 	$(CC) $(CFLAGS) $(OBJECTS) -o $@ | ||||
|  | ||||
| # Without this dependance, .o files will not be recompiled if you change  | ||||
| # the config! I spent a few hours debugging because of this... | ||||
| $(OBJECTS): usbdrv/usbconfig.h | ||||
|  | ||||
| # From C source to .o object file | ||||
| %.o: %.c	 | ||||
| 	$(CC) $(CFLAGS) -c $< -o $@ | ||||
|  | ||||
| # From assembler source to .o object file | ||||
| %.o: %.S | ||||
| 	$(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@ | ||||
							
								
								
									
										26
									
								
								Wheel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								Wheel.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| #define DeadWidth 100 | ||||
| #define DebounceWidth 10 | ||||
|  | ||||
| #define USB_LED_OFF 0 | ||||
| #define USB_LED_ON  1 | ||||
| #define USB_DATA_OUT 2 | ||||
| #define USB_DATA_WRITE 3 | ||||
| #define USB_DATA_IN 4 | ||||
|  | ||||
| #define LED_PIN (1<<PB1) | ||||
|  | ||||
| #define abs(x) ((x) > 0 ? (x) : (-x)) | ||||
|  | ||||
| const uint16_t timingtable_in[] = { 0,218,342,380,401,414,423,430,436,440,444,447,450,453,455,457,459,460,563,564,566,567,569,571,574,577,580,584,588,594,601,610,623,644,682,1023 }; | ||||
| const uint8_t timingtable_out[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 }; | ||||
|  | ||||
| static uint16_t LowerDead[] = {512 - DeadWidth / 2, 512 - DebounceWidth - DeadWidth / 2}; | ||||
| static uint16_t UpperDead[] = {512 + DeadWidth / 2, 512 + DebounceWidth + DeadWidth / 2}; | ||||
|  | ||||
| volatile uint8_t Debounce = 1; | ||||
| volatile uint16_t AnalogIn = 128; | ||||
|  | ||||
| volatile uint8_t ticktock = 0; | ||||
| volatile uint8_t timing = 255; | ||||
|  | ||||
| uint8_t get_timing(uint16_t value); | ||||
							
								
								
									
										16
									
								
								libusb/AUTHORS.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								libusb/AUTHORS.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
|  | ||||
| Library, Test Programs: | ||||
|  | ||||
| Stephan Meyer, <ste_meyer@web.de> | ||||
| Johannes Erdfelt, <johannes@erdfelt.com> | ||||
| Thomas Sailer, <sailer@ife.ee.ethz.ch> | ||||
|  | ||||
| Drivers, Installer: | ||||
|  | ||||
| Stephan Meyer, <ste_meyer@web.de> | ||||
| Travis Robinson, <libusbdotnet@gmail.com> | ||||
|  | ||||
| Testing, Technical support: | ||||
|  | ||||
| Xiaofan Chen, <xiaofanc@gmail.com> | ||||
|  | ||||
							
								
								
									
										674
									
								
								libusb/COPYING_GPL.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										674
									
								
								libusb/COPYING_GPL.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,674 @@ | ||||
|                     GNU GENERAL PUBLIC LICENSE | ||||
|                        Version 3, 29 June 2007 | ||||
|  | ||||
|  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
|  | ||||
|                             Preamble | ||||
|  | ||||
|   The GNU General Public License is a free, copyleft license for | ||||
| software and other kinds of works. | ||||
|  | ||||
|   The licenses for most software and other practical works are designed | ||||
| to take away your freedom to share and change the works.  By contrast, | ||||
| the GNU General Public License is intended to guarantee your freedom to | ||||
| share and change all versions of a program--to make sure it remains free | ||||
| software for all its users.  We, the Free Software Foundation, use the | ||||
| GNU General Public License for most of our software; it applies also to | ||||
| any other work released this way by its authors.  You can apply it to | ||||
| your programs, too. | ||||
|  | ||||
|   When we speak of free software, we are referring to freedom, not | ||||
| price.  Our General Public Licenses are designed to make sure that you | ||||
| have the freedom to distribute copies of free software (and charge for | ||||
| them if you wish), that you receive source code or can get it if you | ||||
| want it, that you can change the software or use pieces of it in new | ||||
| free programs, and that you know you can do these things. | ||||
|  | ||||
|   To protect your rights, we need to prevent others from denying you | ||||
| these rights or asking you to surrender the rights.  Therefore, you have | ||||
| certain responsibilities if you distribute copies of the software, or if | ||||
| you modify it: responsibilities to respect the freedom of others. | ||||
|  | ||||
|   For example, if you distribute copies of such a program, whether | ||||
| gratis or for a fee, you must pass on to the recipients the same | ||||
| freedoms that you received.  You must make sure that they, too, receive | ||||
| or can get the source code.  And you must show them these terms so they | ||||
| know their rights. | ||||
|  | ||||
|   Developers that use the GNU GPL protect your rights with two steps: | ||||
| (1) assert copyright on the software, and (2) offer you this License | ||||
| giving you legal permission to copy, distribute and/or modify it. | ||||
|  | ||||
|   For the developers' and authors' protection, the GPL clearly explains | ||||
| that there is no warranty for this free software.  For both users' and | ||||
| authors' sake, the GPL requires that modified versions be marked as | ||||
| changed, so that their problems will not be attributed erroneously to | ||||
| authors of previous versions. | ||||
|  | ||||
|   Some devices are designed to deny users access to install or run | ||||
| modified versions of the software inside them, although the manufacturer | ||||
| can do so.  This is fundamentally incompatible with the aim of | ||||
| protecting users' freedom to change the software.  The systematic | ||||
| pattern of such abuse occurs in the area of products for individuals to | ||||
| use, which is precisely where it is most unacceptable.  Therefore, we | ||||
| have designed this version of the GPL to prohibit the practice for those | ||||
| products.  If such problems arise substantially in other domains, we | ||||
| stand ready to extend this provision to those domains in future versions | ||||
| of the GPL, as needed to protect the freedom of users. | ||||
|  | ||||
|   Finally, every program is threatened constantly by software patents. | ||||
| States should not allow patents to restrict development and use of | ||||
| software on general-purpose computers, but in those that do, we wish to | ||||
| avoid the special danger that patents applied to a free program could | ||||
| make it effectively proprietary.  To prevent this, the GPL assures that | ||||
| patents cannot be used to render the program non-free. | ||||
|  | ||||
|   The precise terms and conditions for copying, distribution and | ||||
| modification follow. | ||||
|  | ||||
|                        TERMS AND CONDITIONS | ||||
|  | ||||
|   0. Definitions. | ||||
|  | ||||
|   "This License" refers to version 3 of the GNU General Public License. | ||||
|  | ||||
|   "Copyright" also means copyright-like laws that apply to other kinds of | ||||
| works, such as semiconductor masks. | ||||
|  | ||||
|   "The Program" refers to any copyrightable work licensed under this | ||||
| License.  Each licensee is addressed as "you".  "Licensees" and | ||||
| "recipients" may be individuals or organizations. | ||||
|  | ||||
|   To "modify" a work means to copy from or adapt all or part of the work | ||||
| in a fashion requiring copyright permission, other than the making of an | ||||
| exact copy.  The resulting work is called a "modified version" of the | ||||
| earlier work or a work "based on" the earlier work. | ||||
|  | ||||
|   A "covered work" means either the unmodified Program or a work based | ||||
| on the Program. | ||||
|  | ||||
|   To "propagate" a work means to do anything with it that, without | ||||
| permission, would make you directly or secondarily liable for | ||||
| infringement under applicable copyright law, except executing it on a | ||||
| computer or modifying a private copy.  Propagation includes copying, | ||||
| distribution (with or without modification), making available to the | ||||
| public, and in some countries other activities as well. | ||||
|  | ||||
|   To "convey" a work means any kind of propagation that enables other | ||||
| parties to make or receive copies.  Mere interaction with a user through | ||||
| a computer network, with no transfer of a copy, is not conveying. | ||||
|  | ||||
|   An interactive user interface displays "Appropriate Legal Notices" | ||||
| to the extent that it includes a convenient and prominently visible | ||||
| feature that (1) displays an appropriate copyright notice, and (2) | ||||
| tells the user that there is no warranty for the work (except to the | ||||
| extent that warranties are provided), that licensees may convey the | ||||
| work under this License, and how to view a copy of this License.  If | ||||
| the interface presents a list of user commands or options, such as a | ||||
| menu, a prominent item in the list meets this criterion. | ||||
|  | ||||
|   1. Source Code. | ||||
|  | ||||
|   The "source code" for a work means the preferred form of the work | ||||
| for making modifications to it.  "Object code" means any non-source | ||||
| form of a work. | ||||
|  | ||||
|   A "Standard Interface" means an interface that either is an official | ||||
| standard defined by a recognized standards body, or, in the case of | ||||
| interfaces specified for a particular programming language, one that | ||||
| is widely used among developers working in that language. | ||||
|  | ||||
|   The "System Libraries" of an executable work include anything, other | ||||
| than the work as a whole, that (a) is included in the normal form of | ||||
| packaging a Major Component, but which is not part of that Major | ||||
| Component, and (b) serves only to enable use of the work with that | ||||
| Major Component, or to implement a Standard Interface for which an | ||||
| implementation is available to the public in source code form.  A | ||||
| "Major Component", in this context, means a major essential component | ||||
| (kernel, window system, and so on) of the specific operating system | ||||
| (if any) on which the executable work runs, or a compiler used to | ||||
| produce the work, or an object code interpreter used to run it. | ||||
|  | ||||
|   The "Corresponding Source" for a work in object code form means all | ||||
| the source code needed to generate, install, and (for an executable | ||||
| work) run the object code and to modify the work, including scripts to | ||||
| control those activities.  However, it does not include the work's | ||||
| System Libraries, or general-purpose tools or generally available free | ||||
| programs which are used unmodified in performing those activities but | ||||
| which are not part of the work.  For example, Corresponding Source | ||||
| includes interface definition files associated with source files for | ||||
| the work, and the source code for shared libraries and dynamically | ||||
| linked subprograms that the work is specifically designed to require, | ||||
| such as by intimate data communication or control flow between those | ||||
| subprograms and other parts of the work. | ||||
|  | ||||
|   The Corresponding Source need not include anything that users | ||||
| can regenerate automatically from other parts of the Corresponding | ||||
| Source. | ||||
|  | ||||
|   The Corresponding Source for a work in source code form is that | ||||
| same work. | ||||
|  | ||||
|   2. Basic Permissions. | ||||
|  | ||||
|   All rights granted under this License are granted for the term of | ||||
| copyright on the Program, and are irrevocable provided the stated | ||||
| conditions are met.  This License explicitly affirms your unlimited | ||||
| permission to run the unmodified Program.  The output from running a | ||||
| covered work is covered by this License only if the output, given its | ||||
| content, constitutes a covered work.  This License acknowledges your | ||||
| rights of fair use or other equivalent, as provided by copyright law. | ||||
|  | ||||
|   You may make, run and propagate covered works that you do not | ||||
| convey, without conditions so long as your license otherwise remains | ||||
| in force.  You may convey covered works to others for the sole purpose | ||||
| of having them make modifications exclusively for you, or provide you | ||||
| with facilities for running those works, provided that you comply with | ||||
| the terms of this License in conveying all material for which you do | ||||
| not control copyright.  Those thus making or running the covered works | ||||
| for you must do so exclusively on your behalf, under your direction | ||||
| and control, on terms that prohibit them from making any copies of | ||||
| your copyrighted material outside their relationship with you. | ||||
|  | ||||
|   Conveying under any other circumstances is permitted solely under | ||||
| the conditions stated below.  Sublicensing is not allowed; section 10 | ||||
| makes it unnecessary. | ||||
|  | ||||
|   3. Protecting Users' Legal Rights From Anti-Circumvention Law. | ||||
|  | ||||
|   No covered work shall be deemed part of an effective technological | ||||
| measure under any applicable law fulfilling obligations under article | ||||
| 11 of the WIPO copyright treaty adopted on 20 December 1996, or | ||||
| similar laws prohibiting or restricting circumvention of such | ||||
| measures. | ||||
|  | ||||
|   When you convey a covered work, you waive any legal power to forbid | ||||
| circumvention of technological measures to the extent such circumvention | ||||
| is effected by exercising rights under this License with respect to | ||||
| the covered work, and you disclaim any intention to limit operation or | ||||
| modification of the work as a means of enforcing, against the work's | ||||
| users, your or third parties' legal rights to forbid circumvention of | ||||
| technological measures. | ||||
|  | ||||
|   4. Conveying Verbatim Copies. | ||||
|  | ||||
|   You may convey verbatim copies of the Program's source code as you | ||||
| receive it, in any medium, provided that you conspicuously and | ||||
| appropriately publish on each copy an appropriate copyright notice; | ||||
| keep intact all notices stating that this License and any | ||||
| non-permissive terms added in accord with section 7 apply to the code; | ||||
| keep intact all notices of the absence of any warranty; and give all | ||||
| recipients a copy of this License along with the Program. | ||||
|  | ||||
|   You may charge any price or no price for each copy that you convey, | ||||
| and you may offer support or warranty protection for a fee. | ||||
|  | ||||
|   5. Conveying Modified Source Versions. | ||||
|  | ||||
|   You may convey a work based on the Program, or the modifications to | ||||
| produce it from the Program, in the form of source code under the | ||||
| terms of section 4, provided that you also meet all of these conditions: | ||||
|  | ||||
|     a) The work must carry prominent notices stating that you modified | ||||
|     it, and giving a relevant date. | ||||
|  | ||||
|     b) The work must carry prominent notices stating that it is | ||||
|     released under this License and any conditions added under section | ||||
|     7.  This requirement modifies the requirement in section 4 to | ||||
|     "keep intact all notices". | ||||
|  | ||||
|     c) You must license the entire work, as a whole, under this | ||||
|     License to anyone who comes into possession of a copy.  This | ||||
|     License will therefore apply, along with any applicable section 7 | ||||
|     additional terms, to the whole of the work, and all its parts, | ||||
|     regardless of how they are packaged.  This License gives no | ||||
|     permission to license the work in any other way, but it does not | ||||
|     invalidate such permission if you have separately received it. | ||||
|  | ||||
|     d) If the work has interactive user interfaces, each must display | ||||
|     Appropriate Legal Notices; however, if the Program has interactive | ||||
|     interfaces that do not display Appropriate Legal Notices, your | ||||
|     work need not make them do so. | ||||
|  | ||||
|   A compilation of a covered work with other separate and independent | ||||
| works, which are not by their nature extensions of the covered work, | ||||
| and which are not combined with it such as to form a larger program, | ||||
| in or on a volume of a storage or distribution medium, is called an | ||||
| "aggregate" if the compilation and its resulting copyright are not | ||||
| used to limit the access or legal rights of the compilation's users | ||||
| beyond what the individual works permit.  Inclusion of a covered work | ||||
| in an aggregate does not cause this License to apply to the other | ||||
| parts of the aggregate. | ||||
|  | ||||
|   6. Conveying Non-Source Forms. | ||||
|  | ||||
|   You may convey a covered work in object code form under the terms | ||||
| of sections 4 and 5, provided that you also convey the | ||||
| machine-readable Corresponding Source under the terms of this License, | ||||
| in one of these ways: | ||||
|  | ||||
|     a) Convey the object code in, or embodied in, a physical product | ||||
|     (including a physical distribution medium), accompanied by the | ||||
|     Corresponding Source fixed on a durable physical medium | ||||
|     customarily used for software interchange. | ||||
|  | ||||
|     b) Convey the object code in, or embodied in, a physical product | ||||
|     (including a physical distribution medium), accompanied by a | ||||
|     written offer, valid for at least three years and valid for as | ||||
|     long as you offer spare parts or customer support for that product | ||||
|     model, to give anyone who possesses the object code either (1) a | ||||
|     copy of the Corresponding Source for all the software in the | ||||
|     product that is covered by this License, on a durable physical | ||||
|     medium customarily used for software interchange, for a price no | ||||
|     more than your reasonable cost of physically performing this | ||||
|     conveying of source, or (2) access to copy the | ||||
|     Corresponding Source from a network server at no charge. | ||||
|  | ||||
|     c) Convey individual copies of the object code with a copy of the | ||||
|     written offer to provide the Corresponding Source.  This | ||||
|     alternative is allowed only occasionally and noncommercially, and | ||||
|     only if you received the object code with such an offer, in accord | ||||
|     with subsection 6b. | ||||
|  | ||||
|     d) Convey the object code by offering access from a designated | ||||
|     place (gratis or for a charge), and offer equivalent access to the | ||||
|     Corresponding Source in the same way through the same place at no | ||||
|     further charge.  You need not require recipients to copy the | ||||
|     Corresponding Source along with the object code.  If the place to | ||||
|     copy the object code is a network server, the Corresponding Source | ||||
|     may be on a different server (operated by you or a third party) | ||||
|     that supports equivalent copying facilities, provided you maintain | ||||
|     clear directions next to the object code saying where to find the | ||||
|     Corresponding Source.  Regardless of what server hosts the | ||||
|     Corresponding Source, you remain obligated to ensure that it is | ||||
|     available for as long as needed to satisfy these requirements. | ||||
|  | ||||
|     e) Convey the object code using peer-to-peer transmission, provided | ||||
|     you inform other peers where the object code and Corresponding | ||||
|     Source of the work are being offered to the general public at no | ||||
|     charge under subsection 6d. | ||||
|  | ||||
|   A separable portion of the object code, whose source code is excluded | ||||
| from the Corresponding Source as a System Library, need not be | ||||
| included in conveying the object code work. | ||||
|  | ||||
|   A "User Product" is either (1) a "consumer product", which means any | ||||
| tangible personal property which is normally used for personal, family, | ||||
| or household purposes, or (2) anything designed or sold for incorporation | ||||
| into a dwelling.  In determining whether a product is a consumer product, | ||||
| doubtful cases shall be resolved in favor of coverage.  For a particular | ||||
| product received by a particular user, "normally used" refers to a | ||||
| typical or common use of that class of product, regardless of the status | ||||
| of the particular user or of the way in which the particular user | ||||
| actually uses, or expects or is expected to use, the product.  A product | ||||
| is a consumer product regardless of whether the product has substantial | ||||
| commercial, industrial or non-consumer uses, unless such uses represent | ||||
| the only significant mode of use of the product. | ||||
|  | ||||
|   "Installation Information" for a User Product means any methods, | ||||
| procedures, authorization keys, or other information required to install | ||||
| and execute modified versions of a covered work in that User Product from | ||||
| a modified version of its Corresponding Source.  The information must | ||||
| suffice to ensure that the continued functioning of the modified object | ||||
| code is in no case prevented or interfered with solely because | ||||
| modification has been made. | ||||
|  | ||||
|   If you convey an object code work under this section in, or with, or | ||||
| specifically for use in, a User Product, and the conveying occurs as | ||||
| part of a transaction in which the right of possession and use of the | ||||
| User Product is transferred to the recipient in perpetuity or for a | ||||
| fixed term (regardless of how the transaction is characterized), the | ||||
| Corresponding Source conveyed under this section must be accompanied | ||||
| by the Installation Information.  But this requirement does not apply | ||||
| if neither you nor any third party retains the ability to install | ||||
| modified object code on the User Product (for example, the work has | ||||
| been installed in ROM). | ||||
|  | ||||
|   The requirement to provide Installation Information does not include a | ||||
| requirement to continue to provide support service, warranty, or updates | ||||
| for a work that has been modified or installed by the recipient, or for | ||||
| the User Product in which it has been modified or installed.  Access to a | ||||
| network may be denied when the modification itself materially and | ||||
| adversely affects the operation of the network or violates the rules and | ||||
| protocols for communication across the network. | ||||
|  | ||||
|   Corresponding Source conveyed, and Installation Information provided, | ||||
| in accord with this section must be in a format that is publicly | ||||
| documented (and with an implementation available to the public in | ||||
| source code form), and must require no special password or key for | ||||
| unpacking, reading or copying. | ||||
|  | ||||
|   7. Additional Terms. | ||||
|  | ||||
|   "Additional permissions" are terms that supplement the terms of this | ||||
| License by making exceptions from one or more of its conditions. | ||||
| Additional permissions that are applicable to the entire Program shall | ||||
| be treated as though they were included in this License, to the extent | ||||
| that they are valid under applicable law.  If additional permissions | ||||
| apply only to part of the Program, that part may be used separately | ||||
| under those permissions, but the entire Program remains governed by | ||||
| this License without regard to the additional permissions. | ||||
|  | ||||
|   When you convey a copy of a covered work, you may at your option | ||||
| remove any additional permissions from that copy, or from any part of | ||||
| it.  (Additional permissions may be written to require their own | ||||
| removal in certain cases when you modify the work.)  You may place | ||||
| additional permissions on material, added by you to a covered work, | ||||
| for which you have or can give appropriate copyright permission. | ||||
|  | ||||
|   Notwithstanding any other provision of this License, for material you | ||||
| add to a covered work, you may (if authorized by the copyright holders of | ||||
| that material) supplement the terms of this License with terms: | ||||
|  | ||||
|     a) Disclaiming warranty or limiting liability differently from the | ||||
|     terms of sections 15 and 16 of this License; or | ||||
|  | ||||
|     b) Requiring preservation of specified reasonable legal notices or | ||||
|     author attributions in that material or in the Appropriate Legal | ||||
|     Notices displayed by works containing it; or | ||||
|  | ||||
|     c) Prohibiting misrepresentation of the origin of that material, or | ||||
|     requiring that modified versions of such material be marked in | ||||
|     reasonable ways as different from the original version; or | ||||
|  | ||||
|     d) Limiting the use for publicity purposes of names of licensors or | ||||
|     authors of the material; or | ||||
|  | ||||
|     e) Declining to grant rights under trademark law for use of some | ||||
|     trade names, trademarks, or service marks; or | ||||
|  | ||||
|     f) Requiring indemnification of licensors and authors of that | ||||
|     material by anyone who conveys the material (or modified versions of | ||||
|     it) with contractual assumptions of liability to the recipient, for | ||||
|     any liability that these contractual assumptions directly impose on | ||||
|     those licensors and authors. | ||||
|  | ||||
|   All other non-permissive additional terms are considered "further | ||||
| restrictions" within the meaning of section 10.  If the Program as you | ||||
| received it, or any part of it, contains a notice stating that it is | ||||
| governed by this License along with a term that is a further | ||||
| restriction, you may remove that term.  If a license document contains | ||||
| a further restriction but permits relicensing or conveying under this | ||||
| License, you may add to a covered work material governed by the terms | ||||
| of that license document, provided that the further restriction does | ||||
| not survive such relicensing or conveying. | ||||
|  | ||||
|   If you add terms to a covered work in accord with this section, you | ||||
| must place, in the relevant source files, a statement of the | ||||
| additional terms that apply to those files, or a notice indicating | ||||
| where to find the applicable terms. | ||||
|  | ||||
|   Additional terms, permissive or non-permissive, may be stated in the | ||||
| form of a separately written license, or stated as exceptions; | ||||
| the above requirements apply either way. | ||||
|  | ||||
|   8. Termination. | ||||
|  | ||||
|   You may not propagate or modify a covered work except as expressly | ||||
| provided under this License.  Any attempt otherwise to propagate or | ||||
| modify it is void, and will automatically terminate your rights under | ||||
| this License (including any patent licenses granted under the third | ||||
| paragraph of section 11). | ||||
|  | ||||
|   However, if you cease all violation of this License, then your | ||||
| license from a particular copyright holder is reinstated (a) | ||||
| provisionally, unless and until the copyright holder explicitly and | ||||
| finally terminates your license, and (b) permanently, if the copyright | ||||
| holder fails to notify you of the violation by some reasonable means | ||||
| prior to 60 days after the cessation. | ||||
|  | ||||
|   Moreover, your license from a particular copyright holder is | ||||
| reinstated permanently if the copyright holder notifies you of the | ||||
| violation by some reasonable means, this is the first time you have | ||||
| received notice of violation of this License (for any work) from that | ||||
| copyright holder, and you cure the violation prior to 30 days after | ||||
| your receipt of the notice. | ||||
|  | ||||
|   Termination of your rights under this section does not terminate the | ||||
| licenses of parties who have received copies or rights from you under | ||||
| this License.  If your rights have been terminated and not permanently | ||||
| reinstated, you do not qualify to receive new licenses for the same | ||||
| material under section 10. | ||||
|  | ||||
|   9. Acceptance Not Required for Having Copies. | ||||
|  | ||||
|   You are not required to accept this License in order to receive or | ||||
| run a copy of the Program.  Ancillary propagation of a covered work | ||||
| occurring solely as a consequence of using peer-to-peer transmission | ||||
| to receive a copy likewise does not require acceptance.  However, | ||||
| nothing other than this License grants you permission to propagate or | ||||
| modify any covered work.  These actions infringe copyright if you do | ||||
| not accept this License.  Therefore, by modifying or propagating a | ||||
| covered work, you indicate your acceptance of this License to do so. | ||||
|  | ||||
|   10. Automatic Licensing of Downstream Recipients. | ||||
|  | ||||
|   Each time you convey a covered work, the recipient automatically | ||||
| receives a license from the original licensors, to run, modify and | ||||
| propagate that work, subject to this License.  You are not responsible | ||||
| for enforcing compliance by third parties with this License. | ||||
|  | ||||
|   An "entity transaction" is a transaction transferring control of an | ||||
| organization, or substantially all assets of one, or subdividing an | ||||
| organization, or merging organizations.  If propagation of a covered | ||||
| work results from an entity transaction, each party to that | ||||
| transaction who receives a copy of the work also receives whatever | ||||
| licenses to the work the party's predecessor in interest had or could | ||||
| give under the previous paragraph, plus a right to possession of the | ||||
| Corresponding Source of the work from the predecessor in interest, if | ||||
| the predecessor has it or can get it with reasonable efforts. | ||||
|  | ||||
|   You may not impose any further restrictions on the exercise of the | ||||
| rights granted or affirmed under this License.  For example, you may | ||||
| not impose a license fee, royalty, or other charge for exercise of | ||||
| rights granted under this License, and you may not initiate litigation | ||||
| (including a cross-claim or counterclaim in a lawsuit) alleging that | ||||
| any patent claim is infringed by making, using, selling, offering for | ||||
| sale, or importing the Program or any portion of it. | ||||
|  | ||||
|   11. Patents. | ||||
|  | ||||
|   A "contributor" is a copyright holder who authorizes use under this | ||||
| License of the Program or a work on which the Program is based.  The | ||||
| work thus licensed is called the contributor's "contributor version". | ||||
|  | ||||
|   A contributor's "essential patent claims" are all patent claims | ||||
| owned or controlled by the contributor, whether already acquired or | ||||
| hereafter acquired, that would be infringed by some manner, permitted | ||||
| by this License, of making, using, or selling its contributor version, | ||||
| but do not include claims that would be infringed only as a | ||||
| consequence of further modification of the contributor version.  For | ||||
| purposes of this definition, "control" includes the right to grant | ||||
| patent sublicenses in a manner consistent with the requirements of | ||||
| this License. | ||||
|  | ||||
|   Each contributor grants you a non-exclusive, worldwide, royalty-free | ||||
| patent license under the contributor's essential patent claims, to | ||||
| make, use, sell, offer for sale, import and otherwise run, modify and | ||||
| propagate the contents of its contributor version. | ||||
|  | ||||
|   In the following three paragraphs, a "patent license" is any express | ||||
| agreement or commitment, however denominated, not to enforce a patent | ||||
| (such as an express permission to practice a patent or covenant not to | ||||
| sue for patent infringement).  To "grant" such a patent license to a | ||||
| party means to make such an agreement or commitment not to enforce a | ||||
| patent against the party. | ||||
|  | ||||
|   If you convey a covered work, knowingly relying on a patent license, | ||||
| and the Corresponding Source of the work is not available for anyone | ||||
| to copy, free of charge and under the terms of this License, through a | ||||
| publicly available network server or other readily accessible means, | ||||
| then you must either (1) cause the Corresponding Source to be so | ||||
| available, or (2) arrange to deprive yourself of the benefit of the | ||||
| patent license for this particular work, or (3) arrange, in a manner | ||||
| consistent with the requirements of this License, to extend the patent | ||||
| license to downstream recipients.  "Knowingly relying" means you have | ||||
| actual knowledge that, but for the patent license, your conveying the | ||||
| covered work in a country, or your recipient's use of the covered work | ||||
| in a country, would infringe one or more identifiable patents in that | ||||
| country that you have reason to believe are valid. | ||||
|  | ||||
|   If, pursuant to or in connection with a single transaction or | ||||
| arrangement, you convey, or propagate by procuring conveyance of, a | ||||
| covered work, and grant a patent license to some of the parties | ||||
| receiving the covered work authorizing them to use, propagate, modify | ||||
| or convey a specific copy of the covered work, then the patent license | ||||
| you grant is automatically extended to all recipients of the covered | ||||
| work and works based on it. | ||||
|  | ||||
|   A patent license is "discriminatory" if it does not include within | ||||
| the scope of its coverage, prohibits the exercise of, or is | ||||
| conditioned on the non-exercise of one or more of the rights that are | ||||
| specifically granted under this License.  You may not convey a covered | ||||
| work if you are a party to an arrangement with a third party that is | ||||
| in the business of distributing software, under which you make payment | ||||
| to the third party based on the extent of your activity of conveying | ||||
| the work, and under which the third party grants, to any of the | ||||
| parties who would receive the covered work from you, a discriminatory | ||||
| patent license (a) in connection with copies of the covered work | ||||
| conveyed by you (or copies made from those copies), or (b) primarily | ||||
| for and in connection with specific products or compilations that | ||||
| contain the covered work, unless you entered into that arrangement, | ||||
| or that patent license was granted, prior to 28 March 2007. | ||||
|  | ||||
|   Nothing in this License shall be construed as excluding or limiting | ||||
| any implied license or other defenses to infringement that may | ||||
| otherwise be available to you under applicable patent law. | ||||
|  | ||||
|   12. No Surrender of Others' Freedom. | ||||
|  | ||||
|   If conditions are imposed on you (whether by court order, agreement or | ||||
| otherwise) that contradict the conditions of this License, they do not | ||||
| excuse you from the conditions of this License.  If you cannot convey a | ||||
| covered work so as to satisfy simultaneously your obligations under this | ||||
| License and any other pertinent obligations, then as a consequence you may | ||||
| not convey it at all.  For example, if you agree to terms that obligate you | ||||
| to collect a royalty for further conveying from those to whom you convey | ||||
| the Program, the only way you could satisfy both those terms and this | ||||
| License would be to refrain entirely from conveying the Program. | ||||
|  | ||||
|   13. Use with the GNU Affero General Public License. | ||||
|  | ||||
|   Notwithstanding any other provision of this License, you have | ||||
| permission to link or combine any covered work with a work licensed | ||||
| under version 3 of the GNU Affero General Public License into a single | ||||
| combined work, and to convey the resulting work.  The terms of this | ||||
| License will continue to apply to the part which is the covered work, | ||||
| but the special requirements of the GNU Affero General Public License, | ||||
| section 13, concerning interaction through a network will apply to the | ||||
| combination as such. | ||||
|  | ||||
|   14. Revised Versions of this License. | ||||
|  | ||||
|   The Free Software Foundation may publish revised and/or new versions of | ||||
| the GNU General Public License from time to time.  Such new versions will | ||||
| be similar in spirit to the present version, but may differ in detail to | ||||
| address new problems or concerns. | ||||
|  | ||||
|   Each version is given a distinguishing version number.  If the | ||||
| Program specifies that a certain numbered version of the GNU General | ||||
| Public License "or any later version" applies to it, you have the | ||||
| option of following the terms and conditions either of that numbered | ||||
| version or of any later version published by the Free Software | ||||
| Foundation.  If the Program does not specify a version number of the | ||||
| GNU General Public License, you may choose any version ever published | ||||
| by the Free Software Foundation. | ||||
|  | ||||
|   If the Program specifies that a proxy can decide which future | ||||
| versions of the GNU General Public License can be used, that proxy's | ||||
| public statement of acceptance of a version permanently authorizes you | ||||
| to choose that version for the Program. | ||||
|  | ||||
|   Later license versions may give you additional or different | ||||
| permissions.  However, no additional obligations are imposed on any | ||||
| author or copyright holder as a result of your choosing to follow a | ||||
| later version. | ||||
|  | ||||
|   15. Disclaimer of Warranty. | ||||
|  | ||||
|   THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | ||||
| APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | ||||
| HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | ||||
| OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | ||||
| THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||
| PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | ||||
| IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | ||||
| ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||||
|  | ||||
|   16. Limitation of Liability. | ||||
|  | ||||
|   IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | ||||
| WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | ||||
| THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | ||||
| GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | ||||
| USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | ||||
| DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | ||||
| PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | ||||
| EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | ||||
| SUCH DAMAGES. | ||||
|  | ||||
|   17. Interpretation of Sections 15 and 16. | ||||
|  | ||||
|   If the disclaimer of warranty and limitation of liability provided | ||||
| above cannot be given local legal effect according to their terms, | ||||
| reviewing courts shall apply local law that most closely approximates | ||||
| an absolute waiver of all civil liability in connection with the | ||||
| Program, unless a warranty or assumption of liability accompanies a | ||||
| copy of the Program in return for a fee. | ||||
|  | ||||
|                      END OF TERMS AND CONDITIONS | ||||
|  | ||||
|             How to Apply These Terms to Your New Programs | ||||
|  | ||||
|   If you develop a new program, and you want it to be of the greatest | ||||
| possible use to the public, the best way to achieve this is to make it | ||||
| free software which everyone can redistribute and change under these terms. | ||||
|  | ||||
|   To do so, attach the following notices to the program.  It is safest | ||||
| to attach them to the start of each source file to most effectively | ||||
| state the exclusion of warranty; and each file should have at least | ||||
| the "copyright" line and a pointer to where the full notice is found. | ||||
|  | ||||
|     <one line to give the program's name and a brief idea of what it does.> | ||||
|     Copyright (C) <year>  <name of author> | ||||
|  | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| Also add information on how to contact you by electronic and paper mail. | ||||
|  | ||||
|   If the program does terminal interaction, make it output a short | ||||
| notice like this when it starts in an interactive mode: | ||||
|  | ||||
|     <program>  Copyright (C) <year>  <name of author> | ||||
|     This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | ||||
|     This is free software, and you are welcome to redistribute it | ||||
|     under certain conditions; type `show c' for details. | ||||
|  | ||||
| The hypothetical commands `show w' and `show c' should show the appropriate | ||||
| parts of the General Public License.  Of course, your program's commands | ||||
| might be different; for a GUI interface, you would use an "about box". | ||||
|  | ||||
|   You should also get your employer (if you work as a programmer) or school, | ||||
| if any, to sign a "copyright disclaimer" for the program, if necessary. | ||||
| For more information on this, and how to apply and follow the GNU GPL, see | ||||
| <http://www.gnu.org/licenses/>. | ||||
|  | ||||
|   The GNU General Public License does not permit incorporating your program | ||||
| into proprietary programs.  If your program is a subroutine library, you | ||||
| may consider it more useful to permit linking proprietary applications with | ||||
| the library.  If this is what you want to do, use the GNU Lesser General | ||||
| Public License instead of this License.  But first, please read | ||||
| <http://www.gnu.org/philosophy/why-not-lgpl.html>. | ||||
							
								
								
									
										165
									
								
								libusb/COPYING_LGPL.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								libusb/COPYING_LGPL.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
|                    GNU LESSER GENERAL PUBLIC LICENSE | ||||
|                        Version 3, 29 June 2007 | ||||
|  | ||||
|  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
|  | ||||
|  | ||||
|   This version of the GNU Lesser General Public License incorporates | ||||
| the terms and conditions of version 3 of the GNU General Public | ||||
| License, supplemented by the additional permissions listed below. | ||||
|  | ||||
|   0. Additional Definitions. | ||||
|  | ||||
|   As used herein, "this License" refers to version 3 of the GNU Lesser | ||||
| General Public License, and the "GNU GPL" refers to version 3 of the GNU | ||||
| General Public License. | ||||
|  | ||||
|   "The Library" refers to a covered work governed by this License, | ||||
| other than an Application or a Combined Work as defined below. | ||||
|  | ||||
|   An "Application" is any work that makes use of an interface provided | ||||
| by the Library, but which is not otherwise based on the Library. | ||||
| Defining a subclass of a class defined by the Library is deemed a mode | ||||
| of using an interface provided by the Library. | ||||
|  | ||||
|   A "Combined Work" is a work produced by combining or linking an | ||||
| Application with the Library.  The particular version of the Library | ||||
| with which the Combined Work was made is also called the "Linked | ||||
| Version". | ||||
|  | ||||
|   The "Minimal Corresponding Source" for a Combined Work means the | ||||
| Corresponding Source for the Combined Work, excluding any source code | ||||
| for portions of the Combined Work that, considered in isolation, are | ||||
| based on the Application, and not on the Linked Version. | ||||
|  | ||||
|   The "Corresponding Application Code" for a Combined Work means the | ||||
| object code and/or source code for the Application, including any data | ||||
| and utility programs needed for reproducing the Combined Work from the | ||||
| Application, but excluding the System Libraries of the Combined Work. | ||||
|  | ||||
|   1. Exception to Section 3 of the GNU GPL. | ||||
|  | ||||
|   You may convey a covered work under sections 3 and 4 of this License | ||||
| without being bound by section 3 of the GNU GPL. | ||||
|  | ||||
|   2. Conveying Modified Versions. | ||||
|  | ||||
|   If you modify a copy of the Library, and, in your modifications, a | ||||
| facility refers to a function or data to be supplied by an Application | ||||
| that uses the facility (other than as an argument passed when the | ||||
| facility is invoked), then you may convey a copy of the modified | ||||
| version: | ||||
|  | ||||
|    a) under this License, provided that you make a good faith effort to | ||||
|    ensure that, in the event an Application does not supply the | ||||
|    function or data, the facility still operates, and performs | ||||
|    whatever part of its purpose remains meaningful, or | ||||
|  | ||||
|    b) under the GNU GPL, with none of the additional permissions of | ||||
|    this License applicable to that copy. | ||||
|  | ||||
|   3. Object Code Incorporating Material from Library Header Files. | ||||
|  | ||||
|   The object code form of an Application may incorporate material from | ||||
| a header file that is part of the Library.  You may convey such object | ||||
| code under terms of your choice, provided that, if the incorporated | ||||
| material is not limited to numerical parameters, data structure | ||||
| layouts and accessors, or small macros, inline functions and templates | ||||
| (ten or fewer lines in length), you do both of the following: | ||||
|  | ||||
|    a) Give prominent notice with each copy of the object code that the | ||||
|    Library is used in it and that the Library and its use are | ||||
|    covered by this License. | ||||
|  | ||||
|    b) Accompany the object code with a copy of the GNU GPL and this license | ||||
|    document. | ||||
|  | ||||
|   4. Combined Works. | ||||
|  | ||||
|   You may convey a Combined Work under terms of your choice that, | ||||
| taken together, effectively do not restrict modification of the | ||||
| portions of the Library contained in the Combined Work and reverse | ||||
| engineering for debugging such modifications, if you also do each of | ||||
| the following: | ||||
|  | ||||
|    a) Give prominent notice with each copy of the Combined Work that | ||||
|    the Library is used in it and that the Library and its use are | ||||
|    covered by this License. | ||||
|  | ||||
|    b) Accompany the Combined Work with a copy of the GNU GPL and this license | ||||
|    document. | ||||
|  | ||||
|    c) For a Combined Work that displays copyright notices during | ||||
|    execution, include the copyright notice for the Library among | ||||
|    these notices, as well as a reference directing the user to the | ||||
|    copies of the GNU GPL and this license document. | ||||
|  | ||||
|    d) Do one of the following: | ||||
|  | ||||
|        0) Convey the Minimal Corresponding Source under the terms of this | ||||
|        License, and the Corresponding Application Code in a form | ||||
|        suitable for, and under terms that permit, the user to | ||||
|        recombine or relink the Application with a modified version of | ||||
|        the Linked Version to produce a modified Combined Work, in the | ||||
|        manner specified by section 6 of the GNU GPL for conveying | ||||
|        Corresponding Source. | ||||
|  | ||||
|        1) Use a suitable shared library mechanism for linking with the | ||||
|        Library.  A suitable mechanism is one that (a) uses at run time | ||||
|        a copy of the Library already present on the user's computer | ||||
|        system, and (b) will operate properly with a modified version | ||||
|        of the Library that is interface-compatible with the Linked | ||||
|        Version. | ||||
|  | ||||
|    e) Provide Installation Information, but only if you would otherwise | ||||
|    be required to provide such information under section 6 of the | ||||
|    GNU GPL, and only to the extent that such information is | ||||
|    necessary to install and execute a modified version of the | ||||
|    Combined Work produced by recombining or relinking the | ||||
|    Application with a modified version of the Linked Version. (If | ||||
|    you use option 4d0, the Installation Information must accompany | ||||
|    the Minimal Corresponding Source and Corresponding Application | ||||
|    Code. If you use option 4d1, you must provide the Installation | ||||
|    Information in the manner specified by section 6 of the GNU GPL | ||||
|    for conveying Corresponding Source.) | ||||
|  | ||||
|   5. Combined Libraries. | ||||
|  | ||||
|   You may place library facilities that are a work based on the | ||||
| Library side by side in a single library together with other library | ||||
| facilities that are not Applications and are not covered by this | ||||
| License, and convey such a combined library under terms of your | ||||
| choice, if you do both of the following: | ||||
|  | ||||
|    a) Accompany the combined library with a copy of the same work based | ||||
|    on the Library, uncombined with any other library facilities, | ||||
|    conveyed under the terms of this License. | ||||
|  | ||||
|    b) Give prominent notice with the combined library that part of it | ||||
|    is a work based on the Library, and explaining where to find the | ||||
|    accompanying uncombined form of the same work. | ||||
|  | ||||
|   6. Revised Versions of the GNU Lesser General Public License. | ||||
|  | ||||
|   The Free Software Foundation may publish revised and/or new versions | ||||
| of the GNU Lesser General Public License from time to time. Such new | ||||
| versions will be similar in spirit to the present version, but may | ||||
| differ in detail to address new problems or concerns. | ||||
|  | ||||
|   Each version is given a distinguishing version number. If the | ||||
| Library as you received it specifies that a certain numbered version | ||||
| of the GNU Lesser General Public License "or any later version" | ||||
| applies to it, you have the option of following the terms and | ||||
| conditions either of that published version or of any later version | ||||
| published by the Free Software Foundation. If the Library as you | ||||
| received it does not specify a version number of the GNU Lesser | ||||
| General Public License, you may choose any version of the GNU Lesser | ||||
| General Public License ever published by the Free Software Foundation. | ||||
|  | ||||
|   If the Library as you received it specifies that a proxy can decide | ||||
| whether future versions of the GNU Lesser General Public License shall | ||||
| apply, that proxy's public statement of acceptance of any version is | ||||
| permanent authorization for you to choose that version for the | ||||
| Library. | ||||
							
								
								
									
										12
									
								
								libusb/README.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								libusb/README.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
|  | ||||
| This is libusb-win32 (http://libusb-win32.sourceforge.net) version 1.2.6.0.  | ||||
| Libusb-win32 is a library that allows userspace application to access USB  | ||||
| devices on Windows operation systems (Win2k, WinXP, Vista, Win7).  | ||||
| It is derived from and fully API compatible to libusb available at  | ||||
| http://libusb.sourceforge.net. | ||||
|  | ||||
| For more information visit the project's web site at: | ||||
|  | ||||
| http://libusb-win32.sourceforge.net | ||||
| http://sourceforge.net/projects/libusb-win32 | ||||
|  | ||||
							
								
								
									
										427
									
								
								libusb/include/lusb0_usb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										427
									
								
								libusb/include/lusb0_usb.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,427 @@ | ||||
| #ifndef __USB_H__ | ||||
| #define __USB_H__ | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <windows.h> | ||||
|  | ||||
| /* | ||||
|  * 'interface' is defined somewhere in the Windows header files. This macro | ||||
|  * is deleted here to avoid conflicts and compile errors. | ||||
|  */ | ||||
|  | ||||
| #ifdef interface | ||||
| #undef interface | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * PATH_MAX from limits.h can't be used on Windows if the dll and | ||||
|  * import libraries are build/used by different compilers | ||||
|  */ | ||||
|  | ||||
| #define LIBUSB_PATH_MAX 512 | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * USB spec information | ||||
|  * | ||||
|  * This is all stuff grabbed from various USB specs and is pretty much | ||||
|  * not subject to change | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Device and/or Interface Class codes | ||||
|  */ | ||||
| #define USB_CLASS_PER_INTERFACE		0	/* for DeviceClass */ | ||||
| #define USB_CLASS_AUDIO			      1 | ||||
| #define USB_CLASS_COMM			      2 | ||||
| #define USB_CLASS_HID			        3 | ||||
| #define USB_CLASS_PRINTER		      7 | ||||
| #define USB_CLASS_MASS_STORAGE		8 | ||||
| #define USB_CLASS_HUB			        9 | ||||
| #define USB_CLASS_DATA			      10 | ||||
| #define USB_CLASS_VENDOR_SPEC		  0xff | ||||
|  | ||||
| /* | ||||
|  * Descriptor types | ||||
|  */ | ||||
| #define USB_DT_DEVICE			0x01 | ||||
| #define USB_DT_CONFIG			0x02 | ||||
| #define USB_DT_STRING			0x03 | ||||
| #define USB_DT_INTERFACE	0x04 | ||||
| #define USB_DT_ENDPOINT		0x05 | ||||
|  | ||||
| #define USB_DT_HID			0x21 | ||||
| #define USB_DT_REPORT		0x22 | ||||
| #define USB_DT_PHYSICAL	0x23 | ||||
| #define USB_DT_HUB			0x29 | ||||
|  | ||||
| /* | ||||
|  * Descriptor sizes per descriptor type | ||||
|  */ | ||||
| #define USB_DT_DEVICE_SIZE		18 | ||||
| #define USB_DT_CONFIG_SIZE		9 | ||||
| #define USB_DT_INTERFACE_SIZE		9 | ||||
| #define USB_DT_ENDPOINT_SIZE		7 | ||||
| #define USB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */ | ||||
| #define USB_DT_HUB_NONVAR_SIZE		7 | ||||
|  | ||||
|  | ||||
| /* ensure byte-packed structures */ | ||||
| #include <pshpack1.h> | ||||
|  | ||||
|  | ||||
| /* All standard descriptors have these 2 fields in common */ | ||||
| struct usb_descriptor_header | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
| }; | ||||
|  | ||||
| /* String descriptor */ | ||||
| struct usb_string_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned short wData[1]; | ||||
| }; | ||||
|  | ||||
| /* HID descriptor */ | ||||
| struct usb_hid_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned short bcdHID; | ||||
|     unsigned char  bCountryCode; | ||||
|     unsigned char  bNumDescriptors; | ||||
| }; | ||||
|  | ||||
| /* Endpoint descriptor */ | ||||
| #define USB_MAXENDPOINTS	32 | ||||
| struct usb_endpoint_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned char  bEndpointAddress; | ||||
|     unsigned char  bmAttributes; | ||||
|     unsigned short wMaxPacketSize; | ||||
|     unsigned char  bInterval; | ||||
|     unsigned char  bRefresh; | ||||
|     unsigned char  bSynchAddress; | ||||
|  | ||||
|     unsigned char *extra;	/* Extra descriptors */ | ||||
|     int extralen; | ||||
| }; | ||||
|  | ||||
| #define USB_ENDPOINT_ADDRESS_MASK	0x0f    /* in bEndpointAddress */ | ||||
| #define USB_ENDPOINT_DIR_MASK		  0x80 | ||||
|  | ||||
| #define USB_ENDPOINT_TYPE_MASK		0x03    /* in bmAttributes */ | ||||
| #define USB_ENDPOINT_TYPE_CONTROL	    0 | ||||
| #define USB_ENDPOINT_TYPE_ISOCHRONOUS	1 | ||||
| #define USB_ENDPOINT_TYPE_BULK		    2 | ||||
| #define USB_ENDPOINT_TYPE_INTERRUPT	  3 | ||||
|  | ||||
| /* Interface descriptor */ | ||||
| #define USB_MAXINTERFACES	32 | ||||
| struct usb_interface_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned char  bInterfaceNumber; | ||||
|     unsigned char  bAlternateSetting; | ||||
|     unsigned char  bNumEndpoints; | ||||
|     unsigned char  bInterfaceClass; | ||||
|     unsigned char  bInterfaceSubClass; | ||||
|     unsigned char  bInterfaceProtocol; | ||||
|     unsigned char  iInterface; | ||||
|  | ||||
|     struct usb_endpoint_descriptor *endpoint; | ||||
|  | ||||
|     unsigned char *extra;	/* Extra descriptors */ | ||||
|     int extralen; | ||||
| }; | ||||
|  | ||||
| #define USB_MAXALTSETTING	128	/* Hard limit */ | ||||
|  | ||||
| struct usb_interface | ||||
| { | ||||
|     struct usb_interface_descriptor *altsetting; | ||||
|  | ||||
|     int num_altsetting; | ||||
| }; | ||||
|  | ||||
| /* Configuration descriptor information.. */ | ||||
| #define USB_MAXCONFIG		8 | ||||
| struct usb_config_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned short wTotalLength; | ||||
|     unsigned char  bNumInterfaces; | ||||
|     unsigned char  bConfigurationValue; | ||||
|     unsigned char  iConfiguration; | ||||
|     unsigned char  bmAttributes; | ||||
|     unsigned char  MaxPower; | ||||
|  | ||||
|     struct usb_interface *interface; | ||||
|  | ||||
|     unsigned char *extra;	/* Extra descriptors */ | ||||
|     int extralen; | ||||
| }; | ||||
|  | ||||
| /* Device descriptor */ | ||||
| struct usb_device_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned short bcdUSB; | ||||
|     unsigned char  bDeviceClass; | ||||
|     unsigned char  bDeviceSubClass; | ||||
|     unsigned char  bDeviceProtocol; | ||||
|     unsigned char  bMaxPacketSize0; | ||||
|     unsigned short idVendor; | ||||
|     unsigned short idProduct; | ||||
|     unsigned short bcdDevice; | ||||
|     unsigned char  iManufacturer; | ||||
|     unsigned char  iProduct; | ||||
|     unsigned char  iSerialNumber; | ||||
|     unsigned char  bNumConfigurations; | ||||
| }; | ||||
|  | ||||
| struct usb_ctrl_setup | ||||
| { | ||||
|     unsigned char  bRequestType; | ||||
|     unsigned char  bRequest; | ||||
|     unsigned short wValue; | ||||
|     unsigned short wIndex; | ||||
|     unsigned short wLength; | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Standard requests | ||||
|  */ | ||||
| #define USB_REQ_GET_STATUS		    0x00 | ||||
| #define USB_REQ_CLEAR_FEATURE	    0x01 | ||||
| /* 0x02 is reserved */ | ||||
| #define USB_REQ_SET_FEATURE		    0x03 | ||||
| /* 0x04 is reserved */ | ||||
| #define USB_REQ_SET_ADDRESS		    0x05 | ||||
| #define USB_REQ_GET_DESCRIPTOR		0x06 | ||||
| #define USB_REQ_SET_DESCRIPTOR		0x07 | ||||
| #define USB_REQ_GET_CONFIGURATION	0x08 | ||||
| #define USB_REQ_SET_CONFIGURATION	0x09 | ||||
| #define USB_REQ_GET_INTERFACE		  0x0A | ||||
| #define USB_REQ_SET_INTERFACE		  0x0B | ||||
| #define USB_REQ_SYNCH_FRAME		    0x0C | ||||
|  | ||||
| #define USB_TYPE_STANDARD		(0x00 << 5) | ||||
| #define USB_TYPE_CLASS			(0x01 << 5) | ||||
| #define USB_TYPE_VENDOR			(0x02 << 5) | ||||
| #define USB_TYPE_RESERVED		(0x03 << 5) | ||||
|  | ||||
| #define USB_RECIP_DEVICE		0x00 | ||||
| #define USB_RECIP_INTERFACE	0x01 | ||||
| #define USB_RECIP_ENDPOINT	0x02 | ||||
| #define USB_RECIP_OTHER			0x03 | ||||
|  | ||||
| /* | ||||
|  * Various libusb API related stuff | ||||
|  */ | ||||
|  | ||||
| #define USB_ENDPOINT_IN			0x80 | ||||
| #define USB_ENDPOINT_OUT		0x00 | ||||
|  | ||||
| /* Error codes */ | ||||
| #define USB_ERROR_BEGIN			500000 | ||||
|  | ||||
| /* | ||||
|  * This is supposed to look weird. This file is generated from autoconf | ||||
|  * and I didn't want to make this too complicated. | ||||
|  */ | ||||
| #define USB_LE16_TO_CPU(x) | ||||
|  | ||||
| /* | ||||
|  * Device reset types for usb_reset_ex. | ||||
|  * http://msdn.microsoft.com/en-us/library/ff537269%28VS.85%29.aspx | ||||
|  * http://msdn.microsoft.com/en-us/library/ff537243%28v=vs.85%29.aspx | ||||
|  */ | ||||
| #define USB_RESET_TYPE_RESET_PORT (1 << 0) | ||||
| #define USB_RESET_TYPE_CYCLE_PORT (1 << 1) | ||||
| #define USB_RESET_TYPE_FULL_RESET (USB_RESET_TYPE_CYCLE_PORT | USB_RESET_TYPE_RESET_PORT) | ||||
|  | ||||
|  | ||||
| /* Data types */ | ||||
| /* struct usb_device; */ | ||||
| /* struct usb_bus; */ | ||||
|  | ||||
| struct usb_device | ||||
| { | ||||
|     struct usb_device *next, *prev; | ||||
|  | ||||
|     char filename[LIBUSB_PATH_MAX]; | ||||
|  | ||||
|     struct usb_bus *bus; | ||||
|  | ||||
|     struct usb_device_descriptor descriptor; | ||||
|     struct usb_config_descriptor *config; | ||||
|  | ||||
|     void *dev;		/* Darwin support */ | ||||
|  | ||||
|     unsigned char devnum; | ||||
|  | ||||
|     unsigned char num_children; | ||||
|     struct usb_device **children; | ||||
| }; | ||||
|  | ||||
| struct usb_bus | ||||
| { | ||||
|     struct usb_bus *next, *prev; | ||||
|  | ||||
|     char dirname[LIBUSB_PATH_MAX]; | ||||
|  | ||||
|     struct usb_device *devices; | ||||
|     unsigned long location; | ||||
|  | ||||
|     struct usb_device *root_dev; | ||||
| }; | ||||
|  | ||||
| /* Version information, Windows specific */ | ||||
| struct usb_version | ||||
| { | ||||
|     struct | ||||
|     { | ||||
|         int major; | ||||
|         int minor; | ||||
|         int micro; | ||||
|         int nano; | ||||
|     } dll; | ||||
|     struct | ||||
|     { | ||||
|         int major; | ||||
|         int minor; | ||||
|         int micro; | ||||
|         int nano; | ||||
|     } driver; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct usb_dev_handle; | ||||
| typedef struct usb_dev_handle usb_dev_handle; | ||||
|  | ||||
| /* Variables */ | ||||
| #ifndef __USB_C__ | ||||
| #define usb_busses usb_get_busses() | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
| #include <poppack.h> | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| { | ||||
| #endif | ||||
|  | ||||
|     /* Function prototypes */ | ||||
|  | ||||
|     /* usb.c */ | ||||
|     usb_dev_handle *usb_open(struct usb_device *dev); | ||||
|     int usb_close(usb_dev_handle *dev); | ||||
|     int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf, | ||||
|                        size_t buflen); | ||||
|     int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, | ||||
|                               size_t buflen); | ||||
|  | ||||
|     /* descriptors.c */ | ||||
|     int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep, | ||||
|                                        unsigned char type, unsigned char index, | ||||
|                                        void *buf, int size); | ||||
|     int usb_get_descriptor(usb_dev_handle *udev, unsigned char type, | ||||
|                            unsigned char index, void *buf, int size); | ||||
|  | ||||
|     /* <arch>.c */ | ||||
|     int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                        int timeout); | ||||
|     int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                       int timeout); | ||||
|     int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                             int timeout); | ||||
|     int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                            int timeout); | ||||
|     int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, | ||||
|                         int value, int index, char *bytes, int size, | ||||
|                         int timeout); | ||||
|     int usb_set_configuration(usb_dev_handle *dev, int configuration); | ||||
|     int usb_claim_interface(usb_dev_handle *dev, int interface); | ||||
|     int usb_release_interface(usb_dev_handle *dev, int interface); | ||||
|     int usb_set_altinterface(usb_dev_handle *dev, int alternate); | ||||
|     int usb_resetep(usb_dev_handle *dev, unsigned int ep); | ||||
|     int usb_clear_halt(usb_dev_handle *dev, unsigned int ep); | ||||
|     int usb_reset(usb_dev_handle *dev); | ||||
|     int usb_reset_ex(usb_dev_handle *dev, unsigned int reset_type); | ||||
|  | ||||
|     char *usb_strerror(void); | ||||
|  | ||||
|     void usb_init(void); | ||||
|     void usb_set_debug(int level); | ||||
|     int usb_find_busses(void); | ||||
|     int usb_find_devices(void); | ||||
|     struct usb_device *usb_device(usb_dev_handle *dev); | ||||
|     struct usb_bus *usb_get_busses(void); | ||||
|  | ||||
|  | ||||
|     /* Windows specific functions */ | ||||
|  | ||||
| #define LIBUSB_HAS_INSTALL_SERVICE_NP 1 | ||||
|     int usb_install_service_np(void); | ||||
|     void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance, | ||||
|             LPSTR cmd_line, int cmd_show); | ||||
|  | ||||
| #define LIBUSB_HAS_UNINSTALL_SERVICE_NP 1 | ||||
|     int usb_uninstall_service_np(void); | ||||
|     void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance, | ||||
|             LPSTR cmd_line, int cmd_show); | ||||
|  | ||||
| #define LIBUSB_HAS_INSTALL_DRIVER_NP 1 | ||||
|     int usb_install_driver_np(const char *inf_file); | ||||
|     void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance, | ||||
|             LPSTR cmd_line, int cmd_show); | ||||
|  | ||||
| #define LIBUSB_HAS_TOUCH_INF_FILE_NP 1 | ||||
|     int usb_touch_inf_file_np(const char *inf_file); | ||||
|     void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance, | ||||
|             LPSTR cmd_line, int cmd_show); | ||||
|  | ||||
| #define LIBUSB_HAS_INSTALL_NEEDS_RESTART_NP 1 | ||||
|     int usb_install_needs_restart_np(void); | ||||
|  | ||||
| #define LIBUSB_HAS_INSTALL_NP 1 | ||||
|     int usb_install_npW(HWND hwnd, HINSTANCE instance, LPCWSTR cmd_line, int starg_arg); | ||||
|     int usb_install_npA(HWND hwnd, HINSTANCE instance, LPCSTR cmd_line, int starg_arg); | ||||
| 	#define usb_install_np usb_install_npA | ||||
|     void CALLBACK usb_install_np_rundll(HWND wnd, HINSTANCE instance,  | ||||
|             LPSTR cmd_line, int cmd_show); | ||||
|  | ||||
|     const struct usb_version *usb_get_version(void); | ||||
|  | ||||
|     int usb_isochronous_setup_async(usb_dev_handle *dev, void **context, | ||||
|                                     unsigned char ep, int pktsize); | ||||
|     int usb_bulk_setup_async(usb_dev_handle *dev, void **context, | ||||
|                              unsigned char ep); | ||||
|     int usb_interrupt_setup_async(usb_dev_handle *dev, void **context, | ||||
|                                   unsigned char ep); | ||||
|  | ||||
|     int usb_submit_async(void *context, char *bytes, int size); | ||||
|     int usb_reap_async(void *context, int timeout); | ||||
|     int usb_reap_async_nocancel(void *context, int timeout); | ||||
|     int usb_cancel_async(void *context); | ||||
|     int usb_free_async(void **context); | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* __USB_H__ */ | ||||
|  | ||||
							
								
								
									
										427
									
								
								libusb/include/usb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										427
									
								
								libusb/include/usb.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,427 @@ | ||||
| #ifndef __USB_H__ | ||||
| #define __USB_H__ | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <windows.h> | ||||
|  | ||||
| /* | ||||
|  * 'interface' is defined somewhere in the Windows header files. This macro | ||||
|  * is deleted here to avoid conflicts and compile errors. | ||||
|  */ | ||||
|  | ||||
| #ifdef interface | ||||
| #undef interface | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * PATH_MAX from limits.h can't be used on Windows if the dll and | ||||
|  * import libraries are build/used by different compilers | ||||
|  */ | ||||
|  | ||||
| #define LIBUSB_PATH_MAX 512 | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * USB spec information | ||||
|  * | ||||
|  * This is all stuff grabbed from various USB specs and is pretty much | ||||
|  * not subject to change | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Device and/or Interface Class codes | ||||
|  */ | ||||
| #define USB_CLASS_PER_INTERFACE		0	/* for DeviceClass */ | ||||
| #define USB_CLASS_AUDIO			      1 | ||||
| #define USB_CLASS_COMM			      2 | ||||
| #define USB_CLASS_HID			        3 | ||||
| #define USB_CLASS_PRINTER		      7 | ||||
| #define USB_CLASS_MASS_STORAGE		8 | ||||
| #define USB_CLASS_HUB			        9 | ||||
| #define USB_CLASS_DATA			      10 | ||||
| #define USB_CLASS_VENDOR_SPEC		  0xff | ||||
|  | ||||
| /* | ||||
|  * Descriptor types | ||||
|  */ | ||||
| #define USB_DT_DEVICE			0x01 | ||||
| #define USB_DT_CONFIG			0x02 | ||||
| #define USB_DT_STRING			0x03 | ||||
| #define USB_DT_INTERFACE	0x04 | ||||
| #define USB_DT_ENDPOINT		0x05 | ||||
|  | ||||
| #define USB_DT_HID			0x21 | ||||
| #define USB_DT_REPORT		0x22 | ||||
| #define USB_DT_PHYSICAL	0x23 | ||||
| #define USB_DT_HUB			0x29 | ||||
|  | ||||
| /* | ||||
|  * Descriptor sizes per descriptor type | ||||
|  */ | ||||
| #define USB_DT_DEVICE_SIZE		18 | ||||
| #define USB_DT_CONFIG_SIZE		9 | ||||
| #define USB_DT_INTERFACE_SIZE		9 | ||||
| #define USB_DT_ENDPOINT_SIZE		7 | ||||
| #define USB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */ | ||||
| #define USB_DT_HUB_NONVAR_SIZE		7 | ||||
|  | ||||
|  | ||||
| /* ensure byte-packed structures */ | ||||
| #include <pshpack1.h> | ||||
|  | ||||
|  | ||||
| /* All standard descriptors have these 2 fields in common */ | ||||
| struct usb_descriptor_header | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
| }; | ||||
|  | ||||
| /* String descriptor */ | ||||
| struct usb_string_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned short wData[1]; | ||||
| }; | ||||
|  | ||||
| /* HID descriptor */ | ||||
| struct usb_hid_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned short bcdHID; | ||||
|     unsigned char  bCountryCode; | ||||
|     unsigned char  bNumDescriptors; | ||||
| }; | ||||
|  | ||||
| /* Endpoint descriptor */ | ||||
| #define USB_MAXENDPOINTS	32 | ||||
| struct usb_endpoint_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned char  bEndpointAddress; | ||||
|     unsigned char  bmAttributes; | ||||
|     unsigned short wMaxPacketSize; | ||||
|     unsigned char  bInterval; | ||||
|     unsigned char  bRefresh; | ||||
|     unsigned char  bSynchAddress; | ||||
|  | ||||
|     unsigned char *extra;	/* Extra descriptors */ | ||||
|     int extralen; | ||||
| }; | ||||
|  | ||||
| #define USB_ENDPOINT_ADDRESS_MASK	0x0f    /* in bEndpointAddress */ | ||||
| #define USB_ENDPOINT_DIR_MASK		  0x80 | ||||
|  | ||||
| #define USB_ENDPOINT_TYPE_MASK		0x03    /* in bmAttributes */ | ||||
| #define USB_ENDPOINT_TYPE_CONTROL	    0 | ||||
| #define USB_ENDPOINT_TYPE_ISOCHRONOUS	1 | ||||
| #define USB_ENDPOINT_TYPE_BULK		    2 | ||||
| #define USB_ENDPOINT_TYPE_INTERRUPT	  3 | ||||
|  | ||||
| /* Interface descriptor */ | ||||
| #define USB_MAXINTERFACES	32 | ||||
| struct usb_interface_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned char  bInterfaceNumber; | ||||
|     unsigned char  bAlternateSetting; | ||||
|     unsigned char  bNumEndpoints; | ||||
|     unsigned char  bInterfaceClass; | ||||
|     unsigned char  bInterfaceSubClass; | ||||
|     unsigned char  bInterfaceProtocol; | ||||
|     unsigned char  iInterface; | ||||
|  | ||||
|     struct usb_endpoint_descriptor *endpoint; | ||||
|  | ||||
|     unsigned char *extra;	/* Extra descriptors */ | ||||
|     int extralen; | ||||
| }; | ||||
|  | ||||
| #define USB_MAXALTSETTING	128	/* Hard limit */ | ||||
|  | ||||
| struct usb_interface | ||||
| { | ||||
|     struct usb_interface_descriptor *altsetting; | ||||
|  | ||||
|     int num_altsetting; | ||||
| }; | ||||
|  | ||||
| /* Configuration descriptor information.. */ | ||||
| #define USB_MAXCONFIG		8 | ||||
| struct usb_config_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned short wTotalLength; | ||||
|     unsigned char  bNumInterfaces; | ||||
|     unsigned char  bConfigurationValue; | ||||
|     unsigned char  iConfiguration; | ||||
|     unsigned char  bmAttributes; | ||||
|     unsigned char  MaxPower; | ||||
|  | ||||
|     struct usb_interface *interface; | ||||
|  | ||||
|     unsigned char *extra;	/* Extra descriptors */ | ||||
|     int extralen; | ||||
| }; | ||||
|  | ||||
| /* Device descriptor */ | ||||
| struct usb_device_descriptor | ||||
| { | ||||
|     unsigned char  bLength; | ||||
|     unsigned char  bDescriptorType; | ||||
|     unsigned short bcdUSB; | ||||
|     unsigned char  bDeviceClass; | ||||
|     unsigned char  bDeviceSubClass; | ||||
|     unsigned char  bDeviceProtocol; | ||||
|     unsigned char  bMaxPacketSize0; | ||||
|     unsigned short idVendor; | ||||
|     unsigned short idProduct; | ||||
|     unsigned short bcdDevice; | ||||
|     unsigned char  iManufacturer; | ||||
|     unsigned char  iProduct; | ||||
|     unsigned char  iSerialNumber; | ||||
|     unsigned char  bNumConfigurations; | ||||
| }; | ||||
|  | ||||
| struct usb_ctrl_setup | ||||
| { | ||||
|     unsigned char  bRequestType; | ||||
|     unsigned char  bRequest; | ||||
|     unsigned short wValue; | ||||
|     unsigned short wIndex; | ||||
|     unsigned short wLength; | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Standard requests | ||||
|  */ | ||||
| #define USB_REQ_GET_STATUS		    0x00 | ||||
| #define USB_REQ_CLEAR_FEATURE	    0x01 | ||||
| /* 0x02 is reserved */ | ||||
| #define USB_REQ_SET_FEATURE		    0x03 | ||||
| /* 0x04 is reserved */ | ||||
| #define USB_REQ_SET_ADDRESS		    0x05 | ||||
| #define USB_REQ_GET_DESCRIPTOR		0x06 | ||||
| #define USB_REQ_SET_DESCRIPTOR		0x07 | ||||
| #define USB_REQ_GET_CONFIGURATION	0x08 | ||||
| #define USB_REQ_SET_CONFIGURATION	0x09 | ||||
| #define USB_REQ_GET_INTERFACE		  0x0A | ||||
| #define USB_REQ_SET_INTERFACE		  0x0B | ||||
| #define USB_REQ_SYNCH_FRAME		    0x0C | ||||
|  | ||||
| #define USB_TYPE_STANDARD		(0x00 << 5) | ||||
| #define USB_TYPE_CLASS			(0x01 << 5) | ||||
| #define USB_TYPE_VENDOR			(0x02 << 5) | ||||
| #define USB_TYPE_RESERVED		(0x03 << 5) | ||||
|  | ||||
| #define USB_RECIP_DEVICE		0x00 | ||||
| #define USB_RECIP_INTERFACE	0x01 | ||||
| #define USB_RECIP_ENDPOINT	0x02 | ||||
| #define USB_RECIP_OTHER			0x03 | ||||
|  | ||||
| /* | ||||
|  * Various libusb API related stuff | ||||
|  */ | ||||
|  | ||||
| #define USB_ENDPOINT_IN			0x80 | ||||
| #define USB_ENDPOINT_OUT		0x00 | ||||
|  | ||||
| /* Error codes */ | ||||
| #define USB_ERROR_BEGIN			500000 | ||||
|  | ||||
| /* | ||||
|  * This is supposed to look weird. This file is generated from autoconf | ||||
|  * and I didn't want to make this too complicated. | ||||
|  */ | ||||
| #define USB_LE16_TO_CPU(x) | ||||
|  | ||||
| /* | ||||
|  * Device reset types for usb_reset_ex. | ||||
|  * http://msdn.microsoft.com/en-us/library/ff537269%28VS.85%29.aspx | ||||
|  * http://msdn.microsoft.com/en-us/library/ff537243%28v=vs.85%29.aspx | ||||
|  */ | ||||
| #define USB_RESET_TYPE_RESET_PORT (1 << 0) | ||||
| #define USB_RESET_TYPE_CYCLE_PORT (1 << 1) | ||||
| #define USB_RESET_TYPE_FULL_RESET (USB_RESET_TYPE_CYCLE_PORT | USB_RESET_TYPE_RESET_PORT) | ||||
|  | ||||
|  | ||||
| /* Data types */ | ||||
| /* struct usb_device; */ | ||||
| /* struct usb_bus; */ | ||||
|  | ||||
| struct usb_device | ||||
| { | ||||
|     struct usb_device *next, *prev; | ||||
|  | ||||
|     char filename[LIBUSB_PATH_MAX]; | ||||
|  | ||||
|     struct usb_bus *bus; | ||||
|  | ||||
|     struct usb_device_descriptor descriptor; | ||||
|     struct usb_config_descriptor *config; | ||||
|  | ||||
|     void *dev;		/* Darwin support */ | ||||
|  | ||||
|     unsigned char devnum; | ||||
|  | ||||
|     unsigned char num_children; | ||||
|     struct usb_device **children; | ||||
| }; | ||||
|  | ||||
| struct usb_bus | ||||
| { | ||||
|     struct usb_bus *next, *prev; | ||||
|  | ||||
|     char dirname[LIBUSB_PATH_MAX]; | ||||
|  | ||||
|     struct usb_device *devices; | ||||
|     unsigned long location; | ||||
|  | ||||
|     struct usb_device *root_dev; | ||||
| }; | ||||
|  | ||||
| /* Version information, Windows specific */ | ||||
| struct usb_version | ||||
| { | ||||
|     struct | ||||
|     { | ||||
|         int major; | ||||
|         int minor; | ||||
|         int micro; | ||||
|         int nano; | ||||
|     } dll; | ||||
|     struct | ||||
|     { | ||||
|         int major; | ||||
|         int minor; | ||||
|         int micro; | ||||
|         int nano; | ||||
|     } driver; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct usb_dev_handle; | ||||
| typedef struct usb_dev_handle usb_dev_handle; | ||||
|  | ||||
| /* Variables */ | ||||
| #ifndef __USB_C__ | ||||
| #define usb_busses usb_get_busses() | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
| #include <poppack.h> | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| { | ||||
| #endif | ||||
|  | ||||
|     /* Function prototypes */ | ||||
|  | ||||
|     /* usb.c */ | ||||
|     usb_dev_handle *usb_open(struct usb_device *dev); | ||||
|     int usb_close(usb_dev_handle *dev); | ||||
|     int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf, | ||||
|                        size_t buflen); | ||||
|     int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, | ||||
|                               size_t buflen); | ||||
|  | ||||
|     /* descriptors.c */ | ||||
|     int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep, | ||||
|                                        unsigned char type, unsigned char index, | ||||
|                                        void *buf, int size); | ||||
|     int usb_get_descriptor(usb_dev_handle *udev, unsigned char type, | ||||
|                            unsigned char index, void *buf, int size); | ||||
|  | ||||
|     /* <arch>.c */ | ||||
|     int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                        int timeout); | ||||
|     int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                       int timeout); | ||||
|     int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                             int timeout); | ||||
|     int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                            int timeout); | ||||
|     int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, | ||||
|                         int value, int index, char *bytes, int size, | ||||
|                         int timeout); | ||||
|     int usb_set_configuration(usb_dev_handle *dev, int configuration); | ||||
|     int usb_claim_interface(usb_dev_handle *dev, int interface); | ||||
|     int usb_release_interface(usb_dev_handle *dev, int interface); | ||||
|     int usb_set_altinterface(usb_dev_handle *dev, int alternate); | ||||
|     int usb_resetep(usb_dev_handle *dev, unsigned int ep); | ||||
|     int usb_clear_halt(usb_dev_handle *dev, unsigned int ep); | ||||
|     int usb_reset(usb_dev_handle *dev); | ||||
|     int usb_reset_ex(usb_dev_handle *dev, unsigned int reset_type); | ||||
|  | ||||
|     char *usb_strerror(void); | ||||
|  | ||||
|     void usb_init(void); | ||||
|     void usb_set_debug(int level); | ||||
|     int usb_find_busses(void); | ||||
|     int usb_find_devices(void); | ||||
|     struct usb_device *usb_device(usb_dev_handle *dev); | ||||
|     struct usb_bus *usb_get_busses(void); | ||||
|  | ||||
|  | ||||
|     /* Windows specific functions */ | ||||
|  | ||||
| #define LIBUSB_HAS_INSTALL_SERVICE_NP 1 | ||||
|     int usb_install_service_np(void); | ||||
|     void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance, | ||||
|             LPSTR cmd_line, int cmd_show); | ||||
|  | ||||
| #define LIBUSB_HAS_UNINSTALL_SERVICE_NP 1 | ||||
|     int usb_uninstall_service_np(void); | ||||
|     void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance, | ||||
|             LPSTR cmd_line, int cmd_show); | ||||
|  | ||||
| #define LIBUSB_HAS_INSTALL_DRIVER_NP 1 | ||||
|     int usb_install_driver_np(const char *inf_file); | ||||
|     void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance, | ||||
|             LPSTR cmd_line, int cmd_show); | ||||
|  | ||||
| #define LIBUSB_HAS_TOUCH_INF_FILE_NP 1 | ||||
|     int usb_touch_inf_file_np(const char *inf_file); | ||||
|     void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance, | ||||
|             LPSTR cmd_line, int cmd_show); | ||||
|  | ||||
| #define LIBUSB_HAS_INSTALL_NEEDS_RESTART_NP 1 | ||||
|     int usb_install_needs_restart_np(void); | ||||
|  | ||||
| #define LIBUSB_HAS_INSTALL_NP 1 | ||||
|     int usb_install_npW(HWND hwnd, HINSTANCE instance, LPCWSTR cmd_line, int starg_arg); | ||||
|     int usb_install_npA(HWND hwnd, HINSTANCE instance, LPCSTR cmd_line, int starg_arg); | ||||
| 	#define usb_install_np usb_install_npA | ||||
|     void CALLBACK usb_install_np_rundll(HWND wnd, HINSTANCE instance,  | ||||
|             LPSTR cmd_line, int cmd_show); | ||||
|  | ||||
|     const struct usb_version *usb_get_version(void); | ||||
|  | ||||
|     int usb_isochronous_setup_async(usb_dev_handle *dev, void **context, | ||||
|                                     unsigned char ep, int pktsize); | ||||
|     int usb_bulk_setup_async(usb_dev_handle *dev, void **context, | ||||
|                              unsigned char ep); | ||||
|     int usb_interrupt_setup_async(usb_dev_handle *dev, void **context, | ||||
|                                   unsigned char ep); | ||||
|  | ||||
|     int usb_submit_async(void *context, char *bytes, int size); | ||||
|     int usb_reap_async(void *context, int timeout); | ||||
|     int usb_reap_async_nocancel(void *context, int timeout); | ||||
|     int usb_cancel_async(void *context); | ||||
|     int usb_free_async(void **context); | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* __USB_H__ */ | ||||
|  | ||||
							
								
								
									
										851
									
								
								libusb/installer_license.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										851
									
								
								libusb/installer_license.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,851 @@ | ||||
| Copyright (c) 2002-2004 Stephan Meyer, <ste_meyer@web.de> | ||||
| Copyright (c) 2000-2004 Johannes Erdfelt, <johannes@erdfelt.com> | ||||
| Copyright (c) 2000-2004 Thomas Sailer, <sailer@ife.ee.ethz.ch> | ||||
| Copyright (c) 2010 Travis Robinson, <libusbdotnet@gmail.com> | ||||
|  | ||||
| This software is distributed under the following licenses: | ||||
| Driver:      GNU General Public License (GPL) | ||||
| Library, Test Files, Installer:    GNU Lesser General Public License (LGPL) | ||||
|  | ||||
| *********************************************************************** | ||||
|                     GNU GENERAL PUBLIC LICENSE | ||||
|                        Version 3, 29 June 2007 | ||||
|  | ||||
|  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
|  | ||||
|                             Preamble | ||||
|  | ||||
|   The GNU General Public License is a free, copyleft license for | ||||
| software and other kinds of works. | ||||
|  | ||||
|   The licenses for most software and other practical works are designed | ||||
| to take away your freedom to share and change the works.  By contrast, | ||||
| the GNU General Public License is intended to guarantee your freedom to | ||||
| share and change all versions of a program--to make sure it remains free | ||||
| software for all its users.  We, the Free Software Foundation, use the | ||||
| GNU General Public License for most of our software; it applies also to | ||||
| any other work released this way by its authors.  You can apply it to | ||||
| your programs, too. | ||||
|  | ||||
|   When we speak of free software, we are referring to freedom, not | ||||
| price.  Our General Public Licenses are designed to make sure that you | ||||
| have the freedom to distribute copies of free software (and charge for | ||||
| them if you wish), that you receive source code or can get it if you | ||||
| want it, that you can change the software or use pieces of it in new | ||||
| free programs, and that you know you can do these things. | ||||
|  | ||||
|   To protect your rights, we need to prevent others from denying you | ||||
| these rights or asking you to surrender the rights.  Therefore, you have | ||||
| certain responsibilities if you distribute copies of the software, or if | ||||
| you modify it: responsibilities to respect the freedom of others. | ||||
|  | ||||
|   For example, if you distribute copies of such a program, whether | ||||
| gratis or for a fee, you must pass on to the recipients the same | ||||
| freedoms that you received.  You must make sure that they, too, receive | ||||
| or can get the source code.  And you must show them these terms so they | ||||
| know their rights. | ||||
|  | ||||
|   Developers that use the GNU GPL protect your rights with two steps: | ||||
| (1) assert copyright on the software, and (2) offer you this License | ||||
| giving you legal permission to copy, distribute and/or modify it. | ||||
|  | ||||
|   For the developers' and authors' protection, the GPL clearly explains | ||||
| that there is no warranty for this free software.  For both users' and | ||||
| authors' sake, the GPL requires that modified versions be marked as | ||||
| changed, so that their problems will not be attributed erroneously to | ||||
| authors of previous versions. | ||||
|  | ||||
|   Some devices are designed to deny users access to install or run | ||||
| modified versions of the software inside them, although the manufacturer | ||||
| can do so.  This is fundamentally incompatible with the aim of | ||||
| protecting users' freedom to change the software.  The systematic | ||||
| pattern of such abuse occurs in the area of products for individuals to | ||||
| use, which is precisely where it is most unacceptable.  Therefore, we | ||||
| have designed this version of the GPL to prohibit the practice for those | ||||
| products.  If such problems arise substantially in other domains, we | ||||
| stand ready to extend this provision to those domains in future versions | ||||
| of the GPL, as needed to protect the freedom of users. | ||||
|  | ||||
|   Finally, every program is threatened constantly by software patents. | ||||
| States should not allow patents to restrict development and use of | ||||
| software on general-purpose computers, but in those that do, we wish to | ||||
| avoid the special danger that patents applied to a free program could | ||||
| make it effectively proprietary.  To prevent this, the GPL assures that | ||||
| patents cannot be used to render the program non-free. | ||||
|  | ||||
|   The precise terms and conditions for copying, distribution and | ||||
| modification follow. | ||||
|  | ||||
|                        TERMS AND CONDITIONS | ||||
|  | ||||
|   0. Definitions. | ||||
|  | ||||
|   "This License" refers to version 3 of the GNU General Public License. | ||||
|  | ||||
|   "Copyright" also means copyright-like laws that apply to other kinds of | ||||
| works, such as semiconductor masks. | ||||
|  | ||||
|   "The Program" refers to any copyrightable work licensed under this | ||||
| License.  Each licensee is addressed as "you".  "Licensees" and | ||||
| "recipients" may be individuals or organizations. | ||||
|  | ||||
|   To "modify" a work means to copy from or adapt all or part of the work | ||||
| in a fashion requiring copyright permission, other than the making of an | ||||
| exact copy.  The resulting work is called a "modified version" of the | ||||
| earlier work or a work "based on" the earlier work. | ||||
|  | ||||
|   A "covered work" means either the unmodified Program or a work based | ||||
| on the Program. | ||||
|  | ||||
|   To "propagate" a work means to do anything with it that, without | ||||
| permission, would make you directly or secondarily liable for | ||||
| infringement under applicable copyright law, except executing it on a | ||||
| computer or modifying a private copy.  Propagation includes copying, | ||||
| distribution (with or without modification), making available to the | ||||
| public, and in some countries other activities as well. | ||||
|  | ||||
|   To "convey" a work means any kind of propagation that enables other | ||||
| parties to make or receive copies.  Mere interaction with a user through | ||||
| a computer network, with no transfer of a copy, is not conveying. | ||||
|  | ||||
|   An interactive user interface displays "Appropriate Legal Notices" | ||||
| to the extent that it includes a convenient and prominently visible | ||||
| feature that (1) displays an appropriate copyright notice, and (2) | ||||
| tells the user that there is no warranty for the work (except to the | ||||
| extent that warranties are provided), that licensees may convey the | ||||
| work under this License, and how to view a copy of this License.  If | ||||
| the interface presents a list of user commands or options, such as a | ||||
| menu, a prominent item in the list meets this criterion. | ||||
|  | ||||
|   1. Source Code. | ||||
|  | ||||
|   The "source code" for a work means the preferred form of the work | ||||
| for making modifications to it.  "Object code" means any non-source | ||||
| form of a work. | ||||
|  | ||||
|   A "Standard Interface" means an interface that either is an official | ||||
| standard defined by a recognized standards body, or, in the case of | ||||
| interfaces specified for a particular programming language, one that | ||||
| is widely used among developers working in that language. | ||||
|  | ||||
|   The "System Libraries" of an executable work include anything, other | ||||
| than the work as a whole, that (a) is included in the normal form of | ||||
| packaging a Major Component, but which is not part of that Major | ||||
| Component, and (b) serves only to enable use of the work with that | ||||
| Major Component, or to implement a Standard Interface for which an | ||||
| implementation is available to the public in source code form.  A | ||||
| "Major Component", in this context, means a major essential component | ||||
| (kernel, window system, and so on) of the specific operating system | ||||
| (if any) on which the executable work runs, or a compiler used to | ||||
| produce the work, or an object code interpreter used to run it. | ||||
|  | ||||
|   The "Corresponding Source" for a work in object code form means all | ||||
| the source code needed to generate, install, and (for an executable | ||||
| work) run the object code and to modify the work, including scripts to | ||||
| control those activities.  However, it does not include the work's | ||||
| System Libraries, or general-purpose tools or generally available free | ||||
| programs which are used unmodified in performing those activities but | ||||
| which are not part of the work.  For example, Corresponding Source | ||||
| includes interface definition files associated with source files for | ||||
| the work, and the source code for shared libraries and dynamically | ||||
| linked subprograms that the work is specifically designed to require, | ||||
| such as by intimate data communication or control flow between those | ||||
| subprograms and other parts of the work. | ||||
|  | ||||
|   The Corresponding Source need not include anything that users | ||||
| can regenerate automatically from other parts of the Corresponding | ||||
| Source. | ||||
|  | ||||
|   The Corresponding Source for a work in source code form is that | ||||
| same work. | ||||
|  | ||||
|   2. Basic Permissions. | ||||
|  | ||||
|   All rights granted under this License are granted for the term of | ||||
| copyright on the Program, and are irrevocable provided the stated | ||||
| conditions are met.  This License explicitly affirms your unlimited | ||||
| permission to run the unmodified Program.  The output from running a | ||||
| covered work is covered by this License only if the output, given its | ||||
| content, constitutes a covered work.  This License acknowledges your | ||||
| rights of fair use or other equivalent, as provided by copyright law. | ||||
|  | ||||
|   You may make, run and propagate covered works that you do not | ||||
| convey, without conditions so long as your license otherwise remains | ||||
| in force.  You may convey covered works to others for the sole purpose | ||||
| of having them make modifications exclusively for you, or provide you | ||||
| with facilities for running those works, provided that you comply with | ||||
| the terms of this License in conveying all material for which you do | ||||
| not control copyright.  Those thus making or running the covered works | ||||
| for you must do so exclusively on your behalf, under your direction | ||||
| and control, on terms that prohibit them from making any copies of | ||||
| your copyrighted material outside their relationship with you. | ||||
|  | ||||
|   Conveying under any other circumstances is permitted solely under | ||||
| the conditions stated below.  Sublicensing is not allowed; section 10 | ||||
| makes it unnecessary. | ||||
|  | ||||
|   3. Protecting Users' Legal Rights From Anti-Circumvention Law. | ||||
|  | ||||
|   No covered work shall be deemed part of an effective technological | ||||
| measure under any applicable law fulfilling obligations under article | ||||
| 11 of the WIPO copyright treaty adopted on 20 December 1996, or | ||||
| similar laws prohibiting or restricting circumvention of such | ||||
| measures. | ||||
|  | ||||
|   When you convey a covered work, you waive any legal power to forbid | ||||
| circumvention of technological measures to the extent such circumvention | ||||
| is effected by exercising rights under this License with respect to | ||||
| the covered work, and you disclaim any intention to limit operation or | ||||
| modification of the work as a means of enforcing, against the work's | ||||
| users, your or third parties' legal rights to forbid circumvention of | ||||
| technological measures. | ||||
|  | ||||
|   4. Conveying Verbatim Copies. | ||||
|  | ||||
|   You may convey verbatim copies of the Program's source code as you | ||||
| receive it, in any medium, provided that you conspicuously and | ||||
| appropriately publish on each copy an appropriate copyright notice; | ||||
| keep intact all notices stating that this License and any | ||||
| non-permissive terms added in accord with section 7 apply to the code; | ||||
| keep intact all notices of the absence of any warranty; and give all | ||||
| recipients a copy of this License along with the Program. | ||||
|  | ||||
|   You may charge any price or no price for each copy that you convey, | ||||
| and you may offer support or warranty protection for a fee. | ||||
|  | ||||
|   5. Conveying Modified Source Versions. | ||||
|  | ||||
|   You may convey a work based on the Program, or the modifications to | ||||
| produce it from the Program, in the form of source code under the | ||||
| terms of section 4, provided that you also meet all of these conditions: | ||||
|  | ||||
|     a) The work must carry prominent notices stating that you modified | ||||
|     it, and giving a relevant date. | ||||
|  | ||||
|     b) The work must carry prominent notices stating that it is | ||||
|     released under this License and any conditions added under section | ||||
|     7.  This requirement modifies the requirement in section 4 to | ||||
|     "keep intact all notices". | ||||
|  | ||||
|     c) You must license the entire work, as a whole, under this | ||||
|     License to anyone who comes into possession of a copy.  This | ||||
|     License will therefore apply, along with any applicable section 7 | ||||
|     additional terms, to the whole of the work, and all its parts, | ||||
|     regardless of how they are packaged.  This License gives no | ||||
|     permission to license the work in any other way, but it does not | ||||
|     invalidate such permission if you have separately received it. | ||||
|  | ||||
|     d) If the work has interactive user interfaces, each must display | ||||
|     Appropriate Legal Notices; however, if the Program has interactive | ||||
|     interfaces that do not display Appropriate Legal Notices, your | ||||
|     work need not make them do so. | ||||
|  | ||||
|   A compilation of a covered work with other separate and independent | ||||
| works, which are not by their nature extensions of the covered work, | ||||
| and which are not combined with it such as to form a larger program, | ||||
| in or on a volume of a storage or distribution medium, is called an | ||||
| "aggregate" if the compilation and its resulting copyright are not | ||||
| used to limit the access or legal rights of the compilation's users | ||||
| beyond what the individual works permit.  Inclusion of a covered work | ||||
| in an aggregate does not cause this License to apply to the other | ||||
| parts of the aggregate. | ||||
|  | ||||
|   6. Conveying Non-Source Forms. | ||||
|  | ||||
|   You may convey a covered work in object code form under the terms | ||||
| of sections 4 and 5, provided that you also convey the | ||||
| machine-readable Corresponding Source under the terms of this License, | ||||
| in one of these ways: | ||||
|  | ||||
|     a) Convey the object code in, or embodied in, a physical product | ||||
|     (including a physical distribution medium), accompanied by the | ||||
|     Corresponding Source fixed on a durable physical medium | ||||
|     customarily used for software interchange. | ||||
|  | ||||
|     b) Convey the object code in, or embodied in, a physical product | ||||
|     (including a physical distribution medium), accompanied by a | ||||
|     written offer, valid for at least three years and valid for as | ||||
|     long as you offer spare parts or customer support for that product | ||||
|     model, to give anyone who possesses the object code either (1) a | ||||
|     copy of the Corresponding Source for all the software in the | ||||
|     product that is covered by this License, on a durable physical | ||||
|     medium customarily used for software interchange, for a price no | ||||
|     more than your reasonable cost of physically performing this | ||||
|     conveying of source, or (2) access to copy the | ||||
|     Corresponding Source from a network server at no charge. | ||||
|  | ||||
|     c) Convey individual copies of the object code with a copy of the | ||||
|     written offer to provide the Corresponding Source.  This | ||||
|     alternative is allowed only occasionally and noncommercially, and | ||||
|     only if you received the object code with such an offer, in accord | ||||
|     with subsection 6b. | ||||
|  | ||||
|     d) Convey the object code by offering access from a designated | ||||
|     place (gratis or for a charge), and offer equivalent access to the | ||||
|     Corresponding Source in the same way through the same place at no | ||||
|     further charge.  You need not require recipients to copy the | ||||
|     Corresponding Source along with the object code.  If the place to | ||||
|     copy the object code is a network server, the Corresponding Source | ||||
|     may be on a different server (operated by you or a third party) | ||||
|     that supports equivalent copying facilities, provided you maintain | ||||
|     clear directions next to the object code saying where to find the | ||||
|     Corresponding Source.  Regardless of what server hosts the | ||||
|     Corresponding Source, you remain obligated to ensure that it is | ||||
|     available for as long as needed to satisfy these requirements. | ||||
|  | ||||
|     e) Convey the object code using peer-to-peer transmission, provided | ||||
|     you inform other peers where the object code and Corresponding | ||||
|     Source of the work are being offered to the general public at no | ||||
|     charge under subsection 6d. | ||||
|  | ||||
|   A separable portion of the object code, whose source code is excluded | ||||
| from the Corresponding Source as a System Library, need not be | ||||
| included in conveying the object code work. | ||||
|  | ||||
|   A "User Product" is either (1) a "consumer product", which means any | ||||
| tangible personal property which is normally used for personal, family, | ||||
| or household purposes, or (2) anything designed or sold for incorporation | ||||
| into a dwelling.  In determining whether a product is a consumer product, | ||||
| doubtful cases shall be resolved in favor of coverage.  For a particular | ||||
| product received by a particular user, "normally used" refers to a | ||||
| typical or common use of that class of product, regardless of the status | ||||
| of the particular user or of the way in which the particular user | ||||
| actually uses, or expects or is expected to use, the product.  A product | ||||
| is a consumer product regardless of whether the product has substantial | ||||
| commercial, industrial or non-consumer uses, unless such uses represent | ||||
| the only significant mode of use of the product. | ||||
|  | ||||
|   "Installation Information" for a User Product means any methods, | ||||
| procedures, authorization keys, or other information required to install | ||||
| and execute modified versions of a covered work in that User Product from | ||||
| a modified version of its Corresponding Source.  The information must | ||||
| suffice to ensure that the continued functioning of the modified object | ||||
| code is in no case prevented or interfered with solely because | ||||
| modification has been made. | ||||
|  | ||||
|   If you convey an object code work under this section in, or with, or | ||||
| specifically for use in, a User Product, and the conveying occurs as | ||||
| part of a transaction in which the right of possession and use of the | ||||
| User Product is transferred to the recipient in perpetuity or for a | ||||
| fixed term (regardless of how the transaction is characterized), the | ||||
| Corresponding Source conveyed under this section must be accompanied | ||||
| by the Installation Information.  But this requirement does not apply | ||||
| if neither you nor any third party retains the ability to install | ||||
| modified object code on the User Product (for example, the work has | ||||
| been installed in ROM). | ||||
|  | ||||
|   The requirement to provide Installation Information does not include a | ||||
| requirement to continue to provide support service, warranty, or updates | ||||
| for a work that has been modified or installed by the recipient, or for | ||||
| the User Product in which it has been modified or installed.  Access to a | ||||
| network may be denied when the modification itself materially and | ||||
| adversely affects the operation of the network or violates the rules and | ||||
| protocols for communication across the network. | ||||
|  | ||||
|   Corresponding Source conveyed, and Installation Information provided, | ||||
| in accord with this section must be in a format that is publicly | ||||
| documented (and with an implementation available to the public in | ||||
| source code form), and must require no special password or key for | ||||
| unpacking, reading or copying. | ||||
|  | ||||
|   7. Additional Terms. | ||||
|  | ||||
|   "Additional permissions" are terms that supplement the terms of this | ||||
| License by making exceptions from one or more of its conditions. | ||||
| Additional permissions that are applicable to the entire Program shall | ||||
| be treated as though they were included in this License, to the extent | ||||
| that they are valid under applicable law.  If additional permissions | ||||
| apply only to part of the Program, that part may be used separately | ||||
| under those permissions, but the entire Program remains governed by | ||||
| this License without regard to the additional permissions. | ||||
|  | ||||
|   When you convey a copy of a covered work, you may at your option | ||||
| remove any additional permissions from that copy, or from any part of | ||||
| it.  (Additional permissions may be written to require their own | ||||
| removal in certain cases when you modify the work.)  You may place | ||||
| additional permissions on material, added by you to a covered work, | ||||
| for which you have or can give appropriate copyright permission. | ||||
|  | ||||
|   Notwithstanding any other provision of this License, for material you | ||||
| add to a covered work, you may (if authorized by the copyright holders of | ||||
| that material) supplement the terms of this License with terms: | ||||
|  | ||||
|     a) Disclaiming warranty or limiting liability differently from the | ||||
|     terms of sections 15 and 16 of this License; or | ||||
|  | ||||
|     b) Requiring preservation of specified reasonable legal notices or | ||||
|     author attributions in that material or in the Appropriate Legal | ||||
|     Notices displayed by works containing it; or | ||||
|  | ||||
|     c) Prohibiting misrepresentation of the origin of that material, or | ||||
|     requiring that modified versions of such material be marked in | ||||
|     reasonable ways as different from the original version; or | ||||
|  | ||||
|     d) Limiting the use for publicity purposes of names of licensors or | ||||
|     authors of the material; or | ||||
|  | ||||
|     e) Declining to grant rights under trademark law for use of some | ||||
|     trade names, trademarks, or service marks; or | ||||
|  | ||||
|     f) Requiring indemnification of licensors and authors of that | ||||
|     material by anyone who conveys the material (or modified versions of | ||||
|     it) with contractual assumptions of liability to the recipient, for | ||||
|     any liability that these contractual assumptions directly impose on | ||||
|     those licensors and authors. | ||||
|  | ||||
|   All other non-permissive additional terms are considered "further | ||||
| restrictions" within the meaning of section 10.  If the Program as you | ||||
| received it, or any part of it, contains a notice stating that it is | ||||
| governed by this License along with a term that is a further | ||||
| restriction, you may remove that term.  If a license document contains | ||||
| a further restriction but permits relicensing or conveying under this | ||||
| License, you may add to a covered work material governed by the terms | ||||
| of that license document, provided that the further restriction does | ||||
| not survive such relicensing or conveying. | ||||
|  | ||||
|   If you add terms to a covered work in accord with this section, you | ||||
| must place, in the relevant source files, a statement of the | ||||
| additional terms that apply to those files, or a notice indicating | ||||
| where to find the applicable terms. | ||||
|  | ||||
|   Additional terms, permissive or non-permissive, may be stated in the | ||||
| form of a separately written license, or stated as exceptions; | ||||
| the above requirements apply either way. | ||||
|  | ||||
|   8. Termination. | ||||
|  | ||||
|   You may not propagate or modify a covered work except as expressly | ||||
| provided under this License.  Any attempt otherwise to propagate or | ||||
| modify it is void, and will automatically terminate your rights under | ||||
| this License (including any patent licenses granted under the third | ||||
| paragraph of section 11). | ||||
|  | ||||
|   However, if you cease all violation of this License, then your | ||||
| license from a particular copyright holder is reinstated (a) | ||||
| provisionally, unless and until the copyright holder explicitly and | ||||
| finally terminates your license, and (b) permanently, if the copyright | ||||
| holder fails to notify you of the violation by some reasonable means | ||||
| prior to 60 days after the cessation. | ||||
|  | ||||
|   Moreover, your license from a particular copyright holder is | ||||
| reinstated permanently if the copyright holder notifies you of the | ||||
| violation by some reasonable means, this is the first time you have | ||||
| received notice of violation of this License (for any work) from that | ||||
| copyright holder, and you cure the violation prior to 30 days after | ||||
| your receipt of the notice. | ||||
|  | ||||
|   Termination of your rights under this section does not terminate the | ||||
| licenses of parties who have received copies or rights from you under | ||||
| this License.  If your rights have been terminated and not permanently | ||||
| reinstated, you do not qualify to receive new licenses for the same | ||||
| material under section 10. | ||||
|  | ||||
|   9. Acceptance Not Required for Having Copies. | ||||
|  | ||||
|   You are not required to accept this License in order to receive or | ||||
| run a copy of the Program.  Ancillary propagation of a covered work | ||||
| occurring solely as a consequence of using peer-to-peer transmission | ||||
| to receive a copy likewise does not require acceptance.  However, | ||||
| nothing other than this License grants you permission to propagate or | ||||
| modify any covered work.  These actions infringe copyright if you do | ||||
| not accept this License.  Therefore, by modifying or propagating a | ||||
| covered work, you indicate your acceptance of this License to do so. | ||||
|  | ||||
|   10. Automatic Licensing of Downstream Recipients. | ||||
|  | ||||
|   Each time you convey a covered work, the recipient automatically | ||||
| receives a license from the original licensors, to run, modify and | ||||
| propagate that work, subject to this License.  You are not responsible | ||||
| for enforcing compliance by third parties with this License. | ||||
|  | ||||
|   An "entity transaction" is a transaction transferring control of an | ||||
| organization, or substantially all assets of one, or subdividing an | ||||
| organization, or merging organizations.  If propagation of a covered | ||||
| work results from an entity transaction, each party to that | ||||
| transaction who receives a copy of the work also receives whatever | ||||
| licenses to the work the party's predecessor in interest had or could | ||||
| give under the previous paragraph, plus a right to possession of the | ||||
| Corresponding Source of the work from the predecessor in interest, if | ||||
| the predecessor has it or can get it with reasonable efforts. | ||||
|  | ||||
|   You may not impose any further restrictions on the exercise of the | ||||
| rights granted or affirmed under this License.  For example, you may | ||||
| not impose a license fee, royalty, or other charge for exercise of | ||||
| rights granted under this License, and you may not initiate litigation | ||||
| (including a cross-claim or counterclaim in a lawsuit) alleging that | ||||
| any patent claim is infringed by making, using, selling, offering for | ||||
| sale, or importing the Program or any portion of it. | ||||
|  | ||||
|   11. Patents. | ||||
|  | ||||
|   A "contributor" is a copyright holder who authorizes use under this | ||||
| License of the Program or a work on which the Program is based.  The | ||||
| work thus licensed is called the contributor's "contributor version". | ||||
|  | ||||
|   A contributor's "essential patent claims" are all patent claims | ||||
| owned or controlled by the contributor, whether already acquired or | ||||
| hereafter acquired, that would be infringed by some manner, permitted | ||||
| by this License, of making, using, or selling its contributor version, | ||||
| but do not include claims that would be infringed only as a | ||||
| consequence of further modification of the contributor version.  For | ||||
| purposes of this definition, "control" includes the right to grant | ||||
| patent sublicenses in a manner consistent with the requirements of | ||||
| this License. | ||||
|  | ||||
|   Each contributor grants you a non-exclusive, worldwide, royalty-free | ||||
| patent license under the contributor's essential patent claims, to | ||||
| make, use, sell, offer for sale, import and otherwise run, modify and | ||||
| propagate the contents of its contributor version. | ||||
|  | ||||
|   In the following three paragraphs, a "patent license" is any express | ||||
| agreement or commitment, however denominated, not to enforce a patent | ||||
| (such as an express permission to practice a patent or covenant not to | ||||
| sue for patent infringement).  To "grant" such a patent license to a | ||||
| party means to make such an agreement or commitment not to enforce a | ||||
| patent against the party. | ||||
|  | ||||
|   If you convey a covered work, knowingly relying on a patent license, | ||||
| and the Corresponding Source of the work is not available for anyone | ||||
| to copy, free of charge and under the terms of this License, through a | ||||
| publicly available network server or other readily accessible means, | ||||
| then you must either (1) cause the Corresponding Source to be so | ||||
| available, or (2) arrange to deprive yourself of the benefit of the | ||||
| patent license for this particular work, or (3) arrange, in a manner | ||||
| consistent with the requirements of this License, to extend the patent | ||||
| license to downstream recipients.  "Knowingly relying" means you have | ||||
| actual knowledge that, but for the patent license, your conveying the | ||||
| covered work in a country, or your recipient's use of the covered work | ||||
| in a country, would infringe one or more identifiable patents in that | ||||
| country that you have reason to believe are valid. | ||||
|  | ||||
|   If, pursuant to or in connection with a single transaction or | ||||
| arrangement, you convey, or propagate by procuring conveyance of, a | ||||
| covered work, and grant a patent license to some of the parties | ||||
| receiving the covered work authorizing them to use, propagate, modify | ||||
| or convey a specific copy of the covered work, then the patent license | ||||
| you grant is automatically extended to all recipients of the covered | ||||
| work and works based on it. | ||||
|  | ||||
|   A patent license is "discriminatory" if it does not include within | ||||
| the scope of its coverage, prohibits the exercise of, or is | ||||
| conditioned on the non-exercise of one or more of the rights that are | ||||
| specifically granted under this License.  You may not convey a covered | ||||
| work if you are a party to an arrangement with a third party that is | ||||
| in the business of distributing software, under which you make payment | ||||
| to the third party based on the extent of your activity of conveying | ||||
| the work, and under which the third party grants, to any of the | ||||
| parties who would receive the covered work from you, a discriminatory | ||||
| patent license (a) in connection with copies of the covered work | ||||
| conveyed by you (or copies made from those copies), or (b) primarily | ||||
| for and in connection with specific products or compilations that | ||||
| contain the covered work, unless you entered into that arrangement, | ||||
| or that patent license was granted, prior to 28 March 2007. | ||||
|  | ||||
|   Nothing in this License shall be construed as excluding or limiting | ||||
| any implied license or other defenses to infringement that may | ||||
| otherwise be available to you under applicable patent law. | ||||
|  | ||||
|   12. No Surrender of Others' Freedom. | ||||
|  | ||||
|   If conditions are imposed on you (whether by court order, agreement or | ||||
| otherwise) that contradict the conditions of this License, they do not | ||||
| excuse you from the conditions of this License.  If you cannot convey a | ||||
| covered work so as to satisfy simultaneously your obligations under this | ||||
| License and any other pertinent obligations, then as a consequence you may | ||||
| not convey it at all.  For example, if you agree to terms that obligate you | ||||
| to collect a royalty for further conveying from those to whom you convey | ||||
| the Program, the only way you could satisfy both those terms and this | ||||
| License would be to refrain entirely from conveying the Program. | ||||
|  | ||||
|   13. Use with the GNU Affero General Public License. | ||||
|  | ||||
|   Notwithstanding any other provision of this License, you have | ||||
| permission to link or combine any covered work with a work licensed | ||||
| under version 3 of the GNU Affero General Public License into a single | ||||
| combined work, and to convey the resulting work.  The terms of this | ||||
| License will continue to apply to the part which is the covered work, | ||||
| but the special requirements of the GNU Affero General Public License, | ||||
| section 13, concerning interaction through a network will apply to the | ||||
| combination as such. | ||||
|  | ||||
|   14. Revised Versions of this License. | ||||
|  | ||||
|   The Free Software Foundation may publish revised and/or new versions of | ||||
| the GNU General Public License from time to time.  Such new versions will | ||||
| be similar in spirit to the present version, but may differ in detail to | ||||
| address new problems or concerns. | ||||
|  | ||||
|   Each version is given a distinguishing version number.  If the | ||||
| Program specifies that a certain numbered version of the GNU General | ||||
| Public License "or any later version" applies to it, you have the | ||||
| option of following the terms and conditions either of that numbered | ||||
| version or of any later version published by the Free Software | ||||
| Foundation.  If the Program does not specify a version number of the | ||||
| GNU General Public License, you may choose any version ever published | ||||
| by the Free Software Foundation. | ||||
|  | ||||
|   If the Program specifies that a proxy can decide which future | ||||
| versions of the GNU General Public License can be used, that proxy's | ||||
| public statement of acceptance of a version permanently authorizes you | ||||
| to choose that version for the Program. | ||||
|  | ||||
|   Later license versions may give you additional or different | ||||
| permissions.  However, no additional obligations are imposed on any | ||||
| author or copyright holder as a result of your choosing to follow a | ||||
| later version. | ||||
|  | ||||
|   15. Disclaimer of Warranty. | ||||
|  | ||||
|   THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | ||||
| APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | ||||
| HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | ||||
| OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | ||||
| THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||
| PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | ||||
| IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | ||||
| ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||||
|  | ||||
|   16. Limitation of Liability. | ||||
|  | ||||
|   IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | ||||
| WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | ||||
| THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | ||||
| GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | ||||
| USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | ||||
| DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | ||||
| PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | ||||
| EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | ||||
| SUCH DAMAGES. | ||||
|  | ||||
|   17. Interpretation of Sections 15 and 16. | ||||
|  | ||||
|   If the disclaimer of warranty and limitation of liability provided | ||||
| above cannot be given local legal effect according to their terms, | ||||
| reviewing courts shall apply local law that most closely approximates | ||||
| an absolute waiver of all civil liability in connection with the | ||||
| Program, unless a warranty or assumption of liability accompanies a | ||||
| copy of the Program in return for a fee. | ||||
|  | ||||
|                      END OF TERMS AND CONDITIONS | ||||
|  | ||||
|             How to Apply These Terms to Your New Programs | ||||
|  | ||||
|   If you develop a new program, and you want it to be of the greatest | ||||
| possible use to the public, the best way to achieve this is to make it | ||||
| free software which everyone can redistribute and change under these terms. | ||||
|  | ||||
|   To do so, attach the following notices to the program.  It is safest | ||||
| to attach them to the start of each source file to most effectively | ||||
| state the exclusion of warranty; and each file should have at least | ||||
| the "copyright" line and a pointer to where the full notice is found. | ||||
|  | ||||
|     <one line to give the program's name and a brief idea of what it does.> | ||||
|     Copyright (C) <year>  <name of author> | ||||
|  | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| Also add information on how to contact you by electronic and paper mail. | ||||
|  | ||||
|   If the program does terminal interaction, make it output a short | ||||
| notice like this when it starts in an interactive mode: | ||||
|  | ||||
|     <program>  Copyright (C) <year>  <name of author> | ||||
|     This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | ||||
|     This is free software, and you are welcome to redistribute it | ||||
|     under certain conditions; type `show c' for details. | ||||
|  | ||||
| The hypothetical commands `show w' and `show c' should show the appropriate | ||||
| parts of the General Public License.  Of course, your program's commands | ||||
| might be different; for a GUI interface, you would use an "about box". | ||||
|  | ||||
|   You should also get your employer (if you work as a programmer) or school, | ||||
| if any, to sign a "copyright disclaimer" for the program, if necessary. | ||||
| For more information on this, and how to apply and follow the GNU GPL, see | ||||
| <http://www.gnu.org/licenses/>. | ||||
|  | ||||
|   The GNU General Public License does not permit incorporating your program | ||||
| into proprietary programs.  If your program is a subroutine library, you | ||||
| may consider it more useful to permit linking proprietary applications with | ||||
| the library.  If this is what you want to do, use the GNU Lesser General | ||||
| Public License instead of this License.  But first, please read | ||||
| <http://www.gnu.org/philosophy/why-not-lgpl.html>. | ||||
|  | ||||
|                    GNU LESSER GENERAL PUBLIC LICENSE | ||||
|                        Version 3, 29 June 2007 | ||||
|  | ||||
|  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
|  | ||||
|  | ||||
|   This version of the GNU Lesser General Public License incorporates | ||||
| the terms and conditions of version 3 of the GNU General Public | ||||
| License, supplemented by the additional permissions listed below. | ||||
|  | ||||
|   0. Additional Definitions. | ||||
|  | ||||
|   As used herein, "this License" refers to version 3 of the GNU Lesser | ||||
| General Public License, and the "GNU GPL" refers to version 3 of the GNU | ||||
| General Public License. | ||||
|  | ||||
|   "The Library" refers to a covered work governed by this License, | ||||
| other than an Application or a Combined Work as defined below. | ||||
|  | ||||
|   An "Application" is any work that makes use of an interface provided | ||||
| by the Library, but which is not otherwise based on the Library. | ||||
| Defining a subclass of a class defined by the Library is deemed a mode | ||||
| of using an interface provided by the Library. | ||||
|  | ||||
|   A "Combined Work" is a work produced by combining or linking an | ||||
| Application with the Library.  The particular version of the Library | ||||
| with which the Combined Work was made is also called the "Linked | ||||
| Version". | ||||
|  | ||||
|   The "Minimal Corresponding Source" for a Combined Work means the | ||||
| Corresponding Source for the Combined Work, excluding any source code | ||||
| for portions of the Combined Work that, considered in isolation, are | ||||
| based on the Application, and not on the Linked Version. | ||||
|  | ||||
|   The "Corresponding Application Code" for a Combined Work means the | ||||
| object code and/or source code for the Application, including any data | ||||
| and utility programs needed for reproducing the Combined Work from the | ||||
| Application, but excluding the System Libraries of the Combined Work. | ||||
|  | ||||
|   1. Exception to Section 3 of the GNU GPL. | ||||
|  | ||||
|   You may convey a covered work under sections 3 and 4 of this License | ||||
| without being bound by section 3 of the GNU GPL. | ||||
|  | ||||
|   2. Conveying Modified Versions. | ||||
|  | ||||
|   If you modify a copy of the Library, and, in your modifications, a | ||||
| facility refers to a function or data to be supplied by an Application | ||||
| that uses the facility (other than as an argument passed when the | ||||
| facility is invoked), then you may convey a copy of the modified | ||||
| version: | ||||
|  | ||||
|    a) under this License, provided that you make a good faith effort to | ||||
|    ensure that, in the event an Application does not supply the | ||||
|    function or data, the facility still operates, and performs | ||||
|    whatever part of its purpose remains meaningful, or | ||||
|  | ||||
|    b) under the GNU GPL, with none of the additional permissions of | ||||
|    this License applicable to that copy. | ||||
|  | ||||
|   3. Object Code Incorporating Material from Library Header Files. | ||||
|  | ||||
|   The object code form of an Application may incorporate material from | ||||
| a header file that is part of the Library.  You may convey such object | ||||
| code under terms of your choice, provided that, if the incorporated | ||||
| material is not limited to numerical parameters, data structure | ||||
| layouts and accessors, or small macros, inline functions and templates | ||||
| (ten or fewer lines in length), you do both of the following: | ||||
|  | ||||
|    a) Give prominent notice with each copy of the object code that the | ||||
|    Library is used in it and that the Library and its use are | ||||
|    covered by this License. | ||||
|  | ||||
|    b) Accompany the object code with a copy of the GNU GPL and this license | ||||
|    document. | ||||
|  | ||||
|   4. Combined Works. | ||||
|  | ||||
|   You may convey a Combined Work under terms of your choice that, | ||||
| taken together, effectively do not restrict modification of the | ||||
| portions of the Library contained in the Combined Work and reverse | ||||
| engineering for debugging such modifications, if you also do each of | ||||
| the following: | ||||
|  | ||||
|    a) Give prominent notice with each copy of the Combined Work that | ||||
|    the Library is used in it and that the Library and its use are | ||||
|    covered by this License. | ||||
|  | ||||
|    b) Accompany the Combined Work with a copy of the GNU GPL and this license | ||||
|    document. | ||||
|  | ||||
|    c) For a Combined Work that displays copyright notices during | ||||
|    execution, include the copyright notice for the Library among | ||||
|    these notices, as well as a reference directing the user to the | ||||
|    copies of the GNU GPL and this license document. | ||||
|  | ||||
|    d) Do one of the following: | ||||
|  | ||||
|        0) Convey the Minimal Corresponding Source under the terms of this | ||||
|        License, and the Corresponding Application Code in a form | ||||
|        suitable for, and under terms that permit, the user to | ||||
|        recombine or relink the Application with a modified version of | ||||
|        the Linked Version to produce a modified Combined Work, in the | ||||
|        manner specified by section 6 of the GNU GPL for conveying | ||||
|        Corresponding Source. | ||||
|  | ||||
|        1) Use a suitable shared library mechanism for linking with the | ||||
|        Library.  A suitable mechanism is one that (a) uses at run time | ||||
|        a copy of the Library already present on the user's computer | ||||
|        system, and (b) will operate properly with a modified version | ||||
|        of the Library that is interface-compatible with the Linked | ||||
|        Version. | ||||
|  | ||||
|    e) Provide Installation Information, but only if you would otherwise | ||||
|    be required to provide such information under section 6 of the | ||||
|    GNU GPL, and only to the extent that such information is | ||||
|    necessary to install and execute a modified version of the | ||||
|    Combined Work produced by recombining or relinking the | ||||
|    Application with a modified version of the Linked Version. (If | ||||
|    you use option 4d0, the Installation Information must accompany | ||||
|    the Minimal Corresponding Source and Corresponding Application | ||||
|    Code. If you use option 4d1, you must provide the Installation | ||||
|    Information in the manner specified by section 6 of the GNU GPL | ||||
|    for conveying Corresponding Source.) | ||||
|  | ||||
|   5. Combined Libraries. | ||||
|  | ||||
|   You may place library facilities that are a work based on the | ||||
| Library side by side in a single library together with other library | ||||
| facilities that are not Applications and are not covered by this | ||||
| License, and convey such a combined library under terms of your | ||||
| choice, if you do both of the following: | ||||
|  | ||||
|    a) Accompany the combined library with a copy of the same work based | ||||
|    on the Library, uncombined with any other library facilities, | ||||
|    conveyed under the terms of this License. | ||||
|  | ||||
|    b) Give prominent notice with the combined library that part of it | ||||
|    is a work based on the Library, and explaining where to find the | ||||
|    accompanying uncombined form of the same work. | ||||
|  | ||||
|   6. Revised Versions of the GNU Lesser General Public License. | ||||
|  | ||||
|   The Free Software Foundation may publish revised and/or new versions | ||||
| of the GNU Lesser General Public License from time to time. Such new | ||||
| versions will be similar in spirit to the present version, but may | ||||
| differ in detail to address new problems or concerns. | ||||
|  | ||||
|   Each version is given a distinguishing version number. If the | ||||
| Library as you received it specifies that a certain numbered version | ||||
| of the GNU Lesser General Public License "or any later version" | ||||
| applies to it, you have the option of following the terms and | ||||
| conditions either of that published version or of any later version | ||||
| published by the Free Software Foundation. If the Library as you | ||||
| received it does not specify a version number of the GNU Lesser | ||||
| General Public License, you may choose any version of the GNU Lesser | ||||
| General Public License ever published by the Free Software Foundation. | ||||
|  | ||||
|   If the Library as you received it specifies that a proxy can decide | ||||
| whether future versions of the GNU Lesser General Public License shall | ||||
| apply, that proxy's public statement of acceptance of any version is | ||||
| permanent authorization for you to choose that version for the | ||||
| Library. | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								libusb/lib/bcc/libusb.lib
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								libusb/lib/bcc/libusb.lib
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										497
									
								
								libusb/lib/dynamic/libusb_dyn.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										497
									
								
								libusb/lib/dynamic/libusb_dyn.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,497 @@ | ||||
| /* LIBUSB-WIN32, Generic Windows USB Library | ||||
|  * Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de> | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include <windows.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| #include "usb.h" | ||||
|  | ||||
| #define LIBUSB_DLL_NAME "libusb0.dll" | ||||
|  | ||||
|  | ||||
| typedef usb_dev_handle * (*usb_open_t)(struct usb_device *dev); | ||||
| typedef int (*usb_close_t)(usb_dev_handle *dev); | ||||
| typedef int (*usb_get_string_t)(usb_dev_handle *dev, int index, int langid, | ||||
|                                 char *buf, size_t buflen); | ||||
| typedef int (*usb_get_string_simple_t)(usb_dev_handle *dev, int index, | ||||
|                                        char *buf, size_t buflen); | ||||
| typedef int (*usb_get_descriptor_by_endpoint_t)(usb_dev_handle *udev, int ep, | ||||
|         unsigned char type, | ||||
|         unsigned char index, | ||||
|         void *buf, int size); | ||||
| typedef int (*usb_get_descriptor_t)(usb_dev_handle *udev, unsigned char type, | ||||
|                                     unsigned char index, void *buf, int size); | ||||
| typedef int (*usb_bulk_write_t)(usb_dev_handle *dev, int ep, char *bytes, | ||||
|                                 int size, int timeout); | ||||
| typedef int (*usb_bulk_read_t)(usb_dev_handle *dev, int ep, char *bytes, | ||||
|                                int size, int timeout); | ||||
| typedef int (*usb_interrupt_write_t)(usb_dev_handle *dev, int ep, char *bytes, | ||||
|                                      int size, int timeout); | ||||
| typedef int (*usb_interrupt_read_t)(usb_dev_handle *dev, int ep, char *bytes, | ||||
|                                     int size, int timeout); | ||||
| typedef int (*usb_control_msg_t)(usb_dev_handle *dev, int requesttype, | ||||
|                                  int request, int value, int index, | ||||
|                                  char *bytes, int size, int timeout); | ||||
| typedef int (*usb_set_configuration_t)(usb_dev_handle *dev, int configuration); | ||||
| typedef int (*usb_claim_interface_t)(usb_dev_handle *dev, int interface); | ||||
| typedef int (*usb_release_interface_t)(usb_dev_handle *dev, int interface); | ||||
| typedef int (*usb_set_altinterface_t)(usb_dev_handle *dev, int alternate); | ||||
| typedef int (*usb_resetep_t)(usb_dev_handle *dev, unsigned int ep); | ||||
| typedef int (*usb_clear_halt_t)(usb_dev_handle *dev, unsigned int ep); | ||||
| typedef int (*usb_reset_t)(usb_dev_handle *dev); | ||||
| typedef int (*usb_reset_ex_t)(usb_dev_handle *dev, unsigned int reset_type); | ||||
| typedef char * (*usb_strerror_t)(void); | ||||
| typedef void (*usb_init_t)(void); | ||||
| typedef void (*usb_set_debug_t)(int level); | ||||
| typedef int (*usb_find_busses_t)(void); | ||||
| typedef int (*usb_find_devices_t)(void); | ||||
| typedef struct usb_device * (*usb_device_t)(usb_dev_handle *dev); | ||||
| typedef struct usb_bus * (*usb_get_busses_t)(void); | ||||
| typedef int (*usb_install_service_np_t)(void); | ||||
| typedef int (*usb_uninstall_service_np_t)(void); | ||||
| typedef int (*usb_install_driver_np_t)(const char *inf_file); | ||||
| typedef const struct usb_version * (*usb_get_version_t)(void); | ||||
| typedef int (*usb_isochronous_setup_async_t)(usb_dev_handle *dev, | ||||
|         void **context, | ||||
|         unsigned char ep, int pktsize); | ||||
| typedef int (*usb_bulk_setup_async_t)(usb_dev_handle *dev, void **context, | ||||
|                                       unsigned char ep); | ||||
| typedef int (*usb_interrupt_setup_async_t)(usb_dev_handle *dev, void **context, | ||||
|         unsigned char ep); | ||||
| typedef int (*usb_submit_async_t)(void *context, char *bytes, int size); | ||||
| typedef int (*usb_reap_async_t)(void *context, int timeout); | ||||
| typedef int (*usb_free_async_t)(void **context); | ||||
|  | ||||
|  | ||||
| static usb_open_t _usb_open = NULL; | ||||
| static usb_close_t _usb_close = NULL; | ||||
| static usb_get_string_t _usb_get_string = NULL; | ||||
| static usb_get_string_simple_t _usb_get_string_simple = NULL; | ||||
| static usb_get_descriptor_by_endpoint_t _usb_get_descriptor_by_endpoint = NULL; | ||||
| static usb_get_descriptor_t _usb_get_descriptor = NULL; | ||||
| static usb_bulk_write_t _usb_bulk_write = NULL; | ||||
| static usb_bulk_read_t _usb_bulk_read = NULL; | ||||
| static usb_interrupt_write_t _usb_interrupt_write = NULL; | ||||
| static usb_interrupt_read_t _usb_interrupt_read = NULL; | ||||
| static usb_control_msg_t _usb_control_msg = NULL; | ||||
| static usb_set_configuration_t _usb_set_configuration = NULL; | ||||
| static usb_claim_interface_t _usb_claim_interface = NULL; | ||||
| static usb_release_interface_t _usb_release_interface = NULL; | ||||
| static usb_set_altinterface_t _usb_set_altinterface = NULL; | ||||
| static usb_resetep_t _usb_resetep = NULL; | ||||
| static usb_clear_halt_t _usb_clear_halt = NULL; | ||||
| static usb_reset_t _usb_reset = NULL; | ||||
| static usb_reset_ex_t _usb_reset_ex = NULL; | ||||
| static usb_strerror_t _usb_strerror = NULL; | ||||
| static usb_init_t _usb_init = NULL; | ||||
| static usb_set_debug_t _usb_set_debug = NULL; | ||||
| static usb_find_busses_t _usb_find_busses = NULL; | ||||
| static usb_find_devices_t _usb_find_devices = NULL; | ||||
| static usb_device_t _usb_device = NULL; | ||||
| static usb_get_busses_t _usb_get_busses = NULL; | ||||
| static usb_install_service_np_t _usb_install_service_np = NULL; | ||||
| static usb_uninstall_service_np_t _usb_uninstall_service_np = NULL; | ||||
| static usb_install_driver_np_t _usb_install_driver_np = NULL; | ||||
| static usb_get_version_t _usb_get_version = NULL; | ||||
| static usb_isochronous_setup_async_t _usb_isochronous_setup_async = NULL; | ||||
| static usb_bulk_setup_async_t _usb_bulk_setup_async = NULL; | ||||
| static usb_interrupt_setup_async_t _usb_interrupt_setup_async = NULL; | ||||
| static usb_submit_async_t _usb_submit_async = NULL; | ||||
| static usb_reap_async_t _usb_reap_async = NULL; | ||||
| static usb_free_async_t _usb_free_async = NULL; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void usb_init(void) | ||||
| { | ||||
|     HINSTANCE libusb_dll  = LoadLibrary(LIBUSB_DLL_NAME); | ||||
|  | ||||
|     if (!libusb_dll) | ||||
|         return; | ||||
|  | ||||
|     _usb_open = (usb_open_t) | ||||
|                 GetProcAddress(libusb_dll, "usb_open"); | ||||
|     _usb_close = (usb_close_t) | ||||
|                  GetProcAddress(libusb_dll, "usb_close"); | ||||
|     _usb_get_string = (usb_get_string_t) | ||||
|                       GetProcAddress(libusb_dll, "usb_get_string"); | ||||
|     _usb_get_string_simple = (usb_get_string_simple_t) | ||||
|                              GetProcAddress(libusb_dll, "usb_get_string_simple"); | ||||
|     _usb_get_descriptor_by_endpoint = (usb_get_descriptor_by_endpoint_t) | ||||
|                                       GetProcAddress(libusb_dll, "usb_get_descriptor_by_endpoint"); | ||||
|     _usb_get_descriptor = (usb_get_descriptor_t) | ||||
|                           GetProcAddress(libusb_dll, "usb_get_descriptor"); | ||||
|     _usb_bulk_write = (usb_bulk_write_t) | ||||
|                       GetProcAddress(libusb_dll, "usb_bulk_write"); | ||||
|     _usb_bulk_read = (usb_bulk_read_t) | ||||
|                      GetProcAddress(libusb_dll, "usb_bulk_read"); | ||||
|     _usb_interrupt_write = (usb_interrupt_write_t) | ||||
|                            GetProcAddress(libusb_dll, "usb_interrupt_write"); | ||||
|     _usb_interrupt_read = (usb_interrupt_read_t) | ||||
|                           GetProcAddress(libusb_dll, "usb_interrupt_read"); | ||||
|     _usb_control_msg = (usb_control_msg_t) | ||||
|                        GetProcAddress(libusb_dll, "usb_control_msg"); | ||||
|     _usb_set_configuration = (usb_set_configuration_t) | ||||
|                              GetProcAddress(libusb_dll, "usb_set_configuration"); | ||||
|     _usb_claim_interface = (usb_claim_interface_t) | ||||
|                            GetProcAddress(libusb_dll, "usb_claim_interface"); | ||||
|     _usb_release_interface = (usb_release_interface_t) | ||||
|                              GetProcAddress(libusb_dll, "usb_release_interface"); | ||||
|     _usb_set_altinterface = (usb_set_altinterface_t) | ||||
|                             GetProcAddress(libusb_dll, "usb_set_altinterface"); | ||||
|     _usb_resetep = (usb_resetep_t) | ||||
|                    GetProcAddress(libusb_dll, "usb_resetep"); | ||||
|     _usb_clear_halt = (usb_clear_halt_t) | ||||
|                       GetProcAddress(libusb_dll, "usb_clear_halt"); | ||||
|     _usb_reset = (usb_reset_t) | ||||
|                  GetProcAddress(libusb_dll, "usb_reset"); | ||||
|     _usb_reset_ex = (usb_reset_ex_t) | ||||
|                  GetProcAddress(libusb_dll, "usb_reset_ex"); | ||||
|     _usb_strerror = (usb_strerror_t) | ||||
|                     GetProcAddress(libusb_dll, "usb_strerror"); | ||||
|     _usb_init = (usb_init_t) | ||||
|                 GetProcAddress(libusb_dll, "usb_init"); | ||||
|     _usb_set_debug = (usb_set_debug_t) | ||||
|                      GetProcAddress(libusb_dll, "usb_set_debug"); | ||||
|     _usb_find_busses = (usb_find_busses_t) | ||||
|                        GetProcAddress(libusb_dll, "usb_find_busses"); | ||||
|     _usb_find_devices = (usb_find_devices_t) | ||||
|                         GetProcAddress(libusb_dll, "usb_find_devices"); | ||||
|     _usb_device = (usb_device_t) | ||||
|                   GetProcAddress(libusb_dll, "usb_device"); | ||||
|     _usb_get_busses = (usb_get_busses_t) | ||||
|                       GetProcAddress(libusb_dll, "usb_get_busses"); | ||||
|     _usb_install_service_np = (usb_install_service_np_t) | ||||
|                               GetProcAddress(libusb_dll, "usb_install_service_np"); | ||||
|     _usb_uninstall_service_np = (usb_uninstall_service_np_t) | ||||
|                                 GetProcAddress(libusb_dll, "usb_uninstall_service_np"); | ||||
|     _usb_install_driver_np = (usb_install_driver_np_t) | ||||
|                              GetProcAddress(libusb_dll, "usb_install_driver_np"); | ||||
|     _usb_get_version = (usb_get_version_t) | ||||
|                        GetProcAddress(libusb_dll, "usb_get_version"); | ||||
|     _usb_isochronous_setup_async = (usb_isochronous_setup_async_t) | ||||
|                                    GetProcAddress(libusb_dll, "usb_isochronous_setup_async"); | ||||
|     _usb_bulk_setup_async = (usb_bulk_setup_async_t) | ||||
|                             GetProcAddress(libusb_dll, "usb_bulk_setup_async"); | ||||
|     _usb_interrupt_setup_async = (usb_interrupt_setup_async_t) | ||||
|                                  GetProcAddress(libusb_dll, "usb_interrupt_setup_async"); | ||||
|     _usb_submit_async = (usb_submit_async_t) | ||||
|                         GetProcAddress(libusb_dll, "usb_submit_async"); | ||||
|     _usb_reap_async = (usb_reap_async_t) | ||||
|                       GetProcAddress(libusb_dll, "usb_reap_async"); | ||||
|     _usb_free_async = (usb_free_async_t) | ||||
|                       GetProcAddress(libusb_dll, "usb_free_async"); | ||||
|  | ||||
|     if (_usb_init) | ||||
|         _usb_init(); | ||||
| } | ||||
|  | ||||
| usb_dev_handle *usb_open(struct usb_device *dev) | ||||
| { | ||||
|     if (_usb_open) | ||||
|         return _usb_open(dev); | ||||
|     else | ||||
|         return NULL; | ||||
| } | ||||
|  | ||||
| int usb_close(usb_dev_handle *dev) | ||||
| { | ||||
|     if (_usb_close) | ||||
|         return _usb_close(dev); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf, | ||||
|                    size_t buflen) | ||||
| { | ||||
|     if (_usb_get_string) | ||||
|         return _usb_get_string(dev, index, langid, buf, buflen); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, | ||||
|                           size_t buflen) | ||||
| { | ||||
|     if (_usb_get_string_simple) | ||||
|         return _usb_get_string_simple(dev, index, buf, buflen); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep, | ||||
|                                    unsigned char type, unsigned char index, | ||||
|                                    void *buf, int size) | ||||
| { | ||||
|     if (_usb_get_descriptor_by_endpoint) | ||||
|         return _usb_get_descriptor_by_endpoint(udev, ep, type, index, buf, size); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_get_descriptor(usb_dev_handle *udev, unsigned char type, | ||||
|                        unsigned char index, void *buf, int size) | ||||
| { | ||||
|     if (_usb_get_descriptor) | ||||
|         return _usb_get_descriptor(udev, type, index, buf, size); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                    int timeout) | ||||
| { | ||||
|     if (_usb_bulk_write) | ||||
|         return _usb_bulk_write(dev, ep, bytes, size, timeout); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                   int timeout) | ||||
| { | ||||
|     if (_usb_bulk_read) | ||||
|         return _usb_bulk_read(dev, ep, bytes, size, timeout); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                         int timeout) | ||||
| { | ||||
|     if (_usb_interrupt_write) | ||||
|         return _usb_interrupt_write(dev, ep, bytes, size, timeout); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, | ||||
|                        int timeout) | ||||
| { | ||||
|     if (_usb_interrupt_read) | ||||
|         return _usb_interrupt_read(dev, ep, bytes, size, timeout); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, | ||||
|                     int value, int index, char *bytes, int size, | ||||
|                     int timeout) | ||||
| { | ||||
|     if (_usb_control_msg) | ||||
|         return _usb_control_msg(dev, requesttype, request, value, index, bytes, | ||||
|                                 size, timeout); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_set_configuration(usb_dev_handle *dev, int configuration) | ||||
| { | ||||
|     if (_usb_set_configuration) | ||||
|         return _usb_set_configuration(dev, configuration); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_claim_interface(usb_dev_handle *dev, int interface) | ||||
| { | ||||
|     if (_usb_claim_interface) | ||||
|         return _usb_claim_interface(dev, interface); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_release_interface(usb_dev_handle *dev, int interface) | ||||
| { | ||||
|     if (_usb_release_interface) | ||||
|         return _usb_release_interface(dev, interface); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_set_altinterface(usb_dev_handle *dev, int alternate) | ||||
| { | ||||
|     if (_usb_set_altinterface) | ||||
|         return _usb_set_altinterface(dev, alternate); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_resetep(usb_dev_handle *dev, unsigned int ep) | ||||
| { | ||||
|     if (_usb_resetep) | ||||
|         return _usb_resetep(dev, ep); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_clear_halt(usb_dev_handle *dev, unsigned int ep) | ||||
| { | ||||
|     if (_usb_clear_halt) | ||||
|         return _usb_clear_halt(dev, ep); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_reset(usb_dev_handle *dev) | ||||
| { | ||||
|     if (_usb_reset) | ||||
|         return _usb_reset(dev); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_reset_ex(usb_dev_handle *dev, unsigned int reset_type) | ||||
| { | ||||
|     if (_usb_reset_ex) | ||||
|         return _usb_reset_ex(dev, reset_type); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| char *usb_strerror(void) | ||||
| { | ||||
|     if (_usb_strerror) | ||||
|         return _usb_strerror(); | ||||
|     else | ||||
|         return NULL; | ||||
| } | ||||
|  | ||||
| void usb_set_debug(int level) | ||||
| { | ||||
|     if (_usb_set_debug) | ||||
|         return _usb_set_debug(level); | ||||
| } | ||||
|  | ||||
| int usb_find_busses(void) | ||||
| { | ||||
|     if (_usb_find_busses) | ||||
|         return _usb_find_busses(); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_find_devices(void) | ||||
| { | ||||
|     if (_usb_find_devices) | ||||
|         return _usb_find_devices(); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| struct usb_device *usb_device(usb_dev_handle *dev) | ||||
| { | ||||
|     if (_usb_device) | ||||
|         return _usb_device(dev); | ||||
|     else | ||||
|         return NULL; | ||||
| } | ||||
|  | ||||
| struct usb_bus *usb_get_busses(void) | ||||
| { | ||||
|     if (_usb_get_busses) | ||||
|         return _usb_get_busses(); | ||||
|     else | ||||
|         return NULL; | ||||
| } | ||||
|  | ||||
| int usb_install_service_np(void) | ||||
| { | ||||
|     if (_usb_install_service_np) | ||||
|         return _usb_install_service_np(); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_uninstall_service_np(void) | ||||
| { | ||||
|     if (_usb_uninstall_service_np) | ||||
|         return _usb_uninstall_service_np(); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_install_driver_np(const char *inf_file) | ||||
| { | ||||
|     if (_usb_install_driver_np) | ||||
|         return _usb_install_driver_np(inf_file); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| const struct usb_version *usb_get_version(void) | ||||
| { | ||||
|     if (_usb_get_version) | ||||
|         return _usb_get_version(); | ||||
|     else | ||||
|         return NULL; | ||||
| } | ||||
|  | ||||
| int usb_isochronous_setup_async(usb_dev_handle *dev, void **context, | ||||
|                                 unsigned char ep, int pktsize) | ||||
| { | ||||
|     if (_usb_isochronous_setup_async) | ||||
|         return _usb_isochronous_setup_async(dev, context, ep, pktsize); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_bulk_setup_async(usb_dev_handle *dev, void **context, | ||||
|                          unsigned char ep) | ||||
| { | ||||
|     if (_usb_bulk_setup_async) | ||||
|         return _usb_bulk_setup_async(dev, context, ep); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_interrupt_setup_async(usb_dev_handle *dev, void **context, | ||||
|                               unsigned char ep) | ||||
| { | ||||
|     if (_usb_interrupt_setup_async) | ||||
|         return _usb_interrupt_setup_async(dev, context, ep); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_submit_async(void *context, char *bytes, int size) | ||||
| { | ||||
|     if (_usb_submit_async) | ||||
|         return _usb_submit_async(context, bytes, size); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_reap_async(void *context, int timeout) | ||||
| { | ||||
|     if (_usb_reap_async) | ||||
|         return _usb_reap_async(context, timeout); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
|  | ||||
| int usb_free_async(void **context) | ||||
| { | ||||
|     if (_usb_free_async) | ||||
|         return _usb_free_async(context); | ||||
|     else | ||||
|         return -ENOFILE; | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								libusb/lib/gcc/libusb.a
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								libusb/lib/gcc/libusb.a
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								libusb/lib/msvc/libusb.lib
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								libusb/lib/msvc/libusb.lib
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								libusb/lib/msvc_i64/libusb.lib
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								libusb/lib/msvc_i64/libusb.lib
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								libusb/lib/msvc_x64/libusb.lib
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								libusb/lib/msvc_x64/libusb.lib
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										239
									
								
								libusb/libusb-win32-changelog-1.2.6.0.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								libusb/libusb-win32-changelog-1.2.6.0.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,239 @@ | ||||
| LibUsb-Win32 Change Log | ||||
| V1.2.6.0 (01/17/2012) | ||||
| ============================================== | ||||
| * Official release. | ||||
|  | ||||
| * Removed ISO maximum transfer size restrictions/transfer spltting. | ||||
|  | ||||
| * Fixed inf-wizard device notification issue. | ||||
|  | ||||
| V1.2.5.0 (07/23/2011) | ||||
| ============================================== | ||||
| * Official release. | ||||
|  | ||||
| V1.2.4.9 (07/13/2011) - SNAPSHOT RELEASE | ||||
| ============================================== | ||||
| * Updated GCC lib file 'libusb.a' | ||||
|  | ||||
| V1.2.4.8 (07/12/2011) - SNAPSHOT RELEASE | ||||
| ============================================== | ||||
| * Added new public api function 'usb_reset_ex'. This is an extended  | ||||
|   device reset function which allows developers to specify a port reset, a  | ||||
|   port cycle, or both.  | ||||
|  | ||||
| * Added new public defines 'USB_RESET_TYPE_XXX' for 'usb_reset_ex'  | ||||
|   function.  | ||||
|  | ||||
| V1.2.4.7 (07/02/2011) - SNAPSHOT RELEASE | ||||
| ============================================== | ||||
| * Sync transfers which specify a zero (0) timeout are now considered to be  | ||||
|   INFINITE.  | ||||
|  | ||||
| V1.2.4.6 (05/12/2011) - SNAPSHOT RELEASE | ||||
| ============================================== | ||||
| * Added device interface registration. This provides identical  | ||||
|   functionality to the "DeviceInterfaceGUIDs" supported by WinUSB and  | ||||
|   libusbK. A device interface guid can be specified in the .inf file. They  | ||||
|   can be used to quickly locate a usb device or set of USB devices using  | ||||
|   the setup api as well as device notification registration.  | ||||
|  | ||||
| * New IOCTL codes added to for native libusbK/WinUSB compatibility. | ||||
|   NOTE: These IOCTLs are currently used only by libusbK.dll. | ||||
|   o LIBUSB_IOCTL_QUERY_DEVICE_INFORMATION | ||||
|   o LIBUSB_IOCTL_SET_PIPE_POLICY | ||||
|   o LIBUSB_IOCTL_GET_PIPE_POLICY | ||||
|   o LIBUSB_IOCTL_SET_POWER_POLICY | ||||
|   o LIBUSB_IOCTL_GET_POWER_POLICY | ||||
|   o LIBUSB_IOCTL_CONTROL_WRITE | ||||
|   o LIBUSB_IOCTL_CONTROL_READ | ||||
|   o LIBUSB_IOCTL_FLUSH_PIPE | ||||
|   o LIBUSBK_IOCTL_CLAIM_INTERFACE | ||||
|   o LIBUSBK_IOCTL_RELEASE_INTERFACE | ||||
|   o LIBUSBK_IOCTL_RELEASE_ALL_INTERFACES | ||||
|   o LIBUSBK_IOCTL_SET_INTERFACE | ||||
|   o LIBUSBK_IOCTL_GET_INTERFACE | ||||
|  | ||||
| * Renamed main header file (usb.h) to lusb0_usb.h. This eliminates  | ||||
|   conflicts with the main WDK usb include as well as making the  | ||||
|   libusb-win32 header more distinguishable from other usb library header  | ||||
|   files.  | ||||
|  | ||||
| * Added device descriptor caching and active/first config descriptor  | ||||
|   caching. Descriptor caching prevents unnecessary control requests from  | ||||
|   interrupting devices that could potentially be in-use. It also makes  | ||||
|   libusb0.sys more compliant with usb libraries targeting platform where  | ||||
|   descriptor caching is done automatically. (linux/mac) | ||||
|    | ||||
| * Upgraded to libwdi v1.1.1 | ||||
|   o Zadig UI improvements | ||||
|   o wdi-simple now handles certificate related operations | ||||
|   o New NSIS (Nullsoft Scriptable Install System) script sample | ||||
|   o improved INNO Setup script sample | ||||
|   o libusbK support | ||||
|   o autogeneration and self-signing of a .cat file, to prevent further security | ||||
|     prompts during driver installation on Vista and later. | ||||
|     for more information, see http://libwdi-cps.akeo.ie | ||||
|   o disable restore point creation during installation | ||||
|   o Visual Studio 2010 support and overall MS file cleanup | ||||
|   o use of the Kerberos/e2fsprogs parser in Zadig instead of libconfig | ||||
|  | ||||
| V1.2.4.0 (04/11/2011) | ||||
| ======================= | ||||
| * Removed get configuration request from the core driver  | ||||
|   set_configuration function.  This caused problems with | ||||
|   some non-compliant usb devices. | ||||
|  | ||||
| * Added device descriptor dump to test applications. | ||||
|  | ||||
| V1.2.3.0 (03/16/2011) | ||||
| ======================= | ||||
| * Fixed bug-id 3117686 reported by Tim Schuerewegen. | ||||
|  | ||||
| * Added LIBUSB_IOCTL_GET_OBJECT_NAME.  This new IOCTL code retrieves object | ||||
|   from the driver.  The only valid object name index is 0.  Index 0 is | ||||
|   returns the devices plug and play registry key pathname. | ||||
|  | ||||
| * Removed maximum timeout restriction for vendor class requests. | ||||
|  | ||||
| V1.2.2.0 (10/02/2010) | ||||
| ======================= | ||||
| * Added install-filter-win.exe.  A gui installer for device filters. | ||||
|  | ||||
| * Added new libusb0.dll function usb_install_np_rundll().  This function | ||||
|   is designed for rundll32.exe and takes the same parameters as | ||||
|   install-filter.exe. | ||||
|  | ||||
| * Updated install-filter.exe.  This application has several new features. | ||||
|   Type "install-filter --help" for more details. | ||||
|  | ||||
| * Updated libusb-win32-devel-filter package.  This package is once again | ||||
|   available for download as a setup.exe. | ||||
|  | ||||
| * Updated libusb-win32 "bin" package format.  inf-wizard.exe has been moved | ||||
|   up one directory. | ||||
|  | ||||
| * Updated driver_installer_template.iss example. This is an Inno Setup | ||||
|   Script showing how to create your own setup.exe for installing your | ||||
|   application and driver. | ||||
|  | ||||
| * Fixed missing byte order marker in inf-wizard.exe .inf files. (libwdi) | ||||
|  | ||||
| * Fixed auto-configuration issue when there is more than one driver in the | ||||
|   stack. | ||||
|  | ||||
| * Fixed BSOD when using the filter driver with devices that are auto | ||||
|   suspended by other drivers in the stack. | ||||
|    | ||||
| * Fixed BSOD for devices with endpoints that have '0' for wMaxPacketSize. | ||||
|  | ||||
| * Fixed BSOD when cancelling large transfers on high speed devices. | ||||
|  | ||||
|    | ||||
| V1.2.1.0 (07/28/2010) | ||||
| ======================= | ||||
| * Updated bulk.c to include async i/o example code. | ||||
|  | ||||
| * Fixed usb_install_driver_np() issue with inf-wizard generated infs. | ||||
|  | ||||
| * Fixed inf2cat.exe issue with inf-wizard generated infs. | ||||
|    | ||||
| * Added 'Install Now' feature to inf-wizard. (libwdi) | ||||
|  | ||||
| * Added embedded libusb-win32 binaries to inf-wizard. (libwdi) | ||||
|  | ||||
| * Added libwdi (http://www.libusb.org/wiki/libwdi) to inf-wizard.  | ||||
|  | ||||
| * Added get cached configuration request to usb_open(). This is a new | ||||
|   control code that involves no device i/o and allows  | ||||
|   usb_set_configuration() to be omitted if the driver has already | ||||
|   configured it. | ||||
|  | ||||
| * Fixed set_configuration() failure for devices that do not properly | ||||
|   support get_configuration(). | ||||
|  | ||||
| V1.2.0.0 (07/07/2010) | ||||
| ======================= | ||||
| * First signed driver release! The libusb-win32 kernel driver (libusb0.sys) | ||||
|   can now be used on x64 Windows machines that require signed drivers.  | ||||
|  | ||||
| * Fixed 2128187 reported by Tim Green. usb_get_descriptor() can fail | ||||
|   because the given buffer of 8 bytes is too small. | ||||
|  | ||||
| * Fixed 2928293 reported by Tim Green. Sometimes the call to  | ||||
|   usb_fetch_and_parse_descriptors() in usb_find_devices() can fail. This  | ||||
|   patch moves the LIST_ADD to after a successful read of the device's  | ||||
|   configuration descriptors. | ||||
|  | ||||
| * Fixed issue causing libusb-win32 to not act as power policy owner | ||||
|   when it should. | ||||
|  | ||||
| * Fixed issue in which on rare occasion, a libusb-win32 filter device could | ||||
|   run as a "normal" device. | ||||
|    | ||||
| * Fixed filter driver issue for device using wudfr.sys. | ||||
|  | ||||
| * Added large transfer splitting to driver (bulk, int, iso). NOTE: | ||||
|   The dll continues to break transfers in the same manner it always has. | ||||
|  | ||||
|  | ||||
| V1.1.14.3 (06/12/2010) | ||||
| ======================= | ||||
| * Remove get_configuration() request from usb_open().  This caused claim | ||||
|   interface to fail when used as a filter driver. | ||||
|    | ||||
| V1.1.14.0 (06/01/2010) | ||||
| ======================= | ||||
| * Updated logging functions and standardized log message display format. | ||||
|  | ||||
| * Updated inf-wizard to use the new directory format for the libusb-win32 | ||||
|   binaries. | ||||
|  | ||||
| * Updated package directories to reflect the winddk BUILDARCH env variable. | ||||
|   (i64 := ia64, x64 := amd64) | ||||
|    | ||||
| * Added request to get the current configuration in usb_open(). | ||||
|  | ||||
| * Fixed 2960644 (reported by farthen) crash on shutdown with x64 based | ||||
|   systems while using inf files for each libusb device. | ||||
|  | ||||
| * Added additional log message only included in debug/chk builds. | ||||
|    | ||||
| * Updated default log levels to highest verbose level for debug builds. | ||||
|  | ||||
| * Added test signing support to the libusb-win32 make.cmd. This allows | ||||
|   libusb0.sys and libusb0.dll to be signed with a digital signature. | ||||
|   (see make.cmd for mmore details) | ||||
|  | ||||
| * Added MSVC 2008 project files | ||||
|  | ||||
| * Moved version defines to an include file (libusb_version.h) | ||||
|   This file is generated from libusb_version_h.in with "make.cmd makever" | ||||
|  | ||||
| * Removed all "dist" commands from cyg/mingw makefile.  Instead use "make.cmd" | ||||
|   in the "ddk_make" directory. | ||||
|  | ||||
| * Fixed filter setup not running in 64bit mode | ||||
|  | ||||
| * Fixed 64bit inf-wizard, testlibusb-win builds | ||||
|  | ||||
| * Added set initial config value #1 when the driver is not a filter. | ||||
|   optionally, the initial configuration value can be specified in the inf | ||||
|   file: HKR,,"InitialConfigValue",0x00010001,<your config value> | ||||
|  | ||||
| * Added support for querying device registry keys  | ||||
|  (LIBUSB_IOCTL_GET_CUSTOM_REG_PROPERTY) | ||||
|  | ||||
| * Added support for querying device properties  | ||||
|  (LIBUSB_IOCTL_GET_DEVICE_PROPERTY) | ||||
|  | ||||
| * Fixed possible race condition in kernel add_device() | ||||
|  | ||||
| * Updated default ddk build version number to 1.1.14.0 to facilitate | ||||
|   Microsoft WHQL submission. | ||||
|  | ||||
| * Added DDK build distribution system.  Official libusb-win32 releases  | ||||
|  (after 0.1.12.2) are built using Microsoft's WinDDK.  (see make.cmd) | ||||
|  | ||||
| * Fixed 2658937 (reported by Tim Roberts) The libusb-win32 driver always | ||||
|   acts as a power policy owner. | ||||
|  | ||||
							
								
								
									
										302
									
								
								main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								main.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,302 @@ | ||||
| #include <avr/io.h> | ||||
| #include <avr/interrupt.h>  /* for sei() */ | ||||
| #include <avr/wdt.h> | ||||
| #include <util/delay.h>     /* for _delay_ms() */ | ||||
|  | ||||
| #include <avr/pgmspace.h>   /* required by usbdrv.h */ | ||||
| #include "usbdrv.h" | ||||
| #include "oddebug.h"        /* This is also an example for using debug macros */ | ||||
|  | ||||
| #include "Wheel.h" | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| /* ----------------------------- USB interface ----------------------------- */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| PROGMEM const char usbHidReportDescriptor[52] = { /* USB report descriptor, size must match usbconfig.h */ | ||||
|     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop) | ||||
|     0x09, 0x02,                    // USAGE (Mouse) | ||||
|     0xa1, 0x01,                    // COLLECTION (Application) | ||||
|     0x09, 0x01,                    //   USAGE (Pointer) | ||||
|     0xA1, 0x00,                    //   COLLECTION (Physical) | ||||
|     0x05, 0x09,                    //     USAGE_PAGE (Button) | ||||
|     0x19, 0x01,                    //     USAGE_MINIMUM | ||||
|     0x29, 0x03,                    //     USAGE_MAXIMUM | ||||
|     0x15, 0x00,                    //     LOGICAL_MINIMUM (0) | ||||
|     0x25, 0x01,                    //     LOGICAL_MAXIMUM (1) | ||||
|     0x95, 0x03,                    //     REPORT_COUNT (3) | ||||
|     0x75, 0x01,                    //     REPORT_SIZE (1) | ||||
|     0x81, 0x02,                    //     INPUT (Data,Var,Abs) | ||||
|     0x95, 0x01,                    //     REPORT_COUNT (1) | ||||
|     0x75, 0x05,                    //     REPORT_SIZE (5) | ||||
|     0x81, 0x03,                    //     INPUT (Const,Var,Abs) | ||||
|     0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop) | ||||
|     0x09, 0x30,                    //     USAGE (X) | ||||
|     0x09, 0x31,                    //     USAGE (Y) | ||||
|     0x09, 0x38,                    //     USAGE (Wheel) | ||||
|     0x15, 0x81,                    //     LOGICAL_MINIMUM (-127) | ||||
|     0x25, 0x7F,                    //     LOGICAL_MAXIMUM (127) | ||||
|     0x75, 0x08,                    //     REPORT_SIZE (8) | ||||
|     0x95, 0x03,                    //     REPORT_COUNT (3) | ||||
|     0x81, 0x06,                    //     INPUT (Data,Var,Rel) | ||||
|     0xC0,                          //   END_COLLECTION | ||||
|     0xC0,                          // END COLLECTION | ||||
| }; | ||||
| /* This is the same report descriptor as seen in a Logitech mouse. The data | ||||
|  * described by this descriptor consists of 4 bytes: | ||||
|  *      .  .  .  .  . B2 B1 B0 .... one byte with mouse button states | ||||
|  *     X7 X6 X5 X4 X3 X2 X1 X0 .... 8 bit signed relative coordinate x | ||||
|  *     Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 .... 8 bit signed relative coordinate y | ||||
|  *     W7 W6 W5 W4 W3 W2 W1 W0 .... 8 bit signed relative coordinate wheel | ||||
|  */ | ||||
| typedef struct{ | ||||
|     uchar   buttonMask; | ||||
|     char    dx; | ||||
|     char    dy; | ||||
|     char    dWheel; | ||||
| }report_t; | ||||
|  | ||||
| static report_t reportBuffer; | ||||
| static uchar    idleRate;   /* repeat rate for keyboards, never used for mice */ | ||||
|  | ||||
|  | ||||
| /* The following function advances sin/cos by a fixed angle | ||||
|  * and stores the difference to the previous coordinates in the report | ||||
|  * descriptor. | ||||
|  * The algorithm is the simulation of a second order differential equation. | ||||
|  */ | ||||
| // static void advanceCircleByFixedAngle(void) | ||||
| // { | ||||
| // char    d; | ||||
|  | ||||
| // #define DIVIDE_BY_64(val)  (val + (val > 0 ? 32 : -32)) >> 6    /* rounding divide */ | ||||
| //     reportBuffer.dx = d = DIVIDE_BY_64(cosinus); | ||||
| //     sinus += d; | ||||
| //     reportBuffer.dy = d = DIVIDE_BY_64(sinus); | ||||
| //     cosinus -= d; | ||||
| // } | ||||
|  | ||||
| static void read_Wheel(void) | ||||
| { | ||||
|     reportBuffer.dx = 0; | ||||
| 	reportBuffer.dy = 0; | ||||
| 	reportBuffer.dWheel = 0; | ||||
|  | ||||
| 	int Direction = (AnalogIn < 512) ? -1 : 1; | ||||
|  | ||||
| 	// PORTD = 0; | ||||
|  | ||||
| 	if (AnalogIn < LowerDead[Debounce] || AnalogIn > UpperDead[Debounce]) | ||||
| 	{ | ||||
| 		if (Debounce == 1 || ticktock >= timing) | ||||
| 		{ | ||||
| 			reportBuffer.dWheel = Direction; | ||||
| 			Debounce = 0; | ||||
| 			// ticktock = 0; | ||||
| 			// LEDs_ToggleLEDs(LEDS_LED2); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		if (Debounce == 0) | ||||
| 		{ | ||||
| 			// PORTD = (1<<PD1); | ||||
| 			Debounce = 1; | ||||
| 		} | ||||
| 		 | ||||
| 	} | ||||
|  | ||||
| 	// *ReportSize = sizeof(USB_MouseReport_Data_t); | ||||
| 	// return true; | ||||
| } | ||||
|  | ||||
|  | ||||
| uint8_t get_timing(uint16_t value) | ||||
| { | ||||
|    int index = 0; | ||||
|    while (value > timingtable_in[index]) | ||||
|    { | ||||
|       index++; | ||||
|    } | ||||
|    return timingtable_out[index]; | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| ISR(ADC_vect) | ||||
| { | ||||
| 	AnalogIn = ADC; | ||||
| 	timing = get_timing(ADC); | ||||
| } | ||||
|  | ||||
| ISR(TIMER1_COMPA_vect) | ||||
| { | ||||
|     // PINB |= _BV(PB1); | ||||
|     if (ticktock > 0) | ||||
|     { | ||||
|         PINB |= _BV(PB1); | ||||
|         usbPoll(); | ||||
|         if(usbInterruptIsReady()) | ||||
|         { | ||||
|             // PINB |= (1<<PB1); | ||||
|              | ||||
|             /* called after every poll of the interrupt endpoint */ | ||||
|             read_Wheel(); | ||||
|             // DBG1(0x03, 0, 0);   /* debug output: interrupt report prepared */ | ||||
|             usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer)); | ||||
|         } | ||||
| 	// HID_Device_USBTask(&Mouse_HID_Interface); | ||||
| 	// USB_USBTask(); | ||||
|         ticktock = 0; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // PINB &= ~(1<<PB1); | ||||
|         ticktock++; | ||||
|     } | ||||
| 	 | ||||
| 	// LEDs_ToggleLEDs(LEDS_LED1); | ||||
|     wdt_reset(); | ||||
| } | ||||
|  | ||||
| /** Configures the board hardware and chip peripherals for the demo's functionality. */ | ||||
| void SetupHardware(void) | ||||
| { | ||||
| 	/* Disable watchdog if enabled by bootloader/fuses */ | ||||
| 	MCUSR &= ~(1 << WDRF); | ||||
| 	wdt_disable(); | ||||
|  | ||||
| 	/* Hardware Initialization */ | ||||
| 	// LEDs_Init(); | ||||
| 	// USB_Init(); | ||||
|  | ||||
| 	/* ADC Settings */ | ||||
| 	// prescaler = 128 | ||||
| 	ADCSRA = (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); | ||||
| 	// VCC Ref, ADC6 | ||||
| 	ADMUX = (1<<MUX0); | ||||
| 	ADCSRA |= (1<<ADEN)|(1<<ADIE)|(1<<ADSC)|(1<<ADATE); | ||||
|  | ||||
| 	// /* Timer1 settings */ | ||||
| 	// TCCR1A = 0; | ||||
| 	// // Mode = CTC, Prescaler = 64 | ||||
| 	// TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10); | ||||
|  | ||||
|     TCCR1 |= (1<<CTC1)|(1<<CS13)|(1<<CS11)|(1<<CS10); | ||||
|  | ||||
| 	// initialize counter | ||||
| 	TCNT1 = 0; | ||||
| 	 | ||||
| 	// initialize compare value | ||||
|     OCR1A = 241; // 15ms | ||||
|     OCR1C = 241; // 15ms | ||||
|  | ||||
| 	// enable compare interrupt | ||||
|     TIMSK = (1 << OCIE1A); | ||||
|  | ||||
| 	// LEDs_TurnOffLEDs(LEDS_ALL_LEDS); | ||||
|  | ||||
|     DDRB |= (1<<PB1); | ||||
|  | ||||
|     usbInit(); | ||||
|     usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */ | ||||
|  | ||||
|     for (int i = 0; i<250; i++) | ||||
|     {             /* fake USB disconnect for > 250 ms */ | ||||
|         wdt_reset(); | ||||
|         _delay_ms(2); | ||||
|     } | ||||
|     usbDeviceConnect(); | ||||
|     sei(); | ||||
|     wdt_enable(WDTO_1S); | ||||
| } | ||||
|  | ||||
| usbMsgLen_t usbFunctionSetup(uchar data[8]) | ||||
| { | ||||
| usbRequest_t    *rq = (void *)data; | ||||
|  | ||||
|     /* The following requests are never used. But since they are required by | ||||
|      * the specification, we implement them in this example. | ||||
|      */ | ||||
|     if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */ | ||||
|         DBG1(0x50, &rq->bRequest, 1);   /* debug output: print our request */ | ||||
|         if(rq->bRequest == USBRQ_HID_GET_REPORT){  /* wValue: ReportType (highbyte), ReportID (lowbyte) */ | ||||
|             /* we only have one report type, so don't look at wValue */ | ||||
|             usbMsgPtr = (void *)&reportBuffer; | ||||
|             return sizeof(reportBuffer); | ||||
|         }else if(rq->bRequest == USBRQ_HID_GET_IDLE){ | ||||
|             usbMsgPtr = &idleRate; | ||||
|             return 1; | ||||
|         }else if(rq->bRequest == USBRQ_HID_SET_IDLE){ | ||||
|             idleRate = rq->wValue.bytes[1]; | ||||
|         } | ||||
|     }else{ | ||||
|         /* no vendor specific requests implemented */ | ||||
|     } | ||||
|     return 0;   /* default for not implemented requests: return no data back to host */ | ||||
| } | ||||
|  | ||||
| // Called by V-USB after device reset | ||||
| void hadUsbReset() { | ||||
|     int frameLength, targetLength = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5); | ||||
|     int bestDeviation = 9999; | ||||
|     uchar trialCal, bestCal, step, region; | ||||
|  | ||||
|     bestCal = 0; | ||||
|  | ||||
|     // do a binary search in regions 0-127 and 128-255 to get optimum OSCCAL | ||||
|     for(region = 0; region <= 1; region++) { | ||||
|         frameLength = 0; | ||||
|         trialCal = (region == 0) ? 0 : 128; | ||||
|          | ||||
|         for(step = 64; step > 0; step >>= 1) {  | ||||
|             if(frameLength < targetLength) // true for initial iteration | ||||
|                 trialCal += step; // frequency too low | ||||
|             else | ||||
|                 trialCal -= step; // frequency too high | ||||
|                  | ||||
|             OSCCAL = trialCal; | ||||
|             frameLength = usbMeasureFrameLength(); | ||||
|              | ||||
|             if(abs(frameLength-targetLength) < bestDeviation) { | ||||
|                 bestCal = trialCal; // new optimum found | ||||
|                 bestDeviation = abs(frameLength -targetLength); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     OSCCAL = bestCal; | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| int main(void) | ||||
| { | ||||
| // uchar   i; | ||||
|  | ||||
|     SetupHardware(); | ||||
|      | ||||
|     /* If you don't use the watchdog, replace the call above with a wdt_disable(). | ||||
|      * On newer devices, the status of the watchdog (on/off, period) is PRESERVED | ||||
|      * OVER RESET! | ||||
|      */ | ||||
|     /* RESET status: all port bits are inputs without pull-up. | ||||
|      * That's the way we need D+ and D-. Therefore we don't need any | ||||
|      * additional hardware initialization. | ||||
|      */ | ||||
|     // for (int a = 0; a<6; a++) | ||||
|     // { | ||||
|     //     PINB |= _BV(PB1); | ||||
|     //     _delay_ms(500); | ||||
|     // } | ||||
|  | ||||
|     for(;;){                /* main event loop */ | ||||
|         // DBG1(0x02, 0, 0);   /* debug output: main loop iterates */ | ||||
|         // wdt_reset(); | ||||
|          | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
							
								
								
									
										158
									
								
								main.hex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								main.hex
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,158 @@ | ||||
| :100000005FC0E6C178C080C376C075C074C073C0DD | ||||
| :100010004EC371C070C06FC06EC06DC06CC00902AD | ||||
| :100020002200010100A00A090400000103000000F1 | ||||
| :100030000921010100012234000705810308006441 | ||||
| :100040001201100100000008C016DC0500010102C9 | ||||
| :10005000000116035500530042006500780061005E | ||||
| :100060006D0070006C006500200363006F00640089 | ||||
| :10007000650061006E0064006C0069006600650048 | ||||
| :100080002E0063006F006D000403090405010902DE | ||||
| :10009000A1010901A1000509190129031500250184 | ||||
| :1000A00095037501810295017505810305010930EC | ||||
| :1000B000093109381581257F750895038106C0C06F | ||||
| :1000C00011241FBECFE5D2E0DEBFCDBF10E0A0E619 | ||||
| :1000D000B0E0EEE4F9E002C005900D92AA3DB10750 | ||||
| :1000E000D9F721E0AAEDB0E001C01D92A831B20716 | ||||
| :1000F000E1F729D42AC484CFCF93C62F2091EC00F6 | ||||
| :1001000024FF07C03091ED0028E823272093ED005D | ||||
| :1001100003C02AE52093EC002C2FFC01AEEEB0E0EA | ||||
| :1001200081918D9321501216DCF36C2F8EEE90E0AE | ||||
| :1001300038D1CC5FC093EC00CF910895CF93DF937B | ||||
| :100140008091FE00835087FDA8C09091FA009D32F7 | ||||
| :1001500009F0A1C0883009F09EC08091FB00CCE07E | ||||
| :10016000D0E0C81BD109CE5FDE4F83EC8093E10065 | ||||
| :100170008AE5809361001092F9008881807619F0F9 | ||||
| :10018000CE0176D37FC09A811092EA0089818111D5 | ||||
| :1001900006C01092EB002AEE30E082E06FC085309E | ||||
| :1001A00019F49093FF0067C0863009F04EC08B8130 | ||||
| :1001B000813041F480E490E09093FD008093FC0056 | ||||
| :1001C00082E13FC0823041F48EE190E09093FD00E7 | ||||
| :1001D0008093FC0082E235C08330F1F4911108C0B5 | ||||
| :1001E00088E890E09093FD008093FC0084E029C0B3 | ||||
| :1001F000913041F488E690E09093FD008093FC00FC | ||||
| :1002000080E21FC09230E1F482E590E09093FD001F | ||||
| :100210008093FC0086E115C0813241F480E390E0D8 | ||||
| :100220009093FD008093FC0089E00BC0823241F482 | ||||
| :100230008CE890E09093FD008093FC0084E301C083 | ||||
| :1002400080E090E49093F9001DC0883069F0893017 | ||||
| :1002500019F4909301010FC08A3049F08B3059F4A2 | ||||
| :100260008BE48093ED0007C021E031E002C02AEE6C | ||||
| :1002700030E081E003C02AEE30E080E03093FD0002 | ||||
| :100280002093FC009F81911104C09E81981708F46F | ||||
| :10029000892F809360001092FE008091610084FF9E | ||||
| :1002A00046C0809160008F3F09F441C0C82F89305B | ||||
| :1002B00008F0C8E08C1B809360009091E10088E812 | ||||
| :1002C00089278093E100CC2331F14091FC005091CB | ||||
| :1002D000FD008091F90086FF0AC0A2EEB0E0FA01AD | ||||
| :1002E0009C2F84918D9331969150D9F708C0DA01F3 | ||||
| :1002F000E2EEF0E09C2F8D9181939150E1F72FEF8A | ||||
| :100300002C0F30E02F5F3F4FCA01820F931F909355 | ||||
| :10031000FD008093FC006C2F82EE90E042D0CC5F19 | ||||
| :10032000CC3019F08FEF80936000C093610084E1BE | ||||
| :1003300096B3987131F48150D9F71092FF00109262 | ||||
| :10034000F800C1E08111C0E09091DA00C91721F0F6 | ||||
| :100350008111AFD2C093DA00DF91CF91089585B7B4 | ||||
| :10036000826085BF8BB780648BBFECEEF0E08BE4DE | ||||
| :1003700081838AE580830895A82FB92F80E090E0DB | ||||
| :1003800041E050EA609530E009C02D9182279795B1 | ||||
| :10039000879510F084279527305EC8F36F5FA8F328 | ||||
| :1003A0000895EADF8D939D930895A6E08827992705 | ||||
| :1003B000AA9569F00197E1F3B499FCCFB49BFECF05 | ||||
| :1003C00081E09927A6B3019611F0A871D9F7089595 | ||||
| :1003D000CF93CFB7CF93C395B49BE9F7B49B0BC032 | ||||
| :1003E000B49B09C0B49B07C0B49B05C0B49B03C0B9 | ||||
| :1003F000B49B01C0D5C00F92DF93C091FB00DD27F5 | ||||
| :10040000CE5FDE4F012EB49B03C0DF910F90E6CF8D | ||||
| :100410002F930F931F934F932FEF4F6F06B304FB50 | ||||
| :1004200020F95F933F9350E03BE065C016B301268F | ||||
| :10043000502954FDC89556B3012704FB25F92F73A5 | ||||
| :1004400006B3B1F05027102714FB26F906B222306C | ||||
| :10045000F0F000C016B3012704FB27F9012650294C | ||||
| :1004600006B22430E8F54F77206816B30000F6CFC7 | ||||
| :1004700050274F7D206206B2102F000000C006B347 | ||||
| :1004800000265029102714FB26F906B2E2CF4F7B35 | ||||
| :1004900006B3206400C0DACF01265029187106B2D5 | ||||
| :1004A00069F14E7F2160012F16B328C00026502924 | ||||
| :1004B0004D7F06B22260102F29C0012650294B7FA4 | ||||
| :1004C00006B22460012F2DC016B301265029477FA4 | ||||
| :1004D0002860000006B22EC04F7E06B3206130C0F7 | ||||
| :1004E000422706B3499300265029102706B24FEF42 | ||||
| :1004F00014FB20F9297F16B379F2187159F10126FE | ||||
| :10050000502906B2012704FB21F9237F06B371F2BB | ||||
| :10051000002650293150D0F006B2102714FB22F9E2 | ||||
| :10052000277E16B351F201265029012704FB06B29B | ||||
| :1005300023F92F7C49F2000006B3102714FB24F99D | ||||
| :100540000026502906B22F7939F270CF10E41ABF75 | ||||
| :10055000002719C03B503195C31BD04010E41ABF8F | ||||
| :100560000881033C09F10B34F9F02091F80019815E | ||||
| :10057000110F1213EDCF4A81441F093651F10D328C | ||||
| :1005800011F0013E29F7009300013F915F914F91D7 | ||||
| :100590001F910F912F91DF910F90CAB7C6FD1BCF0E | ||||
| :1005A000CF91CFBFCF91189520910001222369F3FD | ||||
| :1005B0001091FE00112379F534307AF13093FE006A | ||||
| :1005C0002093FA001091FB003BE0311B3093FB00BD | ||||
| :1005D00024C00091FE000130F4F40AE54F7049F4A4 | ||||
| :1005E0003091610034FD1AC000936100C1EED0E08B | ||||
| :1005F00019C03091EC0034FD11C00093EC00CDEE39 | ||||
| :10060000D0E010C0052710E000C021C0052710E091 | ||||
| :10061000C89508BB14C03AE501C032ED032EC0E016 | ||||
| :10062000D0E032E017B31861C49A08B317BB58E1A1 | ||||
| :1006300020E84FEF20FF052708BB279517951C3FA3 | ||||
| :1006400028F700004552B0F720FF0527279508BB83 | ||||
| :1006500017951C3FB8F629913A9561F7077E1091DE | ||||
| :10066000FF00110F08BBC250D04011F01093F800EA | ||||
| :1006700010E41ABF006117B3177E402F477E54E085 | ||||
| :100680005A95F1F708BB17BB48BB7FCFE2E9F0E012 | ||||
| :1006900020E030E0419151914817590718F42F5F3D | ||||
| :1006A0003F4FF8CFF901E259FF4F808108951F9223 | ||||
| :1006B0000F920FB60F9211242F933F934F935F9396 | ||||
| :1006C0006F937F938F939F93AF93BF93EF93FF931A | ||||
| :1006D00084B195B1909364008093630084B195B127 | ||||
| :1006E000D5DF80936200FF91EF91BF91AF919F9111 | ||||
| :1006F0008F917F916F915F914F913F912F910F90CB | ||||
| :100700000FBE0F901F9018951F920F920FB60F9269 | ||||
| :1007100011242F933F934F935F936F937F938F9306 | ||||
| :100720009F93AF93BF93EF93FF938091DB00882358 | ||||
| :1007300009F453C0B19A02DD8091EC0084FF4AC0F5 | ||||
| :100740001092DE001092DF001092E00080916300B2 | ||||
| :10075000909164008115924010F081E001C08FEF0C | ||||
| :10076000E09165002091630030916400F0E0EE0FAD | ||||
| :10077000FF1FE659FF4F408151812417350780F054 | ||||
| :10078000E09165002091630030916400F0E0EE0F8D | ||||
| :10079000FF1FEA59FF4F408151814217530778F4F8 | ||||
| :1007A00090916500913031F02091DB0090916200D2 | ||||
| :1007B000291760F08093E0001092650007C08091D7 | ||||
| :1007C0006500811103C081E08093650064E08DEDD8 | ||||
| :1007D00090E092DC1092DB0005C08091DB008F5F1F | ||||
| :1007E0008093DB00A895FF91EF91BF91AF919F910E | ||||
| :1007F0008F917F916F915F914F913F912F910F90CA | ||||
| :100800000FBE0F901F90189584B7877F84BF0FB6D7 | ||||
| :10081000F894A89581B5886181BD11BC0FBE87E0B1 | ||||
| :1008200086B981E087B986B1886E86B980B78B6852 | ||||
| :1008300080BF1FBC81EF8EBD8DBD80E489BFB99A9A | ||||
| :100840008EDDBC9A8AEF90E0A895E9E3F0E231975B | ||||
| :10085000F1F700C000000197B9F7BC9878949EE0CA | ||||
| :1008600088E10FB6F894A89581BD0FBE91BD08959B | ||||
| :10087000FC01808180768032D1F48181813041F425 | ||||
| :100880008DED90E09093FD008093FC0084E008954E | ||||
| :10089000823041F48CED90E09093FD008093FC0059 | ||||
| :1008A00081E008958A3019F483818093DC0080E030 | ||||
| :1008B0000895AF92BF92CF92DF92EF92FF920F9383 | ||||
| :1008C0001F93CF93DF93D0E0E12C0FE017E22CECE5 | ||||
| :1008D000C22E26EFD22ED11102C0C0E001C0C0E866 | ||||
| :1008E00087E0A82EB12C90E4F92E80E090E08433CC | ||||
| :1008F000994014F4CF0D01C0CF19C1BF56DD853327 | ||||
| :1009000029E0920724F09C012453394003C096014A | ||||
| :10091000281B390B2017310714F4EC2E8901F694AB | ||||
| :1009200021E0A21AB10819F7DF5FD230A1F6E1BECB | ||||
| :10093000DF91CF911F910F91FF90EF90DF90CF90BB | ||||
| :0E094000BF90AF90089560DFFFCFF894FFCF17 | ||||
| :10094E00FF5AFF80000132023C02CE01C4010001B9 | ||||
| :10095E0002030405060708090A0B0C0D0E0F1011F1 | ||||
| :10096E0011100F0E0D0C0B0A0908070605040302E1 | ||||
| :10097E0001000000DA0056017C0191019E01A701E1 | ||||
| :10098E00AE01B401B801BC01BF01C201C501C7016E | ||||
| :10099E00C901CB01CC0133023402360237023902CF | ||||
| :1009AE003B023E024102440248024C0252025902EC | ||||
| :0A09BE0062026F028402AA02FF0326 | ||||
| :00000001FF | ||||
							
								
								
									
										13
									
								
								usbconfig.h.old
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								usbconfig.h.old
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| #define USB_CFG_IOPORTNAME      B | ||||
| #define USB_CFG_DMINUS_BIT      1 | ||||
| #define USB_CFG_DPLUS_BIT       2 | ||||
| #define USB_CFG_CLOCK_KHZ       (F_CPU/1000) | ||||
| #define USB_CFG_HAVE_MEASURE_FRAME_LENGTH   1 | ||||
|  | ||||
| // The following needs to be uncommented | ||||
| #define USB_RESET_HOOK(resetStarts)     if(!resetStarts){hadUsbReset();} | ||||
|  | ||||
| // Add the following after USB_RESET_HOOK | ||||
| #ifndef __ASSEMBLER__ | ||||
| extern void hadUsbReset(void); // define the function for usbdrv.c | ||||
| #endif | ||||
							
								
								
									
										329
									
								
								usbdrv/Changelog.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										329
									
								
								usbdrv/Changelog.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,329 @@ | ||||
| This file documents changes in the firmware-only USB driver for atmel's AVR | ||||
| microcontrollers. New entries are always appended to the end of the file. | ||||
| Scroll down to the bottom to see the most recent changes. | ||||
|  | ||||
| 2005-04-01: | ||||
|   - Implemented endpoint 1 as interrupt-in endpoint. | ||||
|   - Moved all configuration options to usbconfig.h which is not part of the | ||||
|     driver. | ||||
|   - Changed interface for usbVendorSetup(). | ||||
|   - Fixed compatibility with ATMega8 device. | ||||
|   - Various minor optimizations. | ||||
|  | ||||
| 2005-04-11: | ||||
|   - Changed interface to application: Use usbFunctionSetup(), usbFunctionRead() | ||||
|     and usbFunctionWrite() now. Added configuration options to choose which | ||||
|     of these functions to compile in. | ||||
|   - Assembler module delivers receive data non-inverted now. | ||||
|   - Made register and bit names compatible with more AVR devices. | ||||
|  | ||||
| 2005-05-03: | ||||
|   - Allow address of usbRxBuf on any memory page as long as the buffer does | ||||
|     not cross 256 byte page boundaries. | ||||
|   - Better device compatibility: works with Mega88 now. | ||||
|   - Code optimization in debugging module. | ||||
|   - Documentation updates. | ||||
|  | ||||
| 2006-01-02: | ||||
|   - Added (free) default Vendor- and Product-IDs bought from voti.nl. | ||||
|   - Added USBID-License.txt file which defines the rules for using the free | ||||
|     shared VID/PID pair. | ||||
|   - Added Readme.txt to the usbdrv directory which clarifies administrative | ||||
|     issues. | ||||
|  | ||||
| 2006-01-25: | ||||
|   - Added "configured state" to become more standards compliant. | ||||
|   - Added "HALT" state for interrupt endpoint. | ||||
|   - Driver passes the "USB Command Verifier" test from usb.org now. | ||||
|   - Made "serial number" a configuration option. | ||||
|   - Minor optimizations, we now recommend compiler option "-Os" for best | ||||
|     results. | ||||
|   - Added a version number to usbdrv.h | ||||
|  | ||||
| 2006-02-03: | ||||
|   - New configuration variable USB_BUFFER_SECTION for the memory section where | ||||
|     the USB rx buffer will go. This defaults to ".bss" if not defined. Since | ||||
|     this buffer MUST NOT cross 256 byte pages (not even touch a page at the | ||||
|     end), the user may want to pass a linker option similar to | ||||
|     "-Wl,--section-start=.mybuffer=0x800060". | ||||
|   - Provide structure for usbRequest_t. | ||||
|   - New defines for USB constants. | ||||
|   - Prepared for HID implementations. | ||||
|   - Increased data size limit for interrupt transfers to 8 bytes. | ||||
|   - New macro usbInterruptIsReady() to query interrupt buffer state. | ||||
|  | ||||
| 2006-02-18: | ||||
|   - Ensure that the data token which is sent as an ack to an OUT transfer is | ||||
|     always zero sized. This fixes a bug where the host reports an error after | ||||
|     sending an out transfer to the device, although all data arrived at the | ||||
|     device. | ||||
|   - Updated docs in usbdrv.h to reflect changed API in usbFunctionWrite(). | ||||
|  | ||||
| * Release 2006-02-20 | ||||
|  | ||||
|   - Give a compiler warning when compiling with debugging turned on. | ||||
|   - Added Oleg Semyonov's changes for IAR-cc compatibility. | ||||
|   - Added new (optional) functions usbDeviceConnect() and usbDeviceDisconnect() | ||||
|     (also thanks to Oleg!). | ||||
|   - Rearranged tests in usbPoll() to save a couple of instructions in the most | ||||
|     likely case that no actions are pending. | ||||
|   - We need a delay between the SET ADDRESS request until the new address | ||||
|     becomes active. This delay was handled in usbPoll() until now. Since the | ||||
|     spec says that the delay must not exceed 2ms, previous versions required | ||||
|     aggressive polling during the enumeration phase. We have now moved the | ||||
|     handling of the delay into the interrupt routine. | ||||
|   - We must not reply with NAK to a SETUP transaction. We can only achieve this | ||||
|     by making sure that the rx buffer is empty when SETUP tokens are expected. | ||||
|     We therefore don't pass zero sized data packets from the status phase of | ||||
|     a transfer to usbPoll(). This change MAY cause troubles if you rely on | ||||
|     receiving a less than 8 bytes long packet in usbFunctionWrite() to | ||||
|     identify the end of a transfer. usbFunctionWrite() will NEVER be called | ||||
|     with a zero length. | ||||
|  | ||||
| * Release 2006-03-14 | ||||
|  | ||||
|   - Improved IAR C support: tiny memory model, more devices | ||||
|   - Added template usbconfig.h file under the name usbconfig-prototype.h | ||||
|  | ||||
| * Release 2006-03-26 | ||||
|  | ||||
|   - Added provision for one more interrupt-in endpoint (endpoint 3). | ||||
|   - Added provision for one interrupt-out endpoint (endpoint 1). | ||||
|   - Added flowcontrol macros for USB. | ||||
|   - Added provision for custom configuration descriptor. | ||||
|   - Allow ANY two port bits for D+ and D-. | ||||
|   - Merged (optional) receive endpoint number into global usbRxToken variable. | ||||
|   - Use USB_CFG_IOPORTNAME instead of USB_CFG_IOPORT. We now construct the | ||||
|     variable name from the single port letter instead of computing the address | ||||
|     of related ports from the output-port address. | ||||
|  | ||||
| * Release 2006-06-26 | ||||
|  | ||||
|   - Updated documentation in usbdrv.h and usbconfig-prototype.h to reflect the | ||||
|     new features. | ||||
|   - Removed "#warning" directives because IAR does not understand them. Use | ||||
|     unused static variables instead to generate a warning. | ||||
|   - Do not include <avr/io.h> when compiling with IAR. | ||||
|   - Introduced USB_CFG_DESCR_PROPS_* in usbconfig.h to configure how each | ||||
|     USB descriptor should be handled. It is now possible to provide descriptor | ||||
|     data in Flash, RAM or dynamically at runtime. | ||||
|   - STALL is now a status in usbTxLen* instead of a message. We can now conform | ||||
|     to the spec and leave the stall status pending until it is cleared. | ||||
|   - Made usbTxPacketCnt1 and usbTxPacketCnt3 public. This allows the | ||||
|     application code to reset data toggling on interrupt pipes. | ||||
|  | ||||
| * Release 2006-07-18 | ||||
|  | ||||
|   - Added an #if !defined __ASSEMBLER__ to the warning in usbdrv.h. This fixes | ||||
|     an assembler error. | ||||
|   - usbDeviceDisconnect() takes pull-up resistor to high impedance now. | ||||
|  | ||||
| * Release 2007-02-01 | ||||
|  | ||||
|   - Merged in some code size improvements from usbtiny (thanks to Dick | ||||
|     Streefland for these optimizations!) | ||||
|   - Special alignment requirement for usbRxBuf not required any more. Thanks | ||||
|     again to Dick Streefland for this hint! | ||||
|   - Reverted to "#warning" instead of unused static variables -- new versions | ||||
|     of IAR CC should handle this directive. | ||||
|   - Changed Open Source license to GNU GPL v2 in order to make linking against | ||||
|     other free libraries easier. We no longer require publication of the | ||||
|     circuit diagrams, but we STRONGLY encourage it. If you improve the driver | ||||
|     itself, PLEASE grant us a royalty free license to your changes for our | ||||
|     commercial license. | ||||
|  | ||||
| * Release 2007-03-29 | ||||
|  | ||||
|   - New configuration option "USB_PUBLIC" in usbconfig.h. | ||||
|   - Set USB version number to 1.10 instead of 1.01. | ||||
|   - Code used USB_CFG_DESCR_PROPS_STRING_DEVICE and | ||||
|     USB_CFG_DESCR_PROPS_STRING_PRODUCT inconsistently. Changed all occurrences | ||||
|     to USB_CFG_DESCR_PROPS_STRING_PRODUCT. | ||||
|   - New assembler module for 16.5 MHz RC oscillator clock with PLL in receiver | ||||
|     code. | ||||
|   - New assembler module for 16 MHz crystal. | ||||
|   - usbdrvasm.S contains common code only, clock-specific parts have been moved | ||||
|     to usbdrvasm12.S, usbdrvasm16.S and usbdrvasm165.S respectively. | ||||
|  | ||||
| * Release 2007-06-25 | ||||
|  | ||||
|   - 16 MHz module: Do SE0 check in stuffed bits as well. | ||||
|  | ||||
| * Release 2007-07-07 | ||||
|  | ||||
|   - Define hi8(x) for IAR compiler to limit result to 8 bits. This is necessary | ||||
|     for negative values. | ||||
|   - Added 15 MHz module contributed by V. Bosch. | ||||
|   - Interrupt vector name can now be configured. This is useful if somebody | ||||
|     wants to use a different hardware interrupt than INT0. | ||||
|  | ||||
| * Release 2007-08-07 | ||||
|  | ||||
|   - Moved handleIn3 routine in usbdrvasm16.S so that relative jump range is | ||||
|     not exceeded. | ||||
|   - More config options: USB_RX_USER_HOOK(), USB_INITIAL_DATATOKEN, | ||||
|     USB_COUNT_SOF | ||||
|   - USB_INTR_PENDING can now be a memory address, not just I/O | ||||
|  | ||||
| * Release 2007-09-19 | ||||
|  | ||||
|   - Split out common parts of assembler modules into separate include file | ||||
|   - Made endpoint numbers configurable so that given interface definitions | ||||
|     can be matched. See USB_CFG_EP3_NUMBER in usbconfig-prototype.h. | ||||
|   - Store endpoint number for interrupt/bulk-out so that usbFunctionWriteOut() | ||||
|     can handle any number of endpoints. | ||||
|   - Define usbDeviceConnect() and usbDeviceDisconnect() even if no | ||||
|     USB_CFG_PULLUP_IOPORTNAME is defined. Directly set D+ and D- to 0 in this | ||||
|     case. | ||||
|  | ||||
| * Release 2007-12-01 | ||||
|  | ||||
|   - Optimize usbDeviceConnect() and usbDeviceDisconnect() for less code size | ||||
|     when USB_CFG_PULLUP_IOPORTNAME is not defined. | ||||
|  | ||||
| * Release 2007-12-13 | ||||
|  | ||||
|   - Renamed all include-only assembler modules from *.S to *.inc so that | ||||
|     people don't add them to their project sources. | ||||
|   - Distribute leap bits in tx loop more evenly for 16 MHz module. | ||||
|   - Use "macro" and "endm" instead of ".macro" and ".endm" for IAR | ||||
|   - Avoid compiler warnings for constant expr range by casting some values in | ||||
|     USB descriptors. | ||||
|  | ||||
| * Release 2008-01-21 | ||||
|  | ||||
|   - Fixed bug in 15 and 16 MHz module where the new address set with | ||||
|     SET_ADDRESS was already accepted at the next NAK or ACK we send, not at | ||||
|     the next data packet we send. This caused problems when the host polled | ||||
|     too fast. Thanks to Alexander Neumann for his help and patience debugging | ||||
|     this issue! | ||||
|  | ||||
| * Release 2008-02-05 | ||||
|  | ||||
|   - Fixed bug in 16.5 MHz module where a register was used in the interrupt | ||||
|     handler before it was pushed. This bug was introduced with version | ||||
|     2007-09-19 when common parts were moved to a separate file. | ||||
|   - Optimized CRC routine (thanks to Reimar Doeffinger). | ||||
|  | ||||
| * Release 2008-02-16 | ||||
|  | ||||
|   - Removed outdated IAR compatibility stuff (code sections). | ||||
|   - Added hook macros for USB_RESET_HOOK() and USB_SET_ADDRESS_HOOK(). | ||||
|   - Added optional routine usbMeasureFrameLength() for calibration of the | ||||
|     internal RC oscillator. | ||||
|  | ||||
| * Release 2008-02-28 | ||||
|  | ||||
|   - USB_INITIAL_DATATOKEN defaults to USBPID_DATA1 now, which means that we | ||||
|     start with sending USBPID_DATA0. | ||||
|   - Changed defaults in usbconfig-prototype.h | ||||
|   - Added free USB VID/PID pair for MIDI class devices | ||||
|   - Restructured AVR-USB as separate package, not part of PowerSwitch any more. | ||||
|  | ||||
| * Release 2008-04-18 | ||||
|  | ||||
|   - Restructured usbdrv.c so that it is easier to read and understand. | ||||
|   - Better code optimization with gcc 4. | ||||
|   - If a second interrupt in endpoint is enabled, also add it to config | ||||
|     descriptor. | ||||
|   - Added config option for long transfers (above 254 bytes), see | ||||
|     USB_CFG_LONG_TRANSFERS in usbconfig.h. | ||||
|   - Added 20 MHz module contributed by Jeroen Benschop. | ||||
|  | ||||
| * Release 2008-05-13 | ||||
|  | ||||
|   - Fixed bug in libs-host/hiddata.c function usbhidGetReport(): length | ||||
|     was not incremented, pointer to length was incremented instead. | ||||
|   - Added code to command line tool(s) which claims an interface. This code | ||||
|     is disabled by default, but may be necessary on newer Linux kernels. | ||||
|   - Added usbconfig.h option "USB_CFG_CHECK_DATA_TOGGLING". | ||||
|   - New header "usbportability.h" prepares ports to other development | ||||
|     environments. | ||||
|   - Long transfers (above 254 bytes) did not work when usbFunctionRead() was | ||||
|     used to supply the data. Fixed this bug. [Thanks to Alexander Neumann!] | ||||
|   - In hiddata.c (example code for sending/receiving data over HID), use | ||||
|     USB_RECIP_DEVICE instead of USB_RECIP_INTERFACE for control transfers so | ||||
|     that we need not claim the interface. | ||||
|   - in usbPoll() loop 20 times polling for RESET state instead of 10 times. | ||||
|     This accounts for the higher clock rates we now support. | ||||
|   - Added a module for 12.8 MHz RC oscillator with PLL in receiver loop. | ||||
|   - Added hook to SOF code so that oscillator can be tuned to USB frame clock. | ||||
|   - Added timeout to waitForJ loop. Helps preventing unexpected hangs. | ||||
|   - Added example code for oscillator tuning to libs-device (thanks to | ||||
|     Henrik Haftmann for the idea to this routine). | ||||
|   - Implemented option USB_CFG_SUPPRESS_INTR_CODE. | ||||
|  | ||||
| * Release 2008-10-22 | ||||
|  | ||||
|   - Fixed libs-device/osctune.h: OSCCAL is memory address on ATMega88 and | ||||
|     similar, not offset of 0x20 needs to be added. | ||||
|   - Allow distribution under GPLv3 for those who have to link against other | ||||
|     code distributed under GPLv3. | ||||
|  | ||||
| * Release 2008-11-26 | ||||
|  | ||||
|   - Removed libusb-win32 dependency for hid-data example in Makefile.windows. | ||||
|     It was never required and confused many people. | ||||
|   - Added extern uchar usbRxToken to usbdrv.h. | ||||
|   - Integrated a module with CRC checks at 18 MHz by Lukas Schrittwieser. | ||||
|  | ||||
| * Release 2009-03-23 | ||||
|  | ||||
|   - Hid-mouse example used settings from hid-data example, fixed that. | ||||
|   - Renamed project to V-USB due to a trademark issue with Atmel(r). | ||||
|   - Changed CommercialLicense.txt and USBID-License.txt to make the | ||||
|     background of USB ID registration clearer. | ||||
|  | ||||
| * Release 2009-04-15 | ||||
|  | ||||
|   - Changed CommercialLicense.txt to reflect the new range of PIDs from | ||||
|     Jason Kotzin. | ||||
|   - Removed USBID-License.txt in favor of USB-IDs-for-free.txt and | ||||
|     USB-ID-FAQ.txt | ||||
|   - Fixed a bug in the 12.8 MHz module: End Of Packet decection was made in | ||||
|     the center between bit 0 and 1 of each byte. This is where the data lines | ||||
|     are expected to change and the sampled data may therefore be nonsense. | ||||
|     We therefore check EOP ONLY if bits 0 AND 1 have both been read as 0 on D-. | ||||
|   - Fixed a bitstuffing problem in the 16 MHz module: If bit 6 was stuffed, | ||||
|     the unstuffing code in the receiver routine was 1 cycle too long. If | ||||
|     multiple bytes had the unstuffing in bit 6, the error summed up until the | ||||
|     receiver was out of sync. | ||||
|   - Included option for faster CRC routine. | ||||
|     Thanks to Slawomir Fras (BoskiDialer) for this code! | ||||
|   - Updated bits in Configuration Descriptor's bmAttributes according to | ||||
|     USB 1.1 (in particular bit 7, it is a must-be-set bit now). | ||||
|  | ||||
| * Release 2009-08-22 | ||||
|  | ||||
|   - Moved first DBG1() after odDebugInit() in all examples. | ||||
|   - Use vector INT0_vect instead of SIG_INTERRUPT0 if defined. This makes | ||||
|     V-USB compatible with the new "p" suffix devices (e.g. ATMega328p). | ||||
|   - USB_CFG_CLOCK_KHZ setting is now required in usbconfig.h (no default any | ||||
|     more). | ||||
|   - New option USB_CFG_DRIVER_FLASH_PAGE allows boot loaders on devices with | ||||
|     more than 64 kB flash. | ||||
|   - Built-in configuration descriptor allows custom definition for second | ||||
|     endpoint now. | ||||
|  | ||||
| * Release 2010-07-15 | ||||
|  | ||||
|   - Fixed bug in usbDriverSetup() which prevented descriptor sizes above 255 | ||||
|     bytes. | ||||
|   - Avoid a compiler warning for unused parameter in usbHandleResetHook() when | ||||
|     compiler option -Wextra is enabled. | ||||
|   - Fixed wrong hex value for some IDs in USB-IDs-for-free.txt. | ||||
|   - Keep a define for USBATTR_BUSPOWER, although the flag does not exist | ||||
|     in USB 1.1 any more. Set it to 0. This is for backward compatibility. | ||||
|  | ||||
| * Release 2012-01-09 | ||||
|  | ||||
|   - Define a separate (defined) type for usbMsgPtr so that projects using a | ||||
|     tiny memory model can define it to an 8 bit type in usbconfig.h. This | ||||
|     change also saves a couple of bytes when using a scalar 16 bit type. | ||||
|   - Inserted "const" keyword for all PROGMEM declarations because new GCC | ||||
|     requires it. | ||||
|   - Fixed problem with dependence of usbportability.h on usbconfig.h. This | ||||
|     problem occurred with IAR CC only. | ||||
|   - Prepared repository for github.com. | ||||
|  | ||||
| * Release 2012-12-06 | ||||
							
								
								
									
										166
									
								
								usbdrv/CommercialLicense.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								usbdrv/CommercialLicense.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | ||||
| V-USB Driver Software License Agreement | ||||
| Version 2012-07-09 | ||||
|  | ||||
| THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN | ||||
| ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING | ||||
| THE AMOUNT ACCORDING TO SECTION 4 ("PAYMENT") TO OBJECTIVE DEVELOPMENT. | ||||
|  | ||||
|  | ||||
| 1 DEFINITIONS | ||||
|  | ||||
| 1.1 "OBJECTIVE DEVELOPMENT" shall mean OBJECTIVE DEVELOPMENT Software GmbH, | ||||
| Grosse Schiffgasse 1A/7, 1020 Wien, AUSTRIA. | ||||
|  | ||||
| 1.2 "You" shall mean the Licensee. | ||||
|  | ||||
| 1.3 "V-USB" shall mean all files included in the package distributed under | ||||
| the name "vusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/vusb/) | ||||
| unless otherwise noted. This includes the firmware-only USB device | ||||
| implementation for Atmel AVR microcontrollers, some simple device examples | ||||
| and host side software examples and libraries. | ||||
|  | ||||
|  | ||||
| 2 LICENSE GRANTS | ||||
|  | ||||
| 2.1 Source Code. OBJECTIVE DEVELOPMENT shall furnish you with the source | ||||
| code of V-USB. | ||||
|  | ||||
| 2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the | ||||
| non-exclusive right to use, copy and distribute V-USB with your hardware | ||||
| product(s), restricted by the limitations in section 3 below. | ||||
|  | ||||
| 2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify | ||||
| the source code and your copy of V-USB according to your needs. | ||||
|  | ||||
| 2.4 USB IDs. OBJECTIVE DEVELOPMENT furnishes you with one or two USB | ||||
| Product ID(s), sent to you in e-mail. These Product IDs are reserved | ||||
| exclusively for you. OBJECTIVE DEVELOPMENT has obtained USB Product ID | ||||
| ranges under the Vendor ID 5824 from Wouter van Ooijen (Van Ooijen | ||||
| Technische Informatica, www.voti.nl) and under the Vendor ID 8352 from | ||||
| Jason Kotzin (now flirc.tv, Inc.). Both owners of the Vendor IDs have | ||||
| obtained these IDs from the USB Implementers Forum, Inc. (www.usb.org). | ||||
| OBJECTIVE DEVELOPMENT disclaims all liability which might arise from the | ||||
| assignment of USB IDs. | ||||
|  | ||||
| 2.5 USB Certification. Although not part of this agreement, we want to make | ||||
| it clear that you cannot become USB certified when you use V-USB or a USB | ||||
| Product ID assigned by OBJECTIVE DEVELOPMENT. AVR microcontrollers don't | ||||
| meet the electrical specifications required by the USB specification and | ||||
| the USB Implementers Forum certifies only members who bought a Vendor ID of | ||||
| their own. | ||||
|  | ||||
|  | ||||
| 3 LICENSE RESTRICTIONS | ||||
|  | ||||
| 3.1 Number of Units. Only one of the following three definitions is | ||||
| applicable. Which one is determined by the amount you pay to OBJECTIVE | ||||
| DEVELOPMENT, see section 4 ("Payment") below. | ||||
|  | ||||
| Hobby License: You may use V-USB according to section 2 above in no more | ||||
| than 5 hardware units. These units must not be sold for profit. | ||||
|  | ||||
| Entry Level License: You may use V-USB according to section 2 above in no | ||||
| more than 150 hardware units. | ||||
|  | ||||
| Professional License: You may use V-USB according to section 2 above in | ||||
| any number of hardware units, except for large scale production ("unlimited | ||||
| fair use"). Quantities below 10,000 units are not considered large scale | ||||
| production. If your reach quantities which are obviously large scale | ||||
| production, you must pay a license fee of 0.10 EUR per unit for all units | ||||
| above 10,000. | ||||
|  | ||||
| 3.2 Rental. You may not rent, lease, or lend V-USB or otherwise encumber | ||||
| any copy of V-USB, or any of the rights granted herein. | ||||
|  | ||||
| 3.3 Transfer. You may not transfer your rights under this Agreement to | ||||
| another party without OBJECTIVE DEVELOPMENT's prior written consent. If | ||||
| such consent is obtained, you may permanently transfer this License to | ||||
| another party. The recipient of such transfer must agree to all terms and | ||||
| conditions of this Agreement. | ||||
|  | ||||
| 3.4 Reservation of Rights. OBJECTIVE DEVELOPMENT retains all rights not | ||||
| expressly granted. | ||||
|  | ||||
| 3.5 Non-Exclusive Rights. Your license rights under this Agreement are | ||||
| non-exclusive. | ||||
|  | ||||
| 3.6 Third Party Rights. This Agreement cannot grant you rights controlled | ||||
| by third parties. In particular, you are not allowed to use the USB logo or | ||||
| other trademarks owned by the USB Implementers Forum, Inc. without their | ||||
| consent. Since such consent depends on USB certification, it should be | ||||
| noted that V-USB will not pass certification because it does not | ||||
| implement checksum verification and the microcontroller ports do not meet | ||||
| the electrical specifications. | ||||
|  | ||||
|  | ||||
| 4 PAYMENT | ||||
|  | ||||
| The payment amount depends on the variation of this agreement (according to | ||||
| section 3.1) into which you want to enter. Concrete prices are listed on | ||||
| OBJECTIVE DEVELOPMENT's web site, usually at | ||||
| http://www.obdev.at/vusb/license.html. You agree to pay the amount listed | ||||
| there to OBJECTIVE DEVELOPMENT or OBJECTIVE DEVELOPMENT's payment processor | ||||
| or reseller. | ||||
|  | ||||
|  | ||||
| 5 COPYRIGHT AND OWNERSHIP | ||||
|  | ||||
| V-USB is protected by copyright laws and international copyright | ||||
| treaties, as well as other intellectual property laws and treaties. V-USB | ||||
| is licensed, not sold. | ||||
|  | ||||
|  | ||||
| 6 TERM AND TERMINATION | ||||
|  | ||||
| 6.1 Term. This Agreement shall continue indefinitely. However, OBJECTIVE | ||||
| DEVELOPMENT may terminate this Agreement and revoke the granted license and | ||||
| USB-IDs if you fail to comply with any of its terms and conditions. | ||||
|  | ||||
| 6.2 Survival of Terms. All provisions regarding secrecy, confidentiality | ||||
| and limitation of liability shall survive termination of this agreement. | ||||
|  | ||||
|  | ||||
| 7 DISCLAIMER OF WARRANTY AND LIABILITY | ||||
|  | ||||
| LIMITED WARRANTY. V-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | ||||
| KIND. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, OBJECTIVE | ||||
| DEVELOPMENT AND ITS SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES, EITHER | ||||
| EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||
| OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND | ||||
| NON-INFRINGEMENT, WITH REGARD TO V-USB, AND THE PROVISION OF OR FAILURE | ||||
| TO PROVIDE SUPPORT SERVICES. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL | ||||
| RIGHTS. YOU MAY HAVE OTHERS, WHICH VARY FROM STATE/JURISDICTION TO | ||||
| STATE/JURISDICTION. | ||||
|  | ||||
| LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, | ||||
| IN NO EVENT SHALL OBJECTIVE DEVELOPMENT OR ITS SUPPLIERS BE LIABLE FOR ANY | ||||
| SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER | ||||
| (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, | ||||
| BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY | ||||
| LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE V-USB OR THE | ||||
| PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, EVEN IF OBJECTIVE | ||||
| DEVELOPMENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY | ||||
| CASE, OBJECTIVE DEVELOPMENT'S ENTIRE LIABILITY UNDER ANY PROVISION OF THIS | ||||
| AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR V-USB. | ||||
|  | ||||
|  | ||||
| 8 MISCELLANEOUS TERMS | ||||
|  | ||||
| 8.1 Marketing. OBJECTIVE DEVELOPMENT has the right to mention for marketing | ||||
| purposes that you entered into this agreement. | ||||
|  | ||||
| 8.2 Entire Agreement. This document represents the entire agreement between | ||||
| OBJECTIVE DEVELOPMENT and you. It may only be modified in writing signed by | ||||
| an authorized representative of both, OBJECTIVE DEVELOPMENT and you. | ||||
|  | ||||
| 8.3 Severability. In case a provision of these terms and conditions should | ||||
| be or become partly or entirely invalid, ineffective, or not executable, | ||||
| the validity of all other provisions shall not be affected. | ||||
|  | ||||
| 8.4 Applicable Law. This agreement is governed by the laws of the Republic | ||||
| of Austria. | ||||
|  | ||||
| 8.5 Responsible Courts. The responsible courts in Vienna/Austria will have | ||||
| exclusive jurisdiction regarding all disputes in connection with this | ||||
| agreement. | ||||
|  | ||||
							
								
								
									
										361
									
								
								usbdrv/License.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										361
									
								
								usbdrv/License.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,361 @@ | ||||
| OBJECTIVE DEVELOPMENT GmbH's V-USB driver software is distributed under the | ||||
| terms and conditions of the GNU GPL version 2 or the GNU GPL version 3. It is | ||||
| your choice whether you apply the terms of version 2 or version 3. The full | ||||
| text of GPLv2 is included below. In addition to the requirements in the GPL, | ||||
| we STRONGLY ENCOURAGE you to do the following: | ||||
|  | ||||
| (1) Publish your entire project on a web site and drop us a note with the URL. | ||||
| Use the form at http://www.obdev.at/vusb/feedback.html for your submission. | ||||
|  | ||||
| (2) Adhere to minimum publication standards. Please include AT LEAST: | ||||
|     - a circuit diagram in PDF, PNG or GIF format | ||||
|     - full source code for the host software | ||||
|     - a Readme.txt file in ASCII format which describes the purpose of the | ||||
|       project and what can be found in which directories and which files | ||||
|     - a reference to http://www.obdev.at/vusb/ | ||||
|  | ||||
| (3) If you improve the driver firmware itself, please give us a free license | ||||
| to your modifications for our commercial license offerings. | ||||
|  | ||||
|  | ||||
|  | ||||
|                     GNU GENERAL PUBLIC LICENSE | ||||
|                        Version 2, June 1991 | ||||
|  | ||||
|  Copyright (C) 1989, 1991 Free Software Foundation, Inc. | ||||
|                        59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
|  | ||||
|                             Preamble | ||||
|  | ||||
|   The licenses for most software are designed to take away your | ||||
| freedom to share and change it.  By contrast, the GNU General Public | ||||
| License is intended to guarantee your freedom to share and change free | ||||
| software--to make sure the software is free for all its users.  This | ||||
| General Public License applies to most of the Free Software | ||||
| Foundation's software and to any other program whose authors commit to | ||||
| using it.  (Some other Free Software Foundation software is covered by | ||||
| the GNU Library General Public License instead.)  You can apply it to | ||||
| your programs, too. | ||||
|  | ||||
|   When we speak of free software, we are referring to freedom, not | ||||
| price.  Our General Public Licenses are designed to make sure that you | ||||
| have the freedom to distribute copies of free software (and charge for | ||||
| this service if you wish), that you receive source code or can get it | ||||
| if you want it, that you can change the software or use pieces of it | ||||
| in new free programs; and that you know you can do these things. | ||||
|  | ||||
|   To protect your rights, we need to make restrictions that forbid | ||||
| anyone to deny you these rights or to ask you to surrender the rights. | ||||
| These restrictions translate to certain responsibilities for you if you | ||||
| distribute copies of the software, or if you modify it. | ||||
|  | ||||
|   For example, if you distribute copies of such a program, whether | ||||
| gratis or for a fee, you must give the recipients all the rights that | ||||
| you have.  You must make sure that they, too, receive or can get the | ||||
| source code.  And you must show them these terms so they know their | ||||
| rights. | ||||
|  | ||||
|   We protect your rights with two steps: (1) copyright the software, and | ||||
| (2) offer you this license which gives you legal permission to copy, | ||||
| distribute and/or modify the software. | ||||
|  | ||||
|   Also, for each author's protection and ours, we want to make certain | ||||
| that everyone understands that there is no warranty for this free | ||||
| software.  If the software is modified by someone else and passed on, we | ||||
| want its recipients to know that what they have is not the original, so | ||||
| that any problems introduced by others will not reflect on the original | ||||
| authors' reputations. | ||||
|  | ||||
|   Finally, any free program is threatened constantly by software | ||||
| patents.  We wish to avoid the danger that redistributors of a free | ||||
| program will individually obtain patent licenses, in effect making the | ||||
| program proprietary.  To prevent this, we have made it clear that any | ||||
| patent must be licensed for everyone's free use or not licensed at all. | ||||
|  | ||||
|   The precise terms and conditions for copying, distribution and | ||||
| modification follow. | ||||
|  | ||||
|                     GNU GENERAL PUBLIC LICENSE | ||||
|    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||||
|  | ||||
|   0. This License applies to any program or other work which contains | ||||
| a notice placed by the copyright holder saying it may be distributed | ||||
| under the terms of this General Public License.  The "Program", below, | ||||
| refers to any such program or work, and a "work based on the Program" | ||||
| means either the Program or any derivative work under copyright law: | ||||
| that is to say, a work containing the Program or a portion of it, | ||||
| either verbatim or with modifications and/or translated into another | ||||
| language.  (Hereinafter, translation is included without limitation in | ||||
| the term "modification".)  Each licensee is addressed as "you". | ||||
|  | ||||
| Activities other than copying, distribution and modification are not | ||||
| covered by this License; they are outside its scope.  The act of | ||||
| running the Program is not restricted, and the output from the Program | ||||
| is covered only if its contents constitute a work based on the | ||||
| Program (independent of having been made by running the Program). | ||||
| Whether that is true depends on what the Program does. | ||||
|  | ||||
|   1. You may copy and distribute verbatim copies of the Program's | ||||
| source code as you receive it, in any medium, provided that you | ||||
| conspicuously and appropriately publish on each copy an appropriate | ||||
| copyright notice and disclaimer of warranty; keep intact all the | ||||
| notices that refer to this License and to the absence of any warranty; | ||||
| and give any other recipients of the Program a copy of this License | ||||
| along with the Program. | ||||
|  | ||||
| You may charge a fee for the physical act of transferring a copy, and | ||||
| you may at your option offer warranty protection in exchange for a fee. | ||||
|  | ||||
|   2. You may modify your copy or copies of the Program or any portion | ||||
| of it, thus forming a work based on the Program, and copy and | ||||
| distribute such modifications or work under the terms of Section 1 | ||||
| above, provided that you also meet all of these conditions: | ||||
|  | ||||
|     a) You must cause the modified files to carry prominent notices | ||||
|     stating that you changed the files and the date of any change. | ||||
|  | ||||
|     b) You must cause any work that you distribute or publish, that in | ||||
|     whole or in part contains or is derived from the Program or any | ||||
|     part thereof, to be licensed as a whole at no charge to all third | ||||
|     parties under the terms of this License. | ||||
|  | ||||
|     c) If the modified program normally reads commands interactively | ||||
|     when run, you must cause it, when started running for such | ||||
|     interactive use in the most ordinary way, to print or display an | ||||
|     announcement including an appropriate copyright notice and a | ||||
|     notice that there is no warranty (or else, saying that you provide | ||||
|     a warranty) and that users may redistribute the program under | ||||
|     these conditions, and telling the user how to view a copy of this | ||||
|     License.  (Exception: if the Program itself is interactive but | ||||
|     does not normally print such an announcement, your work based on | ||||
|     the Program is not required to print an announcement.) | ||||
|  | ||||
| These requirements apply to the modified work as a whole.  If | ||||
| identifiable sections of that work are not derived from the Program, | ||||
| and can be reasonably considered independent and separate works in | ||||
| themselves, then this License, and its terms, do not apply to those | ||||
| sections when you distribute them as separate works.  But when you | ||||
| distribute the same sections as part of a whole which is a work based | ||||
| on the Program, the distribution of the whole must be on the terms of | ||||
| this License, whose permissions for other licensees extend to the | ||||
| entire whole, and thus to each and every part regardless of who wrote it. | ||||
|  | ||||
| Thus, it is not the intent of this section to claim rights or contest | ||||
| your rights to work written entirely by you; rather, the intent is to | ||||
| exercise the right to control the distribution of derivative or | ||||
| collective works based on the Program. | ||||
|  | ||||
| In addition, mere aggregation of another work not based on the Program | ||||
| with the Program (or with a work based on the Program) on a volume of | ||||
| a storage or distribution medium does not bring the other work under | ||||
| the scope of this License. | ||||
|  | ||||
|   3. You may copy and distribute the Program (or a work based on it, | ||||
| under Section 2) in object code or executable form under the terms of | ||||
| Sections 1 and 2 above provided that you also do one of the following: | ||||
|  | ||||
|     a) Accompany it with the complete corresponding machine-readable | ||||
|     source code, which must be distributed under the terms of Sections | ||||
|     1 and 2 above on a medium customarily used for software interchange; or, | ||||
|  | ||||
|     b) Accompany it with a written offer, valid for at least three | ||||
|     years, to give any third party, for a charge no more than your | ||||
|     cost of physically performing source distribution, a complete | ||||
|     machine-readable copy of the corresponding source code, to be | ||||
|     distributed under the terms of Sections 1 and 2 above on a medium | ||||
|     customarily used for software interchange; or, | ||||
|  | ||||
|     c) Accompany it with the information you received as to the offer | ||||
|     to distribute corresponding source code.  (This alternative is | ||||
|     allowed only for noncommercial distribution and only if you | ||||
|     received the program in object code or executable form with such | ||||
|     an offer, in accord with Subsection b above.) | ||||
|  | ||||
| The source code for a work means the preferred form of the work for | ||||
| making modifications to it.  For an executable work, complete source | ||||
| code means all the source code for all modules it contains, plus any | ||||
| associated interface definition files, plus the scripts used to | ||||
| control compilation and installation of the executable.  However, as a | ||||
| special exception, the source code distributed need not include | ||||
| anything that is normally distributed (in either source or binary | ||||
| form) with the major components (compiler, kernel, and so on) of the | ||||
| operating system on which the executable runs, unless that component | ||||
| itself accompanies the executable. | ||||
|  | ||||
| If distribution of executable or object code is made by offering | ||||
| access to copy from a designated place, then offering equivalent | ||||
| access to copy the source code from the same place counts as | ||||
| distribution of the source code, even though third parties are not | ||||
| compelled to copy the source along with the object code. | ||||
|  | ||||
|   4. You may not copy, modify, sublicense, or distribute the Program | ||||
| except as expressly provided under this License.  Any attempt | ||||
| otherwise to copy, modify, sublicense or distribute the Program is | ||||
| void, and will automatically terminate your rights under this License. | ||||
| However, parties who have received copies, or rights, from you under | ||||
| this License will not have their licenses terminated so long as such | ||||
| parties remain in full compliance. | ||||
|  | ||||
|   5. You are not required to accept this License, since you have not | ||||
| signed it.  However, nothing else grants you permission to modify or | ||||
| distribute the Program or its derivative works.  These actions are | ||||
| prohibited by law if you do not accept this License.  Therefore, by | ||||
| modifying or distributing the Program (or any work based on the | ||||
| Program), you indicate your acceptance of this License to do so, and | ||||
| all its terms and conditions for copying, distributing or modifying | ||||
| the Program or works based on it. | ||||
|  | ||||
|   6. Each time you redistribute the Program (or any work based on the | ||||
| Program), the recipient automatically receives a license from the | ||||
| original licensor to copy, distribute or modify the Program subject to | ||||
| these terms and conditions.  You may not impose any further | ||||
| restrictions on the recipients' exercise of the rights granted herein. | ||||
| You are not responsible for enforcing compliance by third parties to | ||||
| this License. | ||||
|  | ||||
|   7. If, as a consequence of a court judgment or allegation of patent | ||||
| infringement or for any other reason (not limited to patent issues), | ||||
| conditions are imposed on you (whether by court order, agreement or | ||||
| otherwise) that contradict the conditions of this License, they do not | ||||
| excuse you from the conditions of this License.  If you cannot | ||||
| distribute so as to satisfy simultaneously your obligations under this | ||||
| License and any other pertinent obligations, then as a consequence you | ||||
| may not distribute the Program at all.  For example, if a patent | ||||
| license would not permit royalty-free redistribution of the Program by | ||||
| all those who receive copies directly or indirectly through you, then | ||||
| the only way you could satisfy both it and this License would be to | ||||
| refrain entirely from distribution of the Program. | ||||
|  | ||||
| If any portion of this section is held invalid or unenforceable under | ||||
| any particular circumstance, the balance of the section is intended to | ||||
| apply and the section as a whole is intended to apply in other | ||||
| circumstances. | ||||
|  | ||||
| It is not the purpose of this section to induce you to infringe any | ||||
| patents or other property right claims or to contest validity of any | ||||
| such claims; this section has the sole purpose of protecting the | ||||
| integrity of the free software distribution system, which is | ||||
| implemented by public license practices.  Many people have made | ||||
| generous contributions to the wide range of software distributed | ||||
| through that system in reliance on consistent application of that | ||||
| system; it is up to the author/donor to decide if he or she is willing | ||||
| to distribute software through any other system and a licensee cannot | ||||
| impose that choice. | ||||
|  | ||||
| This section is intended to make thoroughly clear what is believed to | ||||
| be a consequence of the rest of this License. | ||||
|  | ||||
|   8. If the distribution and/or use of the Program is restricted in | ||||
| certain countries either by patents or by copyrighted interfaces, the | ||||
| original copyright holder who places the Program under this License | ||||
| may add an explicit geographical distribution limitation excluding | ||||
| those countries, so that distribution is permitted only in or among | ||||
| countries not thus excluded.  In such case, this License incorporates | ||||
| the limitation as if written in the body of this License. | ||||
|  | ||||
|   9. The Free Software Foundation may publish revised and/or new versions | ||||
| of the General Public License from time to time.  Such new versions will | ||||
| be similar in spirit to the present version, but may differ in detail to | ||||
| address new problems or concerns. | ||||
|  | ||||
| Each version is given a distinguishing version number.  If the Program | ||||
| specifies a version number of this License which applies to it and "any | ||||
| later version", you have the option of following the terms and conditions | ||||
| either of that version or of any later version published by the Free | ||||
| Software Foundation.  If the Program does not specify a version number of | ||||
| this License, you may choose any version ever published by the Free Software | ||||
| Foundation. | ||||
|  | ||||
|   10. If you wish to incorporate parts of the Program into other free | ||||
| programs whose distribution conditions are different, write to the author | ||||
| to ask for permission.  For software which is copyrighted by the Free | ||||
| Software Foundation, write to the Free Software Foundation; we sometimes | ||||
| make exceptions for this.  Our decision will be guided by the two goals | ||||
| of preserving the free status of all derivatives of our free software and | ||||
| of promoting the sharing and reuse of software generally. | ||||
|  | ||||
|                             NO WARRANTY | ||||
|  | ||||
|   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | ||||
| FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN | ||||
| OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | ||||
| PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | ||||
| OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS | ||||
| TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE | ||||
| PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | ||||
| REPAIR OR CORRECTION. | ||||
|  | ||||
|   12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | ||||
| WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | ||||
| REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | ||||
| INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | ||||
| OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | ||||
| TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | ||||
| YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | ||||
| PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | ||||
| POSSIBILITY OF SUCH DAMAGES. | ||||
|  | ||||
|                      END OF TERMS AND CONDITIONS | ||||
|  | ||||
|             How to Apply These Terms to Your New Programs | ||||
|  | ||||
|   If you develop a new program, and you want it to be of the greatest | ||||
| possible use to the public, the best way to achieve this is to make it | ||||
| free software which everyone can redistribute and change under these terms. | ||||
|  | ||||
|   To do so, attach the following notices to the program.  It is safest | ||||
| to attach them to the start of each source file to most effectively | ||||
| convey the exclusion of warranty; and each file should have at least | ||||
| the "copyright" line and a pointer to where the full notice is found. | ||||
|  | ||||
|     <one line to give the program's name and a brief idea of what it does.> | ||||
|     Copyright (C) <year>  <name of author> | ||||
|  | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  | ||||
|  | ||||
| Also add information on how to contact you by electronic and paper mail. | ||||
|  | ||||
| If the program is interactive, make it output a short notice like this | ||||
| when it starts in an interactive mode: | ||||
|  | ||||
|     Gnomovision version 69, Copyright (C) year name of author | ||||
|     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | ||||
|     This is free software, and you are welcome to redistribute it | ||||
|     under certain conditions; type `show c' for details. | ||||
|  | ||||
| The hypothetical commands `show w' and `show c' should show the appropriate | ||||
| parts of the General Public License.  Of course, the commands you use may | ||||
| be called something other than `show w' and `show c'; they could even be | ||||
| mouse-clicks or menu items--whatever suits your program. | ||||
|  | ||||
| You should also get your employer (if you work as a programmer) or your | ||||
| school, if any, to sign a "copyright disclaimer" for the program, if | ||||
| necessary.  Here is a sample; alter the names: | ||||
|  | ||||
|   Yoyodyne, Inc., hereby disclaims all copyright interest in the program | ||||
|   `Gnomovision' (which makes passes at compilers) written by James Hacker. | ||||
|  | ||||
|   <signature of Ty Coon>, 1 April 1989 | ||||
|   Ty Coon, President of Vice | ||||
|  | ||||
| This General Public License does not permit incorporating your program into | ||||
| proprietary programs.  If your program is a subroutine library, you may | ||||
| consider it more useful to permit linking proprietary applications with the | ||||
| library.  If this is what you want to do, use the GNU Library General | ||||
| Public License instead of this License. | ||||
							
								
								
									
										172
									
								
								usbdrv/Readme.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								usbdrv/Readme.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,172 @@ | ||||
| This is the Readme file to Objective Development's firmware-only USB driver | ||||
| for Atmel AVR microcontrollers. For more information please visit | ||||
| http://www.obdev.at/vusb/ | ||||
|  | ||||
| This directory contains the USB firmware only. Copy it as-is to your own | ||||
| project and add all .c and .S files to your project (these files are marked | ||||
| with an asterisk in the list below). Then copy usbconfig-prototype.h as | ||||
| usbconfig.h to your project and edit it according to your configuration. | ||||
|  | ||||
|  | ||||
| TECHNICAL DOCUMENTATION | ||||
| ======================= | ||||
| The technical documentation (API) for the firmware driver is contained in the | ||||
| file "usbdrv.h". Please read all of it carefully! Configuration options are | ||||
| documented in "usbconfig-prototype.h". | ||||
|  | ||||
| The driver consists of the following files: | ||||
|   Readme.txt ............. The file you are currently reading. | ||||
|   Changelog.txt .......... Release notes for all versions of the driver. | ||||
|   usbdrv.h ............... Driver interface definitions and technical docs. | ||||
| * usbdrv.c ............... High level language part of the driver. Link this | ||||
|                            module to your code! | ||||
| * usbdrvasm.S ............ Assembler part of the driver. This module is mostly | ||||
|                            a stub and includes one of the usbdrvasm*.S files | ||||
|                            depending on processor clock. Link this module to | ||||
|                            your code! | ||||
|   usbdrvasm*.inc ......... Assembler routines for particular clock frequencies. | ||||
|                            Included by usbdrvasm.S, don't link it directly! | ||||
|   asmcommon.inc .......... Common assembler routines. Included by | ||||
|                            usbdrvasm*.inc, don't link it directly! | ||||
|   usbconfig-prototype.h .. Prototype for your own usbdrv.h file. | ||||
| * oddebug.c .............. Debug functions. Only used when DEBUG_LEVEL is | ||||
|                            defined to a value greater than 0. Link this module | ||||
|                            to your code! | ||||
|   oddebug.h .............. Interface definitions of the debug module. | ||||
|   usbportability.h ....... Header with compiler-dependent stuff. | ||||
|   usbdrvasm.asm .......... Compatibility stub for IAR-C-compiler. Use this | ||||
|                            module instead of usbdrvasm.S when you assembler | ||||
|                            with IAR's tools. | ||||
|   License.txt ............ Open Source license for this driver. | ||||
|   CommercialLicense.txt .. Optional commercial license for this driver. | ||||
|   USB-ID-FAQ.txt ......... General infos about USB Product- and Vendor-IDs. | ||||
|   USB-IDs-for-free.txt ... List and terms of use for free shared PIDs. | ||||
|  | ||||
| (*) ... These files should be linked to your project. | ||||
|  | ||||
|  | ||||
| CPU CORE CLOCK FREQUENCY | ||||
| ======================== | ||||
| We supply assembler modules for clock frequencies of 12 MHz, 12.8 MHz, 15 MHz, | ||||
| 16 MHz, 16.5 MHz 18 MHz and 20 MHz. Other clock rates are not supported. The | ||||
| actual clock rate must be configured in usbconfig.h. | ||||
|  | ||||
| 12 MHz Clock | ||||
| This is the traditional clock rate of V-USB because it's the lowest clock | ||||
| rate where the timing constraints of the USB spec can be met. | ||||
|  | ||||
| 15 MHz Clock | ||||
| Similar to 12 MHz, but some NOPs inserted. On the other hand, the higher clock | ||||
| rate allows for some loops which make the resulting code size somewhat smaller | ||||
| than the 12 MHz version. | ||||
|  | ||||
| 16 MHz Clock | ||||
| This clock rate has been added for users of the Arduino board and other | ||||
| ready-made boards which come with a fixed 16 MHz crystal. It's also an option | ||||
| if you need the slightly higher clock rate for performance reasons. Since | ||||
| 16 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code | ||||
| is somewhat tricky and has to insert a leap cycle every third byte. | ||||
|  | ||||
| 12.8 MHz and 16.5 MHz Clock | ||||
| The assembler modules for these clock rates differ from the other modules | ||||
| because they have been built for an RC oscillator with only 1% precision. The | ||||
| receiver code inserts leap cycles to compensate for clock deviations. 1% is | ||||
| also the precision which can be achieved by calibrating the internal RC | ||||
| oscillator of the AVR. Please note that only AVRs with internal 64 MHz PLL | ||||
| oscillator can reach 16.5 MHz with the RC oscillator. This includes the very | ||||
| popular ATTiny25, ATTiny45, ATTiny85 series as well as the ATTiny26. Almost | ||||
| all AVRs can reach 12.8 MHz, although this is outside the specified range. | ||||
|  | ||||
| See the EasyLogger example at http://www.obdev.at/vusb/easylogger.html for | ||||
| code which calibrates the RC oscillator based on the USB frame clock. | ||||
|  | ||||
| 18 MHz Clock | ||||
| This module is closer to the USB specification because it performs an on the | ||||
| fly CRC check for incoming packets. Packets with invalid checksum are | ||||
| discarded as required by the spec. If you also implement checks for data | ||||
| PID toggling on application level (see option USB_CFG_CHECK_DATA_TOGGLING | ||||
| in usbconfig.h for more info), this ensures data integrity. Due to the CRC | ||||
| tables and alignment requirements, this code is bigger than modules for other | ||||
| clock rates. To activate this module, you must define USB_CFG_CHECK_CRC to 1 | ||||
| and USB_CFG_CLOCK_KHZ to 18000 in usbconfig.h. | ||||
|  | ||||
| 20 MHz Clock | ||||
| This module is for people who won't do it with less than the maximum. Since | ||||
| 20 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code | ||||
| uses similar tricks as the 16 MHz module to insert leap cycles. | ||||
|  | ||||
|  | ||||
| USB IDENTIFIERS | ||||
| =============== | ||||
| Every USB device needs a vendor- and a product-identifier (VID and PID). VIDs | ||||
| are obtained from usb.org for a price of 1,500 USD. Once you have a VID, you | ||||
| can assign PIDs at will. | ||||
|  | ||||
| Since an entry level cost of 1,500 USD is too high for most small companies | ||||
| and hobbyists, we provide some VID/PID pairs for free. See the file | ||||
| USB-IDs-for-free.txt for details. | ||||
|  | ||||
| Objective Development also has some license offerings which include product | ||||
| IDs. See http://www.obdev.at/vusb/ for details. | ||||
|  | ||||
|  | ||||
| DEVELOPMENT SYSTEM | ||||
| ================== | ||||
| This driver has been developed and optimized for the GNU compiler version 3 | ||||
| and 4. We recommend that you use the GNU compiler suite because it is freely | ||||
| available. V-USB has also been ported to the IAR compiler and assembler. It | ||||
| has been tested with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the | ||||
| "small" and "tiny" memory model. Not every release is tested with IAR CC and | ||||
| the driver may therefore fail to compile with IAR. Please note that gcc is | ||||
| more efficient for usbdrv.c because this module has been deliberately | ||||
| optimized for gcc. | ||||
|  | ||||
| Gcc version 3 produces smaller code than version 4 due to new optimizing | ||||
| capabilities which don't always improve things on 8 bit CPUs. The code size | ||||
| generated by gcc 4 can be reduced with the compiler options | ||||
| -fno-move-loop-invariants, -fno-tree-scev-cprop and | ||||
| -fno-inline-small-functions in addition to -Os. On devices with more than | ||||
| 8k of flash memory, we also recommend the linker option --relax (written as | ||||
| -Wl,--relax for gcc) to convert absolute calls into relative where possible. | ||||
|  | ||||
| For more information about optimizing options see: | ||||
|  | ||||
|     http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html | ||||
|  | ||||
| These optimizations are good for gcc 4.x. Version 3.x of gcc does not support | ||||
| most of these options and produces good code anyway. | ||||
|  | ||||
|  | ||||
| USING V-USB FOR FREE | ||||
| ==================== | ||||
| The AVR firmware driver is published under the GNU General Public License | ||||
| Version 2 (GPL2) and the GNU General Public License Version 3 (GPL3). It is | ||||
| your choice whether you apply the terms of version 2 or version 3. | ||||
|  | ||||
| If you decide for the free GPL2 or GPL3, we STRONGLY ENCOURAGE you to do the | ||||
| following things IN ADDITION to the obligations from the GPL: | ||||
|  | ||||
| (1) Publish your entire project on a web site and drop us a note with the URL. | ||||
| Use the form at http://www.obdev.at/vusb/feedback.html for your submission. | ||||
| If you don't have a web site, you can publish the project in obdev's | ||||
| documentation wiki at | ||||
| http://www.obdev.at/goto.php?t=vusb-wiki&p=hosted-projects. | ||||
|  | ||||
| (2) Adhere to minimum publication standards. Please include AT LEAST: | ||||
|     - a circuit diagram in PDF, PNG or GIF format | ||||
|     - full source code for the host software | ||||
|     - a Readme.txt file in ASCII format which describes the purpose of the | ||||
|       project and what can be found in which directories and which files | ||||
|     - a reference to http://www.obdev.at/vusb/ | ||||
|  | ||||
| (3) If you improve the driver firmware itself, please give us a free license | ||||
| to your modifications for our commercial license offerings. | ||||
|  | ||||
|  | ||||
| COMMERCIAL LICENSES FOR V-USB | ||||
| ============================= | ||||
| If you don't want to publish your source code under the terms of the GPL, | ||||
| you can simply pay money for V-USB. As an additional benefit you get | ||||
| USB PIDs for free, reserved exclusively to you. See the file | ||||
| "CommercialLicense.txt" for details. | ||||
|  | ||||
							
								
								
									
										149
									
								
								usbdrv/USB-ID-FAQ.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								usbdrv/USB-ID-FAQ.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| Version 2012-07-09 | ||||
|  | ||||
| ========================== | ||||
| WHY DO WE NEED THESE IDs? | ||||
| ========================== | ||||
|  | ||||
| USB is more than a low level protocol for data transport. It also defines a | ||||
| common set of requests which must be understood by all devices. And as part | ||||
| of these common requests, the specification defines data structures, the | ||||
| USB Descriptors, which are used to describe the properties of the device. | ||||
|  | ||||
| From the perspective of an operating system, it is therefore possible to find | ||||
| out basic properties of a device (such as e.g. the manufacturer and the name | ||||
| of the device) without a device-specific driver. This is essential because | ||||
| the operating system can choose a driver to load based on this information | ||||
| (Plug-And-Play). | ||||
|  | ||||
| Among the most important properties in the Device Descriptor are the USB | ||||
| Vendor- and Product-ID. Both are 16 bit integers. The most simple form of | ||||
| driver matching is based on these IDs. The driver announces the Vendor- and | ||||
| Product-IDs of the devices it can handle and the operating system loads the | ||||
| appropriate driver when the device is connected. | ||||
|  | ||||
| It is obvious that this technique only works if the pair Vendor- plus | ||||
| Product-ID is unique: Only devices which require the same driver can have the | ||||
| same pair of IDs. | ||||
|  | ||||
|  | ||||
| ===================================================== | ||||
| HOW DOES THE USB STANDARD ENSURE THAT IDs ARE UNIQUE? | ||||
| ===================================================== | ||||
|  | ||||
| Since it is so important that USB IDs are unique, the USB Implementers Forum, | ||||
| Inc. (usb.org) needs a way to enforce this legally. It is not forbidden by | ||||
| law to build a device and assign it any random numbers as IDs. Usb.org | ||||
| therefore needs an agreement to regulate the use of USB IDs. The agreement | ||||
| binds only parties who agreed to it, of course. Everybody else is free to use | ||||
| any numbers for their IDs. | ||||
|  | ||||
| So how can usb.org ensure that every manufacturer of USB devices enters into | ||||
| an agreement with them? They do it via trademark licensing. Usb.org has | ||||
| registered the trademark "USB", all associated logos and related terms. If | ||||
| you want to put an USB logo on your product or claim that it is USB | ||||
| compliant, you must license these trademarks from usb.org. And this is where | ||||
| you enter into an agreement. See the "USB-IF Trademark License Agreement and | ||||
| Usage Guidelines for the USB-IF Logo" at | ||||
| http://www.usb.org/developers/logo_license/. | ||||
|  | ||||
| Licensing the USB trademarks requires that you buy a USB Vendor-ID from | ||||
| usb.org (one-time fee of ca. 2,000 USD), that you become a member of usb.org | ||||
| (yearly fee of ca. 4,000 USD) and that you meet all the technical | ||||
| specifications from the USB spec. | ||||
|  | ||||
| This means that most hobbyists and small companies will never be able to | ||||
| become USB compliant, just because membership is so expensive. And you can't | ||||
| be compliant with a driver based on V-USB anyway, because the AVR's port pins | ||||
| don't meet the electrical specifications for USB. So, in principle, all | ||||
| hobbyists and small companies are free to choose any random numbers for their | ||||
| IDs. They have nothing to lose... | ||||
|  | ||||
| There is one exception worth noting, though: If you use a sub-component which | ||||
| implements USB, the vendor of the sub-components may guarantee USB | ||||
| compliance. This might apply to some or all of FTDI's solutions. | ||||
|  | ||||
|  | ||||
| ======================================================================= | ||||
| WHY SHOULD YOU OBTAIN USB IDs EVEN IF YOU DON'T LICENSE USB TRADEMARKS? | ||||
| ======================================================================= | ||||
|  | ||||
| You have learned in the previous section that you are free to choose any | ||||
| numbers for your IDs anyway. So why not do exactly this? There is still the | ||||
| technical issue. If you choose IDs which are already in use by somebody else, | ||||
| operating systems will load the wrong drivers and your device won't work. | ||||
| Even if you choose IDs which are not currently in use, they may be in use in | ||||
| the next version of the operating system or even after an automatic update. | ||||
|  | ||||
| So what you need is a pair of Vendor- and Product-IDs for which you have the | ||||
| guarantee that no USB compliant product uses them. This implies that no | ||||
| operating system will ever ship with drivers responsible for these IDs. | ||||
|  | ||||
|  | ||||
| ============================================== | ||||
| HOW DOES OBJECTIVE DEVELOPMENT HANDLE USB IDs? | ||||
| ============================================== | ||||
|  | ||||
| Objective Development gives away pairs of USB-IDs with their V-USB licenses. | ||||
| In order to ensure that these IDs are unique, Objective Development has an | ||||
| agreement with the company/person who has bought the USB Vendor-ID from | ||||
| usb.org. This agreement ensures that a range of USB Product-IDs is reserved | ||||
| for assignment by Objective Development and that the owner of the Vendor-ID | ||||
| won't give it to anybody else. | ||||
|  | ||||
| This means that you have to trust three parties to ensure uniqueness of | ||||
| your IDs: | ||||
|  | ||||
|   - Objective Development, that they don't give the same PID to more than | ||||
|     one person. | ||||
|   - The owner of the Vendor-ID that they don't assign PIDs from the range | ||||
|     assigned to Objective Development to anybody else. | ||||
|   - Usb.org that they don't assign the same Vendor-ID a second time. | ||||
|  | ||||
|  | ||||
| ================================== | ||||
| WHO IS THE OWNER OF THE VENDOR-ID? | ||||
| ================================== | ||||
|  | ||||
| Objective Development has obtained ranges of USB Product-IDs under two | ||||
| Vendor-IDs: Under Vendor-ID 5824 from Wouter van Ooijen (Van Ooijen | ||||
| Technische Informatica, www.voti.nl) and under Vendor-ID 8352 from Jason | ||||
| Kotzin (now flirc.tv, Inc.). Both VID owners have received their Vendor-ID | ||||
| directly from usb.org. | ||||
|  | ||||
|  | ||||
| ========================================================================= | ||||
| CAN I USE USB-IDs FROM OBJECTIVE DEVELOPMENT WITH OTHER DRIVERS/HARDWARE? | ||||
| ========================================================================= | ||||
|  | ||||
| The short answer is: Yes. All you get is a guarantee that the IDs are never | ||||
| assigned to anybody else. What more do you need? | ||||
|  | ||||
|  | ||||
| ============================ | ||||
| WHAT ABOUT SHARED ID PAIRS? | ||||
| ============================ | ||||
|  | ||||
| Objective Development has reserved some PID/VID pairs for shared use. You | ||||
| have no guarantee of uniqueness for them, except that no USB compliant device | ||||
| uses them. In order to avoid technical problems, we must ensure that all | ||||
| devices with the same pair of IDs use the same driver on kernel level. For | ||||
| details, see the file USB-IDs-for-free.txt. | ||||
|  | ||||
|  | ||||
| ====================================================== | ||||
| I HAVE HEARD THAT SUB-LICENSING OF USB-IDs IS ILLEGAL? | ||||
| ====================================================== | ||||
|  | ||||
| A 16 bit integer number cannot be protected by copyright laws. It is not | ||||
| sufficiently complex. And since none of the parties involved entered into the | ||||
| USB-IF Trademark License Agreement, we are not bound by this agreement. So | ||||
| there is no reason why it should be illegal to sub-license USB-IDs. | ||||
|  | ||||
|  | ||||
| ============================================= | ||||
| WHO IS LIABLE IF THERE ARE INCOMPATIBILITIES? | ||||
| ============================================= | ||||
|  | ||||
| Objective Development disclaims all liabilities which might arise from the | ||||
| assignment of IDs. If you guarantee product features to your customers | ||||
| without proper disclaimer, YOU are liable for that. | ||||
							
								
								
									
										168
									
								
								usbdrv/USB-IDs-for-free.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								usbdrv/USB-IDs-for-free.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | ||||
| Version 2009-08-22 | ||||
|  | ||||
| =========================== | ||||
| FREE USB-IDs FOR SHARED USE | ||||
| =========================== | ||||
|  | ||||
| Objective Development has reserved a set of USB Product-IDs for use according | ||||
| to the guidelines outlined below. For more information about the concept of | ||||
| USB IDs please see the file USB-ID-FAQ.txt. Objective Development guarantees | ||||
| that the IDs listed below are not used by any USB compliant devices. | ||||
|  | ||||
|  | ||||
| ==================== | ||||
| MECHANISM OF SHARING | ||||
| ==================== | ||||
|  | ||||
| From a technical point of view, two different devices can share the same USB | ||||
| Vendor- and Product-ID if they require the same driver on operating system | ||||
| level. We make use of this fact by assigning separate IDs for various device | ||||
| classes. On application layer, devices must be distinguished by their textual | ||||
| name or serial number. We offer separate sets of IDs for discrimination by | ||||
| textual name and for serial number. | ||||
|  | ||||
| Examples for shared use of USB IDs are included with V-USB in the "examples" | ||||
| subdirectory. | ||||
|  | ||||
|  | ||||
| ====================================== | ||||
| IDs FOR DISCRIMINATION BY TEXTUAL NAME | ||||
| ====================================== | ||||
|  | ||||
| If you use one of the IDs listed below, your device and host-side software | ||||
| must conform to these rules: | ||||
|  | ||||
| (1) The USB device MUST provide a textual representation of the manufacturer | ||||
| and product identification. The manufacturer identification MUST be available | ||||
| at least in USB language 0x0409 (English/US). | ||||
|  | ||||
| (2) The textual manufacturer identification MUST contain either an Internet | ||||
| domain name (e.g. "mycompany.com") registered and owned by you, or an e-mail | ||||
| address under your control (e.g. "myname@gmx.net"). You can embed the domain | ||||
| name or e-mail address in any string you like, e.g.  "Objective Development | ||||
| http://www.obdev.at/vusb/". | ||||
|  | ||||
| (3) You are responsible for retaining ownership of the domain or e-mail | ||||
| address for as long as any of your products are in use. | ||||
|  | ||||
| (4) You may choose any string for the textual product identification, as long | ||||
| as this string is unique within the scope of your textual manufacturer | ||||
| identification. | ||||
|  | ||||
| (5) Application side device look-up MUST be based on the textual manufacturer | ||||
| and product identification in addition to VID/PID matching. The driver | ||||
| matching MUST be a comparison of the entire strings, NOT a sub-string match. | ||||
|  | ||||
| (6) For devices which implement a particular USB device class (e.g. HID), the | ||||
| operating system's default class driver MUST be used. If an operating system | ||||
| driver for Vendor Class devices is needed, this driver must be libusb or | ||||
| libusb-win32 (see http://libusb.org/ and | ||||
| http://libusb-win32.sourceforge.net/). | ||||
|  | ||||
| Table if IDs for discrimination by textual name: | ||||
|  | ||||
| PID dec (hex) | VID dec (hex) | Description of use | ||||
| ==============+===============+============================================ | ||||
| 1500 (0x05dc) | 5824 (0x16c0) | For Vendor Class devices with libusb | ||||
| --------------+---------------+-------------------------------------------- | ||||
| 1503 (0x05df) | 5824 (0x16c0) | For generic HID class devices (which are | ||||
|               |               | NOT mice, keyboards or joysticks) | ||||
| --------------+---------------+-------------------------------------------- | ||||
| 1505 (0x05e1) | 5824 (0x16c0) | For CDC-ACM class devices (modems) | ||||
| --------------+---------------+-------------------------------------------- | ||||
| 1508 (0x05e4) | 5824 (0x16c0) | For MIDI class devices | ||||
| --------------+---------------+-------------------------------------------- | ||||
|  | ||||
| Note that Windows caches the textual product- and vendor-description for | ||||
| mice, keyboards and joysticks. Name-bsed discrimination is therefore not | ||||
| recommended for these device classes. | ||||
|  | ||||
|  | ||||
| ======================================= | ||||
| IDs FOR DISCRIMINATION BY SERIAL NUMBER | ||||
| ======================================= | ||||
|  | ||||
| If you use one of the IDs listed below, your device and host-side software | ||||
| must conform to these rules: | ||||
|  | ||||
| (1) The USB device MUST provide a textual representation of the serial | ||||
| number, unless ONLY the operating system's default class driver is used. | ||||
| The serial number string MUST be available at least in USB language 0x0409 | ||||
| (English/US). | ||||
|  | ||||
| (2) The serial number MUST start with either an Internet domain name (e.g. | ||||
| "mycompany.com") registered and owned by you, or an e-mail address under your | ||||
| control (e.g. "myname@gmx.net"), both terminated with a colon (":") character. | ||||
| You MAY append any string you like for further discrimination of your devices. | ||||
|  | ||||
| (3) You are responsible for retaining ownership of the domain or e-mail | ||||
| address for as long as any of your products are in use. | ||||
|  | ||||
| (5) Application side device look-up MUST be based on the serial number string | ||||
| in addition to VID/PID matching. The matching must start at the first | ||||
| character of the serial number string and include the colon character | ||||
| terminating your domain or e-mail address. It MAY stop anywhere after that. | ||||
|  | ||||
| (6) For devices which implement a particular USB device class (e.g. HID), the | ||||
| operating system's default class driver MUST be used. If an operating system | ||||
| driver for Vendor Class devices is needed, this driver must be libusb or | ||||
| libusb-win32 (see http://libusb.org/ and | ||||
| http://libusb-win32.sourceforge.net/). | ||||
|  | ||||
| (7) If ONLY the operating system's default class driver is used, e.g. for | ||||
| mice, keyboards, joysticks, CDC or MIDI devices and no discrimination by an | ||||
| application is needed, the serial number may be omitted. | ||||
|  | ||||
|  | ||||
| Table if IDs for discrimination by serial number string: | ||||
|  | ||||
| PID dec (hex)  | VID dec (hex) | Description of use | ||||
| ===============+===============+=========================================== | ||||
| 10200 (0x27d8) | 5824 (0x16c0) | For Vendor Class devices with libusb | ||||
| ---------------+---------------+------------------------------------------- | ||||
| 10201 (0x27d9) | 5824 (0x16c0) | For generic HID class devices (which are | ||||
|                |               | NOT mice, keyboards or joysticks) | ||||
| ---------------+---------------+------------------------------------------- | ||||
| 10202 (0x27da) | 5824 (0x16c0) | For USB Mice | ||||
| ---------------+---------------+------------------------------------------- | ||||
| 10203 (0x27db) | 5824 (0x16c0) | For USB Keyboards | ||||
| ---------------+---------------+------------------------------------------- | ||||
| 10204 (0x27dc) | 5824 (0x16c0) | For USB Joysticks | ||||
| ---------------+---------------+------------------------------------------- | ||||
| 10205 (0x27dd) | 5824 (0x16c0) | For CDC-ACM class devices (modems) | ||||
| ---------------+---------------+------------------------------------------- | ||||
| 10206 (0x27de) | 5824 (0x16c0) | For MIDI class devices | ||||
| ---------------+---------------+------------------------------------------- | ||||
| 10207 (0x27df) | 5824 (0x16c0) | For Mass Storage class devices | ||||
| ---------------+---------------+------------------------------------------- | ||||
| 10208 (0x27e0) | 5824 (0x16c0) | For Audio class devices | ||||
| ---------------+---------------+------------------------------------------- | ||||
| 10209 (0x27e1) | 5824 (0x16c0) | For CDC-ECM class devices | ||||
| ---------------+---------------+------------------------------------------- | ||||
| 10210 (0x27e2) | 5824 (0x16c0) | For MTP class devices | ||||
| ---------------+---------------+------------------------------------------- | ||||
|  | ||||
| Note that the last six cannot be implemented using V-USB in a standards | ||||
| compliant way because they require bulk endpoints which are forbidden for | ||||
| low speed devices. We provide them nevertheless, either if you want to | ||||
| implement a non-compliant device or implement it using other technology | ||||
| than V-USB. | ||||
|  | ||||
|  | ||||
| ================= | ||||
| ORIGIN OF USB-IDs | ||||
| ================= | ||||
|  | ||||
| OBJECTIVE DEVELOPMENT Software GmbH has obtained all VID/PID pairs listed | ||||
| here from Wouter van Ooijen (see www.voti.nl) for exclusive disposition. | ||||
| Wouter van Ooijen has obtained the VID from the USB Implementers Forum, Inc. | ||||
| (see www.usb.org). The VID is registered for the company name "Van Ooijen | ||||
| Technische Informatica". | ||||
|  | ||||
|  | ||||
| ========== | ||||
| DISCLAIMER | ||||
| ========== | ||||
|  | ||||
| OBJECTIVE DEVELOPMENT Software GmbH disclaims all liability for any | ||||
| problems which are caused by the shared use of these VID/PID pairs. | ||||
							
								
								
									
										187
									
								
								usbdrv/asmcommon.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								usbdrv/asmcommon.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | ||||
| /* Name: asmcommon.inc | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2007-11-05 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* Do not link this file! Link usbdrvasm.S instead, which includes the | ||||
|  * appropriate implementation! | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file contains assembler code which is shared among the USB driver | ||||
| implementations for different CPU cocks. Since the code must be inserted | ||||
| in the middle of the module, it's split out into this file and #included. | ||||
|  | ||||
| Jump destinations called from outside: | ||||
|     sofError: Called when no start sequence was found. | ||||
|     se0: Called when a package has been successfully received. | ||||
|     overflow: Called when receive buffer overflows. | ||||
|     doReturn: Called after sending data. | ||||
|  | ||||
| Outside jump destinations used by this module: | ||||
|     waitForJ: Called to receive an already arriving packet. | ||||
|     sendAckAndReti: | ||||
|     sendNakAndReti: | ||||
|     sendCntAndReti: | ||||
|     usbSendAndReti: | ||||
|  | ||||
| The following macros must be defined before this file is included: | ||||
|     .macro POP_STANDARD | ||||
|     .endm | ||||
|     .macro POP_RETI | ||||
|     .endm | ||||
| */ | ||||
|  | ||||
| #define token   x1 | ||||
|  | ||||
| overflow: | ||||
|     ldi     x2, 1<<USB_INTR_PENDING_BIT | ||||
|     USB_STORE_PENDING(x2)       ; clear any pending interrupts | ||||
| ignorePacket: | ||||
|     clr     token | ||||
|     rjmp    storeTokenAndReturn | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Processing of received packet (numbers in brackets are cycles after center of SE0) | ||||
| ;---------------------------------------------------------------------------- | ||||
| ;This is the only non-error exit point for the software receiver loop | ||||
| ;we don't check any CRCs here because there is no time left. | ||||
| se0: | ||||
|     subi    cnt, USB_BUFSIZE    ;[5] | ||||
|     neg     cnt                 ;[6] | ||||
|     sub     YL, cnt             ;[7] | ||||
|     sbci    YH, 0               ;[8] | ||||
|     ldi     x2, 1<<USB_INTR_PENDING_BIT ;[9] | ||||
|     USB_STORE_PENDING(x2)       ;[10] clear pending intr and check flag later. SE0 should be over. | ||||
|     ld      token, y            ;[11] | ||||
|     cpi     token, USBPID_DATA0 ;[13] | ||||
|     breq    handleData          ;[14] | ||||
|     cpi     token, USBPID_DATA1 ;[15] | ||||
|     breq    handleData          ;[16] | ||||
|     lds     shift, usbDeviceAddr;[17] | ||||
|     ldd     x2, y+1             ;[19] ADDR and 1 bit endpoint number | ||||
|     lsl     x2                  ;[21] shift out 1 bit endpoint number | ||||
|     cpse    x2, shift           ;[22] | ||||
|     rjmp    ignorePacket        ;[23] | ||||
| /* only compute endpoint number in x3 if required later */ | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT || USB_CFG_IMPLEMENT_FN_WRITEOUT | ||||
|     ldd     x3, y+2             ;[24] endpoint number + crc | ||||
|     rol     x3                  ;[26] shift in LSB of endpoint | ||||
| #endif | ||||
|     cpi     token, USBPID_IN    ;[27] | ||||
|     breq    handleIn            ;[28] | ||||
|     cpi     token, USBPID_SETUP ;[29] | ||||
|     breq    handleSetupOrOut    ;[30] | ||||
|     cpi     token, USBPID_OUT   ;[31] | ||||
|     brne    ignorePacket        ;[32] must be ack, nak or whatever | ||||
| ;   rjmp    handleSetupOrOut    ; fallthrough | ||||
|  | ||||
| ;Setup and Out are followed by a data packet two bit times (16 cycles) after | ||||
| ;the end of SE0. The sync code allows up to 40 cycles delay from the start of | ||||
| ;the sync pattern until the first bit is sampled. That's a total of 56 cycles. | ||||
| handleSetupOrOut:               ;[32] | ||||
| #if USB_CFG_IMPLEMENT_FN_WRITEOUT   /* if we have data for endpoint != 0, set usbCurrentTok to address */ | ||||
|     andi    x3, 0xf             ;[32] | ||||
|     breq    storeTokenAndReturn ;[33] | ||||
|     mov     token, x3           ;[34] indicate that this is endpoint x OUT | ||||
| #endif | ||||
| storeTokenAndReturn: | ||||
|     sts     usbCurrentTok, token;[35] | ||||
| doReturn: | ||||
|     POP_STANDARD                ;[37] 12...16 cycles | ||||
|     USB_LOAD_PENDING(YL)        ;[49] | ||||
|     sbrc    YL, USB_INTR_PENDING_BIT;[50] check whether data is already arriving | ||||
|     rjmp    waitForJ            ;[51] save the pops and pushes -- a new interrupt is already pending | ||||
| sofError: | ||||
|     POP_RETI                    ;macro call | ||||
|     reti | ||||
|  | ||||
| handleData: | ||||
| #if USB_CFG_CHECK_CRC | ||||
|     CRC_CLEANUP_AND_CHECK       ; jumps to ignorePacket if CRC error | ||||
| #endif | ||||
|     lds     shift, usbCurrentTok;[18] | ||||
|     tst     shift               ;[20] | ||||
|     breq    doReturn            ;[21] | ||||
|     lds     x2, usbRxLen        ;[22] | ||||
|     tst     x2                  ;[24] | ||||
|     brne    sendNakAndReti      ;[25] | ||||
| ; 2006-03-11: The following two lines fix a problem where the device was not | ||||
| ; recognized if usbPoll() was called less frequently than once every 4 ms. | ||||
|     cpi     cnt, 4              ;[26] zero sized data packets are status phase only -- ignore and ack | ||||
|     brmi    sendAckAndReti      ;[27] keep rx buffer clean -- we must not NAK next SETUP | ||||
| #if USB_CFG_CHECK_DATA_TOGGLING | ||||
|     sts     usbCurrentDataToken, token  ; store for checking by C code | ||||
| #endif | ||||
|     sts     usbRxLen, cnt       ;[28] store received data, swap buffers | ||||
|     sts     usbRxToken, shift   ;[30] | ||||
|     lds     x2, usbInputBufOffset;[32] swap buffers | ||||
|     ldi     cnt, USB_BUFSIZE    ;[34] | ||||
|     sub     cnt, x2             ;[35] | ||||
|     sts     usbInputBufOffset, cnt;[36] buffers now swapped | ||||
|     rjmp    sendAckAndReti      ;[38] 40 + 17 = 57 until SOP | ||||
|  | ||||
| handleIn: | ||||
| ;We don't send any data as long as the C code has not processed the current | ||||
| ;input data and potentially updated the output data. That's more efficient | ||||
| ;in terms of code size than clearing the tx buffers when a packet is received. | ||||
|     lds     x1, usbRxLen        ;[30] | ||||
|     cpi     x1, 1               ;[32] negative values are flow control, 0 means "buffer free" | ||||
|     brge    sendNakAndReti      ;[33] unprocessed input packet? | ||||
|     ldi     x1, USBPID_NAK      ;[34] prepare value for usbTxLen | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT | ||||
|     andi    x3, 0xf             ;[35] x3 contains endpoint | ||||
| #if USB_CFG_SUPPRESS_INTR_CODE | ||||
|     brne    sendNakAndReti      ;[36] | ||||
| #else | ||||
|     brne    handleIn1           ;[36] | ||||
| #endif | ||||
| #endif | ||||
|     lds     cnt, usbTxLen       ;[37] | ||||
|     sbrc    cnt, 4              ;[39] all handshake tokens have bit 4 set | ||||
|     rjmp    sendCntAndReti      ;[40] 42 + 16 = 58 until SOP | ||||
|     sts     usbTxLen, x1        ;[41] x1 == USBPID_NAK from above | ||||
|     ldi     YL, lo8(usbTxBuf)   ;[43] | ||||
|     ldi     YH, hi8(usbTxBuf)   ;[44] | ||||
|     rjmp    usbSendAndReti      ;[45] 57 + 12 = 59 until SOP | ||||
|  | ||||
| ; Comment about when to set usbTxLen to USBPID_NAK: | ||||
| ; We should set it back when we receive the ACK from the host. This would | ||||
| ; be simple to implement: One static variable which stores whether the last | ||||
| ; tx was for endpoint 0 or 1 and a compare in the receiver to distinguish the | ||||
| ; ACK. However, we set it back immediately when we send the package, | ||||
| ; assuming that no error occurs and the host sends an ACK. We save one byte | ||||
| ; RAM this way and avoid potential problems with endless retries. The rest of | ||||
| ; the driver assumes error-free transfers anyway. | ||||
|  | ||||
| #if !USB_CFG_SUPPRESS_INTR_CODE && USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */ | ||||
| handleIn1:                      ;[38] | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT3 | ||||
| ; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint | ||||
|     cpi     x3, USB_CFG_EP3_NUMBER;[38] | ||||
|     breq    handleIn3           ;[39] | ||||
| #endif | ||||
|     lds     cnt, usbTxLen1      ;[40] | ||||
|     sbrc    cnt, 4              ;[42] all handshake tokens have bit 4 set | ||||
|     rjmp    sendCntAndReti      ;[43] 47 + 16 = 63 until SOP | ||||
|     sts     usbTxLen1, x1       ;[44] x1 == USBPID_NAK from above | ||||
|     ldi     YL, lo8(usbTxBuf1)  ;[46] | ||||
|     ldi     YH, hi8(usbTxBuf1)  ;[47] | ||||
|     rjmp    usbSendAndReti      ;[48] 50 + 12 = 62 until SOP | ||||
|  | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT3 | ||||
| handleIn3: | ||||
|     lds     cnt, usbTxLen3      ;[41] | ||||
|     sbrc    cnt, 4              ;[43] | ||||
|     rjmp    sendCntAndReti      ;[44] 49 + 16 = 65 until SOP | ||||
|     sts     usbTxLen3, x1       ;[45] x1 == USBPID_NAK from above | ||||
|     ldi     YL, lo8(usbTxBuf3)  ;[47] | ||||
|     ldi     YH, hi8(usbTxBuf3)  ;[48] | ||||
|     rjmp    usbSendAndReti      ;[49] 51 + 12 = 63 until SOP | ||||
| #endif | ||||
| #endif | ||||
							
								
								
									
										49
									
								
								usbdrv/oddebug.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								usbdrv/oddebug.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| /* Name: oddebug.c | ||||
|  * Project: AVR library | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2005-01-16 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| #include "oddebug.h" | ||||
|  | ||||
| #if DEBUG_LEVEL > 0 | ||||
|  | ||||
| #warning "Never compile production devices with debugging enabled" | ||||
|  | ||||
| static void uartPutc(char c) | ||||
| { | ||||
|     while(!(ODDBG_USR & (1 << ODDBG_UDRE)));    /* wait for data register empty */ | ||||
|     ODDBG_UDR = c; | ||||
| } | ||||
|  | ||||
| static uchar    hexAscii(uchar h) | ||||
| { | ||||
|     h &= 0xf; | ||||
|     if(h >= 10) | ||||
|         h += 'a' - (uchar)10 - '0'; | ||||
|     h += '0'; | ||||
|     return h; | ||||
| } | ||||
|  | ||||
| static void printHex(uchar c) | ||||
| { | ||||
|     uartPutc(hexAscii(c >> 4)); | ||||
|     uartPutc(hexAscii(c)); | ||||
| } | ||||
|  | ||||
| void    odDebug(uchar prefix, uchar *data, uchar len) | ||||
| { | ||||
|     printHex(prefix); | ||||
|     uartPutc(':'); | ||||
|     while(len--){ | ||||
|         uartPutc(' '); | ||||
|         printHex(*data++); | ||||
|     } | ||||
|     uartPutc('\r'); | ||||
|     uartPutc('\n'); | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										122
									
								
								usbdrv/oddebug.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								usbdrv/oddebug.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| /* Name: oddebug.h | ||||
|  * Project: AVR library | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2005-01-16 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| #ifndef __oddebug_h_included__ | ||||
| #define __oddebug_h_included__ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This module implements a function for debug logs on the serial line of the | ||||
| AVR microcontroller. Debugging can be configured with the define | ||||
| 'DEBUG_LEVEL'. If this macro is not defined or defined to 0, all debugging | ||||
| calls are no-ops. If it is 1, DBG1 logs will appear, but not DBG2. If it is | ||||
| 2, DBG1 and DBG2 logs will be printed. | ||||
|  | ||||
| A debug log consists of a label ('prefix') to indicate which debug log created | ||||
| the output and a memory block to dump in hex ('data' and 'len'). | ||||
| */ | ||||
|  | ||||
|  | ||||
| #ifndef F_CPU | ||||
| #   define  F_CPU   12000000    /* 12 MHz */ | ||||
| #endif | ||||
|  | ||||
| /* make sure we have the UART defines: */ | ||||
| #include "usbportability.h" | ||||
|  | ||||
| #ifndef uchar | ||||
| #   define  uchar   unsigned char | ||||
| #endif | ||||
|  | ||||
| #if DEBUG_LEVEL > 0 && !(defined TXEN || defined TXEN0) /* no UART in device */ | ||||
| #   warning "Debugging disabled because device has no UART" | ||||
| #   undef   DEBUG_LEVEL | ||||
| #endif | ||||
|  | ||||
| #ifndef DEBUG_LEVEL | ||||
| #   define  DEBUG_LEVEL 0 | ||||
| #endif | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| #if DEBUG_LEVEL > 0 | ||||
| #   define  DBG1(prefix, data, len) odDebug(prefix, data, len) | ||||
| #else | ||||
| #   define  DBG1(prefix, data, len) | ||||
| #endif | ||||
|  | ||||
| #if DEBUG_LEVEL > 1 | ||||
| #   define  DBG2(prefix, data, len) odDebug(prefix, data, len) | ||||
| #else | ||||
| #   define  DBG2(prefix, data, len) | ||||
| #endif | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| #if DEBUG_LEVEL > 0 | ||||
| extern void odDebug(uchar prefix, uchar *data, uchar len); | ||||
|  | ||||
| /* Try to find our control registers; ATMEL likes to rename these */ | ||||
|  | ||||
| #if defined UBRR | ||||
| #   define  ODDBG_UBRR  UBRR | ||||
| #elif defined UBRRL | ||||
| #   define  ODDBG_UBRR  UBRRL | ||||
| #elif defined UBRR0 | ||||
| #   define  ODDBG_UBRR  UBRR0 | ||||
| #elif defined UBRR0L | ||||
| #   define  ODDBG_UBRR  UBRR0L | ||||
| #endif | ||||
|  | ||||
| #if defined UCR | ||||
| #   define  ODDBG_UCR   UCR | ||||
| #elif defined UCSRB | ||||
| #   define  ODDBG_UCR   UCSRB | ||||
| #elif defined UCSR0B | ||||
| #   define  ODDBG_UCR   UCSR0B | ||||
| #endif | ||||
|  | ||||
| #if defined TXEN | ||||
| #   define  ODDBG_TXEN  TXEN | ||||
| #else | ||||
| #   define  ODDBG_TXEN  TXEN0 | ||||
| #endif | ||||
|  | ||||
| #if defined USR | ||||
| #   define  ODDBG_USR   USR | ||||
| #elif defined UCSRA | ||||
| #   define  ODDBG_USR   UCSRA | ||||
| #elif defined UCSR0A | ||||
| #   define  ODDBG_USR   UCSR0A | ||||
| #endif | ||||
|  | ||||
| #if defined UDRE | ||||
| #   define  ODDBG_UDRE  UDRE | ||||
| #else | ||||
| #   define  ODDBG_UDRE  UDRE0 | ||||
| #endif | ||||
|  | ||||
| #if defined UDR | ||||
| #   define  ODDBG_UDR   UDR | ||||
| #elif defined UDR0 | ||||
| #   define  ODDBG_UDR   UDR0 | ||||
| #endif | ||||
|  | ||||
| static inline void  odDebugInit(void) | ||||
| { | ||||
|     ODDBG_UCR |= (1<<ODDBG_TXEN); | ||||
|     ODDBG_UBRR = F_CPU / (19200 * 16L) - 1; | ||||
| } | ||||
| #else | ||||
| #   define odDebugInit() | ||||
| #endif | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| #endif /* __oddebug_h_included__ */ | ||||
							
								
								
									
										
											BIN
										
									
								
								usbdrv/oddebug.o
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								usbdrv/oddebug.o
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										384
									
								
								usbdrv/usbconfig-prototype.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										384
									
								
								usbdrv/usbconfig-prototype.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,384 @@ | ||||
| /* Name: usbconfig.h | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2005-04-01 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| #ifndef __usbconfig_h_included__ | ||||
| #define __usbconfig_h_included__ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file is an example configuration (with inline documentation) for the USB | ||||
| driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is | ||||
| also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may | ||||
| wire the lines to any other port, as long as D+ is also wired to INT0 (or any | ||||
| other hardware interrupt, as long as it is the highest level interrupt, see | ||||
| section at the end of this file). | ||||
| + To create your own usbconfig.h file, copy this file to your project's | ||||
| + firmware source directory) and rename it to "usbconfig.h". | ||||
| + Then edit it accordingly. | ||||
| */ | ||||
|  | ||||
| /* ---------------------------- Hardware Config ---------------------------- */ | ||||
|  | ||||
| #define USB_CFG_IOPORTNAME      D | ||||
| /* This is the port where the USB bus is connected. When you configure it to | ||||
|  * "B", the registers PORTB, PINB and DDRB will be used. | ||||
|  */ | ||||
| #define USB_CFG_DMINUS_BIT      4 | ||||
| /* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. | ||||
|  * This may be any bit in the port. | ||||
|  */ | ||||
| #define USB_CFG_DPLUS_BIT       2 | ||||
| /* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. | ||||
|  * This may be any bit in the port. Please note that D+ must also be connected | ||||
|  * to interrupt pin INT0! [You can also use other interrupts, see section | ||||
|  * "Optional MCU Description" below, or you can connect D- to the interrupt, as | ||||
|  * it is required if you use the USB_COUNT_SOF feature. If you use D- for the | ||||
|  * interrupt, the USB interrupt will also be triggered at Start-Of-Frame | ||||
|  * markers every millisecond.] | ||||
|  */ | ||||
| #define USB_CFG_CLOCK_KHZ       (F_CPU/1000) | ||||
| /* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000, | ||||
|  * 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code | ||||
|  * require no crystal, they tolerate +/- 1% deviation from the nominal | ||||
|  * frequency. All other rates require a precision of 2000 ppm and thus a | ||||
|  * crystal! | ||||
|  * Since F_CPU should be defined to your actual clock rate anyway, you should | ||||
|  * not need to modify this setting. | ||||
|  */ | ||||
| #define USB_CFG_CHECK_CRC       0 | ||||
| /* Define this to 1 if you want that the driver checks integrity of incoming | ||||
|  * data packets (CRC checks). CRC checks cost quite a bit of code size and are | ||||
|  * currently only available for 18 MHz crystal clock. You must choose | ||||
|  * USB_CFG_CLOCK_KHZ = 18000 if you enable this option. | ||||
|  */ | ||||
|  | ||||
| /* ----------------------- Optional Hardware Config ------------------------ */ | ||||
|  | ||||
| /* #define USB_CFG_PULLUP_IOPORTNAME   D */ | ||||
| /* If you connect the 1.5k pullup resistor from D- to a port pin instead of | ||||
|  * V+, you can connect and disconnect the device from firmware by calling | ||||
|  * the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h). | ||||
|  * This constant defines the port on which the pullup resistor is connected. | ||||
|  */ | ||||
| /* #define USB_CFG_PULLUP_BIT          4 */ | ||||
| /* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined | ||||
|  * above) where the 1.5k pullup resistor is connected. See description | ||||
|  * above for details. | ||||
|  */ | ||||
|  | ||||
| /* --------------------------- Functional Range ---------------------------- */ | ||||
|  | ||||
| #define USB_CFG_HAVE_INTRIN_ENDPOINT    0 | ||||
| /* Define this to 1 if you want to compile a version with two endpoints: The | ||||
|  * default control endpoint 0 and an interrupt-in endpoint (any other endpoint | ||||
|  * number). | ||||
|  */ | ||||
| #define USB_CFG_HAVE_INTRIN_ENDPOINT3   0 | ||||
| /* Define this to 1 if you want to compile a version with three endpoints: The | ||||
|  * default control endpoint 0, an interrupt-in endpoint 3 (or the number | ||||
|  * configured below) and a catch-all default interrupt-in endpoint as above. | ||||
|  * You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature. | ||||
|  */ | ||||
| #define USB_CFG_EP3_NUMBER              3 | ||||
| /* If the so-called endpoint 3 is used, it can now be configured to any other | ||||
|  * endpoint number (except 0) with this macro. Default if undefined is 3. | ||||
|  */ | ||||
| /* #define USB_INITIAL_DATATOKEN           USBPID_DATA1 */ | ||||
| /* The above macro defines the startup condition for data toggling on the | ||||
|  * interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1. | ||||
|  * Since the token is toggled BEFORE sending any data, the first packet is | ||||
|  * sent with the oposite value of this configuration! | ||||
|  */ | ||||
| #define USB_CFG_IMPLEMENT_HALT          0 | ||||
| /* Define this to 1 if you also want to implement the ENDPOINT_HALT feature | ||||
|  * for endpoint 1 (interrupt endpoint). Although you may not need this feature, | ||||
|  * it is required by the standard. We have made it a config option because it | ||||
|  * bloats the code considerably. | ||||
|  */ | ||||
| #define USB_CFG_SUPPRESS_INTR_CODE      0 | ||||
| /* Define this to 1 if you want to declare interrupt-in endpoints, but don't | ||||
|  * want to send any data over them. If this macro is defined to 1, functions | ||||
|  * usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if | ||||
|  * you need the interrupt-in endpoints in order to comply to an interface | ||||
|  * (e.g. HID), but never want to send any data. This option saves a couple | ||||
|  * of bytes in flash memory and the transmit buffers in RAM. | ||||
|  */ | ||||
| #define USB_CFG_INTR_POLL_INTERVAL      10 | ||||
| /* If you compile a version with endpoint 1 (interrupt-in), this is the poll | ||||
|  * interval. The value is in milliseconds and must not be less than 10 ms for | ||||
|  * low speed devices. | ||||
|  */ | ||||
| #define USB_CFG_IS_SELF_POWERED         0 | ||||
| /* Define this to 1 if the device has its own power supply. Set it to 0 if the | ||||
|  * device is powered from the USB bus. | ||||
|  */ | ||||
| #define USB_CFG_MAX_BUS_POWER           100 | ||||
| /* Set this variable to the maximum USB bus power consumption of your device. | ||||
|  * The value is in milliamperes. [It will be divided by two since USB | ||||
|  * communicates power requirements in units of 2 mA.] | ||||
|  */ | ||||
| #define USB_CFG_IMPLEMENT_FN_WRITE      0 | ||||
| /* Set this to 1 if you want usbFunctionWrite() to be called for control-out | ||||
|  * transfers. Set it to 0 if you don't need it and want to save a couple of | ||||
|  * bytes. | ||||
|  */ | ||||
| #define USB_CFG_IMPLEMENT_FN_READ       0 | ||||
| /* Set this to 1 if you need to send control replies which are generated | ||||
|  * "on the fly" when usbFunctionRead() is called. If you only want to send | ||||
|  * data from a static buffer, set it to 0 and return the data from | ||||
|  * usbFunctionSetup(). This saves a couple of bytes. | ||||
|  */ | ||||
| #define USB_CFG_IMPLEMENT_FN_WRITEOUT   0 | ||||
| /* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints. | ||||
|  * You must implement the function usbFunctionWriteOut() which receives all | ||||
|  * interrupt/bulk data sent to any endpoint other than 0. The endpoint number | ||||
|  * can be found in 'usbRxToken'. | ||||
|  */ | ||||
| #define USB_CFG_HAVE_FLOWCONTROL        0 | ||||
| /* Define this to 1 if you want flowcontrol over USB data. See the definition | ||||
|  * of the macros usbDisableAllRequests() and usbEnableAllRequests() in | ||||
|  * usbdrv.h. | ||||
|  */ | ||||
| #define USB_CFG_DRIVER_FLASH_PAGE       0 | ||||
| /* If the device has more than 64 kBytes of flash, define this to the 64 k page | ||||
|  * where the driver's constants (descriptors) are located. Or in other words: | ||||
|  * Define this to 1 for boot loaders on the ATMega128. | ||||
|  */ | ||||
| #define USB_CFG_LONG_TRANSFERS          0 | ||||
| /* Define this to 1 if you want to send/receive blocks of more than 254 bytes | ||||
|  * in a single control-in or control-out transfer. Note that the capability | ||||
|  * for long transfers increases the driver size. | ||||
|  */ | ||||
| /* #define USB_RX_USER_HOOK(data, len)     if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */ | ||||
| /* This macro is a hook if you want to do unconventional things. If it is | ||||
|  * defined, it's inserted at the beginning of received message processing. | ||||
|  * If you eat the received message and don't want default processing to | ||||
|  * proceed, do a return after doing your things. One possible application | ||||
|  * (besides debugging) is to flash a status LED on each packet. | ||||
|  */ | ||||
| /* #define USB_RESET_HOOK(resetStarts)     if(!resetStarts){hadUsbReset();} */ | ||||
| /* This macro is a hook if you need to know when an USB RESET occurs. It has | ||||
|  * one parameter which distinguishes between the start of RESET state and its | ||||
|  * end. | ||||
|  */ | ||||
| /* #define USB_SET_ADDRESS_HOOK()              hadAddressAssigned(); */ | ||||
| /* This macro (if defined) is executed when a USB SET_ADDRESS request was | ||||
|  * received. | ||||
|  */ | ||||
| #define USB_COUNT_SOF                   0 | ||||
| /* define this macro to 1 if you need the global variable "usbSofCount" which | ||||
|  * counts SOF packets. This feature requires that the hardware interrupt is | ||||
|  * connected to D- instead of D+. | ||||
|  */ | ||||
| /* #ifdef __ASSEMBLER__ | ||||
|  * macro myAssemblerMacro | ||||
|  *     in      YL, TCNT0 | ||||
|  *     sts     timer0Snapshot, YL | ||||
|  *     endm | ||||
|  * #endif | ||||
|  * #define USB_SOF_HOOK                    myAssemblerMacro | ||||
|  * This macro (if defined) is executed in the assembler module when a | ||||
|  * Start Of Frame condition is detected. It is recommended to define it to | ||||
|  * the name of an assembler macro which is defined here as well so that more | ||||
|  * than one assembler instruction can be used. The macro may use the register | ||||
|  * YL and modify SREG. If it lasts longer than a couple of cycles, USB messages | ||||
|  * immediately after an SOF pulse may be lost and must be retried by the host. | ||||
|  * What can you do with this hook? Since the SOF signal occurs exactly every | ||||
|  * 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in | ||||
|  * designs running on the internal RC oscillator. | ||||
|  * Please note that Start Of Frame detection works only if D- is wired to the | ||||
|  * interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES! | ||||
|  */ | ||||
| #define USB_CFG_CHECK_DATA_TOGGLING     0 | ||||
| /* define this macro to 1 if you want to filter out duplicate data packets | ||||
|  * sent by the host. Duplicates occur only as a consequence of communication | ||||
|  * errors, when the host does not receive an ACK. Please note that you need to | ||||
|  * implement the filtering yourself in usbFunctionWriteOut() and | ||||
|  * usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable | ||||
|  * for each control- and out-endpoint to check for duplicate packets. | ||||
|  */ | ||||
| #define USB_CFG_HAVE_MEASURE_FRAME_LENGTH   0 | ||||
| /* define this macro to 1 if you want the function usbMeasureFrameLength() | ||||
|  * compiled in. This function can be used to calibrate the AVR's RC oscillator. | ||||
|  */ | ||||
| #define USB_USE_FAST_CRC                0 | ||||
| /* The assembler module has two implementations for the CRC algorithm. One is | ||||
|  * faster, the other is smaller. This CRC routine is only used for transmitted | ||||
|  * messages where timing is not critical. The faster routine needs 31 cycles | ||||
|  * per byte while the smaller one needs 61 to 69 cycles. The faster routine | ||||
|  * may be worth the 32 bytes bigger code size if you transmit lots of data and | ||||
|  * run the AVR close to its limit. | ||||
|  */ | ||||
|  | ||||
| /* -------------------------- Device Description --------------------------- */ | ||||
|  | ||||
| #define  USB_CFG_VENDOR_ID       0xc0, 0x16 /* = 0x16c0 = 5824 = voti.nl */ | ||||
| /* USB vendor ID for the device, low byte first. If you have registered your | ||||
|  * own Vendor ID, define it here. Otherwise you may use one of obdev's free | ||||
|  * shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules! | ||||
|  * *** IMPORTANT NOTE *** | ||||
|  * This template uses obdev's shared VID/PID pair for Vendor Class devices | ||||
|  * with libusb: 0x16c0/0x5dc.  Use this VID/PID pair ONLY if you understand | ||||
|  * the implications! | ||||
|  */ | ||||
| #define  USB_CFG_DEVICE_ID       0xdc, 0x05 /* = 0x05dc = 1500 */ | ||||
| /* This is the ID of the product, low byte first. It is interpreted in the | ||||
|  * scope of the vendor ID. If you have registered your own VID with usb.org | ||||
|  * or if you have licensed a PID from somebody else, define it here. Otherwise | ||||
|  * you may use one of obdev's free shared VID/PID pairs. See the file | ||||
|  * USB-IDs-for-free.txt for details! | ||||
|  * *** IMPORTANT NOTE *** | ||||
|  * This template uses obdev's shared VID/PID pair for Vendor Class devices | ||||
|  * with libusb: 0x16c0/0x5dc.  Use this VID/PID pair ONLY if you understand | ||||
|  * the implications! | ||||
|  */ | ||||
| #define USB_CFG_DEVICE_VERSION  0x00, 0x01 | ||||
| /* Version number of the device: Minor number first, then major number. | ||||
|  */ | ||||
| #define USB_CFG_VENDOR_NAME     'o', 'b', 'd', 'e', 'v', '.', 'a', 't' | ||||
| #define USB_CFG_VENDOR_NAME_LEN 8 | ||||
| /* These two values define the vendor name returned by the USB device. The name | ||||
|  * must be given as a list of characters under single quotes. The characters | ||||
|  * are interpreted as Unicode (UTF-16) entities. | ||||
|  * If you don't want a vendor name string, undefine these macros. | ||||
|  * ALWAYS define a vendor name containing your Internet domain name if you use | ||||
|  * obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for | ||||
|  * details. | ||||
|  */ | ||||
| #define USB_CFG_DEVICE_NAME     'T', 'e', 'm', 'p', 'l', 'a', 't', 'e' | ||||
| #define USB_CFG_DEVICE_NAME_LEN 8 | ||||
| /* Same as above for the device name. If you don't want a device name, undefine | ||||
|  * the macros. See the file USB-IDs-for-free.txt before you assign a name if | ||||
|  * you use a shared VID/PID. | ||||
|  */ | ||||
| /*#define USB_CFG_SERIAL_NUMBER   'N', 'o', 'n', 'e' */ | ||||
| /*#define USB_CFG_SERIAL_NUMBER_LEN   0 */ | ||||
| /* Same as above for the serial number. If you don't want a serial number, | ||||
|  * undefine the macros. | ||||
|  * It may be useful to provide the serial number through other means than at | ||||
|  * compile time. See the section about descriptor properties below for how | ||||
|  * to fine tune control over USB descriptors such as the string descriptor | ||||
|  * for the serial number. | ||||
|  */ | ||||
| #define USB_CFG_DEVICE_CLASS        0xff    /* set to 0 if deferred to interface */ | ||||
| #define USB_CFG_DEVICE_SUBCLASS     0 | ||||
| /* See USB specification if you want to conform to an existing device class. | ||||
|  * Class 0xff is "vendor specific". | ||||
|  */ | ||||
| #define USB_CFG_INTERFACE_CLASS     0   /* define class here if not at device level */ | ||||
| #define USB_CFG_INTERFACE_SUBCLASS  0 | ||||
| #define USB_CFG_INTERFACE_PROTOCOL  0 | ||||
| /* See USB specification if you want to conform to an existing device class or | ||||
|  * protocol. The following classes must be set at interface level: | ||||
|  * HID class is 3, no subclass and protocol required (but may be useful!) | ||||
|  * CDC class is 2, use subclass 2 and protocol 1 for ACM | ||||
|  */ | ||||
| /* #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    42 */ | ||||
| /* Define this to the length of the HID report descriptor, if you implement | ||||
|  * an HID device. Otherwise don't define it or define it to 0. | ||||
|  * If you use this define, you must add a PROGMEM character array named | ||||
|  * "usbHidReportDescriptor" to your code which contains the report descriptor. | ||||
|  * Don't forget to keep the array and this define in sync! | ||||
|  */ | ||||
|  | ||||
| /* #define USB_PUBLIC static */ | ||||
| /* Use the define above if you #include usbdrv.c instead of linking against it. | ||||
|  * This technique saves a couple of bytes in flash memory. | ||||
|  */ | ||||
|  | ||||
| /* ------------------- Fine Control over USB Descriptors ------------------- */ | ||||
| /* If you don't want to use the driver's default USB descriptors, you can | ||||
|  * provide our own. These can be provided as (1) fixed length static data in | ||||
|  * flash memory, (2) fixed length static data in RAM or (3) dynamically at | ||||
|  * runtime in the function usbFunctionDescriptor(). See usbdrv.h for more | ||||
|  * information about this function. | ||||
|  * Descriptor handling is configured through the descriptor's properties. If | ||||
|  * no properties are defined or if they are 0, the default descriptor is used. | ||||
|  * Possible properties are: | ||||
|  *   + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched | ||||
|  *     at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is | ||||
|  *     used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if | ||||
|  *     you want RAM pointers. | ||||
|  *   + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found | ||||
|  *     in static memory is in RAM, not in flash memory. | ||||
|  *   + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), | ||||
|  *     the driver must know the descriptor's length. The descriptor itself is | ||||
|  *     found at the address of a well known identifier (see below). | ||||
|  * List of static descriptor names (must be declared PROGMEM if in flash): | ||||
|  *   char usbDescriptorDevice[]; | ||||
|  *   char usbDescriptorConfiguration[]; | ||||
|  *   char usbDescriptorHidReport[]; | ||||
|  *   char usbDescriptorString0[]; | ||||
|  *   int usbDescriptorStringVendor[]; | ||||
|  *   int usbDescriptorStringDevice[]; | ||||
|  *   int usbDescriptorStringSerialNumber[]; | ||||
|  * Other descriptors can't be provided statically, they must be provided | ||||
|  * dynamically at runtime. | ||||
|  * | ||||
|  * Descriptor properties are or-ed or added together, e.g.: | ||||
|  * #define USB_CFG_DESCR_PROPS_DEVICE   (USB_PROP_IS_RAM | USB_PROP_LENGTH(18)) | ||||
|  * | ||||
|  * The following descriptors are defined: | ||||
|  *   USB_CFG_DESCR_PROPS_DEVICE | ||||
|  *   USB_CFG_DESCR_PROPS_CONFIGURATION | ||||
|  *   USB_CFG_DESCR_PROPS_STRINGS | ||||
|  *   USB_CFG_DESCR_PROPS_STRING_0 | ||||
|  *   USB_CFG_DESCR_PROPS_STRING_VENDOR | ||||
|  *   USB_CFG_DESCR_PROPS_STRING_PRODUCT | ||||
|  *   USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER | ||||
|  *   USB_CFG_DESCR_PROPS_HID | ||||
|  *   USB_CFG_DESCR_PROPS_HID_REPORT | ||||
|  *   USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) | ||||
|  * | ||||
|  * Note about string descriptors: String descriptors are not just strings, they | ||||
|  * are Unicode strings prefixed with a 2 byte header. Example: | ||||
|  * int  serialNumberDescriptor[] = { | ||||
|  *     USB_STRING_DESCRIPTOR_HEADER(6), | ||||
|  *     'S', 'e', 'r', 'i', 'a', 'l' | ||||
|  * }; | ||||
|  */ | ||||
|  | ||||
| #define USB_CFG_DESCR_PROPS_DEVICE                  0 | ||||
| #define USB_CFG_DESCR_PROPS_CONFIGURATION           0 | ||||
| #define USB_CFG_DESCR_PROPS_STRINGS                 0 | ||||
| #define USB_CFG_DESCR_PROPS_STRING_0                0 | ||||
| #define USB_CFG_DESCR_PROPS_STRING_VENDOR           0 | ||||
| #define USB_CFG_DESCR_PROPS_STRING_PRODUCT          0 | ||||
| #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    0 | ||||
| #define USB_CFG_DESCR_PROPS_HID                     0 | ||||
| #define USB_CFG_DESCR_PROPS_HID_REPORT              0 | ||||
| #define USB_CFG_DESCR_PROPS_UNKNOWN                 0 | ||||
|  | ||||
|  | ||||
| //#define usbMsgPtr_t unsigned short | ||||
| /* If usbMsgPtr_t is not defined, it defaults to 'uchar *'. We may define it to | ||||
|  * a scalar type here because gcc generates slightly shorter code for scalar | ||||
|  * arithmetics than for pointer arithmetics. Remove this define for backward | ||||
|  * type compatibility or define it to an 8 bit type if you use data in RAM only | ||||
|  * and all RAM is below 256 bytes (tiny memory model in IAR CC). | ||||
|  */ | ||||
|  | ||||
| /* ----------------------- Optional MCU Description ------------------------ */ | ||||
|  | ||||
| /* The following configurations have working defaults in usbdrv.h. You | ||||
|  * usually don't need to set them explicitly. Only if you want to run | ||||
|  * the driver on a device which is not yet supported or with a compiler | ||||
|  * which is not fully supported (such as IAR C) or if you use a differnt | ||||
|  * interrupt than INT0, you may have to define some of these. | ||||
|  */ | ||||
| /* #define USB_INTR_CFG            MCUCR */ | ||||
| /* #define USB_INTR_CFG_SET        ((1 << ISC00) | (1 << ISC01)) */ | ||||
| /* #define USB_INTR_CFG_CLR        0 */ | ||||
| /* #define USB_INTR_ENABLE         GIMSK */ | ||||
| /* #define USB_INTR_ENABLE_BIT     INT0 */ | ||||
| /* #define USB_INTR_PENDING        GIFR */ | ||||
| /* #define USB_INTR_PENDING_BIT    INTF0 */ | ||||
| /* #define USB_INTR_VECTOR         INT0_vect */ | ||||
|  | ||||
| #endif /* __usbconfig_h_included__ */ | ||||
							
								
								
									
										378
									
								
								usbdrv/usbconfig.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										378
									
								
								usbdrv/usbconfig.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,378 @@ | ||||
| /* Name: usbconfig.h | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2005-04-01 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  * This Revision: $Id$ | ||||
|  */ | ||||
|  | ||||
| #ifndef __usbconfig_h_included__ | ||||
| #define __usbconfig_h_included__ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file is an example configuration (with inline documentation) for the USB | ||||
| driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is | ||||
| also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may | ||||
| wire the lines to any other port, as long as D+ is also wired to INT0 (or any | ||||
| other hardware interrupt, as long as it is the highest level interrupt, see | ||||
| section at the end of this file). | ||||
| */ | ||||
|  | ||||
| /* ---------------------------- Hardware Config ---------------------------- */ | ||||
|  | ||||
| #define USB_CFG_IOPORTNAME      B | ||||
| /* This is the port where the USB bus is connected. When you configure it to | ||||
|  * "B", the registers PORTB, PINB and DDRB will be used. | ||||
|  */ | ||||
| #define USB_CFG_DMINUS_BIT      4 | ||||
| /* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. | ||||
|  * This may be any bit in the port. | ||||
|  */ | ||||
| #define USB_CFG_DPLUS_BIT       3 | ||||
| /* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. | ||||
|  * This may be any bit in the port. Please note that D+ must also be connected | ||||
|  * to interrupt pin INT0! [You can also use other interrupts, see section | ||||
|  * "Optional MCU Description" below, or you can connect D- to the interrupt, as | ||||
|  * it is required if you use the USB_COUNT_SOF feature. If you use D- for the | ||||
|  * interrupt, the USB interrupt will also be triggered at Start-Of-Frame | ||||
|  * markers every millisecond.] | ||||
|  */ | ||||
| #define USB_CFG_CLOCK_KHZ       (F_CPU/1000) | ||||
| /* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000, | ||||
|  * 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code | ||||
|  * require no crystal, they tolerate +/- 1% deviation from the nominal | ||||
|  * frequency. All other rates require a precision of 2000 ppm and thus a | ||||
|  * crystal! | ||||
|  * Since F_CPU should be defined to your actual clock rate anyway, you should | ||||
|  * not need to modify this setting. | ||||
|  */ | ||||
| #define USB_CFG_CHECK_CRC       0 | ||||
| /* Define this to 1 if you want that the driver checks integrity of incoming | ||||
|  * data packets (CRC checks). CRC checks cost quite a bit of code size and are | ||||
|  * currently only available for 18 MHz crystal clock. You must choose | ||||
|  * USB_CFG_CLOCK_KHZ = 18000 if you enable this option. | ||||
|  */ | ||||
|  | ||||
| /* ----------------------- Optional Hardware Config ------------------------ */ | ||||
|  | ||||
| /* #define USB_CFG_PULLUP_IOPORTNAME   D */ | ||||
| /* If you connect the 1.5k pullup resistor from D- to a port pin instead of | ||||
|  * V+, you can connect and disconnect the device from firmware by calling | ||||
|  * the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h). | ||||
|  * This constant defines the port on which the pullup resistor is connected. | ||||
|  */ | ||||
| /* #define USB_CFG_PULLUP_BIT          4 */ | ||||
| /* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined | ||||
|  * above) where the 1.5k pullup resistor is connected. See description | ||||
|  * above for details. | ||||
|  */ | ||||
|  | ||||
| /* --------------------------- Functional Range ---------------------------- */ | ||||
|  | ||||
| #define USB_CFG_HAVE_INTRIN_ENDPOINT    1 | ||||
| /* Define this to 1 if you want to compile a version with two endpoints: The | ||||
|  * default control endpoint 0 and an interrupt-in endpoint (any other endpoint | ||||
|  * number). | ||||
|  */ | ||||
| #define USB_CFG_HAVE_INTRIN_ENDPOINT3   0 | ||||
| /* Define this to 1 if you want to compile a version with three endpoints: The | ||||
|  * default control endpoint 0, an interrupt-in endpoint 3 (or the number | ||||
|  * configured below) and a catch-all default interrupt-in endpoint as above. | ||||
|  * You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature. | ||||
|  */ | ||||
| #define USB_CFG_EP3_NUMBER              3 | ||||
| /* If the so-called endpoint 3 is used, it can now be configured to any other | ||||
|  * endpoint number (except 0) with this macro. Default if undefined is 3. | ||||
|  */ | ||||
| /* #define USB_INITIAL_DATATOKEN           USBPID_DATA1 */ | ||||
| /* The above macro defines the startup condition for data toggling on the | ||||
|  * interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1. | ||||
|  * Since the token is toggled BEFORE sending any data, the first packet is | ||||
|  * sent with the oposite value of this configuration! | ||||
|  */ | ||||
| #define USB_CFG_IMPLEMENT_HALT          0 | ||||
| /* Define this to 1 if you also want to implement the ENDPOINT_HALT feature | ||||
|  * for endpoint 1 (interrupt endpoint). Although you may not need this feature, | ||||
|  * it is required by the standard. We have made it a config option because it | ||||
|  * bloats the code considerably. | ||||
|  */ | ||||
| #define USB_CFG_SUPPRESS_INTR_CODE      0 | ||||
| /* Define this to 1 if you want to declare interrupt-in endpoints, but don't | ||||
|  * want to send any data over them. If this macro is defined to 1, functions | ||||
|  * usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if | ||||
|  * you need the interrupt-in endpoints in order to comply to an interface | ||||
|  * (e.g. HID), but never want to send any data. This option saves a couple | ||||
|  * of bytes in flash memory and the transmit buffers in RAM. | ||||
|  */ | ||||
| #define USB_CFG_INTR_POLL_INTERVAL      100 | ||||
| /* If you compile a version with endpoint 1 (interrupt-in), this is the poll | ||||
|  * interval. The value is in milliseconds and must not be less than 10 ms for | ||||
|  * low speed devices. | ||||
|  */ | ||||
| #define USB_CFG_IS_SELF_POWERED         0 | ||||
| /* Define this to 1 if the device has its own power supply. Set it to 0 if the | ||||
|  * device is powered from the USB bus. | ||||
|  */ | ||||
| #define USB_CFG_MAX_BUS_POWER           20 | ||||
| /* Set this variable to the maximum USB bus power consumption of your device. | ||||
|  * The value is in milliamperes. [It will be divided by two since USB | ||||
|  * communicates power requirements in units of 2 mA.] | ||||
|  */ | ||||
| #define USB_CFG_IMPLEMENT_FN_WRITE      0 | ||||
| /* Set this to 1 if you want usbFunctionWrite() to be called for control-out | ||||
|  * transfers. Set it to 0 if you don't need it and want to save a couple of | ||||
|  * bytes. | ||||
|  */ | ||||
| #define USB_CFG_IMPLEMENT_FN_READ       0 | ||||
| /* Set this to 1 if you need to send control replies which are generated | ||||
|  * "on the fly" when usbFunctionRead() is called. If you only want to send | ||||
|  * data from a static buffer, set it to 0 and return the data from | ||||
|  * usbFunctionSetup(). This saves a couple of bytes. | ||||
|  */ | ||||
| #define USB_CFG_IMPLEMENT_FN_WRITEOUT   0 | ||||
| /* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints. | ||||
|  * You must implement the function usbFunctionWriteOut() which receives all | ||||
|  * interrupt/bulk data sent to any endpoint other than 0. The endpoint number | ||||
|  * can be found in 'usbRxToken'. | ||||
|  */ | ||||
| #define USB_CFG_HAVE_FLOWCONTROL        0 | ||||
| /* Define this to 1 if you want flowcontrol over USB data. See the definition | ||||
|  * of the macros usbDisableAllRequests() and usbEnableAllRequests() in | ||||
|  * usbdrv.h. | ||||
|  */ | ||||
| #define USB_CFG_DRIVER_FLASH_PAGE       0 | ||||
| /* If the device has more than 64 kBytes of flash, define this to the 64 k page | ||||
|  * where the driver's constants (descriptors) are located. Or in other words: | ||||
|  * Define this to 1 for boot loaders on the ATMega128. | ||||
|  */ | ||||
| #define USB_CFG_LONG_TRANSFERS          0 | ||||
| /* Define this to 1 if you want to send/receive blocks of more than 254 bytes | ||||
|  * in a single control-in or control-out transfer. Note that the capability | ||||
|  * for long transfers increases the driver size. | ||||
|  */ | ||||
| /* #define USB_RX_USER_HOOK(data, len)     if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */ | ||||
| /* This macro is a hook if you want to do unconventional things. If it is | ||||
|  * defined, it's inserted at the beginning of received message processing. | ||||
|  * If you eat the received message and don't want default processing to | ||||
|  * proceed, do a return after doing your things. One possible application | ||||
|  * (besides debugging) is to flash a status LED on each packet. | ||||
|  */ | ||||
| #define USB_RESET_HOOK(resetStarts)     if(!resetStarts){hadUsbReset();} | ||||
| #ifndef __ASSEMBLER__ | ||||
| extern void hadUsbReset(void); // define the function for usbdrv.c | ||||
| #endif | ||||
| /* This macro is a hook if you need to know when an USB RESET occurs. It has | ||||
|  * one parameter which distinguishes between the start of RESET state and its | ||||
|  * end. | ||||
|  */ | ||||
| /* #define USB_SET_ADDRESS_HOOK()              hadAddressAssigned(); */ | ||||
| /* This macro (if defined) is executed when a USB SET_ADDRESS request was | ||||
|  * received. | ||||
|  */ | ||||
| #define USB_COUNT_SOF                   0 | ||||
| /* define this macro to 1 if you need the global variable "usbSofCount" which | ||||
|  * counts SOF packets. This feature requires that the hardware interrupt is | ||||
|  * connected to D- instead of D+. | ||||
|  */ | ||||
| /* #ifdef __ASSEMBLER__ | ||||
|  * macro myAssemblerMacro | ||||
|  *     in      YL, TCNT0 | ||||
|  *     sts     timer0Snapshot, YL | ||||
|  *     endm | ||||
|  * #endif | ||||
|  * #define USB_SOF_HOOK                    myAssemblerMacro | ||||
|  * This macro (if defined) is executed in the assembler module when a | ||||
|  * Start Of Frame condition is detected. It is recommended to define it to | ||||
|  * the name of an assembler macro which is defined here as well so that more | ||||
|  * than one assembler instruction can be used. The macro may use the register | ||||
|  * YL and modify SREG. If it lasts longer than a couple of cycles, USB messages | ||||
|  * immediately after an SOF pulse may be lost and must be retried by the host. | ||||
|  * What can you do with this hook? Since the SOF signal occurs exactly every | ||||
|  * 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in | ||||
|  * designs running on the internal RC oscillator. | ||||
|  * Please note that Start Of Frame detection works only if D- is wired to the | ||||
|  * interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES! | ||||
|  */ | ||||
| #define USB_CFG_CHECK_DATA_TOGGLING     0 | ||||
| /* define this macro to 1 if you want to filter out duplicate data packets | ||||
|  * sent by the host. Duplicates occur only as a consequence of communication | ||||
|  * errors, when the host does not receive an ACK. Please note that you need to | ||||
|  * implement the filtering yourself in usbFunctionWriteOut() and | ||||
|  * usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable | ||||
|  * for each control- and out-endpoint to check for duplicate packets. | ||||
|  */ | ||||
| #define USB_CFG_HAVE_MEASURE_FRAME_LENGTH   1 | ||||
| /* define this macro to 1 if you want the function usbMeasureFrameLength() | ||||
|  * compiled in. This function can be used to calibrate the AVR's RC oscillator. | ||||
|  */ | ||||
| #define USB_USE_FAST_CRC                0 | ||||
| /* The assembler module has two implementations for the CRC algorithm. One is | ||||
|  * faster, the other is smaller. This CRC routine is only used for transmitted | ||||
|  * messages where timing is not critical. The faster routine needs 31 cycles | ||||
|  * per byte while the smaller one needs 61 to 69 cycles. The faster routine | ||||
|  * may be worth the 32 bytes bigger code size if you transmit lots of data and | ||||
|  * run the AVR close to its limit. | ||||
|  */ | ||||
|  | ||||
| /* -------------------------- Device Description --------------------------- */ | ||||
|  | ||||
| #define  USB_CFG_VENDOR_ID       0xc0, 0x16 /* = 0x16c0 = 5824 = voti.nl */ | ||||
| /* USB vendor ID for the device, low byte first. If you have registered your | ||||
|  * own Vendor ID, define it here. Otherwise you may use one of obdev's free | ||||
|  * shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules! | ||||
|  * *** IMPORTANT NOTE *** | ||||
|  * This template uses obdev's shared VID/PID pair for Vendor Class devices | ||||
|  * with libusb: 0x16c0/0x5dc.  Use this VID/PID pair ONLY if you understand | ||||
|  * the implications! | ||||
|  */ | ||||
| #define  USB_CFG_DEVICE_ID       0xdc, 0x05 /* = 0x05dc = 1500 */ | ||||
| /* This is the ID of the product, low byte first. It is interpreted in the | ||||
|  * scope of the vendor ID. If you have registered your own VID with usb.org | ||||
|  * or if you have licensed a PID from somebody else, define it here. Otherwise | ||||
|  * you may use one of obdev's free shared VID/PID pairs. See the file | ||||
|  * USB-IDs-for-free.txt for details! | ||||
|  * *** IMPORTANT NOTE *** | ||||
|  * This template uses obdev's shared VID/PID pair for Vendor Class devices | ||||
|  * with libusb: 0x16c0/0x5dc.  Use this VID/PID pair ONLY if you understand | ||||
|  * the implications! | ||||
|  */ | ||||
| #define USB_CFG_DEVICE_VERSION  0x00, 0x01 | ||||
| /* Version number of the device: Minor number first, then major number. | ||||
|  */ | ||||
| #define USB_CFG_VENDOR_NAME     'c', 'o', 'd', 'e', 'a', 'n', 'd', 'l', \ | ||||
| 								'i', 'f', 'e', '.', 'c', 'o', 'm' | ||||
| #define USB_CFG_VENDOR_NAME_LEN 15 | ||||
| /* These two values define the vendor name returned by the USB device. The name | ||||
|  * must be given as a list of characters under single quotes. The characters | ||||
|  * are interpreted as Unicode (UTF-16) entities. | ||||
|  * If you don't want a vendor name string, undefine these macros. | ||||
|  * ALWAYS define a vendor name containing your Internet domain name if you use | ||||
|  * obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for | ||||
|  * details. | ||||
|  */ | ||||
| #define USB_CFG_DEVICE_NAME     'U', 'S', 'B', 'e', 'x', 'a', 'm', 'p', 'l', 'e' | ||||
| #define USB_CFG_DEVICE_NAME_LEN 10 | ||||
| /* Same as above for the device name. If you don't want a device name, undefine | ||||
|  * the macros. See the file USB-IDs-for-free.txt before you assign a name if | ||||
|  * you use a shared VID/PID. | ||||
|  */ | ||||
| /*#define USB_CFG_SERIAL_NUMBER   'N', 'o', 'n', 'e' */ | ||||
| /*#define USB_CFG_SERIAL_NUMBER_LEN   0 */ | ||||
| /* Same as above for the serial number. If you don't want a serial number, | ||||
|  * undefine the macros. | ||||
|  * It may be useful to provide the serial number through other means than at | ||||
|  * compile time. See the section about descriptor properties below for how | ||||
|  * to fine tune control over USB descriptors such as the string descriptor | ||||
|  * for the serial number. | ||||
|  */ | ||||
| #define USB_CFG_DEVICE_CLASS        0    /* set to 0 if deferred to interface */ | ||||
| #define USB_CFG_DEVICE_SUBCLASS     0 | ||||
| /* See USB specification if you want to conform to an existing device class. | ||||
|  * Class 0xff is "vendor specific". | ||||
|  */ | ||||
| #define USB_CFG_INTERFACE_CLASS     3   /* define class here if not at device level */ | ||||
| #define USB_CFG_INTERFACE_SUBCLASS  0 | ||||
| #define USB_CFG_INTERFACE_PROTOCOL  0 | ||||
| /* See USB specification if you want to conform to an existing device class or | ||||
|  * protocol. The following classes must be set at interface level: | ||||
|  * HID class is 3, no subclass and protocol required (but may be useful!) | ||||
|  * CDC class is 2, use subclass 2 and protocol 1 for ACM | ||||
|  */ | ||||
| /* #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    42 */ | ||||
| #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    52 | ||||
| /* Define this to the length of the HID report descriptor, if you implement | ||||
|  * an HID device. Otherwise don't define it or define it to 0. | ||||
|  * If you use this define, you must add a PROGMEM character array named | ||||
|  * "usbHidReportDescriptor" to your code which contains the report descriptor. | ||||
|  * Don't forget to keep the array and this define in sync! | ||||
|  */ | ||||
|  | ||||
| /* #define USB_PUBLIC static */ | ||||
| /* Use the define above if you #include usbdrv.c instead of linking against it. | ||||
|  * This technique saves a couple of bytes in flash memory. | ||||
|  */ | ||||
|  | ||||
| /* ------------------- Fine Control over USB Descriptors ------------------- */ | ||||
| /* If you don't want to use the driver's default USB descriptors, you can | ||||
|  * provide our own. These can be provided as (1) fixed length static data in | ||||
|  * flash memory, (2) fixed length static data in RAM or (3) dynamically at | ||||
|  * runtime in the function usbFunctionDescriptor(). See usbdrv.h for more | ||||
|  * information about this function. | ||||
|  * Descriptor handling is configured through the descriptor's properties. If | ||||
|  * no properties are defined or if they are 0, the default descriptor is used. | ||||
|  * Possible properties are: | ||||
|  *   + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched | ||||
|  *     at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is | ||||
|  *     used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if | ||||
|  *     you want RAM pointers. | ||||
|  *   + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found | ||||
|  *     in static memory is in RAM, not in flash memory. | ||||
|  *   + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), | ||||
|  *     the driver must know the descriptor's length. The descriptor itself is | ||||
|  *     found at the address of a well known identifier (see below). | ||||
|  * List of static descriptor names (must be declared PROGMEM if in flash): | ||||
|  *   char usbDescriptorDevice[]; | ||||
|  *   char usbDescriptorConfiguration[]; | ||||
|  *   char usbDescriptorHidReport[]; | ||||
|  *   char usbDescriptorString0[]; | ||||
|  *   int usbDescriptorStringVendor[]; | ||||
|  *   int usbDescriptorStringDevice[]; | ||||
|  *   int usbDescriptorStringSerialNumber[]; | ||||
|  * Other descriptors can't be provided statically, they must be provided | ||||
|  * dynamically at runtime. | ||||
|  * | ||||
|  * Descriptor properties are or-ed or added together, e.g.: | ||||
|  * #define USB_CFG_DESCR_PROPS_DEVICE   (USB_PROP_IS_RAM | USB_PROP_LENGTH(18)) | ||||
|  * | ||||
|  * The following descriptors are defined: | ||||
|  *   USB_CFG_DESCR_PROPS_DEVICE | ||||
|  *   USB_CFG_DESCR_PROPS_CONFIGURATION | ||||
|  *   USB_CFG_DESCR_PROPS_STRINGS | ||||
|  *   USB_CFG_DESCR_PROPS_STRING_0 | ||||
|  *   USB_CFG_DESCR_PROPS_STRING_VENDOR | ||||
|  *   USB_CFG_DESCR_PROPS_STRING_PRODUCT | ||||
|  *   USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER | ||||
|  *   USB_CFG_DESCR_PROPS_HID | ||||
|  *   USB_CFG_DESCR_PROPS_HID_REPORT | ||||
|  *   USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) | ||||
|  * | ||||
|  * Note about string descriptors: String descriptors are not just strings, they | ||||
|  * are Unicode strings prefixed with a 2 byte header. Example: | ||||
|  * int  serialNumberDescriptor[] = { | ||||
|  *     USB_STRING_DESCRIPTOR_HEADER(6), | ||||
|  *     'S', 'e', 'r', 'i', 'a', 'l' | ||||
|  * }; | ||||
|  */ | ||||
|  | ||||
| #define USB_CFG_DESCR_PROPS_DEVICE                  0 | ||||
| #define USB_CFG_DESCR_PROPS_CONFIGURATION           0 | ||||
| #define USB_CFG_DESCR_PROPS_STRINGS                 0 | ||||
| #define USB_CFG_DESCR_PROPS_STRING_0                0 | ||||
| #define USB_CFG_DESCR_PROPS_STRING_VENDOR           0 | ||||
| #define USB_CFG_DESCR_PROPS_STRING_PRODUCT          0 | ||||
| #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    0 | ||||
| #define USB_CFG_DESCR_PROPS_HID                     0 | ||||
| #define USB_CFG_DESCR_PROPS_HID_REPORT              0 | ||||
| #define USB_CFG_DESCR_PROPS_UNKNOWN                 0 | ||||
|  | ||||
| /* ----------------------- Optional MCU Description ------------------------ */ | ||||
|  | ||||
| /* The following configurations have working defaults in usbdrv.h. You | ||||
|  * usually don't need to set them explicitly. Only if you want to run | ||||
|  * the driver on a device which is not yet supported or with a compiler | ||||
|  * which is not fully supported (such as IAR C) or if you use a differnt | ||||
|  * interrupt than INT0, you may have to define some of these. | ||||
|  */ | ||||
| /* #define USB_INTR_CFG            MCUCR */ | ||||
| /* #define USB_INTR_CFG_SET        ((1 << ISC00) | (1 << ISC01)) */ | ||||
| /* #define USB_INTR_CFG_CLR        0 */ | ||||
| /* #define USB_INTR_ENABLE         GIMSK */ | ||||
| /* #define USB_INTR_ENABLE_BIT     INT0 */ | ||||
| /* #define USB_INTR_PENDING        GIFR */ | ||||
| /* #define USB_INTR_PENDING_BIT    INTF0 */ | ||||
| /* #define USB_INTR_VECTOR         INT0_vect */ | ||||
|  | ||||
| #endif /* __usbconfig_h_included__ */ | ||||
							
								
								
									
										634
									
								
								usbdrv/usbdrv.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										634
									
								
								usbdrv/usbdrv.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,634 @@ | ||||
| /* Name: usbdrv.c | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2004-12-29 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| #include "usbdrv.h" | ||||
| #include "oddebug.h" | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This module implements the C-part of the USB driver. See usbdrv.h for a | ||||
| documentation of the entire driver. | ||||
| */ | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| /* raw USB registers / interface to assembler code: */ | ||||
| uchar usbRxBuf[2*USB_BUFSIZE];  /* raw RX buffer: PID, 8 bytes data, 2 bytes CRC */ | ||||
| uchar       usbInputBufOffset;  /* offset in usbRxBuf used for low level receiving */ | ||||
| uchar       usbDeviceAddr;      /* assigned during enumeration, defaults to 0 */ | ||||
| uchar       usbNewDeviceAddr;   /* device ID which should be set after status phase */ | ||||
| uchar       usbConfiguration;   /* currently selected configuration. Administered by driver, but not used */ | ||||
| volatile schar usbRxLen;        /* = 0; number of bytes in usbRxBuf; 0 means free, -1 for flow control */ | ||||
| uchar       usbCurrentTok;      /* last token received or endpoint number for last OUT token if != 0 */ | ||||
| uchar       usbRxToken;         /* token for data we received; or endpont number for last OUT */ | ||||
| volatile uchar usbTxLen = USBPID_NAK;   /* number of bytes to transmit with next IN token or handshake token */ | ||||
| uchar       usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbTxLen contains handshake token */ | ||||
| #if USB_COUNT_SOF | ||||
| volatile uchar  usbSofCount;    /* incremented by assembler module every SOF */ | ||||
| #endif | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE | ||||
| usbTxStatus_t  usbTxStatus1; | ||||
| #   if USB_CFG_HAVE_INTRIN_ENDPOINT3 | ||||
| usbTxStatus_t  usbTxStatus3; | ||||
| #   endif | ||||
| #endif | ||||
| #if USB_CFG_CHECK_DATA_TOGGLING | ||||
| uchar       usbCurrentDataToken;/* when we check data toggling to ignore duplicate packets */ | ||||
| #endif | ||||
|  | ||||
| /* USB status registers / not shared with asm code */ | ||||
| usbMsgPtr_t         usbMsgPtr;      /* data to transmit next -- ROM or RAM address */ | ||||
| static usbMsgLen_t  usbMsgLen = USB_NO_MSG; /* remaining number of bytes */ | ||||
| uchar               usbMsgFlags;    /* flag values see USB_FLG_* */ | ||||
|  | ||||
| #define USB_FLG_USE_USER_RW     (1<<7) | ||||
|  | ||||
| /* | ||||
| optimizing hints: | ||||
| - do not post/pre inc/dec integer values in operations | ||||
| - assign value of USB_READ_FLASH() to register variables and don't use side effects in arg | ||||
| - use narrow scope for variables which should be in X/Y/Z register | ||||
| - assign char sized expressions to variables to force 8 bit arithmetics | ||||
| */ | ||||
|  | ||||
| /* -------------------------- String Descriptors --------------------------- */ | ||||
|  | ||||
| #if USB_CFG_DESCR_PROPS_STRINGS == 0 | ||||
|  | ||||
| #if USB_CFG_DESCR_PROPS_STRING_0 == 0 | ||||
| #undef USB_CFG_DESCR_PROPS_STRING_0 | ||||
| #define USB_CFG_DESCR_PROPS_STRING_0    sizeof(usbDescriptorString0) | ||||
| PROGMEM const char usbDescriptorString0[] = { /* language descriptor */ | ||||
|     4,          /* sizeof(usbDescriptorString0): length of descriptor in bytes */ | ||||
|     3,          /* descriptor type */ | ||||
|     0x09, 0x04, /* language index (0x0409 = US-English) */ | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| #if USB_CFG_DESCR_PROPS_STRING_VENDOR == 0 && USB_CFG_VENDOR_NAME_LEN | ||||
| #undef USB_CFG_DESCR_PROPS_STRING_VENDOR | ||||
| #define USB_CFG_DESCR_PROPS_STRING_VENDOR   sizeof(usbDescriptorStringVendor) | ||||
| PROGMEM const int  usbDescriptorStringVendor[] = { | ||||
|     USB_STRING_DESCRIPTOR_HEADER(USB_CFG_VENDOR_NAME_LEN), | ||||
|     USB_CFG_VENDOR_NAME | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| #if USB_CFG_DESCR_PROPS_STRING_PRODUCT == 0 && USB_CFG_DEVICE_NAME_LEN | ||||
| #undef USB_CFG_DESCR_PROPS_STRING_PRODUCT | ||||
| #define USB_CFG_DESCR_PROPS_STRING_PRODUCT   sizeof(usbDescriptorStringDevice) | ||||
| PROGMEM const int  usbDescriptorStringDevice[] = { | ||||
|     USB_STRING_DESCRIPTOR_HEADER(USB_CFG_DEVICE_NAME_LEN), | ||||
|     USB_CFG_DEVICE_NAME | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| #if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN | ||||
| #undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER | ||||
| #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    sizeof(usbDescriptorStringSerialNumber) | ||||
| PROGMEM const int usbDescriptorStringSerialNumber[] = { | ||||
|     USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN), | ||||
|     USB_CFG_SERIAL_NUMBER | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| #endif  /* USB_CFG_DESCR_PROPS_STRINGS == 0 */ | ||||
|  | ||||
| /* --------------------------- Device Descriptor --------------------------- */ | ||||
|  | ||||
| #if USB_CFG_DESCR_PROPS_DEVICE == 0 | ||||
| #undef USB_CFG_DESCR_PROPS_DEVICE | ||||
| #define USB_CFG_DESCR_PROPS_DEVICE  sizeof(usbDescriptorDevice) | ||||
| PROGMEM const char usbDescriptorDevice[] = {    /* USB device descriptor */ | ||||
|     18,         /* sizeof(usbDescriptorDevice): length of descriptor in bytes */ | ||||
|     USBDESCR_DEVICE,        /* descriptor type */ | ||||
|     0x10, 0x01,             /* USB version supported */ | ||||
|     USB_CFG_DEVICE_CLASS, | ||||
|     USB_CFG_DEVICE_SUBCLASS, | ||||
|     0,                      /* protocol */ | ||||
|     8,                      /* max packet size */ | ||||
|     /* the following two casts affect the first byte of the constant only, but | ||||
|      * that's sufficient to avoid a warning with the default values. | ||||
|      */ | ||||
|     (char)USB_CFG_VENDOR_ID,/* 2 bytes */ | ||||
|     (char)USB_CFG_DEVICE_ID,/* 2 bytes */ | ||||
|     USB_CFG_DEVICE_VERSION, /* 2 bytes */ | ||||
|     USB_CFG_DESCR_PROPS_STRING_VENDOR != 0 ? 1 : 0,         /* manufacturer string index */ | ||||
|     USB_CFG_DESCR_PROPS_STRING_PRODUCT != 0 ? 2 : 0,        /* product string index */ | ||||
|     USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER != 0 ? 3 : 0,  /* serial number string index */ | ||||
|     1,          /* number of configurations */ | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| /* ----------------------- Configuration Descriptor ------------------------ */ | ||||
|  | ||||
| #if USB_CFG_DESCR_PROPS_HID_REPORT != 0 && USB_CFG_DESCR_PROPS_HID == 0 | ||||
| #undef USB_CFG_DESCR_PROPS_HID | ||||
| #define USB_CFG_DESCR_PROPS_HID     9   /* length of HID descriptor in config descriptor below */ | ||||
| #endif | ||||
|  | ||||
| #if USB_CFG_DESCR_PROPS_CONFIGURATION == 0 | ||||
| #undef USB_CFG_DESCR_PROPS_CONFIGURATION | ||||
| #define USB_CFG_DESCR_PROPS_CONFIGURATION   sizeof(usbDescriptorConfiguration) | ||||
| PROGMEM const char usbDescriptorConfiguration[] = {    /* USB configuration descriptor */ | ||||
|     9,          /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */ | ||||
|     USBDESCR_CONFIG,    /* descriptor type */ | ||||
|     18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + | ||||
|                 (USB_CFG_DESCR_PROPS_HID & 0xff), 0, | ||||
|                 /* total length of data returned (including inlined descriptors) */ | ||||
|     1,          /* number of interfaces in this configuration */ | ||||
|     1,          /* index of this configuration */ | ||||
|     0,          /* configuration name string index */ | ||||
| #if USB_CFG_IS_SELF_POWERED | ||||
|     (1 << 7) | USBATTR_SELFPOWER,       /* attributes */ | ||||
| #else | ||||
|     (1 << 7) | USBATTR_REMOTEWAKE,      /* attributes */ | ||||
| #endif | ||||
|     USB_CFG_MAX_BUS_POWER/2,            /* max USB current in 2mA units */ | ||||
| /* interface descriptor follows inline: */ | ||||
|     9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */ | ||||
|     USBDESCR_INTERFACE, /* descriptor type */ | ||||
|     0,          /* index of this interface */ | ||||
|     0,          /* alternate setting for this interface */ | ||||
|     USB_CFG_HAVE_INTRIN_ENDPOINT + USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */ | ||||
|     USB_CFG_INTERFACE_CLASS, | ||||
|     USB_CFG_INTERFACE_SUBCLASS, | ||||
|     USB_CFG_INTERFACE_PROTOCOL, | ||||
|     0,          /* string index for interface */ | ||||
| #if (USB_CFG_DESCR_PROPS_HID & 0xff)    /* HID descriptor */ | ||||
|     9,          /* sizeof(usbDescrHID): length of descriptor in bytes */ | ||||
|     USBDESCR_HID,   /* descriptor type: HID */ | ||||
|     0x01, 0x01, /* BCD representation of HID version */ | ||||
|     0x00,       /* target country code */ | ||||
|     0x01,       /* number of HID Report (or other HID class) Descriptor infos to follow */ | ||||
|     0x22,       /* descriptor type: report */ | ||||
|     (USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH & 0xFF), /* descriptor length (low byte) */ | ||||
|     ((USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH >> 8) & 0xFF), /*            (high byte) */ | ||||
| #endif | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT    /* endpoint descriptor for endpoint 1 */ | ||||
|     7,          /* sizeof(usbDescrEndpoint) */ | ||||
|     USBDESCR_ENDPOINT,  /* descriptor type = endpoint */ | ||||
|     (char)0x81, /* IN endpoint number 1 */ | ||||
|     0x03,       /* attrib: Interrupt endpoint */ | ||||
|     8, 0,       /* maximum packet size */ | ||||
|     USB_CFG_INTR_POLL_INTERVAL, /* in ms */ | ||||
| #endif | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT3   /* endpoint descriptor for endpoint 3 */ | ||||
|     7,          /* sizeof(usbDescrEndpoint) */ | ||||
|     USBDESCR_ENDPOINT,  /* descriptor type = endpoint */ | ||||
|     (char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */ | ||||
|     0x03,       /* attrib: Interrupt endpoint */ | ||||
|     8, 0,       /* maximum packet size */ | ||||
|     USB_CFG_INTR_POLL_INTERVAL, /* in ms */ | ||||
| #endif | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| static inline void  usbResetDataToggling(void) | ||||
| { | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE | ||||
|     USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN);  /* reset data toggling for interrupt endpoint */ | ||||
| #   if USB_CFG_HAVE_INTRIN_ENDPOINT3 | ||||
|     USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN);  /* reset data toggling for interrupt endpoint */ | ||||
| #   endif | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static inline void  usbResetStall(void) | ||||
| { | ||||
| #if USB_CFG_IMPLEMENT_HALT && USB_CFG_HAVE_INTRIN_ENDPOINT | ||||
|         usbTxLen1 = USBPID_NAK; | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT3 | ||||
|         usbTxLen3 = USBPID_NAK; | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| #if !USB_CFG_SUPPRESS_INTR_CODE | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT | ||||
| static void usbGenericSetInterrupt(uchar *data, uchar len, usbTxStatus_t *txStatus) | ||||
| { | ||||
| uchar   *p; | ||||
| schar   i; | ||||
|  | ||||
| #if USB_CFG_IMPLEMENT_HALT | ||||
|     if(usbTxLen1 == USBPID_STALL) | ||||
|         return; | ||||
| #endif | ||||
|     if(txStatus->len & 0x10){   /* packet buffer was empty */ | ||||
|         txStatus->buffer[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* toggle token */ | ||||
|     }else{ | ||||
|         txStatus->len = USBPID_NAK; /* avoid sending outdated (overwritten) interrupt data */ | ||||
|     } | ||||
|     p = txStatus->buffer + 1; | ||||
|     i = len; | ||||
|     do{                         /* if len == 0, we still copy 1 byte, but that's no problem */ | ||||
|         *p++ = *data++; | ||||
|     }while(--i > 0);            /* loop control at the end is 2 bytes shorter than at beginning */ | ||||
|     usbCrc16Append(&txStatus->buffer[1], len); | ||||
|     txStatus->len = len + 4;    /* len must be given including sync byte */ | ||||
|     DBG2(0x21 + (((int)txStatus >> 3) & 3), txStatus->buffer, len + 3); | ||||
| } | ||||
|  | ||||
| USB_PUBLIC void usbSetInterrupt(uchar *data, uchar len) | ||||
| { | ||||
|     usbGenericSetInterrupt(data, len, &usbTxStatus1); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT3 | ||||
| USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len) | ||||
| { | ||||
|     usbGenericSetInterrupt(data, len, &usbTxStatus3); | ||||
| } | ||||
| #endif | ||||
| #endif /* USB_CFG_SUPPRESS_INTR_CODE */ | ||||
|  | ||||
| /* ------------------ utilities for code following below ------------------- */ | ||||
|  | ||||
| /* Use defines for the switch statement so that we can choose between an | ||||
|  * if()else if() and a switch/case based implementation. switch() is more | ||||
|  * efficient for a LARGE set of sequential choices, if() is better in all other | ||||
|  * cases. | ||||
|  */ | ||||
| #if USB_CFG_USE_SWITCH_STATEMENT | ||||
| #   define SWITCH_START(cmd)       switch(cmd){{ | ||||
| #   define SWITCH_CASE(value)      }break; case (value):{ | ||||
| #   define SWITCH_CASE2(v1,v2)     }break; case (v1): case(v2):{ | ||||
| #   define SWITCH_CASE3(v1,v2,v3)  }break; case (v1): case(v2): case(v3):{ | ||||
| #   define SWITCH_DEFAULT          }break; default:{ | ||||
| #   define SWITCH_END              }} | ||||
| #else | ||||
| #   define SWITCH_START(cmd)       {uchar _cmd = cmd; if(0){ | ||||
| #   define SWITCH_CASE(value)      }else if(_cmd == (value)){ | ||||
| #   define SWITCH_CASE2(v1,v2)     }else if(_cmd == (v1) || _cmd == (v2)){ | ||||
| #   define SWITCH_CASE3(v1,v2,v3)  }else if(_cmd == (v1) || _cmd == (v2) || (_cmd == v3)){ | ||||
| #   define SWITCH_DEFAULT          }else{ | ||||
| #   define SWITCH_END              }} | ||||
| #endif | ||||
|  | ||||
| #ifndef USB_RX_USER_HOOK | ||||
| #define USB_RX_USER_HOOK(data, len) | ||||
| #endif | ||||
| #ifndef USB_SET_ADDRESS_HOOK | ||||
| #define USB_SET_ADDRESS_HOOK() | ||||
| #endif | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| /* We use if() instead of #if in the macro below because #if can't be used | ||||
|  * in macros and the compiler optimizes constant conditions anyway. | ||||
|  * This may cause problems with undefined symbols if compiled without | ||||
|  * optimizing! | ||||
|  */ | ||||
| #define GET_DESCRIPTOR(cfgProp, staticName)         \ | ||||
|     if(cfgProp){                                    \ | ||||
|         if((cfgProp) & USB_PROP_IS_RAM)             \ | ||||
|             flags = 0;                              \ | ||||
|         if((cfgProp) & USB_PROP_IS_DYNAMIC){        \ | ||||
|             len = usbFunctionDescriptor(rq);        \ | ||||
|         }else{                                      \ | ||||
|             len = USB_PROP_LENGTH(cfgProp);         \ | ||||
|             usbMsgPtr = (usbMsgPtr_t)(staticName);  \ | ||||
|         }                                           \ | ||||
|     } | ||||
|  | ||||
| /* usbDriverDescriptor() is similar to usbFunctionDescriptor(), but used | ||||
|  * internally for all types of descriptors. | ||||
|  */ | ||||
| static inline usbMsgLen_t usbDriverDescriptor(usbRequest_t *rq) | ||||
| { | ||||
| usbMsgLen_t len = 0; | ||||
| uchar       flags = USB_FLG_MSGPTR_IS_ROM; | ||||
|  | ||||
|     SWITCH_START(rq->wValue.bytes[1]) | ||||
|     SWITCH_CASE(USBDESCR_DEVICE)    /* 1 */ | ||||
|         GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice) | ||||
|     SWITCH_CASE(USBDESCR_CONFIG)    /* 2 */ | ||||
|         GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration) | ||||
|     SWITCH_CASE(USBDESCR_STRING)    /* 3 */ | ||||
| #if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC | ||||
|         if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM) | ||||
|             flags = 0; | ||||
|         len = usbFunctionDescriptor(rq); | ||||
| #else   /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ | ||||
|         SWITCH_START(rq->wValue.bytes[0]) | ||||
|         SWITCH_CASE(0) | ||||
|             GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0) | ||||
|         SWITCH_CASE(1) | ||||
|             GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor) | ||||
|         SWITCH_CASE(2) | ||||
|             GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_PRODUCT, usbDescriptorStringDevice) | ||||
|         SWITCH_CASE(3) | ||||
|             GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER, usbDescriptorStringSerialNumber) | ||||
|         SWITCH_DEFAULT | ||||
|             if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ | ||||
|                 if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_RAM){ | ||||
|                     flags = 0; | ||||
|                 } | ||||
|                 len = usbFunctionDescriptor(rq); | ||||
|             } | ||||
|         SWITCH_END | ||||
| #endif  /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ | ||||
| #if USB_CFG_DESCR_PROPS_HID_REPORT  /* only support HID descriptors if enabled */ | ||||
|     SWITCH_CASE(USBDESCR_HID)       /* 0x21 */ | ||||
|         GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID, usbDescriptorConfiguration + 18) | ||||
|     SWITCH_CASE(USBDESCR_HID_REPORT)/* 0x22 */ | ||||
|         GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT, usbDescriptorHidReport) | ||||
| #endif | ||||
|     SWITCH_DEFAULT | ||||
|         if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ | ||||
|             if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_RAM){ | ||||
|                 flags = 0; | ||||
|             } | ||||
|             len = usbFunctionDescriptor(rq); | ||||
|         } | ||||
|     SWITCH_END | ||||
|     usbMsgFlags = flags; | ||||
|     return len; | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| /* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for | ||||
|  * standard requests instead of class and custom requests. | ||||
|  */ | ||||
| static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq) | ||||
| { | ||||
| usbMsgLen_t len = 0; | ||||
| uchar   *dataPtr = usbTxBuf + 9;    /* there are 2 bytes free space at the end of the buffer */ | ||||
| uchar   value = rq->wValue.bytes[0]; | ||||
| #if USB_CFG_IMPLEMENT_HALT | ||||
| uchar   index = rq->wIndex.bytes[0]; | ||||
| #endif | ||||
|  | ||||
|     dataPtr[0] = 0; /* default reply common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */ | ||||
|     SWITCH_START(rq->bRequest) | ||||
|     SWITCH_CASE(USBRQ_GET_STATUS)           /* 0 */ | ||||
|         uchar recipient = rq->bmRequestType & USBRQ_RCPT_MASK;  /* assign arith ops to variables to enforce byte size */ | ||||
|         if(USB_CFG_IS_SELF_POWERED && recipient == USBRQ_RCPT_DEVICE) | ||||
|             dataPtr[0] =  USB_CFG_IS_SELF_POWERED; | ||||
| #if USB_CFG_IMPLEMENT_HALT | ||||
|         if(recipient == USBRQ_RCPT_ENDPOINT && index == 0x81)   /* request status for endpoint 1 */ | ||||
|             dataPtr[0] = usbTxLen1 == USBPID_STALL; | ||||
| #endif | ||||
|         dataPtr[1] = 0; | ||||
|         len = 2; | ||||
| #if USB_CFG_IMPLEMENT_HALT | ||||
|     SWITCH_CASE2(USBRQ_CLEAR_FEATURE, USBRQ_SET_FEATURE)    /* 1, 3 */ | ||||
|         if(value == 0 && index == 0x81){    /* feature 0 == HALT for endpoint == 1 */ | ||||
|             usbTxLen1 = rq->bRequest == USBRQ_CLEAR_FEATURE ? USBPID_NAK : USBPID_STALL; | ||||
|             usbResetDataToggling(); | ||||
|         } | ||||
| #endif | ||||
|     SWITCH_CASE(USBRQ_SET_ADDRESS)          /* 5 */ | ||||
|         usbNewDeviceAddr = value; | ||||
|         USB_SET_ADDRESS_HOOK(); | ||||
|     SWITCH_CASE(USBRQ_GET_DESCRIPTOR)       /* 6 */ | ||||
|         len = usbDriverDescriptor(rq); | ||||
|         goto skipMsgPtrAssignment; | ||||
|     SWITCH_CASE(USBRQ_GET_CONFIGURATION)    /* 8 */ | ||||
|         dataPtr = &usbConfiguration;  /* send current configuration value */ | ||||
|         len = 1; | ||||
|     SWITCH_CASE(USBRQ_SET_CONFIGURATION)    /* 9 */ | ||||
|         usbConfiguration = value; | ||||
|         usbResetStall(); | ||||
|     SWITCH_CASE(USBRQ_GET_INTERFACE)        /* 10 */ | ||||
|         len = 1; | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE | ||||
|     SWITCH_CASE(USBRQ_SET_INTERFACE)        /* 11 */ | ||||
|         usbResetDataToggling(); | ||||
|         usbResetStall(); | ||||
| #endif | ||||
|     SWITCH_DEFAULT                          /* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */ | ||||
|         /* Should we add an optional hook here? */ | ||||
|     SWITCH_END | ||||
|     usbMsgPtr = (usbMsgPtr_t)dataPtr; | ||||
| skipMsgPtrAssignment: | ||||
|     return len; | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| /* usbProcessRx() is called for every message received by the interrupt | ||||
|  * routine. It distinguishes between SETUP and DATA packets and processes | ||||
|  * them accordingly. | ||||
|  */ | ||||
| static inline void usbProcessRx(uchar *data, uchar len) | ||||
| { | ||||
| usbRequest_t    *rq = (void *)data; | ||||
|  | ||||
| /* usbRxToken can be: | ||||
|  * 0x2d 00101101 (USBPID_SETUP for setup data) | ||||
|  * 0xe1 11100001 (USBPID_OUT: data phase of setup transfer) | ||||
|  * 0...0x0f for OUT on endpoint X | ||||
|  */ | ||||
|     DBG2(0x10 + (usbRxToken & 0xf), data, len + 2); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */ | ||||
|     USB_RX_USER_HOOK(data, len) | ||||
| #if USB_CFG_IMPLEMENT_FN_WRITEOUT | ||||
|     if(usbRxToken < 0x10){  /* OUT to endpoint != 0: endpoint number in usbRxToken */ | ||||
|         usbFunctionWriteOut(data, len); | ||||
|         return; | ||||
|     } | ||||
| #endif | ||||
|     if(usbRxToken == (uchar)USBPID_SETUP){ | ||||
|         if(len != 8)    /* Setup size must be always 8 bytes. Ignore otherwise. */ | ||||
|             return; | ||||
|         usbMsgLen_t replyLen; | ||||
|         usbTxBuf[0] = USBPID_DATA0;         /* initialize data toggling */ | ||||
|         usbTxLen = USBPID_NAK;              /* abort pending transmit */ | ||||
|         usbMsgFlags = 0; | ||||
|         uchar type = rq->bmRequestType & USBRQ_TYPE_MASK; | ||||
|         if(type != USBRQ_TYPE_STANDARD){    /* standard requests are handled by driver */ | ||||
|             replyLen = usbFunctionSetup(data); | ||||
|         }else{ | ||||
|             replyLen = usbDriverSetup(rq); | ||||
|         } | ||||
| #if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE | ||||
|         if(replyLen == USB_NO_MSG){         /* use user-supplied read/write function */ | ||||
|             /* do some conditioning on replyLen, but on IN transfers only */ | ||||
|             if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){ | ||||
|                 if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */ | ||||
|                     replyLen = rq->wLength.bytes[0]; | ||||
|                 }else{ | ||||
|                     replyLen = rq->wLength.word; | ||||
|                 } | ||||
|             } | ||||
|             usbMsgFlags = USB_FLG_USE_USER_RW; | ||||
|         }else   /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */ | ||||
| #endif | ||||
|         if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */ | ||||
|             if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0])    /* limit length to max */ | ||||
|                 replyLen = rq->wLength.bytes[0]; | ||||
|         }else{ | ||||
|             if(replyLen > rq->wLength.word)     /* limit length to max */ | ||||
|                 replyLen = rq->wLength.word; | ||||
|         } | ||||
|         usbMsgLen = replyLen; | ||||
|     }else{  /* usbRxToken must be USBPID_OUT, which means data phase of setup (control-out) */ | ||||
| #if USB_CFG_IMPLEMENT_FN_WRITE | ||||
|         if(usbMsgFlags & USB_FLG_USE_USER_RW){ | ||||
|             uchar rval = usbFunctionWrite(data, len); | ||||
|             if(rval == 0xff){   /* an error occurred */ | ||||
|                 usbTxLen = USBPID_STALL; | ||||
|             }else if(rval != 0){    /* This was the final package */ | ||||
|                 usbMsgLen = 0;  /* answer with a zero-sized data packet */ | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| /* This function is similar to usbFunctionRead(), but it's also called for | ||||
|  * data handled automatically by the driver (e.g. descriptor reads). | ||||
|  */ | ||||
| static uchar usbDeviceRead(uchar *data, uchar len) | ||||
| { | ||||
|     if(len > 0){    /* don't bother app with 0 sized reads */ | ||||
| #if USB_CFG_IMPLEMENT_FN_READ | ||||
|         if(usbMsgFlags & USB_FLG_USE_USER_RW){ | ||||
|             len = usbFunctionRead(data, len); | ||||
|         }else | ||||
| #endif | ||||
|         { | ||||
|             uchar i = len; | ||||
|             usbMsgPtr_t r = usbMsgPtr; | ||||
|             if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){    /* ROM data */ | ||||
|                 do{ | ||||
|                     uchar c = USB_READ_FLASH(r);    /* assign to char size variable to enforce byte ops */ | ||||
|                     *data++ = c; | ||||
|                     r++; | ||||
|                 }while(--i); | ||||
|             }else{  /* RAM data */ | ||||
|                 do{ | ||||
|                     *data++ = *((uchar *)r); | ||||
|                     r++; | ||||
|                 }while(--i); | ||||
|             } | ||||
|             usbMsgPtr = r; | ||||
|         } | ||||
|     } | ||||
|     return len; | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| /* usbBuildTxBlock() is called when we have data to transmit and the | ||||
|  * interrupt routine's transmit buffer is empty. | ||||
|  */ | ||||
| static inline void usbBuildTxBlock(void) | ||||
| { | ||||
| usbMsgLen_t wantLen; | ||||
| uchar       len; | ||||
|  | ||||
|     wantLen = usbMsgLen; | ||||
|     if(wantLen > 8) | ||||
|         wantLen = 8; | ||||
|     usbMsgLen -= wantLen; | ||||
|     usbTxBuf[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* DATA toggling */ | ||||
|     len = usbDeviceRead(usbTxBuf + 1, wantLen); | ||||
|     if(len <= 8){           /* valid data packet */ | ||||
|         usbCrc16Append(&usbTxBuf[1], len); | ||||
|         len += 4;           /* length including sync byte */ | ||||
|         if(len < 12)        /* a partial package identifies end of message */ | ||||
|             usbMsgLen = USB_NO_MSG; | ||||
|     }else{ | ||||
|         len = USBPID_STALL;   /* stall the endpoint */ | ||||
|         usbMsgLen = USB_NO_MSG; | ||||
|     } | ||||
|     usbTxLen = len; | ||||
|     DBG2(0x20, usbTxBuf, len-1); | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| static inline void usbHandleResetHook(uchar notResetState) | ||||
| { | ||||
| #ifdef USB_RESET_HOOK | ||||
| static uchar    wasReset; | ||||
| uchar           isReset = !notResetState; | ||||
|  | ||||
|     if(wasReset != isReset){ | ||||
|         USB_RESET_HOOK(isReset); | ||||
|         wasReset = isReset; | ||||
|     } | ||||
| #else | ||||
|     notResetState = notResetState;  // avoid compiler warning | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| USB_PUBLIC void usbPoll(void) | ||||
| { | ||||
| schar   len; | ||||
| uchar   i; | ||||
|  | ||||
|     len = usbRxLen - 3; | ||||
|     if(len >= 0){ | ||||
| /* We could check CRC16 here -- but ACK has already been sent anyway. If you | ||||
|  * need data integrity checks with this driver, check the CRC in your app | ||||
|  * code and report errors back to the host. Since the ACK was already sent, | ||||
|  * retries must be handled on application level. | ||||
|  * unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3); | ||||
|  */ | ||||
|         usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len); | ||||
| #if USB_CFG_HAVE_FLOWCONTROL | ||||
|         if(usbRxLen > 0)    /* only mark as available if not inactivated */ | ||||
|             usbRxLen = 0; | ||||
| #else | ||||
|         usbRxLen = 0;       /* mark rx buffer as available */ | ||||
| #endif | ||||
|     } | ||||
|     if(usbTxLen & 0x10){    /* transmit system idle */ | ||||
|         if(usbMsgLen != USB_NO_MSG){    /* transmit data pending? */ | ||||
|             usbBuildTxBlock(); | ||||
|         } | ||||
|     } | ||||
|     for(i = 20; i > 0; i--){ | ||||
|         uchar usbLineStatus = USBIN & USBMASK; | ||||
|         if(usbLineStatus != 0)  /* SE0 has ended */ | ||||
|             goto isNotReset; | ||||
|     } | ||||
|     /* RESET condition, called multiple times during reset */ | ||||
|     usbNewDeviceAddr = 0; | ||||
|     usbDeviceAddr = 0; | ||||
|     usbResetStall(); | ||||
|     DBG1(0xff, 0, 0); | ||||
| isNotReset: | ||||
|     usbHandleResetHook(i); | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| USB_PUBLIC void usbInit(void) | ||||
| { | ||||
| #if USB_INTR_CFG_SET != 0 | ||||
|     USB_INTR_CFG |= USB_INTR_CFG_SET; | ||||
| #endif | ||||
| #if USB_INTR_CFG_CLR != 0 | ||||
|     USB_INTR_CFG &= ~(USB_INTR_CFG_CLR); | ||||
| #endif | ||||
|     USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); | ||||
|     usbResetDataToggling(); | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE | ||||
|     usbTxLen1 = USBPID_NAK; | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT3 | ||||
|     usbTxLen3 = USBPID_NAK; | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
							
								
								
									
										770
									
								
								usbdrv/usbdrv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										770
									
								
								usbdrv/usbdrv.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,770 @@ | ||||
| /* Name: usbdrv.h | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2004-12-29 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| #ifndef __usbdrv_h_included__ | ||||
| #define __usbdrv_h_included__ | ||||
|  | ||||
| /* | ||||
| Hardware Prerequisites: | ||||
| ======================= | ||||
| USB lines D+ and D- MUST be wired to the same I/O port. We recommend that D+ | ||||
| triggers the interrupt (best achieved by using INT0 for D+), but it is also | ||||
| possible to trigger the interrupt from D-. If D- is used, interrupts are also | ||||
| triggered by SOF packets. D- requires a pull-up of 1.5k to +3.5V (and the | ||||
| device must be powered at 3.5V) to identify as low-speed USB device. A | ||||
| pull-down or pull-up of 1M SHOULD be connected from D+ to +3.5V to prevent | ||||
| interference when no USB master is connected. If you use Zener diodes to limit | ||||
| the voltage on D+ and D-, you MUST use a pull-down resistor, not a pull-up. | ||||
| We use D+ as interrupt source and not D- because it does not trigger on | ||||
| keep-alive and RESET states. If you want to count keep-alive events with | ||||
| USB_COUNT_SOF, you MUST use D- as an interrupt source. | ||||
|  | ||||
| As a compile time option, the 1.5k pull-up resistor on D- can be made | ||||
| switchable to allow the device to disconnect at will. See the definition of | ||||
| usbDeviceConnect() and usbDeviceDisconnect() further down in this file. | ||||
|  | ||||
| Please adapt the values in usbconfig.h according to your hardware! | ||||
|  | ||||
| The device MUST be clocked at exactly 12 MHz, 15 MHz, 16 MHz or 20 MHz | ||||
| or at 12.8 MHz resp. 16.5 MHz +/- 1%. See usbconfig-prototype.h for details. | ||||
|  | ||||
|  | ||||
| Limitations: | ||||
| ============ | ||||
| Robustness with respect to communication errors: | ||||
| The driver assumes error-free communication. It DOES check for errors in | ||||
| the PID, but does NOT check bit stuffing errors, SE0 in middle of a byte, | ||||
| token CRC (5 bit) and data CRC (16 bit). CRC checks can not be performed due | ||||
| to timing constraints: We must start sending a reply within 7 bit times. | ||||
| Bit stuffing and misplaced SE0 would have to be checked in real-time, but CPU | ||||
| performance does not permit that. The driver does not check Data0/Data1 | ||||
| toggling, but application software can implement the check. | ||||
|  | ||||
| Input characteristics: | ||||
| Since no differential receiver circuit is used, electrical interference | ||||
| robustness may suffer. The driver samples only one of the data lines with | ||||
| an ordinary I/O pin's input characteristics. However, since this is only a | ||||
| low speed USB implementation and the specification allows for 8 times the | ||||
| bit rate over the same hardware, we should be on the safe side. Even the spec | ||||
| requires detection of asymmetric states at high bit rate for SE0 detection. | ||||
|  | ||||
| Number of endpoints: | ||||
| The driver supports the following endpoints: | ||||
|  | ||||
| - Endpoint 0, the default control endpoint. | ||||
| - Any number of interrupt- or bulk-out endpoints. The data is sent to | ||||
|   usbFunctionWriteOut() and USB_CFG_IMPLEMENT_FN_WRITEOUT must be defined | ||||
|   to 1 to activate this feature. The endpoint number can be found in the | ||||
|   global variable 'usbRxToken'. | ||||
| - One default interrupt- or bulk-in endpoint. This endpoint is used for | ||||
|   interrupt- or bulk-in transfers which are not handled by any other endpoint. | ||||
|   You must define USB_CFG_HAVE_INTRIN_ENDPOINT in order to activate this | ||||
|   feature and call usbSetInterrupt() to send interrupt/bulk data. | ||||
| - One additional interrupt- or bulk-in endpoint. This was endpoint 3 in | ||||
|   previous versions of this driver but can now be configured to any endpoint | ||||
|   number. You must define USB_CFG_HAVE_INTRIN_ENDPOINT3 in order to activate | ||||
|   this feature and call usbSetInterrupt3() to send interrupt/bulk data. The | ||||
|   endpoint number can be set with USB_CFG_EP3_NUMBER. | ||||
|  | ||||
| Please note that the USB standard forbids bulk endpoints for low speed devices! | ||||
| Most operating systems allow them anyway, but the AVR will spend 90% of the CPU | ||||
| time in the USB interrupt polling for bulk data. | ||||
|  | ||||
| Maximum data payload: | ||||
| Data payload of control in and out transfers may be up to 254 bytes. In order | ||||
| to accept payload data of out transfers, you need to implement | ||||
| 'usbFunctionWrite()'. | ||||
|  | ||||
| USB Suspend Mode supply current: | ||||
| The USB standard limits power consumption to 500uA when the bus is in suspend | ||||
| mode. This is not a problem for self-powered devices since they don't need | ||||
| bus power anyway. Bus-powered devices can achieve this only by putting the | ||||
| CPU in sleep mode. The driver does not implement suspend handling by itself. | ||||
| However, the application may implement activity monitoring and wakeup from | ||||
| sleep. The host sends regular SE0 states on the bus to keep it active. These | ||||
| SE0 states can be detected by using D- as the interrupt source. Define | ||||
| USB_COUNT_SOF to 1 and use the global variable usbSofCount to check for bus | ||||
| activity. | ||||
|  | ||||
| Operation without an USB master: | ||||
| The driver behaves neutral without connection to an USB master if D- reads | ||||
| as 1. To avoid spurious interrupts, we recommend a high impedance (e.g. 1M) | ||||
| pull-down or pull-up resistor on D+ (interrupt). If Zener diodes are used, | ||||
| use a pull-down. If D- becomes statically 0, the driver may block in the | ||||
| interrupt routine. | ||||
|  | ||||
| Interrupt latency: | ||||
| The application must ensure that the USB interrupt is not disabled for more | ||||
| than 25 cycles (this is for 12 MHz, faster clocks allow longer latency). | ||||
| This implies that all interrupt routines must either have the "ISR_NOBLOCK" | ||||
| attribute set (see "avr/interrupt.h") or be written in assembler with "sei" | ||||
| as the first instruction. | ||||
|  | ||||
| Maximum interrupt duration / CPU cycle consumption: | ||||
| The driver handles all USB communication during the interrupt service | ||||
| routine. The routine will not return before an entire USB message is received | ||||
| and the reply is sent. This may be up to ca. 1200 cycles @ 12 MHz (= 100us) if | ||||
| the host conforms to the standard. The driver will consume CPU cycles for all | ||||
| USB messages, even if they address another (low-speed) device on the same bus. | ||||
|  | ||||
| */ | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| // This header should be included as C-header from C++ code. However if usbdrv.c | ||||
| // is incorporated into a C++ module with an include, function names are mangled | ||||
| // and this header must be parsed as C++ header, too. External modules should be | ||||
| // treated as C, though, because they are compiled separately as C code. | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #include "usbconfig.h" | ||||
| #include "usbportability.h" | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| /* --------------------------- Module Interface ---------------------------- */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| #define USBDRV_VERSION  20121206 | ||||
| /* This define uniquely identifies a driver version. It is a decimal number | ||||
|  * constructed from the driver's release date in the form YYYYMMDD. If the | ||||
|  * driver's behavior or interface changes, you can use this constant to | ||||
|  * distinguish versions. If it is not defined, the driver's release date is | ||||
|  * older than 2006-01-25. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #ifndef USB_PUBLIC | ||||
| #define USB_PUBLIC | ||||
| #endif | ||||
| /* USB_PUBLIC is used as declaration attribute for all functions exported by | ||||
|  * the USB driver. The default is no attribute (see above). You may define it | ||||
|  * to static either in usbconfig.h or from the command line if you include | ||||
|  * usbdrv.c instead of linking against it. Including the C module of the driver | ||||
|  * directly in your code saves a couple of bytes in flash memory. | ||||
|  */ | ||||
|  | ||||
| #ifndef __ASSEMBLER__ | ||||
| #ifndef uchar | ||||
| #define uchar   unsigned char | ||||
| #endif | ||||
| #ifndef schar | ||||
| #define schar   signed char | ||||
| #endif | ||||
| /* shortcuts for well defined 8 bit integer types */ | ||||
|  | ||||
| #if USB_CFG_LONG_TRANSFERS  /* if more than 254 bytes transfer size required */ | ||||
| #   define usbMsgLen_t unsigned | ||||
| #else | ||||
| #   define usbMsgLen_t uchar | ||||
| #endif | ||||
| /* usbMsgLen_t is the data type used for transfer lengths. By default, it is | ||||
|  * defined to uchar, allowing a maximum of 254 bytes (255 is reserved for | ||||
|  * USB_NO_MSG below). If the usbconfig.h defines USB_CFG_LONG_TRANSFERS to 1, | ||||
|  * a 16 bit data type is used, allowing up to 16384 bytes (the rest is used | ||||
|  * for flags in the descriptor configuration). | ||||
|  */ | ||||
| #define USB_NO_MSG  ((usbMsgLen_t)-1)   /* constant meaning "no message" */ | ||||
|  | ||||
| #ifndef usbMsgPtr_t | ||||
| #define usbMsgPtr_t uchar * | ||||
| #endif | ||||
| /* Making usbMsgPtr_t a define allows the user of this library to define it to | ||||
|  * an 8 bit type on tiny devices. This reduces code size, especially if the | ||||
|  * compiler supports a tiny memory model. | ||||
|  * The type can be a pointer or scalar type, casts are made where necessary. | ||||
|  * Although it's paradoxical, Gcc 4 generates slightly better code for scalar | ||||
|  * types than for pointers. | ||||
|  */ | ||||
|  | ||||
| struct usbRequest;  /* forward declaration */ | ||||
|  | ||||
| USB_PUBLIC void usbInit(void); | ||||
| /* This function must be called before interrupts are enabled and the main | ||||
|  * loop is entered. We exepct that the PORT and DDR bits for D+ and D- have | ||||
|  * not been changed from their default status (which is 0). If you have changed | ||||
|  * them, set both back to 0 (configure them as input with no internal pull-up). | ||||
|  */ | ||||
| USB_PUBLIC void usbPoll(void); | ||||
| /* This function must be called at regular intervals from the main loop. | ||||
|  * Maximum delay between calls is somewhat less than 50ms (USB timeout for | ||||
|  * accepting a Setup message). Otherwise the device will not be recognized. | ||||
|  * Please note that debug outputs through the UART take ~ 0.5ms per byte | ||||
|  * at 19200 bps. | ||||
|  */ | ||||
| extern usbMsgPtr_t usbMsgPtr; | ||||
| /* This variable may be used to pass transmit data to the driver from the | ||||
|  * implementation of usbFunctionWrite(). It is also used internally by the | ||||
|  * driver for standard control requests. | ||||
|  */ | ||||
|  | ||||
| extern uchar usbMsgFlags;    /* flag values see USB_FLG_* */ | ||||
| /* Can be set to `USB_FLG_MSGPTR_IS_ROM` in `usbFunctionSetup()` or | ||||
|  * `usbFunctionDescriptor()` if `usbMsgPtr` has been set to a flash memory | ||||
|  * address. | ||||
|  */ | ||||
|  | ||||
| #define USB_FLG_MSGPTR_IS_ROM   (1<<6) | ||||
|  | ||||
| USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]); | ||||
| /* This function is called when the driver receives a SETUP transaction from | ||||
|  * the host which is not answered by the driver itself (in practice: class and | ||||
|  * vendor requests). All control transfers start with a SETUP transaction where | ||||
|  * the host communicates the parameters of the following (optional) data | ||||
|  * transfer. The SETUP data is available in the 'data' parameter which can | ||||
|  * (and should) be casted to 'usbRequest_t *' for a more user-friendly access | ||||
|  * to parameters. | ||||
|  * | ||||
|  * If the SETUP indicates a control-in transfer, you should provide the | ||||
|  * requested data to the driver. There are two ways to transfer this data: | ||||
|  * (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data | ||||
|  * block and return the length of the data in 'usbFunctionSetup()'. The driver | ||||
|  * will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The | ||||
|  * driver will then call 'usbFunctionRead()' when data is needed. See the | ||||
|  * documentation for usbFunctionRead() for details. | ||||
|  * | ||||
|  * If the SETUP indicates a control-out transfer, the only way to receive the | ||||
|  * data from the host is through the 'usbFunctionWrite()' call. If you | ||||
|  * implement this function, you must return USB_NO_MSG in 'usbFunctionSetup()' | ||||
|  * to indicate that 'usbFunctionWrite()' should be used. See the documentation | ||||
|  * of this function for more information. If you just want to ignore the data | ||||
|  * sent by the host, return 0 in 'usbFunctionSetup()'. | ||||
|  * | ||||
|  * Note that calls to the functions usbFunctionRead() and usbFunctionWrite() | ||||
|  * are only done if enabled by the configuration in usbconfig.h. | ||||
|  */ | ||||
| USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq); | ||||
| /* You need to implement this function ONLY if you provide USB descriptors at | ||||
|  * runtime (which is an expert feature). It is very similar to | ||||
|  * usbFunctionSetup() above, but it is called only to request USB descriptor | ||||
|  * data. See the documentation of usbFunctionSetup() above for more info. | ||||
|  */ | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT | ||||
| USB_PUBLIC void usbSetInterrupt(uchar *data, uchar len); | ||||
| /* This function sets the message which will be sent during the next interrupt | ||||
|  * IN transfer. The message is copied to an internal buffer and must not exceed | ||||
|  * a length of 8 bytes. The message may be 0 bytes long just to indicate the | ||||
|  * interrupt status to the host. | ||||
|  * If you need to transfer more bytes, use a control read after the interrupt. | ||||
|  */ | ||||
| #define usbInterruptIsReady()   (usbTxLen1 & 0x10) | ||||
| /* This macro indicates whether the last interrupt message has already been | ||||
|  * sent. If you set a new interrupt message before the old was sent, the | ||||
|  * message already buffered will be lost. | ||||
|  */ | ||||
| #if USB_CFG_HAVE_INTRIN_ENDPOINT3 | ||||
| USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len); | ||||
| #define usbInterruptIsReady3()   (usbTxLen3 & 0x10) | ||||
| /* Same as above for endpoint 3 */ | ||||
| #endif | ||||
| #endif /* USB_CFG_HAVE_INTRIN_ENDPOINT */ | ||||
| #if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    /* simplified interface for backward compatibility */ | ||||
| #define usbHidReportDescriptor  usbDescriptorHidReport | ||||
| /* should be declared as: PROGMEM char usbHidReportDescriptor[]; */ | ||||
| /* If you implement an HID device, you need to provide a report descriptor. | ||||
|  * The HID report descriptor syntax is a bit complex. If you understand how | ||||
|  * report descriptors are constructed, we recommend that you use the HID | ||||
|  * Descriptor Tool from usb.org, see http://www.usb.org/developers/hidpage/. | ||||
|  * Otherwise you should probably start with a working example. | ||||
|  */ | ||||
| #endif  /* USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH */ | ||||
| #if USB_CFG_IMPLEMENT_FN_WRITE | ||||
| USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len); | ||||
| /* This function is called by the driver to provide a control transfer's | ||||
|  * payload data (control-out). It is called in chunks of up to 8 bytes. The | ||||
|  * total count provided in the current control transfer can be obtained from | ||||
|  * the 'length' property in the setup data. If an error occurred during | ||||
|  * processing, return 0xff (== -1). The driver will answer the entire transfer | ||||
|  * with a STALL token in this case. If you have received the entire payload | ||||
|  * successfully, return 1. If you expect more data, return 0. If you don't | ||||
|  * know whether the host will send more data (you should know, the total is | ||||
|  * provided in the usbFunctionSetup() call!), return 1. | ||||
|  * NOTE: If you return 0xff for STALL, 'usbFunctionWrite()' may still be called | ||||
|  * for the remaining data. You must continue to return 0xff for STALL in these | ||||
|  * calls. | ||||
|  * In order to get usbFunctionWrite() called, define USB_CFG_IMPLEMENT_FN_WRITE | ||||
|  * to 1 in usbconfig.h and return 0xff in usbFunctionSetup().. | ||||
|  */ | ||||
| #endif /* USB_CFG_IMPLEMENT_FN_WRITE */ | ||||
| #if USB_CFG_IMPLEMENT_FN_READ | ||||
| USB_PUBLIC uchar usbFunctionRead(uchar *data, uchar len); | ||||
| /* This function is called by the driver to ask the application for a control | ||||
|  * transfer's payload data (control-in). It is called in chunks of up to 8 | ||||
|  * bytes each. You should copy the data to the location given by 'data' and | ||||
|  * return the actual number of bytes copied. If you return less than requested, | ||||
|  * the control-in transfer is terminated. If you return 0xff, the driver aborts | ||||
|  * the transfer with a STALL token. | ||||
|  * In order to get usbFunctionRead() called, define USB_CFG_IMPLEMENT_FN_READ | ||||
|  * to 1 in usbconfig.h and return 0xff in usbFunctionSetup().. | ||||
|  */ | ||||
| #endif /* USB_CFG_IMPLEMENT_FN_READ */ | ||||
|  | ||||
| extern uchar usbRxToken;    /* may be used in usbFunctionWriteOut() below */ | ||||
| #if USB_CFG_IMPLEMENT_FN_WRITEOUT | ||||
| USB_PUBLIC void usbFunctionWriteOut(uchar *data, uchar len); | ||||
| /* This function is called by the driver when data is received on an interrupt- | ||||
|  * or bulk-out endpoint. The endpoint number can be found in the global | ||||
|  * variable usbRxToken. You must define USB_CFG_IMPLEMENT_FN_WRITEOUT to 1 in | ||||
|  * usbconfig.h to get this function called. | ||||
|  */ | ||||
| #endif /* USB_CFG_IMPLEMENT_FN_WRITEOUT */ | ||||
| #ifdef USB_CFG_PULLUP_IOPORTNAME | ||||
| #define usbDeviceConnect()      ((USB_PULLUP_DDR |= (1<<USB_CFG_PULLUP_BIT)), \ | ||||
|                                   (USB_PULLUP_OUT |= (1<<USB_CFG_PULLUP_BIT))) | ||||
| #define usbDeviceDisconnect()   ((USB_PULLUP_DDR &= ~(1<<USB_CFG_PULLUP_BIT)), \ | ||||
|                                   (USB_PULLUP_OUT &= ~(1<<USB_CFG_PULLUP_BIT))) | ||||
| #else /* USB_CFG_PULLUP_IOPORTNAME */ | ||||
| #define usbDeviceConnect()      (USBDDR &= ~(1<<USBMINUS)) | ||||
| #define usbDeviceDisconnect()   (USBDDR |= (1<<USBMINUS)) | ||||
| #endif /* USB_CFG_PULLUP_IOPORTNAME */ | ||||
| /* The macros usbDeviceConnect() and usbDeviceDisconnect() (intended to look | ||||
|  * like a function) connect resp. disconnect the device from the host's USB. | ||||
|  * If the constants USB_CFG_PULLUP_IOPORT and USB_CFG_PULLUP_BIT are defined | ||||
|  * in usbconfig.h, a disconnect consists of removing the pull-up resisitor | ||||
|  * from D-, otherwise the disconnect is done by brute-force pulling D- to GND. | ||||
|  * This does not conform to the spec, but it works. | ||||
|  * Please note that the USB interrupt must be disabled while the device is | ||||
|  * in disconnected state, or the interrupt handler will hang! You can either | ||||
|  * turn off the USB interrupt selectively with | ||||
|  *     USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT) | ||||
|  * or use cli() to disable interrupts globally. | ||||
|  */ | ||||
| extern unsigned usbCrc16(unsigned data, uchar len); | ||||
| #define usbCrc16(data, len) usbCrc16((unsigned)(data), len) | ||||
| /* This function calculates the binary complement of the data CRC used in | ||||
|  * USB data packets. The value is used to build raw transmit packets. | ||||
|  * You may want to use this function for data checksums or to verify received | ||||
|  * data. We enforce 16 bit calling conventions for compatibility with IAR's | ||||
|  * tiny memory model. | ||||
|  */ | ||||
| extern unsigned usbCrc16Append(unsigned data, uchar len); | ||||
| #define usbCrc16Append(data, len)    usbCrc16Append((unsigned)(data), len) | ||||
| /* This function is equivalent to usbCrc16() above, except that it appends | ||||
|  * the 2 bytes CRC (lowbyte first) in the 'data' buffer after reading 'len' | ||||
|  * bytes. | ||||
|  */ | ||||
| #if USB_CFG_HAVE_MEASURE_FRAME_LENGTH | ||||
| extern unsigned usbMeasureFrameLength(void); | ||||
| /* This function MUST be called IMMEDIATELY AFTER USB reset and measures 1/7 of | ||||
|  * the number of CPU cycles during one USB frame minus one low speed bit | ||||
|  * length. In other words: return value = 1499 * (F_CPU / 10.5 MHz) | ||||
|  * Since this is a busy wait, you MUST disable all interrupts with cli() before | ||||
|  * calling this function. | ||||
|  * This can be used to calibrate the AVR's RC oscillator. | ||||
|  */ | ||||
| #endif | ||||
| extern uchar    usbConfiguration; | ||||
| /* This value contains the current configuration set by the host. The driver | ||||
|  * allows setting and querying of this variable with the USB SET_CONFIGURATION | ||||
|  * and GET_CONFIGURATION requests, but does not use it otherwise. | ||||
|  * You may want to reflect the "configured" status with a LED on the device or | ||||
|  * switch on high power parts of the circuit only if the device is configured. | ||||
|  */ | ||||
| #if USB_COUNT_SOF | ||||
| extern volatile uchar   usbSofCount; | ||||
| /* This variable is incremented on every SOF packet. It is only available if | ||||
|  * the macro USB_COUNT_SOF is defined to a value != 0. | ||||
|  */ | ||||
| #endif | ||||
| #if USB_CFG_CHECK_DATA_TOGGLING | ||||
| extern uchar    usbCurrentDataToken; | ||||
| /* This variable can be checked in usbFunctionWrite() and usbFunctionWriteOut() | ||||
|  * to ignore duplicate packets. | ||||
|  */ | ||||
| #endif | ||||
|  | ||||
| #define USB_STRING_DESCRIPTOR_HEADER(stringLength) ((2*(stringLength)+2) | (3<<8)) | ||||
| /* This macro builds a descriptor header for a string descriptor given the | ||||
|  * string's length. See usbdrv.c for an example how to use it. | ||||
|  */ | ||||
| #if USB_CFG_HAVE_FLOWCONTROL | ||||
| extern volatile schar   usbRxLen; | ||||
| #define usbDisableAllRequests()     usbRxLen = -1 | ||||
| /* Must be called from usbFunctionWrite(). This macro disables all data input | ||||
|  * from the USB interface. Requests from the host are answered with a NAK | ||||
|  * while they are disabled. | ||||
|  */ | ||||
| #define usbEnableAllRequests()      usbRxLen = 0 | ||||
| /* May only be called if requests are disabled. This macro enables input from | ||||
|  * the USB interface after it has been disabled with usbDisableAllRequests(). | ||||
|  */ | ||||
| #define usbAllRequestsAreDisabled() (usbRxLen < 0) | ||||
| /* Use this macro to find out whether requests are disabled. It may be needed | ||||
|  * to ensure that usbEnableAllRequests() is never called when requests are | ||||
|  * enabled. | ||||
|  */ | ||||
| #endif | ||||
|  | ||||
| #define USB_SET_DATATOKEN1(token)   usbTxBuf1[0] = token | ||||
| #define USB_SET_DATATOKEN3(token)   usbTxBuf3[0] = token | ||||
| /* These two macros can be used by application software to reset data toggling | ||||
|  * for interrupt-in endpoints 1 and 3. Since the token is toggled BEFORE | ||||
|  * sending data, you must set the opposite value of the token which should come | ||||
|  * first. | ||||
|  */ | ||||
|  | ||||
| #endif  /* __ASSEMBLER__ */ | ||||
|  | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| /* ----------------- Definitions for Descriptor Properties ----------------- */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| /* This is advanced stuff. See usbconfig-prototype.h for more information | ||||
|  * about the various methods to define USB descriptors. If you do nothing, | ||||
|  * the default descriptors will be used. | ||||
|  */ | ||||
| #define USB_PROP_IS_DYNAMIC     (1u << 14) | ||||
| /* If this property is set for a descriptor, usbFunctionDescriptor() will be | ||||
|  * used to obtain the particular descriptor. Data directly returned via | ||||
|  * usbMsgPtr are FLASH data by default, combine (OR) with USB_PROP_IS_RAM to | ||||
|  * return RAM data. | ||||
|  */ | ||||
| #define USB_PROP_IS_RAM         (1u << 15) | ||||
| /* If this property is set for a descriptor, the data is read from RAM | ||||
|  * memory instead of Flash. The property is used for all methods to provide | ||||
|  * external descriptors. | ||||
|  */ | ||||
| #define USB_PROP_LENGTH(len)    ((len) & 0x3fff) | ||||
| /* If a static external descriptor is used, this is the total length of the | ||||
|  * descriptor in bytes. | ||||
|  */ | ||||
|  | ||||
| /* all descriptors which may have properties: */ | ||||
| #ifndef USB_CFG_DESCR_PROPS_DEVICE | ||||
| #define USB_CFG_DESCR_PROPS_DEVICE                  0 | ||||
| #endif | ||||
| #ifndef USB_CFG_DESCR_PROPS_CONFIGURATION | ||||
| #define USB_CFG_DESCR_PROPS_CONFIGURATION           0 | ||||
| #endif | ||||
| #ifndef USB_CFG_DESCR_PROPS_STRINGS | ||||
| #define USB_CFG_DESCR_PROPS_STRINGS                 0 | ||||
| #endif | ||||
| #ifndef USB_CFG_DESCR_PROPS_STRING_0 | ||||
| #define USB_CFG_DESCR_PROPS_STRING_0                0 | ||||
| #endif | ||||
| #ifndef USB_CFG_DESCR_PROPS_STRING_VENDOR | ||||
| #define USB_CFG_DESCR_PROPS_STRING_VENDOR           0 | ||||
| #endif | ||||
| #ifndef USB_CFG_DESCR_PROPS_STRING_PRODUCT | ||||
| #define USB_CFG_DESCR_PROPS_STRING_PRODUCT          0 | ||||
| #endif | ||||
| #ifndef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER | ||||
| #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    0 | ||||
| #endif | ||||
| #ifndef USB_CFG_DESCR_PROPS_HID | ||||
| #define USB_CFG_DESCR_PROPS_HID                     0 | ||||
| #endif | ||||
| #if !(USB_CFG_DESCR_PROPS_HID_REPORT) | ||||
| #   undef USB_CFG_DESCR_PROPS_HID_REPORT | ||||
| #   if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH /* do some backward compatibility tricks */ | ||||
| #       define USB_CFG_DESCR_PROPS_HID_REPORT       USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH | ||||
| #   else | ||||
| #       define USB_CFG_DESCR_PROPS_HID_REPORT       0 | ||||
| #   endif | ||||
| #endif | ||||
| #ifndef USB_CFG_DESCR_PROPS_UNKNOWN | ||||
| #define USB_CFG_DESCR_PROPS_UNKNOWN                 0 | ||||
| #endif | ||||
|  | ||||
| /* ------------------ forward declaration of descriptors ------------------- */ | ||||
| /* If you use external static descriptors, they must be stored in global | ||||
|  * arrays as declared below: | ||||
|  */ | ||||
| #ifndef __ASSEMBLER__ | ||||
| extern | ||||
| #if !(USB_CFG_DESCR_PROPS_DEVICE & USB_PROP_IS_RAM) | ||||
| PROGMEM const | ||||
| #endif | ||||
| char usbDescriptorDevice[]; | ||||
|  | ||||
| extern | ||||
| #if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_RAM) | ||||
| PROGMEM const | ||||
| #endif | ||||
| char usbDescriptorConfiguration[]; | ||||
|  | ||||
| extern | ||||
| #if !(USB_CFG_DESCR_PROPS_HID_REPORT & USB_PROP_IS_RAM) | ||||
| PROGMEM const | ||||
| #endif | ||||
| char usbDescriptorHidReport[]; | ||||
|  | ||||
| extern | ||||
| #if !(USB_CFG_DESCR_PROPS_STRING_0 & USB_PROP_IS_RAM) | ||||
| PROGMEM const | ||||
| #endif | ||||
| char usbDescriptorString0[]; | ||||
|  | ||||
| extern | ||||
| #if !(USB_CFG_DESCR_PROPS_STRING_VENDOR & USB_PROP_IS_RAM) | ||||
| PROGMEM const | ||||
| #endif | ||||
| int usbDescriptorStringVendor[]; | ||||
|  | ||||
| extern | ||||
| #if !(USB_CFG_DESCR_PROPS_STRING_PRODUCT & USB_PROP_IS_RAM) | ||||
| PROGMEM const | ||||
| #endif | ||||
| int usbDescriptorStringDevice[]; | ||||
|  | ||||
| extern | ||||
| #if !(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER & USB_PROP_IS_RAM) | ||||
| PROGMEM const | ||||
| #endif | ||||
| int usbDescriptorStringSerialNumber[]; | ||||
|  | ||||
| #endif /* __ASSEMBLER__ */ | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| /* ------------------------ General Purpose Macros ------------------------- */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| #define USB_CONCAT(a, b)            a ## b | ||||
| #define USB_CONCAT_EXPANDED(a, b)   USB_CONCAT(a, b) | ||||
|  | ||||
| #define USB_OUTPORT(name)           USB_CONCAT(PORT, name) | ||||
| #define USB_INPORT(name)            USB_CONCAT(PIN, name) | ||||
| #define USB_DDRPORT(name)           USB_CONCAT(DDR, name) | ||||
| /* The double-define trick above lets us concatenate strings which are | ||||
|  * defined by macros. | ||||
|  */ | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| /* ------------------------- Constant definitions -------------------------- */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| #if !defined __ASSEMBLER__ && (!defined USB_CFG_VENDOR_ID || !defined USB_CFG_DEVICE_ID) | ||||
| #warning "You should define USB_CFG_VENDOR_ID and USB_CFG_DEVICE_ID in usbconfig.h" | ||||
| /* If the user has not defined IDs, we default to obdev's free IDs. | ||||
|  * See USB-IDs-for-free.txt for details. | ||||
|  */ | ||||
| #endif | ||||
|  | ||||
| /* make sure we have a VID and PID defined, byte order is lowbyte, highbyte */ | ||||
| #ifndef USB_CFG_VENDOR_ID | ||||
| #   define  USB_CFG_VENDOR_ID   0xc0, 0x16  /* = 0x16c0 = 5824 = voti.nl */ | ||||
| #endif | ||||
|  | ||||
| #ifndef USB_CFG_DEVICE_ID | ||||
| #   if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH | ||||
| #       define USB_CFG_DEVICE_ID    0xdf, 0x05  /* = 0x5df = 1503, shared PID for HIDs */ | ||||
| #   elif USB_CFG_INTERFACE_CLASS == 2 | ||||
| #       define USB_CFG_DEVICE_ID    0xe1, 0x05  /* = 0x5e1 = 1505, shared PID for CDC Modems */ | ||||
| #   else | ||||
| #       define USB_CFG_DEVICE_ID    0xdc, 0x05  /* = 0x5dc = 1500, obdev's free PID */ | ||||
| #   endif | ||||
| #endif | ||||
|  | ||||
| /* Derive Output, Input and DataDirection ports from port names */ | ||||
| #ifndef USB_CFG_IOPORTNAME | ||||
| #error "You must define USB_CFG_IOPORTNAME in usbconfig.h, see usbconfig-prototype.h" | ||||
| #endif | ||||
|  | ||||
| #define USBOUT          USB_OUTPORT(USB_CFG_IOPORTNAME) | ||||
| #define USB_PULLUP_OUT  USB_OUTPORT(USB_CFG_PULLUP_IOPORTNAME) | ||||
| #define USBIN           USB_INPORT(USB_CFG_IOPORTNAME) | ||||
| #define USBDDR          USB_DDRPORT(USB_CFG_IOPORTNAME) | ||||
| #define USB_PULLUP_DDR  USB_DDRPORT(USB_CFG_PULLUP_IOPORTNAME) | ||||
|  | ||||
| #define USBMINUS    USB_CFG_DMINUS_BIT | ||||
| #define USBPLUS     USB_CFG_DPLUS_BIT | ||||
| #define USBIDLE     (1<<USB_CFG_DMINUS_BIT) /* value representing J state */ | ||||
| #define USBMASK     ((1<<USB_CFG_DPLUS_BIT) | (1<<USB_CFG_DMINUS_BIT))  /* mask for USB I/O bits */ | ||||
|  | ||||
| /* defines for backward compatibility with older driver versions: */ | ||||
| #define USB_CFG_IOPORT          USB_OUTPORT(USB_CFG_IOPORTNAME) | ||||
| #ifdef USB_CFG_PULLUP_IOPORTNAME | ||||
| #define USB_CFG_PULLUP_IOPORT   USB_OUTPORT(USB_CFG_PULLUP_IOPORTNAME) | ||||
| #endif | ||||
|  | ||||
| #ifndef USB_CFG_EP3_NUMBER  /* if not defined in usbconfig.h */ | ||||
| #define USB_CFG_EP3_NUMBER  3 | ||||
| #endif | ||||
|  | ||||
| #ifndef USB_CFG_HAVE_INTRIN_ENDPOINT3 | ||||
| #define USB_CFG_HAVE_INTRIN_ENDPOINT3   0 | ||||
| #endif | ||||
|  | ||||
| #define USB_BUFSIZE     11  /* PID, 8 bytes data, 2 bytes CRC */ | ||||
|  | ||||
| /* ----- Try to find registers and bits responsible for ext interrupt 0 ----- */ | ||||
|  | ||||
| #ifndef USB_INTR_CFG    /* allow user to override our default */ | ||||
| #   if defined  EICRA | ||||
| #       define USB_INTR_CFG EICRA | ||||
| #   else | ||||
| #       define USB_INTR_CFG MCUCR | ||||
| #   endif | ||||
| #endif | ||||
| #ifndef USB_INTR_CFG_SET    /* allow user to override our default */ | ||||
| #   if defined(USB_COUNT_SOF) || defined(USB_SOF_HOOK) | ||||
| #       define USB_INTR_CFG_SET (1 << ISC01)                    /* cfg for falling edge */ | ||||
|         /* If any SOF logic is used, the interrupt must be wired to D- where | ||||
|          * we better trigger on falling edge | ||||
|          */ | ||||
| #   else | ||||
| #       define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01))   /* cfg for rising edge */ | ||||
| #   endif | ||||
| #endif | ||||
| #ifndef USB_INTR_CFG_CLR    /* allow user to override our default */ | ||||
| #   define USB_INTR_CFG_CLR 0    /* no bits to clear */ | ||||
| #endif | ||||
|  | ||||
| #ifndef USB_INTR_ENABLE     /* allow user to override our default */ | ||||
| #   if defined GIMSK | ||||
| #       define USB_INTR_ENABLE  GIMSK | ||||
| #   elif defined EIMSK | ||||
| #       define USB_INTR_ENABLE  EIMSK | ||||
| #   else | ||||
| #       define USB_INTR_ENABLE  GICR | ||||
| #   endif | ||||
| #endif | ||||
| #ifndef USB_INTR_ENABLE_BIT /* allow user to override our default */ | ||||
| #   define USB_INTR_ENABLE_BIT  INT0 | ||||
| #endif | ||||
|  | ||||
| #ifndef USB_INTR_PENDING    /* allow user to override our default */ | ||||
| #   if defined  EIFR | ||||
| #       define USB_INTR_PENDING EIFR | ||||
| #   else | ||||
| #       define USB_INTR_PENDING GIFR | ||||
| #   endif | ||||
| #endif | ||||
| #ifndef USB_INTR_PENDING_BIT    /* allow user to override our default */ | ||||
| #   define USB_INTR_PENDING_BIT INTF0 | ||||
| #endif | ||||
|  | ||||
| /* | ||||
| The defines above don't work for the following chips | ||||
| at90c8534: no ISC0?, no PORTB, can't find a data sheet | ||||
| at86rf401: no PORTB, no MCUCR etc, low clock rate | ||||
| atmega103: no ISC0? (maybe omission in header, can't find data sheet) | ||||
| atmega603: not defined in avr-libc | ||||
| at43usb320, at43usb355, at76c711: have USB anyway | ||||
| at94k: is different... | ||||
|  | ||||
| at90s1200, attiny11, attiny12, attiny15, attiny28: these have no RAM | ||||
| */ | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| /* ----------------- USB Specification Constants and Types ----------------- */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| /* USB Token values */ | ||||
| #define USBPID_SETUP    0x2d | ||||
| #define USBPID_OUT      0xe1 | ||||
| #define USBPID_IN       0x69 | ||||
| #define USBPID_DATA0    0xc3 | ||||
| #define USBPID_DATA1    0x4b | ||||
|  | ||||
| #define USBPID_ACK      0xd2 | ||||
| #define USBPID_NAK      0x5a | ||||
| #define USBPID_STALL    0x1e | ||||
|  | ||||
| #ifndef USB_INITIAL_DATATOKEN | ||||
| #define USB_INITIAL_DATATOKEN   USBPID_DATA1 | ||||
| #endif | ||||
|  | ||||
| #ifndef __ASSEMBLER__ | ||||
|  | ||||
| typedef struct usbTxStatus{ | ||||
|     volatile uchar   len; | ||||
|     uchar   buffer[USB_BUFSIZE]; | ||||
| }usbTxStatus_t; | ||||
|  | ||||
| extern usbTxStatus_t   usbTxStatus1, usbTxStatus3; | ||||
| #define usbTxLen1   usbTxStatus1.len | ||||
| #define usbTxBuf1   usbTxStatus1.buffer | ||||
| #define usbTxLen3   usbTxStatus3.len | ||||
| #define usbTxBuf3   usbTxStatus3.buffer | ||||
|  | ||||
|  | ||||
| typedef union usbWord{ | ||||
|     unsigned    word; | ||||
|     uchar       bytes[2]; | ||||
| }usbWord_t; | ||||
|  | ||||
| typedef struct usbRequest{ | ||||
|     uchar       bmRequestType; | ||||
|     uchar       bRequest; | ||||
|     usbWord_t   wValue; | ||||
|     usbWord_t   wIndex; | ||||
|     usbWord_t   wLength; | ||||
| }usbRequest_t; | ||||
| /* This structure matches the 8 byte setup request */ | ||||
| #endif | ||||
|  | ||||
| /* bmRequestType field in USB setup: | ||||
|  * d t t r r r r r, where | ||||
|  * d ..... direction: 0=host->device, 1=device->host | ||||
|  * t ..... type: 0=standard, 1=class, 2=vendor, 3=reserved | ||||
|  * r ..... recipient: 0=device, 1=interface, 2=endpoint, 3=other | ||||
|  */ | ||||
|  | ||||
| /* USB setup recipient values */ | ||||
| #define USBRQ_RCPT_MASK         0x1f | ||||
| #define USBRQ_RCPT_DEVICE       0 | ||||
| #define USBRQ_RCPT_INTERFACE    1 | ||||
| #define USBRQ_RCPT_ENDPOINT     2 | ||||
|  | ||||
| /* USB request type values */ | ||||
| #define USBRQ_TYPE_MASK         0x60 | ||||
| #define USBRQ_TYPE_STANDARD     (0<<5) | ||||
| #define USBRQ_TYPE_CLASS        (1<<5) | ||||
| #define USBRQ_TYPE_VENDOR       (2<<5) | ||||
|  | ||||
| /* USB direction values: */ | ||||
| #define USBRQ_DIR_MASK              0x80 | ||||
| #define USBRQ_DIR_HOST_TO_DEVICE    (0<<7) | ||||
| #define USBRQ_DIR_DEVICE_TO_HOST    (1<<7) | ||||
|  | ||||
| /* USB Standard Requests */ | ||||
| #define USBRQ_GET_STATUS        0 | ||||
| #define USBRQ_CLEAR_FEATURE     1 | ||||
| #define USBRQ_SET_FEATURE       3 | ||||
| #define USBRQ_SET_ADDRESS       5 | ||||
| #define USBRQ_GET_DESCRIPTOR    6 | ||||
| #define USBRQ_SET_DESCRIPTOR    7 | ||||
| #define USBRQ_GET_CONFIGURATION 8 | ||||
| #define USBRQ_SET_CONFIGURATION 9 | ||||
| #define USBRQ_GET_INTERFACE     10 | ||||
| #define USBRQ_SET_INTERFACE     11 | ||||
| #define USBRQ_SYNCH_FRAME       12 | ||||
|  | ||||
| /* USB descriptor constants */ | ||||
| #define USBDESCR_DEVICE         1 | ||||
| #define USBDESCR_CONFIG         2 | ||||
| #define USBDESCR_STRING         3 | ||||
| #define USBDESCR_INTERFACE      4 | ||||
| #define USBDESCR_ENDPOINT       5 | ||||
| #define USBDESCR_HID            0x21 | ||||
| #define USBDESCR_HID_REPORT     0x22 | ||||
| #define USBDESCR_HID_PHYS       0x23 | ||||
|  | ||||
| //#define USBATTR_BUSPOWER        0x80  // USB 1.1 does not define this value any more | ||||
| #define USBATTR_BUSPOWER        0 | ||||
| #define USBATTR_SELFPOWER       0x40 | ||||
| #define USBATTR_REMOTEWAKE      0x20 | ||||
|  | ||||
| /* USB HID Requests */ | ||||
| #define USBRQ_HID_GET_REPORT    0x01 | ||||
| #define USBRQ_HID_GET_IDLE      0x02 | ||||
| #define USBRQ_HID_GET_PROTOCOL  0x03 | ||||
| #define USBRQ_HID_SET_REPORT    0x09 | ||||
| #define USBRQ_HID_SET_IDLE      0x0a | ||||
| #define USBRQ_HID_SET_PROTOCOL  0x0b | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| #endif /* __usbdrv_h_included__ */ | ||||
							
								
								
									
										
											BIN
										
									
								
								usbdrv/usbdrv.o
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								usbdrv/usbdrv.o
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										389
									
								
								usbdrv/usbdrvasm.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										389
									
								
								usbdrv/usbdrvasm.S
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,389 @@ | ||||
| /* Name: usbdrvasm.S | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2007-06-13 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This module is the assembler part of the USB driver. This file contains | ||||
| general code (preprocessor acrobatics and CRC computation) and then includes | ||||
| the file appropriate for the given clock rate. | ||||
| */ | ||||
|  | ||||
| #define __SFR_OFFSET 0      /* used by avr-libc's register definitions */ | ||||
| #include "usbportability.h" | ||||
| #include "usbdrv.h"         /* for common defs */ | ||||
|  | ||||
| /* register names */ | ||||
| #define x1      r16 | ||||
| #define x2      r17 | ||||
| #define shift   r18 | ||||
| #define cnt     r19 | ||||
| #define x3      r20 | ||||
| #define x4      r21 | ||||
| #define x5		r22 | ||||
| #define bitcnt  x5 | ||||
| #define phase   x4 | ||||
| #define leap    x4 | ||||
|  | ||||
| /* Some assembler dependent definitions and declarations: */ | ||||
|  | ||||
| #ifdef __IAR_SYSTEMS_ASM__ | ||||
|     extern  usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset | ||||
|     extern  usbCurrentTok, usbRxLen, usbRxToken, usbTxLen | ||||
|     extern  usbTxBuf, usbTxStatus1, usbTxStatus3 | ||||
| #   if USB_COUNT_SOF | ||||
|         extern usbSofCount | ||||
| #   endif | ||||
|     public  usbCrc16 | ||||
|     public  usbCrc16Append | ||||
|  | ||||
|     COMMON  INTVEC | ||||
| #   ifndef USB_INTR_VECTOR | ||||
|         ORG     INT0_vect | ||||
| #   else /* USB_INTR_VECTOR */ | ||||
|         ORG     USB_INTR_VECTOR | ||||
| #       undef   USB_INTR_VECTOR | ||||
| #   endif /* USB_INTR_VECTOR */ | ||||
| #   define  USB_INTR_VECTOR usbInterruptHandler | ||||
|     rjmp    USB_INTR_VECTOR | ||||
|     RSEG    CODE | ||||
|  | ||||
| #else /* __IAR_SYSTEMS_ASM__ */ | ||||
|  | ||||
| #   ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */ | ||||
| #       ifdef INT0_vect | ||||
| #           define USB_INTR_VECTOR  INT0_vect       // this is the "new" define for the vector | ||||
| #       else | ||||
| #           define USB_INTR_VECTOR  SIG_INTERRUPT0  // this is the "old" vector | ||||
| #       endif | ||||
| #   endif | ||||
|     .text | ||||
|     .global USB_INTR_VECTOR | ||||
|     .type   USB_INTR_VECTOR, @function | ||||
|     .global usbCrc16 | ||||
|     .global usbCrc16Append | ||||
| #endif /* __IAR_SYSTEMS_ASM__ */ | ||||
|  | ||||
|  | ||||
| #if USB_INTR_PENDING < 0x40 /* This is an I/O address, use in and out */ | ||||
| #   define  USB_LOAD_PENDING(reg)   in reg, USB_INTR_PENDING | ||||
| #   define  USB_STORE_PENDING(reg)  out USB_INTR_PENDING, reg | ||||
| #else   /* It's a memory address, use lds and sts */ | ||||
| #   define  USB_LOAD_PENDING(reg)   lds reg, USB_INTR_PENDING | ||||
| #   define  USB_STORE_PENDING(reg)  sts USB_INTR_PENDING, reg | ||||
| #endif | ||||
|  | ||||
| #define usbTxLen1   usbTxStatus1 | ||||
| #define usbTxBuf1   (usbTxStatus1 + 1) | ||||
| #define usbTxLen3   usbTxStatus3 | ||||
| #define usbTxBuf3   (usbTxStatus3 + 1) | ||||
|  | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Utility functions | ||||
| ;---------------------------------------------------------------------------- | ||||
|  | ||||
| #ifdef __IAR_SYSTEMS_ASM__ | ||||
| /* Register assignments for usbCrc16 on IAR cc */ | ||||
| /* Calling conventions on IAR: | ||||
|  * First parameter passed in r16/r17, second in r18/r19 and so on. | ||||
|  * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer) | ||||
|  * Result is passed in r16/r17 | ||||
|  * In case of the "tiny" memory model, pointers are only 8 bit with no | ||||
|  * padding. We therefore pass argument 1 as "16 bit unsigned". | ||||
|  */ | ||||
| RTMODEL "__rt_version", "3" | ||||
| /* The line above will generate an error if cc calling conventions change. | ||||
|  * The value "3" above is valid for IAR 4.10B/W32 | ||||
|  */ | ||||
| #   define argLen   r18 /* argument 2 */ | ||||
| #   define argPtrL  r16 /* argument 1 */ | ||||
| #   define argPtrH  r17 /* argument 1 */ | ||||
|  | ||||
| #   define resCrcL  r16 /* result */ | ||||
| #   define resCrcH  r17 /* result */ | ||||
|  | ||||
| #   define ptrL     ZL | ||||
| #   define ptrH     ZH | ||||
| #   define ptr      Z | ||||
| #   define byte     r22 | ||||
| #   define bitCnt   r19 | ||||
| #   define polyL    r20 | ||||
| #   define polyH    r21 | ||||
| #   define scratch  r23 | ||||
|  | ||||
| #else  /* __IAR_SYSTEMS_ASM__ */  | ||||
| /* Register assignments for usbCrc16 on gcc */ | ||||
| /* Calling conventions on gcc: | ||||
|  * First parameter passed in r24/r25, second in r22/23 and so on. | ||||
|  * Callee must preserve r1-r17, r28/r29 | ||||
|  * Result is passed in r24/r25 | ||||
|  */ | ||||
| #   define argLen   r22 /* argument 2 */ | ||||
| #   define argPtrL  r24 /* argument 1 */ | ||||
| #   define argPtrH  r25 /* argument 1 */ | ||||
|  | ||||
| #   define resCrcL  r24 /* result */ | ||||
| #   define resCrcH  r25 /* result */ | ||||
|  | ||||
| #   define ptrL     XL | ||||
| #   define ptrH     XH | ||||
| #   define ptr      x | ||||
| #   define byte     r18 | ||||
| #   define bitCnt   r19 | ||||
| #   define polyL    r20 | ||||
| #   define polyH    r21 | ||||
| #   define scratch  r23 | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if USB_USE_FAST_CRC | ||||
|  | ||||
| ; This implementation is faster, but has bigger code size | ||||
| ; Thanks to Slawomir Fras (BoskiDialer) for this code and to Shay Green for | ||||
| ; even further optimizations! | ||||
| ; It implements the following C pseudo-code: | ||||
| ; unsigned table(unsigned char x) | ||||
| ; { | ||||
| ; unsigned    value; | ||||
| ;  | ||||
| ;     value = (unsigned)x << 6; | ||||
| ;     value ^= (unsigned)x << 7; | ||||
| ;     if(parity(x)) | ||||
| ;         value ^= 0xc001; | ||||
| ;     return value; | ||||
| ; } | ||||
| ; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen) | ||||
| ; { | ||||
| ; unsigned crc = 0xffff; | ||||
| ;  | ||||
| ;     while(argLen--) | ||||
| ;         crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc); | ||||
| ;     return ~crc; | ||||
| ; } | ||||
|  | ||||
| ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen); | ||||
| ;   argPtr  r24+25 / r16+r17 | ||||
| ;   argLen  r22 / r18 | ||||
| ; temp variables: | ||||
| ;   byte    r18 / r22 | ||||
| ;   scratch r23 | ||||
| ;   resCrc  r24+r25 / r16+r17 | ||||
| ;   ptr     X / Z | ||||
| usbCrc16: | ||||
|     movw    ptrL, argPtrL | ||||
|     ldi     resCrcL, 0xFF | ||||
|     ldi     resCrcH, 0xFF | ||||
|     clr     bitCnt          ; zero reg | ||||
|     rjmp    usbCrc16LoopTest | ||||
| usbCrc16ByteLoop: | ||||
|     ld      byte, ptr+ | ||||
|     eor     byte, resCrcL   ; scratch is now 'x' in table() | ||||
|     mov     scratch, byte   ; compute parity of 'x' | ||||
|     swap    byte | ||||
|     eor     byte, scratch | ||||
|     mov     resCrcL, byte | ||||
|     lsr     byte | ||||
|     lsr     byte | ||||
|     eor     byte, resCrcL | ||||
|     inc     byte | ||||
|     andi    byte, 2        ; byte is now parity(x) << 1 | ||||
|     cp      bitCnt, byte   ; c = (byte != 0), then put in high bit | ||||
|     ror     scratch        ; so that after xoring, shifting, and xoring, it gives | ||||
|     ror     byte           ; the desired 0xC0 with resCrcH | ||||
|     mov     resCrcL, byte | ||||
|     eor     resCrcL, resCrcH | ||||
|     mov     resCrcH, scratch | ||||
|     lsr     scratch | ||||
|     ror     byte | ||||
|     eor     resCrcH, scratch | ||||
|     eor     resCrcL, byte | ||||
| usbCrc16LoopTest: | ||||
|     subi    argLen, 1 | ||||
|     brsh    usbCrc16ByteLoop | ||||
|     com     resCrcL | ||||
|     com     resCrcH | ||||
|     ret | ||||
|  | ||||
| #else   /* USB_USE_FAST_CRC */ | ||||
|  | ||||
| ; This implementation is slower, but has less code size | ||||
| ; | ||||
| ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen); | ||||
| ;   argPtr  r24+25 / r16+r17 | ||||
| ;   argLen  r22 / r18 | ||||
| ; temp variables: | ||||
| ;   byte    r18 / r22 | ||||
| ;   bitCnt  r19 | ||||
| ;   poly    r20+r21 | ||||
| ;   scratch r23 | ||||
| ;   resCrc  r24+r25 / r16+r17 | ||||
| ;   ptr     X / Z | ||||
| usbCrc16: | ||||
|     mov     ptrL, argPtrL | ||||
|     mov     ptrH, argPtrH | ||||
|     ldi     resCrcL, 0 | ||||
|     ldi     resCrcH, 0 | ||||
|     ldi     polyL, lo8(0xa001) | ||||
|     ldi     polyH, hi8(0xa001) | ||||
|     com     argLen      ; argLen = -argLen - 1: modified loop to ensure that carry is set | ||||
|     ldi     bitCnt, 0   ; loop counter with starnd condition = end condition | ||||
|     rjmp    usbCrcLoopEntry | ||||
| usbCrcByteLoop: | ||||
|     ld      byte, ptr+ | ||||
|     eor     resCrcL, byte | ||||
| usbCrcBitLoop: | ||||
|     ror     resCrcH     ; carry is always set here (see brcs jumps to here) | ||||
|     ror     resCrcL | ||||
|     brcs    usbCrcNoXor | ||||
|     eor     resCrcL, polyL | ||||
|     eor     resCrcH, polyH | ||||
| usbCrcNoXor: | ||||
|     subi    bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times | ||||
|     brcs    usbCrcBitLoop | ||||
| usbCrcLoopEntry: | ||||
|     subi    argLen, -1 | ||||
|     brcs    usbCrcByteLoop | ||||
| usbCrcReady: | ||||
|     ret | ||||
| ; Thanks to Reimar Doeffinger for optimizing this CRC routine! | ||||
|  | ||||
| #endif /* USB_USE_FAST_CRC */ | ||||
|  | ||||
| ; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len); | ||||
| usbCrc16Append: | ||||
|     rcall   usbCrc16 | ||||
|     st      ptr+, resCrcL | ||||
|     st      ptr+, resCrcH | ||||
|     ret | ||||
|  | ||||
| #undef argLen | ||||
| #undef argPtrL | ||||
| #undef argPtrH | ||||
| #undef resCrcL | ||||
| #undef resCrcH | ||||
| #undef ptrL | ||||
| #undef ptrH | ||||
| #undef ptr | ||||
| #undef byte | ||||
| #undef bitCnt | ||||
| #undef polyL | ||||
| #undef polyH | ||||
| #undef scratch | ||||
|  | ||||
|  | ||||
| #if USB_CFG_HAVE_MEASURE_FRAME_LENGTH | ||||
| #ifdef __IAR_SYSTEMS_ASM__ | ||||
| /* Register assignments for usbMeasureFrameLength on IAR cc */ | ||||
| /* Calling conventions on IAR: | ||||
|  * First parameter passed in r16/r17, second in r18/r19 and so on. | ||||
|  * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer) | ||||
|  * Result is passed in r16/r17 | ||||
|  * In case of the "tiny" memory model, pointers are only 8 bit with no | ||||
|  * padding. We therefore pass argument 1 as "16 bit unsigned". | ||||
|  */ | ||||
| #   define resL     r16 | ||||
| #   define resH     r17 | ||||
| #   define cnt16L   r30 | ||||
| #   define cnt16H   r31 | ||||
| #   define cntH     r18 | ||||
|  | ||||
| #else  /* __IAR_SYSTEMS_ASM__ */  | ||||
| /* Register assignments for usbMeasureFrameLength on gcc */ | ||||
| /* Calling conventions on gcc: | ||||
|  * First parameter passed in r24/r25, second in r22/23 and so on. | ||||
|  * Callee must preserve r1-r17, r28/r29 | ||||
|  * Result is passed in r24/r25 | ||||
|  */ | ||||
| #   define resL     r24 | ||||
| #   define resH     r25 | ||||
| #   define cnt16L   r24 | ||||
| #   define cnt16H   r25 | ||||
| #   define cntH     r26 | ||||
| #endif | ||||
| #   define cnt16    cnt16L | ||||
|  | ||||
| ; extern unsigned usbMeasurePacketLength(void); | ||||
| ; returns time between two idle strobes in multiples of 7 CPU clocks | ||||
| .global usbMeasureFrameLength | ||||
| usbMeasureFrameLength: | ||||
|     ldi     cntH, 6         ; wait ~ 10 ms for D- == 0 | ||||
|     clr     cnt16L | ||||
|     clr     cnt16H | ||||
| usbMFTime16: | ||||
|     dec     cntH | ||||
|     breq    usbMFTimeout | ||||
| usbMFWaitStrobe:            ; first wait for D- == 0 (idle strobe) | ||||
|     sbiw    cnt16, 1        ;[0] [6] | ||||
|     breq    usbMFTime16     ;[2] | ||||
|     sbic    USBIN, USBMINUS ;[3] | ||||
|     rjmp    usbMFWaitStrobe ;[4] | ||||
| usbMFWaitIdle:              ; then wait until idle again | ||||
|     sbis    USBIN, USBMINUS ;1 wait for D- == 1 | ||||
|     rjmp    usbMFWaitIdle   ;2 | ||||
|     ldi     cnt16L, 1       ;1 represents cycles so far | ||||
|     clr     cnt16H          ;1 | ||||
| usbMFWaitLoop: | ||||
|     in      cntH, USBIN     ;[0] [7] | ||||
|     adiw    cnt16, 1        ;[1] | ||||
|     breq    usbMFTimeout    ;[3] | ||||
|     andi    cntH, USBMASK   ;[4] | ||||
|     brne    usbMFWaitLoop   ;[5] | ||||
| usbMFTimeout: | ||||
| #if resL != cnt16L | ||||
|     mov     resL, cnt16L | ||||
|     mov     resH, cnt16H | ||||
| #endif | ||||
|     ret | ||||
|  | ||||
| #undef resL | ||||
| #undef resH | ||||
| #undef cnt16 | ||||
| #undef cnt16L | ||||
| #undef cnt16H | ||||
| #undef cntH | ||||
|  | ||||
| #endif  /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */ | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Now include the clock rate specific code | ||||
| ;---------------------------------------------------------------------------- | ||||
|  | ||||
| #ifndef USB_CFG_CLOCK_KHZ | ||||
| #   ifdef F_CPU | ||||
| #       define USB_CFG_CLOCK_KHZ (F_CPU/1000) | ||||
| #   else | ||||
| #       error "USB_CFG_CLOCK_KHZ not defined in usbconfig.h and no F_CPU set!" | ||||
| #   endif | ||||
| #endif | ||||
|  | ||||
| #if USB_CFG_CHECK_CRC   /* separate dispatcher for CRC type modules */ | ||||
| #   if USB_CFG_CLOCK_KHZ == 18000 | ||||
| #       include "usbdrvasm18-crc.inc" | ||||
| #   else | ||||
| #       error "USB_CFG_CLOCK_KHZ is not one of the supported rates for USB_CFG_CHECK_CRC!" | ||||
| #   endif | ||||
| #else   /* USB_CFG_CHECK_CRC */ | ||||
| #   if USB_CFG_CLOCK_KHZ == 12000 | ||||
| #       include "usbdrvasm12.inc" | ||||
| #   elif USB_CFG_CLOCK_KHZ == 12800 | ||||
| #       include "usbdrvasm128.inc" | ||||
| #   elif USB_CFG_CLOCK_KHZ == 15000 | ||||
| #       include "usbdrvasm15.inc" | ||||
| #   elif USB_CFG_CLOCK_KHZ == 16000 | ||||
| #       include "usbdrvasm16.inc" | ||||
| #   elif USB_CFG_CLOCK_KHZ == 16500 | ||||
| #       include "usbdrvasm165.inc" | ||||
| #   elif USB_CFG_CLOCK_KHZ == 18000 | ||||
| #       include "usbdrvasm18.inc" | ||||
| #   elif USB_CFG_CLOCK_KHZ == 20000 | ||||
| #       include "usbdrvasm20.inc" | ||||
| #   else | ||||
| #       error "USB_CFG_CLOCK_KHZ is not one of the supported rates!" | ||||
| #   endif | ||||
| #endif /* USB_CFG_CHECK_CRC */ | ||||
							
								
								
									
										20
									
								
								usbdrv/usbdrvasm.asm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								usbdrv/usbdrvasm.asm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| /* Name: usbdrvasm.asm | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2006-03-01 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| The IAR compiler/assembler system prefers assembler files with file extension | ||||
| ".asm". We simply provide this file as an alias for usbdrvasm.S. | ||||
|  | ||||
| Thanks to Oleg Semyonov for his help with the IAR tools port! | ||||
| */ | ||||
|  | ||||
| #include "usbdrvasm.S" | ||||
|  | ||||
| end | ||||
							
								
								
									
										
											BIN
										
									
								
								usbdrv/usbdrvasm.o
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								usbdrv/usbdrvasm.o
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										392
									
								
								usbdrv/usbdrvasm12.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										392
									
								
								usbdrv/usbdrvasm12.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,392 @@ | ||||
| /* Name: usbdrvasm12.inc | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2004-12-29 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* Do not link this file! Link usbdrvasm.S instead, which includes the | ||||
|  * appropriate implementation! | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file is the 12 MHz version of the asssembler part of the USB driver. It | ||||
| requires a 12 MHz crystal (not a ceramic resonator and not a calibrated RC | ||||
| oscillator). | ||||
|  | ||||
| See usbdrv.h for a description of the entire driver. | ||||
|  | ||||
| Since almost all of this code is timing critical, don't change unless you | ||||
| really know what you are doing! Many parts require not only a maximum number | ||||
| of CPU cycles, but even an exact number of cycles! | ||||
|  | ||||
|  | ||||
| Timing constraints according to spec (in bit times): | ||||
| timing subject                                      min max    CPUcycles | ||||
| --------------------------------------------------------------------------- | ||||
| EOP of OUT/SETUP to sync pattern of DATA0 (both rx) 2   16     16-128 | ||||
| EOP of IN to sync pattern of DATA0 (rx, then tx)    2   7.5    16-60 | ||||
| DATAx (rx) to ACK/NAK/STALL (tx)                    2   7.5    16-60 | ||||
| */ | ||||
|  | ||||
| ;Software-receiver engine. Strict timing! Don't change unless you can preserve timing! | ||||
| ;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled | ||||
| ;max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable | ||||
| ;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes | ||||
| ;Numbers in brackets are maximum cycles since SOF. | ||||
| USB_INTR_VECTOR: | ||||
| ;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt | ||||
|     push    YL              ;2 [35] push only what is necessary to sync with edge ASAP | ||||
|     in      YL, SREG        ;1 [37] | ||||
|     push    YL              ;2 [39] | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Synchronize with sync pattern: | ||||
| ;---------------------------------------------------------------------------- | ||||
| ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] | ||||
| ;sync up with J to K edge during sync pattern -- use fastest possible loops | ||||
| ;The first part waits at most 1 bit long since we must be in sync pattern. | ||||
| ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to | ||||
| ;waitForJ, ensure that this prerequisite is met. | ||||
| waitForJ: | ||||
|     inc     YL | ||||
|     sbis    USBIN, USBMINUS | ||||
|     brne    waitForJ        ; just make sure we have ANY timeout | ||||
| waitForK: | ||||
| ;The following code results in a sampling window of 1/4 bit which meets the spec. | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
| #if USB_COUNT_SOF | ||||
|     lds     YL, usbSofCount | ||||
|     inc     YL | ||||
|     sts     usbSofCount, YL | ||||
| #endif  /* USB_COUNT_SOF */ | ||||
| #ifdef USB_SOF_HOOK | ||||
|     USB_SOF_HOOK | ||||
| #endif | ||||
|     rjmp    sofError | ||||
| foundK: | ||||
| ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] | ||||
| ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets | ||||
| ;are cycles from center of first sync (double K) bit after the instruction | ||||
|     push    YH                  ;2 [2] | ||||
|     lds     YL, usbInputBufOffset;2 [4] | ||||
|     clr     YH                  ;1 [5] | ||||
|     subi    YL, lo8(-(usbRxBuf));1 [6] | ||||
|     sbci    YH, hi8(-(usbRxBuf));1 [7] | ||||
|  | ||||
|     sbis    USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early] | ||||
|     rjmp    haveTwoBitsK    ;2 [10] | ||||
|     pop     YH              ;2 [11] undo the push from before | ||||
|     rjmp    waitForK        ;2 [13] this was not the end of sync, retry | ||||
| haveTwoBitsK: | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; push more registers and initialize values while we sample the first bits: | ||||
| ;---------------------------------------------------------------------------- | ||||
|     push    shift           ;2 [16] | ||||
|     push    x1              ;2 [12] | ||||
|     push    x2              ;2 [14] | ||||
|  | ||||
|     in      x1, USBIN       ;1 [17] <-- sample bit 0 | ||||
|     ldi     shift, 0xff     ;1 [18] | ||||
|     bst     x1, USBMINUS    ;1 [19] | ||||
|     bld     shift, 0        ;1 [20] | ||||
|     push    x3              ;2 [22] | ||||
|     push    cnt             ;2 [24] | ||||
|      | ||||
|     in      x2, USBIN       ;1 [25] <-- sample bit 1 | ||||
|     ser     x3              ;1 [26] [inserted init instruction] | ||||
|     eor     x1, x2          ;1 [27] | ||||
|     bst     x1, USBMINUS    ;1 [28] | ||||
|     bld     shift, 1        ;1 [29] | ||||
|     ldi     cnt, USB_BUFSIZE;1 [30] [inserted init instruction] | ||||
|     rjmp    rxbit2          ;2 [32] | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Receiver loop (numbers in brackets are cycles within byte after instr) | ||||
| ;---------------------------------------------------------------------------- | ||||
|  | ||||
| unstuff0:               ;1 (branch taken) | ||||
|     andi    x3, ~0x01   ;1 [15] | ||||
|     mov     x1, x2      ;1 [16] x2 contains last sampled (stuffed) bit | ||||
|     in      x2, USBIN   ;1 [17] <-- sample bit 1 again | ||||
|     ori     shift, 0x01 ;1 [18] | ||||
|     rjmp    didUnstuff0 ;2 [20] | ||||
|  | ||||
| unstuff1:               ;1 (branch taken) | ||||
|     mov     x2, x1      ;1 [21] x1 contains last sampled (stuffed) bit | ||||
|     andi    x3, ~0x02   ;1 [22] | ||||
|     ori     shift, 0x02 ;1 [23] | ||||
|     nop                 ;1 [24] | ||||
|     in      x1, USBIN   ;1 [25] <-- sample bit 2 again | ||||
|     rjmp    didUnstuff1 ;2 [27] | ||||
|  | ||||
| unstuff2:               ;1 (branch taken) | ||||
|     andi    x3, ~0x04   ;1 [29] | ||||
|     ori     shift, 0x04 ;1 [30] | ||||
|     mov     x1, x2      ;1 [31] x2 contains last sampled (stuffed) bit | ||||
|     nop                 ;1 [32] | ||||
|     in      x2, USBIN   ;1 [33] <-- sample bit 3 | ||||
|     rjmp    didUnstuff2 ;2 [35] | ||||
|  | ||||
| unstuff3:               ;1 (branch taken) | ||||
|     in      x2, USBIN   ;1 [34] <-- sample stuffed bit 3 [one cycle too late] | ||||
|     andi    x3, ~0x08   ;1 [35] | ||||
|     ori     shift, 0x08 ;1 [36] | ||||
|     rjmp    didUnstuff3 ;2 [38] | ||||
|  | ||||
| unstuff4:               ;1 (branch taken) | ||||
|     andi    x3, ~0x10   ;1 [40] | ||||
|     in      x1, USBIN   ;1 [41] <-- sample stuffed bit 4 | ||||
|     ori     shift, 0x10 ;1 [42] | ||||
|     rjmp    didUnstuff4 ;2 [44] | ||||
|  | ||||
| unstuff5:               ;1 (branch taken) | ||||
|     andi    x3, ~0x20   ;1 [48] | ||||
|     in      x2, USBIN   ;1 [49] <-- sample stuffed bit 5 | ||||
|     ori     shift, 0x20 ;1 [50] | ||||
|     rjmp    didUnstuff5 ;2 [52] | ||||
|  | ||||
| unstuff6:               ;1 (branch taken) | ||||
|     andi    x3, ~0x40   ;1 [56] | ||||
|     in      x1, USBIN   ;1 [57] <-- sample stuffed bit 6 | ||||
|     ori     shift, 0x40 ;1 [58] | ||||
|     rjmp    didUnstuff6 ;2 [60] | ||||
|  | ||||
| ; extra jobs done during bit interval: | ||||
| ; bit 0:    store, clear [SE0 is unreliable here due to bit dribbling in hubs] | ||||
| ; bit 1:    se0 check | ||||
| ; bit 2:    overflow check | ||||
| ; bit 3:    recovery from delay [bit 0 tasks took too long] | ||||
| ; bit 4:    none | ||||
| ; bit 5:    none | ||||
| ; bit 6:    none | ||||
| ; bit 7:    jump, eor | ||||
| rxLoop: | ||||
|     eor     x3, shift   ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others | ||||
|     in      x1, USBIN   ;1 [1] <-- sample bit 0 | ||||
|     st      y+, x3      ;2 [3] store data | ||||
|     ser     x3          ;1 [4] | ||||
|     nop                 ;1 [5] | ||||
|     eor     x2, x1      ;1 [6] | ||||
|     bst     x2, USBMINUS;1 [7] | ||||
|     bld     shift, 0    ;1 [8] | ||||
|     in      x2, USBIN   ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed) | ||||
|     andi    x2, USBMASK ;1 [10] | ||||
|     breq    se0         ;1 [11] SE0 check for bit 1 | ||||
|     andi    shift, 0xf9 ;1 [12] | ||||
| didUnstuff0: | ||||
|     breq    unstuff0    ;1 [13] | ||||
|     eor     x1, x2      ;1 [14] | ||||
|     bst     x1, USBMINUS;1 [15] | ||||
|     bld     shift, 1    ;1 [16] | ||||
| rxbit2: | ||||
|     in      x1, USBIN   ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed) | ||||
|     andi    shift, 0xf3 ;1 [18] | ||||
|     breq    unstuff1    ;1 [19] do remaining work for bit 1 | ||||
| didUnstuff1: | ||||
|     subi    cnt, 1      ;1 [20] | ||||
|     brcs    overflow    ;1 [21] loop control | ||||
|     eor     x2, x1      ;1 [22] | ||||
|     bst     x2, USBMINUS;1 [23] | ||||
|     bld     shift, 2    ;1 [24] | ||||
|     in      x2, USBIN   ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed) | ||||
|     andi    shift, 0xe7 ;1 [26] | ||||
|     breq    unstuff2    ;1 [27] | ||||
| didUnstuff2: | ||||
|     eor     x1, x2      ;1 [28] | ||||
|     bst     x1, USBMINUS;1 [29] | ||||
|     bld     shift, 3    ;1 [30] | ||||
| didUnstuff3: | ||||
|     andi    shift, 0xcf ;1 [31] | ||||
|     breq    unstuff3    ;1 [32] | ||||
|     in      x1, USBIN   ;1 [33] <-- sample bit 4 | ||||
|     eor     x2, x1      ;1 [34] | ||||
|     bst     x2, USBMINUS;1 [35] | ||||
|     bld     shift, 4    ;1 [36] | ||||
| didUnstuff4: | ||||
|     andi    shift, 0x9f ;1 [37] | ||||
|     breq    unstuff4    ;1 [38] | ||||
|     nop2                ;2 [40] | ||||
|     in      x2, USBIN   ;1 [41] <-- sample bit 5 | ||||
|     eor     x1, x2      ;1 [42] | ||||
|     bst     x1, USBMINUS;1 [43] | ||||
|     bld     shift, 5    ;1 [44] | ||||
| didUnstuff5: | ||||
|     andi    shift, 0x3f ;1 [45] | ||||
|     breq    unstuff5    ;1 [46] | ||||
|     nop2                ;2 [48] | ||||
|     in      x1, USBIN   ;1 [49] <-- sample bit 6 | ||||
|     eor     x2, x1      ;1 [50] | ||||
|     bst     x2, USBMINUS;1 [51] | ||||
|     bld     shift, 6    ;1 [52] | ||||
| didUnstuff6: | ||||
|     cpi     shift, 0x02 ;1 [53] | ||||
|     brlo    unstuff6    ;1 [54] | ||||
|     nop2                ;2 [56] | ||||
|     in      x2, USBIN   ;1 [57] <-- sample bit 7 | ||||
|     eor     x1, x2      ;1 [58] | ||||
|     bst     x1, USBMINUS;1 [59] | ||||
|     bld     shift, 7    ;1 [60] | ||||
| didUnstuff7: | ||||
|     cpi     shift, 0x04 ;1 [61] | ||||
|     brsh    rxLoop      ;2 [63] loop control | ||||
| unstuff7: | ||||
|     andi    x3, ~0x80   ;1 [63] | ||||
|     ori     shift, 0x80 ;1 [64] | ||||
|     in      x2, USBIN   ;1 [65] <-- sample stuffed bit 7 | ||||
|     nop                 ;1 [66] | ||||
|     rjmp    didUnstuff7 ;2 [68] | ||||
|  | ||||
| macro POP_STANDARD ; 12 cycles | ||||
|     pop     cnt | ||||
|     pop     x3 | ||||
|     pop     x2 | ||||
|     pop     x1 | ||||
|     pop     shift | ||||
|     pop     YH | ||||
|     endm | ||||
| macro POP_RETI     ; 5 cycles | ||||
|     pop     YL | ||||
|     out     SREG, YL | ||||
|     pop     YL | ||||
|     endm | ||||
|  | ||||
| #include "asmcommon.inc" | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Transmitting data | ||||
| ;---------------------------------------------------------------------------- | ||||
|  | ||||
| txByteLoop: | ||||
| txBitloop: | ||||
| stuffN1Delay:                   ;     [03] | ||||
|     ror     shift               ;[-5] [11] [59] | ||||
|     brcc    doExorN1            ;[-4]      [60] | ||||
|     subi    x4, 1               ;[-3] | ||||
|     brne    commonN1            ;[-2] | ||||
|     lsl     shift               ;[-1] compensate ror after rjmp stuffDelay | ||||
|     nop                         ;[00] stuffing consists of just waiting 8 cycles | ||||
|     rjmp    stuffN1Delay        ;[01] after ror, C bit is reliably clear | ||||
|  | ||||
| sendNakAndReti:                 ;0 [-19] 19 cycles until SOP | ||||
|     ldi     x3, USBPID_NAK      ;1 [-18] | ||||
|     rjmp    usbSendX3           ;2 [-16] | ||||
| sendAckAndReti:                 ;0 [-19] 19 cycles until SOP | ||||
|     ldi     x3, USBPID_ACK      ;1 [-18] | ||||
|     rjmp    usbSendX3           ;2 [-16] | ||||
| sendCntAndReti:                 ;0 [-17] 17 cycles until SOP | ||||
|     mov     x3, cnt             ;1 [-16] | ||||
| usbSendX3:                      ;0 [-16] | ||||
|     ldi     YL, 20              ;1 [-15] 'x3' is R20 | ||||
|     ldi     YH, 0               ;1 [-14] | ||||
|     ldi     cnt, 2              ;1 [-13] | ||||
| ;   rjmp    usbSendAndReti      fallthrough | ||||
|  | ||||
| ; USB spec says: | ||||
| ; idle = J | ||||
| ; J = (D+ = 0), (D- = 1) or USBOUT = 0x01 | ||||
| ; K = (D+ = 1), (D- = 0) or USBOUT = 0x02 | ||||
| ; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles) | ||||
|  | ||||
| ;usbSend: | ||||
| ;pointer to data in 'Y' | ||||
| ;number of bytes in 'cnt' -- including sync byte | ||||
| ;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt] | ||||
| ;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction) | ||||
| usbSendAndReti: | ||||
|     in      x2, USBDDR          ;[-12] 12 cycles until SOP | ||||
|     ori     x2, USBMASK         ;[-11] | ||||
|     sbi     USBOUT, USBMINUS    ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) | ||||
|     out     USBDDR, x2          ;[-8] <--- acquire bus | ||||
|     in      x1, USBOUT          ;[-7] port mirror for tx loop | ||||
|     ldi     shift, 0x40         ;[-6] sync byte is first byte sent (we enter loop after ror) | ||||
|     ldi     x2, USBMASK         ;[-5] | ||||
|     push    x4                  ;[-4] | ||||
| doExorN1: | ||||
|     eor     x1, x2              ;[-2] [06] [62] | ||||
|     ldi     x4, 6               ;[-1] [07] [63] | ||||
| commonN1: | ||||
| stuffN2Delay: | ||||
|     out     USBOUT, x1          ;[00] [08] [64] <--- set bit | ||||
|     ror     shift               ;[01] | ||||
|     brcc    doExorN2            ;[02] | ||||
|     subi    x4, 1               ;[03] | ||||
|     brne    commonN2            ;[04] | ||||
|     lsl     shift               ;[05] compensate ror after rjmp stuffDelay | ||||
|     rjmp    stuffN2Delay        ;[06] after ror, C bit is reliably clear | ||||
| doExorN2: | ||||
|     eor     x1, x2              ;[04] [12] | ||||
|     ldi     x4, 6               ;[05] [13] | ||||
| commonN2: | ||||
|     nop                         ;[06] [14] | ||||
|     subi    cnt, 171            ;[07] [15] trick: (3 * 171) & 0xff = 1 | ||||
|     out     USBOUT, x1          ;[08] [16] <--- set bit | ||||
|     brcs    txBitloop           ;[09]      [25] [41] | ||||
|  | ||||
| stuff6Delay: | ||||
|     ror     shift               ;[42] [50] | ||||
|     brcc    doExor6             ;[43] | ||||
|     subi    x4, 1               ;[44] | ||||
|     brne    common6             ;[45] | ||||
|     lsl     shift               ;[46] compensate ror after rjmp stuffDelay | ||||
|     nop                         ;[47] stuffing consists of just waiting 8 cycles | ||||
|     rjmp    stuff6Delay         ;[48] after ror, C bit is reliably clear | ||||
| doExor6: | ||||
|     eor     x1, x2              ;[45] [53] | ||||
|     ldi     x4, 6               ;[46] | ||||
| common6: | ||||
| stuff7Delay: | ||||
|     ror     shift               ;[47] [55] | ||||
|     out     USBOUT, x1          ;[48] <--- set bit | ||||
|     brcc    doExor7             ;[49] | ||||
|     subi    x4, 1               ;[50] | ||||
|     brne    common7             ;[51] | ||||
|     lsl     shift               ;[52] compensate ror after rjmp stuffDelay | ||||
|     rjmp    stuff7Delay         ;[53] after ror, C bit is reliably clear | ||||
| doExor7: | ||||
|     eor     x1, x2              ;[51] [59] | ||||
|     ldi     x4, 6               ;[52] | ||||
| common7: | ||||
|     ld      shift, y+           ;[53] | ||||
|     tst     cnt                 ;[55] | ||||
|     out     USBOUT, x1          ;[56] <--- set bit | ||||
|     brne    txByteLoop          ;[57] | ||||
|  | ||||
| ;make SE0: | ||||
|     cbr     x1, USBMASK         ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles] | ||||
|     lds     x2, usbNewDeviceAddr;[59] | ||||
|     lsl     x2                  ;[61] we compare with left shifted address | ||||
|     subi    YL, 2 + 20          ;[62] Only assign address on data packets, not ACK/NAK in x3 | ||||
|     sbci    YH, 0               ;[63] | ||||
|     out     USBOUT, x1          ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle | ||||
| ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: | ||||
| ;set address only after data packet was sent, not after handshake | ||||
|     breq    skipAddrAssign      ;[01] | ||||
|     sts     usbDeviceAddr, x2   ; if not skipped: SE0 is one cycle longer | ||||
| skipAddrAssign: | ||||
| ;end of usbDeviceAddress transfer | ||||
|     ldi     x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag | ||||
|     USB_STORE_PENDING(x2)       ;[04] | ||||
|     ori     x1, USBIDLE         ;[05] | ||||
|     in      x2, USBDDR          ;[06] | ||||
|     cbr     x2, USBMASK         ;[07] set both pins to input | ||||
|     mov     x3, x1              ;[08] | ||||
|     cbr     x3, USBMASK         ;[09] configure no pullup on both pins | ||||
|     pop     x4                  ;[10] | ||||
|     nop2                        ;[12] | ||||
|     nop2                        ;[14] | ||||
|     out     USBOUT, x1          ;[16] <-- out J (idle) -- end of SE0 (EOP signal) | ||||
|     out     USBDDR, x2          ;[17] <-- release bus now | ||||
|     out     USBOUT, x3          ;[18] <-- ensure no pull-up resistors are active | ||||
|     rjmp    doReturn | ||||
							
								
								
									
										749
									
								
								usbdrv/usbdrvasm128.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										749
									
								
								usbdrv/usbdrvasm128.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,749 @@ | ||||
| /* Name: usbdrvasm128.inc | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2008-10-11 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* Do not link this file! Link usbdrvasm.S instead, which includes the | ||||
|  * appropriate implementation! | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file is the 12.8 MHz version of the USB driver. It is intended for use | ||||
| with the internal RC oscillator. Although 12.8 MHz is outside the guaranteed | ||||
| calibration range of the oscillator, almost all AVRs can reach this frequency. | ||||
| This version contains a phase locked loop in the receiver routine to cope with | ||||
| slight clock rate deviations of up to +/- 1%. | ||||
|  | ||||
| See usbdrv.h for a description of the entire driver. | ||||
|  | ||||
| LIMITATIONS | ||||
| =========== | ||||
| Although it may seem very handy to save the crystal and use the internal | ||||
| RC oscillator of the CPU, this method (and this module) has some serious | ||||
| limitations: | ||||
| (1) The guaranteed calibration range of the oscillator is only 8.1 MHz. | ||||
| They typical range is 14.5 MHz and most AVRs can actually reach this rate. | ||||
| (2) Writing EEPROM and Flash may be unreliable (short data lifetime) since | ||||
| the write procedure is timed from the RC oscillator. | ||||
| (3) End Of Packet detection (SE0) should be in bit 1, bit it is only checked | ||||
| if bits 0 and 1 both read as 0 on D- and D+ read as 0 in the middle. This may | ||||
| cause problems with old hubs which delay SE0 by up to one cycle. | ||||
| (4) Code size is much larger than that of the other modules. | ||||
|  | ||||
| Since almost all of this code is timing critical, don't change unless you | ||||
| really know what you are doing! Many parts require not only a maximum number | ||||
| of CPU cycles, but even an exact number of cycles! | ||||
|  | ||||
| Implementation notes: | ||||
| ====================== | ||||
| min frequency: 67 cycles for 8 bit -> 12.5625 MHz | ||||
| max frequency: 69.286 cycles for 8 bit -> 12.99 MHz | ||||
| nominal frequency: 12.77 MHz ( = sqrt(min * max)) | ||||
|  | ||||
| sampling positions: (next even number in range [+/- 0.5]) | ||||
| cycle index range: 0 ... 66 | ||||
| bits: | ||||
| .5, 8.875, 17.25, 25.625, 34, 42.375, 50.75, 59.125 | ||||
| [0/1], [9], [17], [25/+26], [34], [+42/43], [51], [59] | ||||
|  | ||||
| bit number:     0   1   2   3   4   5   6   7 | ||||
| spare cycles    1   2   1   2   1   1   1   0 | ||||
|  | ||||
| operations to perform:      duration cycle | ||||
|                             ---------------- | ||||
|     eor     fix, shift          1 -> 00 | ||||
|     andi    phase, USBMASK      1 -> 08 | ||||
|     breq    se0                 1 -> 16 (moved to 11) | ||||
|     st      y+, data            2 -> 24, 25 | ||||
|     mov     data, fix           1 -> 33 | ||||
|     ser     data                1 -> 41 | ||||
|     subi    cnt, 1              1 -> 49 | ||||
|     brcs    overflow            1 -> 50 | ||||
|  | ||||
| layout of samples and operations: | ||||
| [##] = sample bit | ||||
| <##> = sample phase | ||||
| *##* = operation | ||||
|  | ||||
| 0:  *00* [01]  02   03   04  <05>  06   07 | ||||
| 1:  *08* [09]  10   11   12  <13>  14   15  *16* | ||||
| 2:  [17]  18   19   20  <21>  22   23 | ||||
| 3:  *24* *25* [26]  27   28   29  <30>  31   32 | ||||
| 4:  *33* [34]  35   36   37  <38>  39   40 | ||||
| 5:  *41* [42]  43   44   45  <46>  47   48 | ||||
| 6:  *49* *50* [51]  52   53   54  <55>  56   57   58 | ||||
| 7:  [59]  60   61   62  <63>  64   65   66 | ||||
| *****************************************************************************/ | ||||
|  | ||||
| /* we prefer positive expressions (do if condition) instead of negative | ||||
|  * (skip if condition), therefore use defines for skip instructions: | ||||
|  */ | ||||
| #define ifioclr sbis | ||||
| #define ifioset sbic | ||||
| #define ifrclr  sbrs | ||||
| #define ifrset  sbrc | ||||
|  | ||||
| /* The registers "fix" and "data" swap their meaning during the loop. Use | ||||
|  * defines to keep their name constant. | ||||
|  */ | ||||
| #define fix     x2 | ||||
| #define data    x1 | ||||
| #undef phase        /* phase has a default definition to x4 */ | ||||
| #define phase   x3 | ||||
|  | ||||
|  | ||||
| USB_INTR_VECTOR: | ||||
| ;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt, r0 | ||||
|     push    YL              ;2 push only what is necessary to sync with edge ASAP | ||||
|     in      YL, SREG        ;1 | ||||
|     push    YL              ;2 | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Synchronize with sync pattern: | ||||
| ;---------------------------------------------------------------------------- | ||||
| ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] | ||||
| ;sync up with J to K edge during sync pattern -- use fastest possible loops | ||||
| ;The first part waits at most 1 bit long since we must be in sync pattern. | ||||
| ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to | ||||
| ;waitForJ, ensure that this prerequisite is met. | ||||
| waitForJ: | ||||
|     inc     YL | ||||
|     sbis    USBIN, USBMINUS | ||||
|     brne    waitForJ        ; just make sure we have ANY timeout | ||||
| waitForK: | ||||
| ;The following code results in a sampling window of 1/4 bit which meets the spec. | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS ;[0] | ||||
|     rjmp    foundK          ;[1] | ||||
| #if USB_COUNT_SOF | ||||
|     lds     YL, usbSofCount | ||||
|     inc     YL | ||||
|     sts     usbSofCount, YL | ||||
| #endif  /* USB_COUNT_SOF */ | ||||
| #ifdef USB_SOF_HOOK | ||||
|     USB_SOF_HOOK | ||||
| #endif | ||||
|     rjmp    sofError | ||||
|  | ||||
| foundK: | ||||
| ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] | ||||
| ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets | ||||
| ;are cycles from center of first sync (double K) bit after the instruction | ||||
|     push    YH                  ;[2] | ||||
|     lds     YL, usbInputBufOffset;[4] | ||||
|     clr     YH                  ;[6] | ||||
|     subi    YL, lo8(-(usbRxBuf));[7] | ||||
|     sbci    YH, hi8(-(usbRxBuf));[8] | ||||
|  | ||||
|     sbis    USBIN, USBMINUS     ;[9] we want two bits K [we want to sample at 8 + 4 - 1.5 = 10.5] | ||||
|     rjmp    haveTwoBitsK        ;[10] | ||||
|     pop     YH                  ;[11] undo the push from before | ||||
|     rjmp    waitForK            ;[13] this was not the end of sync, retry | ||||
| haveTwoBitsK: | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; push more registers and initialize values while we sample the first bits: | ||||
| ;---------------------------------------------------------------------------- | ||||
| #define fix     x2 | ||||
| #define data    x1 | ||||
|  | ||||
|     push    shift               ;[12] | ||||
|     push    x1                  ;[14] | ||||
|     push    x2                  ;[16] | ||||
|     ldi     shift, 0x80         ;[18] prevent bit-unstuffing but init low bits to 0 | ||||
|     ifioset USBIN, USBMINUS     ;[19] [01] <--- bit 0 [10.5 + 8 = 18.5] | ||||
|     ori     shift, 1<<0         ;[02] | ||||
|     push    x3                  ;[03] | ||||
|     push    cnt                 ;[05] | ||||
|     push    r0                  ;[07] | ||||
|     ifioset USBIN, USBMINUS     ;[09] <--- bit 1 | ||||
|     ori     shift, 1<<1         ;[10] | ||||
|     ser     fix                 ;[11] | ||||
|     ldi     cnt, USB_BUFSIZE    ;[12] | ||||
|     mov     data, shift         ;[13] | ||||
|     lsl     shift               ;[14] | ||||
|     nop2                        ;[15] | ||||
|     ifioset USBIN, USBMINUS     ;[17] <--- bit 2 | ||||
|     ori     data, 3<<2          ;[18] store in bit 2 AND bit 3 | ||||
|     eor     shift, data         ;[19] do nrzi decoding | ||||
|     andi    data, 1<<3          ;[20] | ||||
|     in      phase, USBIN        ;[21] <- phase | ||||
|     brne    jumpToEntryAfterSet ;[22] if USBMINS at bit 3 was 1 | ||||
|     nop                         ;[23] | ||||
|     rjmp    entryAfterClr       ;[24] | ||||
| jumpToEntryAfterSet: | ||||
|     rjmp    entryAfterSet       ;[24] | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Receiver loop (numbers in brackets are cycles within byte after instr) | ||||
| ;---------------------------------------------------------------------------- | ||||
| #undef  fix | ||||
| #define  fix    x1 | ||||
| #undef  data | ||||
| #define data    x2 | ||||
|  | ||||
| bit7IsSet: | ||||
|     ifrclr  phase, USBMINUS     ;[62] check phase only if D- changed | ||||
|     lpm                         ;[63] | ||||
|     in      phase, USBIN        ;[64] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 7       ;[65] | ||||
|     nop                         ;[66] | ||||
| ;;;;rjmp    bit0AfterSet        ; -> [00] == [67] moved block up to save jump | ||||
| bit0AfterSet: | ||||
|     eor     fix, shift          ;[00] | ||||
| #undef  fix | ||||
| #define fix     x2 | ||||
| #undef  data | ||||
| #define data    x1  /* we now have result in data, fix is reset to 0xff */ | ||||
|     ifioclr USBIN, USBMINUS     ;[01] <--- sample 0 | ||||
|     rjmp    bit0IsClr           ;[02] | ||||
|     andi    shift, ~(7 << 0)    ;[03] | ||||
|     breq    unstuff0s           ;[04] | ||||
|     in      phase, USBIN        ;[05] <- phase | ||||
|     rjmp    bit1AfterSet        ;[06] | ||||
| unstuff0s: | ||||
|     in      phase, USBIN        ;[06] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << 0)      ;[07] | ||||
|     ifioclr USBIN, USBMINUS     ;[00] | ||||
|     ifioset USBIN, USBPLUS      ;[01] | ||||
|     rjmp    bit0IsClr           ;[02] executed if first expr false or second true | ||||
| se0AndStore:                    ; executed only if both bits 0 | ||||
|     st      y+, x1              ;[15/17] cycles after start of byte | ||||
|     rjmp    se0                 ;[17/19] | ||||
|  | ||||
| bit0IsClr: | ||||
|     ifrset  phase, USBMINUS     ;[04] check phase only if D- changed | ||||
|     lpm                         ;[05] | ||||
|     in      phase, USBIN        ;[06] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 0       ;[07] | ||||
| bit1AfterClr: | ||||
|     andi    phase, USBMASK      ;[08] | ||||
|     ifioset USBIN, USBMINUS     ;[09] <--- sample 1 | ||||
|     rjmp    bit1IsSet           ;[10] | ||||
|     breq    se0AndStore         ;[11] if D- was 0 in bits 0 AND 1 and D+ was 0 in between, we have SE0 | ||||
|     andi    shift, ~(7 << 1)    ;[12] | ||||
|     in      phase, USBIN        ;[13] <- phase | ||||
|     breq    unstuff1c           ;[14] | ||||
|     rjmp    bit2AfterClr        ;[15] | ||||
| unstuff1c: | ||||
|     andi    fix, ~(1 << 1)      ;[16] | ||||
|     nop2                        ;[08] | ||||
|     nop2                        ;[10] | ||||
| bit1IsSet: | ||||
|     ifrclr  phase, USBMINUS     ;[12] check phase only if D- changed | ||||
|     lpm                         ;[13] | ||||
|     in      phase, USBIN        ;[14] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 1       ;[15] | ||||
|     nop                         ;[16] | ||||
| bit2AfterSet: | ||||
|     ifioclr USBIN, USBMINUS     ;[17] <--- sample 2 | ||||
|     rjmp    bit2IsClr           ;[18] | ||||
|     andi    shift, ~(7 << 2)    ;[19] | ||||
|     breq    unstuff2s           ;[20] | ||||
|     in      phase, USBIN        ;[21] <- phase | ||||
|     rjmp    bit3AfterSet        ;[22] | ||||
| unstuff2s: | ||||
|     in      phase, USBIN        ;[22] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << 2)      ;[23] | ||||
|     nop2                        ;[16] | ||||
|     nop2                        ;[18] | ||||
| bit2IsClr: | ||||
|     ifrset  phase, USBMINUS     ;[20] check phase only if D- changed | ||||
|     lpm                         ;[21] | ||||
|     in      phase, USBIN        ;[22] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 2       ;[23] | ||||
| bit3AfterClr: | ||||
|     st      y+, data            ;[24] | ||||
| entryAfterClr: | ||||
|     ifioset USBIN, USBMINUS     ;[26] <--- sample 3 | ||||
|     rjmp    bit3IsSet           ;[27] | ||||
|     andi    shift, ~(7 << 3)    ;[28] | ||||
|     breq    unstuff3c           ;[29] | ||||
|     in      phase, USBIN        ;[30] <- phase | ||||
|     rjmp    bit4AfterClr        ;[31] | ||||
| unstuff3c: | ||||
|     in      phase, USBIN        ;[31] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << 3)      ;[32] | ||||
|     nop2                        ;[25] | ||||
|     nop2                        ;[27] | ||||
| bit3IsSet: | ||||
|     ifrclr  phase, USBMINUS     ;[29] check phase only if D- changed | ||||
|     lpm                         ;[30] | ||||
|     in      phase, USBIN        ;[31] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 3       ;[32] | ||||
| bit4AfterSet: | ||||
|     mov     data, fix           ;[33] undo this move by swapping defines | ||||
| #undef  fix | ||||
| #define fix     x1 | ||||
| #undef  data | ||||
| #define data    x2 | ||||
|     ifioclr USBIN, USBMINUS     ;[34] <--- sample 4 | ||||
|     rjmp    bit4IsClr           ;[35] | ||||
|     andi    shift, ~(7 << 4)    ;[36] | ||||
|     breq    unstuff4s           ;[37] | ||||
|     in      phase, USBIN        ;[38] <- phase | ||||
|     rjmp    bit5AfterSet        ;[39] | ||||
| unstuff4s: | ||||
|     in      phase, USBIN        ;[39] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << 4)      ;[40] | ||||
|     nop2                        ;[33] | ||||
|     nop2                        ;[35] | ||||
| bit4IsClr: | ||||
|     ifrset  phase, USBMINUS     ;[37] check phase only if D- changed | ||||
|     lpm                         ;[38] | ||||
|     in      phase, USBIN        ;[39] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 4       ;[40] | ||||
| bit5AfterClr: | ||||
|     ser     data                ;[41] | ||||
|     ifioset USBIN, USBMINUS     ;[42] <--- sample 5 | ||||
|     rjmp    bit5IsSet           ;[43] | ||||
|     andi    shift, ~(7 << 5)    ;[44] | ||||
|     breq    unstuff5c           ;[45] | ||||
|     in      phase, USBIN        ;[46] <- phase | ||||
|     rjmp    bit6AfterClr        ;[47] | ||||
| unstuff5c: | ||||
|     in      phase, USBIN        ;[47] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << 5)      ;[48] | ||||
|     nop2                        ;[41] | ||||
|     nop2                        ;[43] | ||||
| bit5IsSet: | ||||
|     ifrclr  phase, USBMINUS     ;[45] check phase only if D- changed | ||||
|     lpm                         ;[46] | ||||
|     in      phase, USBIN        ;[47] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 5       ;[48] | ||||
| bit6AfterSet: | ||||
|     subi    cnt, 1              ;[49] | ||||
|     brcs    jumpToOverflow      ;[50] | ||||
|     ifioclr USBIN, USBMINUS     ;[51] <--- sample 6 | ||||
|     rjmp    bit6IsClr           ;[52] | ||||
|     andi    shift, ~(3 << 6)    ;[53] | ||||
|     cpi     shift, 2            ;[54] | ||||
|     in      phase, USBIN        ;[55] <- phase | ||||
|     brlt    unstuff6s           ;[56] | ||||
|     rjmp    bit7AfterSet        ;[57] | ||||
|  | ||||
| jumpToOverflow: | ||||
|     rjmp    overflow | ||||
|  | ||||
| unstuff6s: | ||||
|     andi    fix, ~(1 << 6)      ;[50] | ||||
|     lpm                         ;[51] | ||||
| bit6IsClr: | ||||
|     ifrset  phase, USBMINUS     ;[54] check phase only if D- changed | ||||
|     lpm                         ;[55] | ||||
|     in      phase, USBIN        ;[56] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 6       ;[57] | ||||
|     nop                         ;[58] | ||||
| bit7AfterClr: | ||||
|     ifioset USBIN, USBMINUS     ;[59] <--- sample 7 | ||||
|     rjmp    bit7IsSet           ;[60] | ||||
|     andi    shift, ~(1 << 7)    ;[61] | ||||
|     cpi     shift, 4            ;[62] | ||||
|     in      phase, USBIN        ;[63] <- phase | ||||
|     brlt    unstuff7c           ;[64] | ||||
|     rjmp    bit0AfterClr        ;[65] -> [00] == [67] | ||||
| unstuff7c: | ||||
|     andi    fix, ~(1 << 7)      ;[58] | ||||
|     nop                         ;[59] | ||||
|     rjmp    bit7IsSet           ;[60] | ||||
|  | ||||
| bit7IsClr: | ||||
|     ifrset  phase, USBMINUS     ;[62] check phase only if D- changed | ||||
|     lpm                         ;[63] | ||||
|     in      phase, USBIN        ;[64] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 7       ;[65] | ||||
|     nop                         ;[66] | ||||
| ;;;;rjmp    bit0AfterClr        ; -> [00] == [67] moved block up to save jump | ||||
| bit0AfterClr: | ||||
|     eor     fix, shift          ;[00] | ||||
| #undef  fix | ||||
| #define fix     x2 | ||||
| #undef  data | ||||
| #define data    x1  /* we now have result in data, fix is reset to 0xff */ | ||||
|     ifioset USBIN, USBMINUS     ;[01] <--- sample 0 | ||||
|     rjmp    bit0IsSet           ;[02] | ||||
|     andi    shift, ~(7 << 0)    ;[03] | ||||
|     breq    unstuff0c           ;[04] | ||||
|     in      phase, USBIN        ;[05] <- phase | ||||
|     rjmp    bit1AfterClr        ;[06] | ||||
| unstuff0c: | ||||
|     in      phase, USBIN        ;[06] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << 0)      ;[07] | ||||
|     ifioclr USBIN, USBMINUS     ;[00] | ||||
|     ifioset USBIN, USBPLUS      ;[01] | ||||
|     rjmp    bit0IsSet           ;[02] executed if first expr false or second true | ||||
|     rjmp    se0AndStore         ;[03] executed only if both bits 0 | ||||
| bit0IsSet: | ||||
|     ifrclr  phase, USBMINUS     ;[04] check phase only if D- changed | ||||
|     lpm                         ;[05] | ||||
|     in      phase, USBIN        ;[06] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 0       ;[07] | ||||
| bit1AfterSet: | ||||
|     andi    shift, ~(7 << 1)    ;[08] compensated by "ori shift, 1<<1" if bit1IsClr | ||||
|     ifioclr USBIN, USBMINUS     ;[09] <--- sample 1 | ||||
|     rjmp    bit1IsClr           ;[10] | ||||
|     breq    unstuff1s           ;[11] | ||||
|     nop2                        ;[12] do not check for SE0 if bit 0 was 1 | ||||
|     in      phase, USBIN        ;[14] <- phase (one cycle too late) | ||||
|     rjmp    bit2AfterSet        ;[15] | ||||
| unstuff1s: | ||||
|     in      phase, USBIN        ;[13] <- phase | ||||
|     andi    fix, ~(1 << 1)      ;[14] | ||||
|     lpm                         ;[07] | ||||
|     nop2                        ;[10] | ||||
| bit1IsClr: | ||||
|     ifrset  phase, USBMINUS     ;[12] check phase only if D- changed | ||||
|     lpm                         ;[13] | ||||
|     in      phase, USBIN        ;[14] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 1       ;[15] | ||||
|     nop                         ;[16] | ||||
| bit2AfterClr: | ||||
|     ifioset USBIN, USBMINUS     ;[17] <--- sample 2 | ||||
|     rjmp    bit2IsSet           ;[18] | ||||
|     andi    shift, ~(7 << 2)    ;[19] | ||||
|     breq    unstuff2c           ;[20] | ||||
|     in      phase, USBIN        ;[21] <- phase | ||||
|     rjmp    bit3AfterClr        ;[22] | ||||
| unstuff2c: | ||||
|     in      phase, USBIN        ;[22] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << 2)      ;[23] | ||||
|     nop2                        ;[16] | ||||
|     nop2                        ;[18] | ||||
| bit2IsSet: | ||||
|     ifrclr  phase, USBMINUS     ;[20] check phase only if D- changed | ||||
|     lpm                         ;[21] | ||||
|     in      phase, USBIN        ;[22] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 2       ;[23] | ||||
| bit3AfterSet: | ||||
|     st      y+, data            ;[24] | ||||
| entryAfterSet: | ||||
|     ifioclr USBIN, USBMINUS     ;[26] <--- sample 3 | ||||
|     rjmp    bit3IsClr           ;[27] | ||||
|     andi    shift, ~(7 << 3)    ;[28] | ||||
|     breq    unstuff3s           ;[29] | ||||
|     in      phase, USBIN        ;[30] <- phase | ||||
|     rjmp    bit4AfterSet        ;[31] | ||||
| unstuff3s: | ||||
|     in      phase, USBIN        ;[31] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << 3)      ;[32] | ||||
|     nop2                        ;[25] | ||||
|     nop2                        ;[27] | ||||
| bit3IsClr: | ||||
|     ifrset  phase, USBMINUS     ;[29] check phase only if D- changed | ||||
|     lpm                         ;[30] | ||||
|     in      phase, USBIN        ;[31] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 3       ;[32] | ||||
| bit4AfterClr: | ||||
|     mov     data, fix           ;[33] undo this move by swapping defines | ||||
| #undef  fix | ||||
| #define fix     x1 | ||||
| #undef  data | ||||
| #define data    x2 | ||||
|     ifioset USBIN, USBMINUS     ;[34] <--- sample 4 | ||||
|     rjmp    bit4IsSet           ;[35] | ||||
|     andi    shift, ~(7 << 4)    ;[36] | ||||
|     breq    unstuff4c           ;[37] | ||||
|     in      phase, USBIN        ;[38] <- phase | ||||
|     rjmp    bit5AfterClr        ;[39] | ||||
| unstuff4c: | ||||
|     in      phase, USBIN        ;[39] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << 4)      ;[40] | ||||
|     nop2                        ;[33] | ||||
|     nop2                        ;[35] | ||||
| bit4IsSet: | ||||
|     ifrclr  phase, USBMINUS     ;[37] check phase only if D- changed | ||||
|     lpm                         ;[38] | ||||
|     in      phase, USBIN        ;[39] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 4       ;[40] | ||||
| bit5AfterSet: | ||||
|     ser     data                ;[41] | ||||
|     ifioclr USBIN, USBMINUS     ;[42] <--- sample 5 | ||||
|     rjmp    bit5IsClr           ;[43] | ||||
|     andi    shift, ~(7 << 5)    ;[44] | ||||
|     breq    unstuff5s           ;[45] | ||||
|     in      phase, USBIN        ;[46] <- phase | ||||
|     rjmp    bit6AfterSet        ;[47] | ||||
| unstuff5s: | ||||
|     in      phase, USBIN        ;[47] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << 5)      ;[48] | ||||
|     nop2                        ;[41] | ||||
|     nop2                        ;[43] | ||||
| bit5IsClr: | ||||
|     ifrset  phase, USBMINUS     ;[45] check phase only if D- changed | ||||
|     lpm                         ;[46] | ||||
|     in      phase, USBIN        ;[47] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 5       ;[48] | ||||
| bit6AfterClr: | ||||
|     subi    cnt, 1              ;[49] | ||||
|     brcs    overflow            ;[50] | ||||
|     ifioset USBIN, USBMINUS     ;[51] <--- sample 6 | ||||
|     rjmp    bit6IsSet           ;[52] | ||||
|     andi    shift, ~(3 << 6)    ;[53] | ||||
|     cpi     shift, 2            ;[54] | ||||
|     in      phase, USBIN        ;[55] <- phase | ||||
|     brlt    unstuff6c           ;[56] | ||||
|     rjmp    bit7AfterClr        ;[57] | ||||
| unstuff6c: | ||||
|     andi    fix, ~(1 << 6)      ;[50] | ||||
|     lpm                         ;[51] | ||||
| bit6IsSet: | ||||
|     ifrclr  phase, USBMINUS     ;[54] check phase only if D- changed | ||||
|     lpm                         ;[55] | ||||
|     in      phase, USBIN        ;[56] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << 6       ;[57] | ||||
| bit7AfterSet: | ||||
|     ifioclr USBIN, USBMINUS     ;[59] <--- sample 7 | ||||
|     rjmp    bit7IsClr           ;[60] | ||||
|     andi    shift, ~(1 << 7)    ;[61] | ||||
|     cpi     shift, 4            ;[62] | ||||
|     in      phase, USBIN        ;[63] <- phase | ||||
|     brlt    unstuff7s           ;[64] | ||||
|     rjmp    bit0AfterSet        ;[65] -> [00] == [67] | ||||
| unstuff7s: | ||||
|     andi    fix, ~(1 << 7)      ;[58] | ||||
|     nop                         ;[59] | ||||
|     rjmp    bit7IsClr           ;[60] | ||||
|  | ||||
| macro POP_STANDARD ; 14 cycles | ||||
|     pop     r0 | ||||
|     pop     cnt | ||||
|     pop     x3 | ||||
|     pop     x2 | ||||
|     pop     x1 | ||||
|     pop     shift | ||||
|     pop     YH | ||||
|     endm | ||||
| macro POP_RETI     ; 5 cycles | ||||
|     pop     YL | ||||
|     out     SREG, YL | ||||
|     pop     YL | ||||
|     endm | ||||
|  | ||||
| #include "asmcommon.inc" | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Transmitting data | ||||
| ;---------------------------------------------------------------------------- | ||||
|  | ||||
| txByteLoop: | ||||
| txBitloop: | ||||
| stuffN1Delay:                   ;     [03] | ||||
|     ror     shift               ;[-5] [11] [63] | ||||
|     brcc    doExorN1            ;[-4]      [64] | ||||
|     subi    x3, 1               ;[-3] | ||||
|     brne    commonN1            ;[-2] | ||||
|     lsl     shift               ;[-1] compensate ror after rjmp stuffDelay | ||||
|     nop                         ;[00] stuffing consists of just waiting 8 cycles | ||||
|     rjmp    stuffN1Delay        ;[01] after ror, C bit is reliably clear | ||||
|  | ||||
| sendNakAndReti: | ||||
|     ldi     cnt, USBPID_NAK ;[-19] | ||||
|     rjmp    sendCntAndReti  ;[-18] | ||||
| sendAckAndReti: | ||||
|     ldi     cnt, USBPID_ACK ;[-17] | ||||
| sendCntAndReti: | ||||
|     mov     r0, cnt         ;[-16] | ||||
|     ldi     YL, 0           ;[-15] R0 address is 0 | ||||
|     ldi     YH, 0           ;[-14] | ||||
|     ldi     cnt, 2          ;[-13] | ||||
| ;   rjmp    usbSendAndReti      fallthrough | ||||
|  | ||||
| ; USB spec says: | ||||
| ; idle = J | ||||
| ; J = (D+ = 0), (D- = 1) or USBOUT = 0x01 | ||||
| ; K = (D+ = 1), (D- = 0) or USBOUT = 0x02 | ||||
| ; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles) | ||||
|  | ||||
| ;usbSend: | ||||
| ;pointer to data in 'Y' | ||||
| ;number of bytes in 'cnt' -- including sync byte | ||||
| ;uses: x1...x3, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x3 = bitstuff cnt] | ||||
| ;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction) | ||||
| usbSendAndReti: | ||||
|     in      x2, USBDDR          ;[-10] 10 cycles until SOP | ||||
|     ori     x2, USBMASK         ;[-9] | ||||
|     sbi     USBOUT, USBMINUS    ;[-8] prepare idle state; D+ and D- must have been 0 (no pullups) | ||||
|     out     USBDDR, x2          ;[-6] <--- acquire bus | ||||
|     in      x1, USBOUT          ;[-5] port mirror for tx loop | ||||
|     ldi     shift, 0x40         ;[-4] sync byte is first byte sent (we enter loop after ror) | ||||
|     ldi     x2, USBMASK         ;[-3] | ||||
| doExorN1: | ||||
|     eor     x1, x2              ;[-2] [06] [62] | ||||
|     ldi     x3, 6               ;[-1] [07] [63] | ||||
| commonN1: | ||||
| stuffN2Delay: | ||||
|     out     USBOUT, x1          ;[00] [08] [64] <--- set bit | ||||
|     ror     shift               ;[01] | ||||
|     brcc    doExorN2            ;[02] | ||||
|     subi    x3, 1               ;[03] | ||||
|     brne    commonN2            ;[04] | ||||
|     lsl     shift               ;[05] compensate ror after rjmp stuffDelay | ||||
|     rjmp    stuffN2Delay        ;[06] after ror, C bit is reliably clear | ||||
| doExorN2: | ||||
|     eor     x1, x2              ;[04] [12] | ||||
|     ldi     x3, 6               ;[05] [13] | ||||
| commonN2: | ||||
|     nop2                        ;[06] [14] | ||||
|     subi    cnt, 171            ;[08] [16] trick: (3 * 171) & 0xff = 1 | ||||
|     out     USBOUT, x1          ;[09] [17] <--- set bit | ||||
|     brcs    txBitloop           ;[10]      [27] [44] | ||||
|  | ||||
| stuff6Delay: | ||||
|     ror     shift               ;[45] [53] | ||||
|     brcc    doExor6             ;[46] | ||||
|     subi    x3, 1               ;[47] | ||||
|     brne    common6             ;[48] | ||||
|     lsl     shift               ;[49] compensate ror after rjmp stuffDelay | ||||
|     nop                         ;[50] stuffing consists of just waiting 8 cycles | ||||
|     rjmp    stuff6Delay         ;[51] after ror, C bit is reliably clear | ||||
| doExor6: | ||||
|     eor     x1, x2              ;[48] [56] | ||||
|     ldi     x3, 6               ;[49] | ||||
| common6: | ||||
| stuff7Delay: | ||||
|     ror     shift               ;[50] [58] | ||||
|     out     USBOUT, x1          ;[51] <--- set bit | ||||
|     brcc    doExor7             ;[52] | ||||
|     subi    x3, 1               ;[53] | ||||
|     brne    common7             ;[54] | ||||
|     lsl     shift               ;[55] compensate ror after rjmp stuffDelay | ||||
|     rjmp    stuff7Delay         ;[56] after ror, C bit is reliably clear | ||||
| doExor7: | ||||
|     eor     x1, x2              ;[54] [62] | ||||
|     ldi     x3, 6               ;[55] | ||||
| common7: | ||||
|     ld      shift, y+           ;[56] | ||||
|     nop                         ;[58] | ||||
|     tst     cnt                 ;[59] | ||||
|     out     USBOUT, x1          ;[60] [00]<--- set bit | ||||
|     brne    txByteLoop          ;[61] [01] | ||||
| ;make SE0: | ||||
|     cbr     x1, USBMASK         ;[02] prepare SE0 [spec says EOP may be 15 to 18 cycles] | ||||
|     lds     x2, usbNewDeviceAddr;[03] | ||||
|     lsl     x2                  ;[05] we compare with left shifted address | ||||
|     subi    YL, 2 + 0           ;[06] Only assign address on data packets, not ACK/NAK in r0 | ||||
|     sbci    YH, 0               ;[07] | ||||
|     out     USBOUT, x1          ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle | ||||
| ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: | ||||
| ;set address only after data packet was sent, not after handshake | ||||
|     breq    skipAddrAssign      ;[01] | ||||
|     sts     usbDeviceAddr, x2   ; if not skipped: SE0 is one cycle longer | ||||
| skipAddrAssign: | ||||
| ;end of usbDeviceAddress transfer | ||||
|     ldi     x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag | ||||
|     USB_STORE_PENDING(x2)       ;[04] | ||||
|     ori     x1, USBIDLE         ;[05] | ||||
|     in      x2, USBDDR          ;[06] | ||||
|     cbr     x2, USBMASK         ;[07] set both pins to input | ||||
|     mov     x3, x1              ;[08] | ||||
|     cbr     x3, USBMASK         ;[09] configure no pullup on both pins | ||||
|     lpm                         ;[10] | ||||
|     lpm                         ;[13] | ||||
|     out     USBOUT, x1          ;[16] <-- out J (idle) -- end of SE0 (EOP signal) | ||||
|     out     USBDDR, x2          ;[17] <-- release bus now | ||||
|     out     USBOUT, x3          ;[18] <-- ensure no pull-up resistors are active | ||||
|     rjmp    doReturn | ||||
|  | ||||
|  | ||||
|  | ||||
| /***************************************************************************** | ||||
| The following PHP script generates a code skeleton for the receiver routine: | ||||
|  | ||||
| <?php | ||||
|  | ||||
| function printCmdBuffer($thisBit) | ||||
| { | ||||
| global $cycle; | ||||
|  | ||||
|     $nextBit = ($thisBit + 1) % 8; | ||||
|     $s = ob_get_contents(); | ||||
|     ob_end_clean(); | ||||
|     $s = str_replace("#", $thisBit, $s); | ||||
|     $s = str_replace("@", $nextBit, $s); | ||||
|     $lines = explode("\n", $s); | ||||
|     for($i = 0; $i < count($lines); $i++){ | ||||
|         $s = $lines[$i]; | ||||
|         if(ereg("\\[([0-9-][0-9])\\]", $s, $regs)){ | ||||
|             $c = $cycle + (int)$regs[1]; | ||||
|             $s = ereg_replace("\\[[0-9-][0-9]\\]", sprintf("[%02d]", $c), $s); | ||||
|         } | ||||
|         if(strlen($s) > 0) | ||||
|             echo "$s\n"; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function printBit($isAfterSet, $bitNum) | ||||
| { | ||||
|     ob_start(); | ||||
|     if($isAfterSet){ | ||||
| ?> | ||||
|     ifioclr USBIN, USBMINUS     ;[00] <--- sample | ||||
|     rjmp    bit#IsClr           ;[01] | ||||
|     andi    shift, ~(7 << #)    ;[02] | ||||
|     breq    unstuff#s           ;[03] | ||||
|     in      phase, USBIN        ;[04] <- phase | ||||
|     rjmp    bit@AfterSet        ;[05] | ||||
| unstuff#s: | ||||
|     in      phase, USBIN        ;[05] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << #)      ;[06] | ||||
|     nop2                        ;[-1] | ||||
|     nop2                        ;[01] | ||||
| bit#IsClr: | ||||
|     ifrset  phase, USBMINUS     ;[03] check phase only if D- changed | ||||
|     lpm                         ;[04] | ||||
|     in      phase, USBIN        ;[05] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << #       ;[06] | ||||
| <?php | ||||
|     }else{ | ||||
| ?> | ||||
|     ifioset USBIN, USBMINUS     ;[00] <--- sample | ||||
|     rjmp    bit#IsSet           ;[01] | ||||
|     andi    shift, ~(7 << #)    ;[02] | ||||
|     breq    unstuff#c           ;[03] | ||||
|     in      phase, USBIN        ;[04] <- phase | ||||
|     rjmp    bit@AfterClr        ;[05] | ||||
| unstuff#c: | ||||
|     in      phase, USBIN        ;[05] <- phase (one cycle too late) | ||||
|     andi    fix, ~(1 << #)      ;[06] | ||||
|     nop2                        ;[-1] | ||||
|     nop2                        ;[01] | ||||
| bit#IsSet: | ||||
|     ifrclr  phase, USBMINUS     ;[03] check phase only if D- changed | ||||
|     lpm                         ;[04] | ||||
|     in      phase, USBIN        ;[05] <- phase (one cycle too late) | ||||
|     ori     shift, 1 << #       ;[06] | ||||
| <?php | ||||
|     } | ||||
|     printCmdBuffer($bitNum); | ||||
| } | ||||
|  | ||||
| $bitStartCycles = array(1, 9, 17, 26, 34, 42, 51, 59); | ||||
| for($i = 0; $i < 16; $i++){ | ||||
|     $bit = $i % 8; | ||||
|     $emitClrCode = ($i + (int)($i / 8)) % 2; | ||||
|     $cycle = $bitStartCycles[$bit]; | ||||
|     if($emitClrCode){ | ||||
|         printf("bit%dAfterClr:\n", $bit); | ||||
|     }else{ | ||||
|         printf("bit%dAfterSet:\n", $bit); | ||||
|     } | ||||
|     ob_start(); | ||||
|     echo "    *****                       ;[-1]\n"; | ||||
|     printCmdBuffer($bit); | ||||
|     printBit(!$emitClrCode, $bit); | ||||
|     if($i == 7) | ||||
|         echo "\n"; | ||||
| } | ||||
|  | ||||
| ?> | ||||
| *****************************************************************************/ | ||||
							
								
								
									
										422
									
								
								usbdrv/usbdrvasm15.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										422
									
								
								usbdrv/usbdrvasm15.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,422 @@ | ||||
| /* Name: usbdrvasm15.inc | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: contributed by V. Bosch | ||||
|  * Creation Date: 2007-08-06 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* Do not link this file! Link usbdrvasm.S instead, which includes the | ||||
|  * appropriate implementation! | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file is the 15 MHz version of the asssembler part of the USB driver. It | ||||
| requires a 15 MHz crystal (not a ceramic resonator and not a calibrated RC | ||||
| oscillator). | ||||
|  | ||||
| See usbdrv.h for a description of the entire driver. | ||||
|  | ||||
| Since almost all of this code is timing critical, don't change unless you | ||||
| really know what you are doing! Many parts require not only a maximum number | ||||
| of CPU cycles, but even an exact number of cycles! | ||||
| */ | ||||
|  | ||||
| ;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes | ||||
| ;nominal frequency: 15 MHz -> 10.0 cycles per bit, 80.0 cycles per byte | ||||
| ; Numbers in brackets are clocks counted from center of last sync bit | ||||
| ; when instruction starts | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; order of registers pushed:  | ||||
| ;	YL, SREG [sofError] YH, shift, x1, x2, x3, bitcnt, cnt, x4 | ||||
| ;---------------------------------------------------------------------------- | ||||
| USB_INTR_VECTOR:               | ||||
|     push    YL                   ;2 	push only what is necessary to sync with edge ASAP | ||||
|     in      YL, SREG             ;1  | ||||
|     push    YL                   ;2  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Synchronize with sync pattern: | ||||
| ; | ||||
| ;   sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] | ||||
| ;   sync up with J to K edge during sync pattern -- use fastest possible loops | ||||
| ;The first part waits at most 1 bit long since we must be in sync pattern. | ||||
| ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to | ||||
| ;waitForJ, ensure that this prerequisite is met. | ||||
| waitForJ: | ||||
|     inc     YL | ||||
|     sbis    USBIN, USBMINUS | ||||
|     brne    waitForJ        ; just make sure we have ANY timeout | ||||
| ;------------------------------------------------------------------------------- | ||||
| ; The following code results in a sampling window of < 1/4 bit  | ||||
| ;	which meets the spec. | ||||
| ;------------------------------------------------------------------------------- | ||||
| waitForK:			 ;-  | ||||
|     sbis    USBIN, USBMINUS      ;1 [00] <-- sample | ||||
|     rjmp    foundK               ;2 [01] | ||||
|     sbis    USBIN, USBMINUS	 ;	 <-- sample | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS	 ;	 <-- sample | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS	 ;	 <-- sample | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS	 ;	 <-- sample | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS	 ;	 <-- sample | ||||
|     rjmp    foundK | ||||
| #if USB_COUNT_SOF | ||||
|     lds     YL, usbSofCount | ||||
|     inc     YL | ||||
|     sts     usbSofCount, YL | ||||
| #endif  /* USB_COUNT_SOF */ | ||||
| #ifdef USB_SOF_HOOK | ||||
|     USB_SOF_HOOK | ||||
| #endif | ||||
|     rjmp    sofError | ||||
| ;------------------------------------------------------------------------------ | ||||
| ; {3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for  | ||||
| ;	center sampling]  | ||||
| ; 	we have 1 bit time for setup purposes, then sample again.  | ||||
| ;	Numbers in brackets are cycles from center of first sync (double K)  | ||||
| ;	bit after the instruction | ||||
| ;------------------------------------------------------------------------------ | ||||
| foundK:                          ;- [02] | ||||
|     lds     YL, usbInputBufOffset;2 [03+04]	tx loop | ||||
|     push    YH                   ;2 [05+06] | ||||
|     clr     YH                   ;1 [07] | ||||
|     subi    YL, lo8(-(usbRxBuf)) ;1 [08] 	[rx loop init] | ||||
|     sbci    YH, hi8(-(usbRxBuf)) ;1 [09] 	[rx loop init] | ||||
|     push    shift                ;2 [10+11] | ||||
|     ser	    shift		 ;1 [12] | ||||
|     sbis    USBIN, USBMINUS      ;1 [-1] [13] <--sample:we want two bits K (sample 1 cycle too early) | ||||
|     rjmp    haveTwoBitsK         ;2 [00] [14] | ||||
|     pop     shift                ;2 	 [15+16] undo the push from before | ||||
|     pop     YH 			 ;2 	 [17+18] undo the push from before | ||||
|     rjmp    waitForK             ;2 	 [19+20] this was not the end of sync, retry | ||||
| ; The entire loop from waitForK until rjmp waitForK above must not exceed two | ||||
| ; bit times (= 20 cycles). | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; push more registers and initialize values while we sample the first bits: | ||||
| ;---------------------------------------------------------------------------- | ||||
| haveTwoBitsK:			;- [01] | ||||
|     push    x1              	;2 [02+03] | ||||
|     push    x2              	;2 [04+05] | ||||
|     push    x3              	;2 [06+07] | ||||
|     push    bitcnt              ;2 [08+09]	 | ||||
|     in      x1, USBIN       	;1 [00] [10] <-- sample bit 0 | ||||
|     bst     x1, USBMINUS    	;1 [01] | ||||
|     bld     shift, 0        	;1 [02] | ||||
|     push    cnt             	;2 [03+04] | ||||
|     ldi     cnt, USB_BUFSIZE	;1 [05]  | ||||
|     push    x4              	;2 [06+07] tx loop | ||||
|     rjmp    rxLoop          	;2 [08] | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Receiver loop (numbers in brackets are cycles within byte after instr) | ||||
| ;---------------------------------------------------------------------------- | ||||
| unstuff0:               	;- [07] (branch taken) | ||||
|     andi    x3, ~0x01   	;1 [08] | ||||
|     mov     x1, x2      	;1 [09] x2 contains last sampled (stuffed) bit | ||||
|     in      x2, USBIN   	;1 [00] [10] <-- sample bit 1 again | ||||
|     andi    x2, USBMASK 	;1 [01] | ||||
|     breq    se0Hop         	;1 [02] SE0 check for bit 1  | ||||
|     ori     shift, 0x01 	;1 [03] 0b00000001 | ||||
|     nop				;1 [04] | ||||
|     rjmp    didUnstuff0 	;2 [05] | ||||
| ;----------------------------------------------------- | ||||
| unstuff1:               	;- [05] (branch taken) | ||||
|     mov     x2, x1      	;1 [06] x1 contains last sampled (stuffed) bit | ||||
|     andi    x3, ~0x02   	;1 [07] | ||||
|     ori     shift, 0x02 	;1 [08] 0b00000010 | ||||
|     nop                 	;1 [09] | ||||
|     in      x1, USBIN   	;1 [00] [10] <-- sample bit 2 again | ||||
|     andi    x1, USBMASK 	;1 [01] | ||||
|     breq    se0Hop         	;1 [02] SE0 check for bit 2  | ||||
|     rjmp    didUnstuff1 	;2 [03] | ||||
| ;----------------------------------------------------- | ||||
| unstuff2:               	;- [05] (branch taken) | ||||
|     andi    x3, ~0x04   	;1 [06] | ||||
|     ori     shift, 0x04 	;1 [07] 0b00000100 | ||||
|     mov     x1, x2      	;1 [08] x2 contains last sampled (stuffed) bit | ||||
|     nop                 	;1 [09] | ||||
|     in      x2, USBIN   	;1 [00] [10] <-- sample bit 3 | ||||
|     andi    x2, USBMASK 	;1 [01] | ||||
|     breq    se0Hop         	;1 [02] SE0 check for bit 3  | ||||
|     rjmp    didUnstuff2 	;2 [03] | ||||
| ;----------------------------------------------------- | ||||
| unstuff3:               	;- [00] [10]  (branch taken) | ||||
|     in      x2, USBIN   	;1 [01] [11] <-- sample stuffed bit 3 one cycle too late | ||||
|     andi    x2, USBMASK 	;1 [02] | ||||
|     breq    se0Hop         	;1 [03] SE0 check for stuffed bit 3  | ||||
|     andi    x3, ~0x08   	;1 [04] | ||||
|     ori     shift, 0x08 	;1 [05] 0b00001000 | ||||
|     rjmp    didUnstuff3 	;2 [06] | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; extra jobs done during bit interval: | ||||
| ; | ||||
| ; bit 0:    store, clear [SE0 is unreliable here due to bit dribbling in hubs],  | ||||
| ; 		overflow check, jump to the head of rxLoop | ||||
| ; bit 1:    SE0 check | ||||
| ; bit 2:    SE0 check, recovery from delay [bit 0 tasks took too long] | ||||
| ; bit 3:    SE0 check, recovery from delay [bit 0 tasks took too long] | ||||
| ; bit 4:    SE0 check, none | ||||
| ; bit 5:    SE0 check, none | ||||
| ; bit 6:    SE0 check, none | ||||
| ; bit 7:    SE0 check, reconstruct: x3 is 0 at bit locations we changed, 1 at others | ||||
| ;---------------------------------------------------------------------------- | ||||
| rxLoop:				;- [09] | ||||
|     in      x2, USBIN   	;1 [00] [10] <-- sample bit 1 (or possibly bit 0 stuffed) | ||||
|     andi    x2, USBMASK 	;1 [01] | ||||
|     brne    SkipSe0Hop		;1 [02] | ||||
| se0Hop:				;- [02] | ||||
|     rjmp    se0         	;2 [03] SE0 check for bit 1  | ||||
| SkipSe0Hop:			;- [03] | ||||
|     ser     x3          	;1 [04] | ||||
|     andi    shift, 0xf9 	;1 [05] 0b11111001 | ||||
|     breq    unstuff0    	;1 [06] | ||||
| didUnstuff0:			;- [06] | ||||
|     eor     x1, x2      	;1 [07] | ||||
|     bst     x1, USBMINUS	;1 [08] | ||||
|     bld     shift, 1    	;1 [09]  | ||||
|     in      x1, USBIN   	;1 [00] [10] <-- sample bit 2 (or possibly bit 1 stuffed) | ||||
|     andi    x1, USBMASK 	;1 [01] | ||||
|     breq    se0Hop         	;1 [02] SE0 check for bit 2  | ||||
|     andi    shift, 0xf3 	;1 [03] 0b11110011 | ||||
|     breq    unstuff1    	;1 [04] do remaining work for bit 1 | ||||
| didUnstuff1:			;- [04] | ||||
|     eor     x2, x1      	;1 [05] | ||||
|     bst     x2, USBMINUS	;1 [06] | ||||
|     bld     shift, 2    	;1 [07] | ||||
|     nop2			;2 [08+09] | ||||
|     in      x2, USBIN   	;1 [00] [10] <-- sample bit 3 (or possibly bit 2 stuffed) | ||||
|     andi    x2, USBMASK 	;1 [01] | ||||
|     breq    se0Hop         	;1 [02] SE0 check for bit 3  | ||||
|     andi    shift, 0xe7 	;1 [03] 0b11100111 | ||||
|     breq    unstuff2    	;1 [04] | ||||
| didUnstuff2:			;- [04] | ||||
|     eor     x1, x2      	;1 [05] | ||||
|     bst     x1, USBMINUS	;1 [06] | ||||
|     bld     shift, 3    	;1 [07] | ||||
| didUnstuff3:			;- [07] | ||||
|     andi    shift, 0xcf 	;1 [08] 0b11001111 | ||||
|     breq    unstuff3    	;1 [09] | ||||
|     in      x1, USBIN   	;1 [00] [10] <-- sample bit 4 | ||||
|     andi    x1, USBMASK 	;1 [01] | ||||
|     breq    se0Hop         	;1 [02] SE0 check for bit 4 | ||||
|     eor     x2, x1      	;1 [03] | ||||
|     bst     x2, USBMINUS	;1 [04] | ||||
|     bld     shift, 4    	;1 [05] | ||||
| didUnstuff4:			;- [05] | ||||
|     andi    shift, 0x9f 	;1 [06] 0b10011111 | ||||
|     breq    unstuff4    	;1 [07] | ||||
|     nop2			;2 [08+09] | ||||
|     in      x2, USBIN   	;1 [00] [10] <-- sample bit 5 | ||||
|     andi    x2, USBMASK 	;1 [01] | ||||
|     breq    se0         	;1 [02] SE0 check for bit 5 | ||||
|     eor     x1, x2      	;1 [03] | ||||
|     bst     x1, USBMINUS	;1 [04] | ||||
|     bld     shift, 5    	;1 [05] | ||||
| didUnstuff5:			;- [05] | ||||
|     andi    shift, 0x3f 	;1 [06] 0b00111111 | ||||
|     breq    unstuff5    	;1 [07] | ||||
|     nop2			;2 [08+09] | ||||
|     in      x1, USBIN   	;1 [00] [10] <-- sample bit 6 | ||||
|     andi    x1, USBMASK 	;1 [01] | ||||
|     breq    se0         	;1 [02] SE0 check for bit 6 | ||||
|     eor     x2, x1      	;1 [03] | ||||
|     bst     x2, USBMINUS	;1 [04] | ||||
|     bld     shift, 6   	 	;1 [05] | ||||
| didUnstuff6:			;- [05] | ||||
|     cpi     shift, 0x02 	;1 [06] 0b00000010 | ||||
|     brlo    unstuff6    	;1 [07] | ||||
|     nop2			;2 [08+09] | ||||
|     in      x2, USBIN   	;1 [00] [10] <-- sample bit 7 | ||||
|     andi    x2, USBMASK 	;1 [01] | ||||
|     breq    se0         	;1 [02] SE0 check for bit 7 | ||||
|     eor     x1, x2      	;1 [03] | ||||
|     bst     x1, USBMINUS	;1 [04] | ||||
|     bld     shift, 7    	;1 [05] | ||||
| didUnstuff7:			;- [05]  | ||||
|     cpi     shift, 0x04 	;1 [06] 0b00000100 | ||||
|     brlo    unstuff7		;1 [07] | ||||
|     eor     x3, shift   	;1 [08] reconstruct: x3 is 0 at bit locations we changed, 1 at others | ||||
|     nop				;1 [09] | ||||
|     in      x1, USBIN   	;1 [00]	[10] <-- sample bit 0 | ||||
|     st      y+, x3      	;2 [01+02] store data | ||||
|     eor     x2, x1      	;1 [03] | ||||
|     bst     x2, USBMINUS	;1 [04] | ||||
|     bld     shift, 0    	;1 [05] | ||||
|     subi    cnt, 1		;1 [06] | ||||
|     brcs    overflow	;1 [07] | ||||
|     rjmp    rxLoop		;2 [08] | ||||
| ;----------------------------------------------------- | ||||
| unstuff4:               	;- [08]  | ||||
|     andi    x3, ~0x10   	;1 [09] | ||||
|     in      x1, USBIN   	;1 [00] [10] <-- sample stuffed bit 4 | ||||
|     andi    x1, USBMASK 	;1 [01] | ||||
|     breq    se0         	;1 [02] SE0 check for stuffed bit 4 | ||||
|     ori     shift, 0x10 	;1 [03] | ||||
|     rjmp    didUnstuff4 	;2 [04] | ||||
| ;----------------------------------------------------- | ||||
| unstuff5:               	;- [08]  | ||||
|     ori     shift, 0x20 	;1 [09] | ||||
|     in      x2, USBIN   	;1 [00] [10] <-- sample stuffed bit 5 | ||||
|     andi    x2, USBMASK 	;1 [01] | ||||
|     breq    se0         	;1 [02] SE0 check for stuffed bit 5 | ||||
|     andi    x3, ~0x20   	;1 [03] | ||||
|     rjmp    didUnstuff5		;2 [04] | ||||
| ;----------------------------------------------------- | ||||
| unstuff6:               	;- [08]  | ||||
|     andi    x3, ~0x40   	;1 [09] | ||||
|     in      x1, USBIN   	;1 [00] [10] <-- sample stuffed bit 6 | ||||
|     andi    x1, USBMASK 	;1 [01] | ||||
|     breq    se0         	;1 [02] SE0 check for stuffed bit 6 | ||||
|     ori     shift, 0x40 	;1 [03] | ||||
|     rjmp    didUnstuff6 	;2 [04] | ||||
| ;----------------------------------------------------- | ||||
| unstuff7:			;- [08] | ||||
|     andi    x3, ~0x80   	;1 [09] | ||||
|     in      x2, USBIN   	;1 [00] [10] <-- sample stuffed bit 7 | ||||
|     andi    x2, USBMASK 	;1 [01] | ||||
|     breq    se0         	;1 [02] SE0 check for stuffed bit 7 | ||||
|     ori     shift, 0x80 	;1 [03] | ||||
|     rjmp    didUnstuff7 	;2 [04] | ||||
|      | ||||
| macro POP_STANDARD ; 16 cycles | ||||
|     pop     x4     | ||||
|     pop     cnt | ||||
|     pop     bitcnt | ||||
|     pop     x3 | ||||
|     pop     x2 | ||||
|     pop     x1 | ||||
|     pop     shift | ||||
|     pop     YH | ||||
|     endm | ||||
| macro POP_RETI     ; 5 cycles | ||||
|     pop     YL | ||||
|     out     SREG, YL | ||||
|     pop     YL | ||||
|     endm | ||||
|  | ||||
| #include "asmcommon.inc" | ||||
|  | ||||
| ;--------------------------------------------------------------------------- | ||||
| ; USB spec says: | ||||
| ; idle = J | ||||
| ; J = (D+ = 0), (D- = 1) | ||||
| ; K = (D+ = 1), (D- = 0) | ||||
| ; Spec allows 7.5 bit times from EOP to SOP for replies | ||||
| ;--------------------------------------------------------------------------- | ||||
| bitstuffN:		    	;- [04] | ||||
|     eor     x1, x4          	;1 [05] | ||||
|     clr	    x2			;1 [06] | ||||
|     nop				;1 [07] | ||||
|     rjmp    didStuffN       	;1 [08] | ||||
| ;---------------------------------------------------------------------------     | ||||
| bitstuff6:		    	;- [04] | ||||
|     eor     x1, x4          	;1 [05] | ||||
|     clr	    x2			;1 [06] | ||||
|     rjmp    didStuff6       	;1 [07] | ||||
| ;--------------------------------------------------------------------------- | ||||
| bitstuff7:		    	;- [02] | ||||
|     eor     x1, x4          	;1 [03] | ||||
|     clr	    x2			;1 [06] | ||||
|     nop			    	;1 [05] | ||||
|     rjmp    didStuff7       	;1 [06] | ||||
| ;--------------------------------------------------------------------------- | ||||
| sendNakAndReti:			;- [-19] | ||||
|     ldi     x3, USBPID_NAK  	;1 [-18] | ||||
|     rjmp    sendX3AndReti   	;1 [-17] | ||||
| ;--------------------------------------------------------------------------- | ||||
| sendAckAndReti:			;- [-17] | ||||
|     ldi     cnt, USBPID_ACK 	;1 [-16] | ||||
| sendCntAndReti:			;- [-16] | ||||
|     mov     x3, cnt         	;1 [-15] | ||||
| sendX3AndReti:			;- [-15] | ||||
|     ldi     YL, 20          	;1 [-14] x3==r20 address is 20 | ||||
|     ldi     YH, 0           	;1 [-13] | ||||
|     ldi     cnt, 2          	;1 [-12] | ||||
| ;   rjmp    usbSendAndReti      fallthrough | ||||
| ;--------------------------------------------------------------------------- | ||||
| ;usbSend: | ||||
| ;pointer to data in 'Y' | ||||
| ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] | ||||
| ;uses: x1...x4, btcnt, shift, cnt, Y | ||||
| ;Numbers in brackets are time since first bit of sync pattern is sent | ||||
| ;We need not to match the transfer rate exactly because the spec demands  | ||||
| ;only 1.5% precision anyway. | ||||
| usbSendAndReti:             	;- [-13] 13 cycles until SOP | ||||
|     in      x2, USBDDR      	;1 [-12] | ||||
|     ori     x2, USBMASK     	;1 [-11] | ||||
|     sbi     USBOUT, USBMINUS	;2 [-09-10] prepare idle state; D+ and D- must have been 0 (no pullups) | ||||
|     in      x1, USBOUT      	;1 [-08] port mirror for tx loop | ||||
|     out     USBDDR, x2      	;1 [-07] <- acquire bus | ||||
| 	; need not init x2 (bitstuff history) because sync starts with 0  | ||||
|     ldi     x4, USBMASK     	;1 [-06] 	exor mask | ||||
|     ldi     shift, 0x80     	;1 [-05] 	sync byte is first byte sent | ||||
|     ldi     bitcnt, 6    	;1 [-04]  | ||||
| txBitLoop:		    	;- [-04] [06] | ||||
|     sbrs    shift, 0        	;1 [-03] [07] | ||||
|     eor     x1, x4          	;1 [-02] [08]  | ||||
|     ror     shift           	;1 [-01] [09]   | ||||
| didStuffN:		    	;-       [09] | ||||
|     out     USBOUT, x1      	;1 [00]  [10] <-- out N | ||||
|     ror     x2              	;1 [01] | ||||
|     cpi     x2, 0xfc        	;1 [02] | ||||
|     brcc    bitstuffN       	;1 [03] | ||||
|     dec     bitcnt          	;1 [04] | ||||
|     brne    txBitLoop       	;1 [05] | ||||
|     sbrs    shift, 0        	;1 [06] | ||||
|     eor     x1, x4          	;1 [07] | ||||
|     ror     shift           	;1 [08] | ||||
| didStuff6:			;- [08] | ||||
|     nop				;1 [09] | ||||
|     out     USBOUT, x1      	;1 [00] [10] <-- out 6 | ||||
|     ror     x2              	;1 [01]  | ||||
|     cpi     x2, 0xfc        	;1 [02] | ||||
|     brcc    bitstuff6       	;1 [03] | ||||
|     sbrs    shift, 0        	;1 [04] | ||||
|     eor     x1, x4          	;1 [05] | ||||
|     ror     shift           	;1 [06] | ||||
|     ror     x2              	;1 [07] | ||||
| didStuff7:			;- [07] | ||||
|     ldi     bitcnt, 6    	;1 [08] | ||||
|     cpi     x2, 0xfc        	;1 [09] | ||||
|     out     USBOUT, x1      	;1 [00] [10] <-- out 7 | ||||
|     brcc    bitstuff7       	;1 [01] | ||||
|     ld      shift, y+       	;2 [02+03] | ||||
|     dec     cnt             	;1 [04] | ||||
|     brne    txBitLoop      	;1 [05] | ||||
| makeSE0: | ||||
|     cbr     x1, USBMASK     	;1 [06] 	prepare SE0 [spec says EOP may be 19 to 23 cycles] | ||||
|     lds     x2, usbNewDeviceAddr;2 [07+08] | ||||
|     lsl     x2                  ;1 [09] we compare with left shifted address | ||||
| ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: | ||||
| ;set address only after data packet was sent, not after handshake | ||||
|     out     USBOUT, x1      	;1 [00] [10] <-- out SE0-- from now 2 bits==20 cycl. until bus idle | ||||
|     subi    YL, 20 + 2          ;1 [01] Only assign address on data packets, not ACK/NAK in x3 | ||||
|     sbci    YH, 0           	;1 [02] | ||||
|     breq    skipAddrAssign  	;1 [03] | ||||
|     sts     usbDeviceAddr, x2	;2 [04+05] if not skipped: SE0 is one cycle longer | ||||
| ;---------------------------------------------------------------------------- | ||||
| ;end of usbDeviceAddress transfer | ||||
| skipAddrAssign:				;- [03/04] | ||||
|     ldi     x2, 1<<USB_INTR_PENDING_BIT	;1 [05] int0 occurred during TX -- clear pending flag | ||||
|     USB_STORE_PENDING(x2)           ;1 [06] | ||||
|     ori     x1, USBIDLE     		;1 [07] | ||||
|     in      x2, USBDDR      		;1 [08] | ||||
|     cbr     x2, USBMASK     		;1 [09] set both pins to input | ||||
|     mov     x3, x1          		;1 [10] | ||||
|     cbr     x3, USBMASK     		;1 [11] configure no pullup on both pins | ||||
|     ldi     x4, 3           		;1 [12] | ||||
| se0Delay:				;- [12] [15]  | ||||
|     dec     x4              		;1 [13] [16]  | ||||
|     brne    se0Delay        		;1 [14] [17]  | ||||
|     nop2				;2      [18+19] | ||||
|     out     USBOUT, x1      		;1      [20] <--out J (idle) -- end of SE0 (EOP sig.) | ||||
|     out     USBDDR, x2      		;1      [21] <--release bus now | ||||
|     out     USBOUT, x3      		;1      [22] <--ensure no pull-up resistors are active | ||||
|     rjmp    doReturn			;1	[23] | ||||
| ;--------------------------------------------------------------------------- | ||||
							
								
								
									
										345
									
								
								usbdrv/usbdrvasm16.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										345
									
								
								usbdrv/usbdrvasm16.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,345 @@ | ||||
| /* Name: usbdrvasm16.inc | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2007-06-15 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* Do not link this file! Link usbdrvasm.S instead, which includes the | ||||
|  * appropriate implementation! | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file is the 16 MHz version of the asssembler part of the USB driver. It | ||||
| requires a 16 MHz crystal (not a ceramic resonator and not a calibrated RC | ||||
| oscillator). | ||||
|  | ||||
| See usbdrv.h for a description of the entire driver. | ||||
|  | ||||
| Since almost all of this code is timing critical, don't change unless you | ||||
| really know what you are doing! Many parts require not only a maximum number | ||||
| of CPU cycles, but even an exact number of cycles! | ||||
| */ | ||||
|  | ||||
| ;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes | ||||
| ;nominal frequency: 16 MHz -> 10.6666666 cycles per bit, 85.333333333 cycles per byte | ||||
| ; Numbers in brackets are clocks counted from center of last sync bit | ||||
| ; when instruction starts | ||||
|  | ||||
| USB_INTR_VECTOR: | ||||
| ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt | ||||
|     push    YL                  ;[-25] push only what is necessary to sync with edge ASAP | ||||
|     in      YL, SREG            ;[-23] | ||||
|     push    YL                  ;[-22] | ||||
|     push    YH                  ;[-20] | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Synchronize with sync pattern: | ||||
| ;---------------------------------------------------------------------------- | ||||
| ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] | ||||
| ;sync up with J to K edge during sync pattern -- use fastest possible loops | ||||
| ;The first part waits at most 1 bit long since we must be in sync pattern. | ||||
| ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to | ||||
| ;waitForJ, ensure that this prerequisite is met. | ||||
| waitForJ: | ||||
|     inc     YL | ||||
|     sbis    USBIN, USBMINUS | ||||
|     brne    waitForJ        ; just make sure we have ANY timeout | ||||
| waitForK: | ||||
| ;The following code results in a sampling window of < 1/4 bit which meets the spec. | ||||
|     sbis    USBIN, USBMINUS     ;[-15] | ||||
|     rjmp    foundK              ;[-14] | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
| #if USB_COUNT_SOF | ||||
|     lds     YL, usbSofCount | ||||
|     inc     YL | ||||
|     sts     usbSofCount, YL | ||||
| #endif  /* USB_COUNT_SOF */ | ||||
| #ifdef USB_SOF_HOOK | ||||
|     USB_SOF_HOOK | ||||
| #endif | ||||
|     rjmp    sofError | ||||
| foundK:                         ;[-12] | ||||
| ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling] | ||||
| ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets | ||||
| ;are cycles from center of first sync (double K) bit after the instruction | ||||
|     push    bitcnt              ;[-12] | ||||
| ;   [---]                       ;[-11] | ||||
|     lds     YL, usbInputBufOffset;[-10] | ||||
| ;   [---]                       ;[-9] | ||||
|     clr     YH                  ;[-8] | ||||
|     subi    YL, lo8(-(usbRxBuf));[-7] [rx loop init] | ||||
|     sbci    YH, hi8(-(usbRxBuf));[-6] [rx loop init] | ||||
|     push    shift               ;[-5] | ||||
| ;   [---]                       ;[-4] | ||||
|     ldi     bitcnt, 0x55        ;[-3] [rx loop init] | ||||
|     sbis    USBIN, USBMINUS     ;[-2] we want two bits K (sample 2 cycles too early) | ||||
|     rjmp    haveTwoBitsK        ;[-1] | ||||
|     pop     shift               ;[0] undo the push from before | ||||
|     pop     bitcnt              ;[2] undo the push from before | ||||
|     rjmp    waitForK            ;[4] this was not the end of sync, retry | ||||
| ; The entire loop from waitForK until rjmp waitForK above must not exceed two | ||||
| ; bit times (= 21 cycles). | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; push more registers and initialize values while we sample the first bits: | ||||
| ;---------------------------------------------------------------------------- | ||||
| haveTwoBitsK: | ||||
|     push    x1              ;[1] | ||||
|     push    x2              ;[3] | ||||
|     push    x3              ;[5] | ||||
|     ldi     shift, 0        ;[7] | ||||
|     ldi     x3, 1<<4        ;[8] [rx loop init] first sample is inverse bit, compensate that | ||||
|     push    x4              ;[9] == leap | ||||
|  | ||||
|     in      x1, USBIN       ;[11] <-- sample bit 0 | ||||
|     andi    x1, USBMASK     ;[12] | ||||
|     bst     x1, USBMINUS    ;[13] | ||||
|     bld     shift, 7        ;[14] | ||||
|     push    cnt             ;[15] | ||||
|     ldi     leap, 0         ;[17] [rx loop init] | ||||
|     ldi     cnt, USB_BUFSIZE;[18] [rx loop init] | ||||
|     rjmp    rxbit1          ;[19] arrives at [21] | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Receiver loop (numbers in brackets are cycles within byte after instr) | ||||
| ;---------------------------------------------------------------------------- | ||||
|  | ||||
| ; duration of unstuffing code should be 10.66666667 cycles. We adjust "leap" | ||||
| ; accordingly to approximate this value in the long run. | ||||
|  | ||||
| unstuff6: | ||||
|     andi    x2, USBMASK ;[03] | ||||
|     ori     x3, 1<<6    ;[04] will not be shifted any more | ||||
|     andi    shift, ~0x80;[05] | ||||
|     mov     x1, x2      ;[06] sampled bit 7 is actually re-sampled bit 6 | ||||
|     subi    leap, -1    ;[07] total duration = 11 bits -> subtract 1/3 | ||||
|     rjmp    didUnstuff6 ;[08] | ||||
|  | ||||
| unstuff7: | ||||
|     ori     x3, 1<<7    ;[09] will not be shifted any more | ||||
|     in      x2, USBIN   ;[00] [10]  re-sample bit 7 | ||||
|     andi    x2, USBMASK ;[01] | ||||
|     andi    shift, ~0x80;[02] | ||||
|     subi    leap, 2     ;[03] total duration = 10 bits -> add 1/3 | ||||
|     rjmp    didUnstuff7 ;[04] | ||||
|  | ||||
| unstuffEven: | ||||
|     ori     x3, 1<<6    ;[09] will be shifted right 6 times for bit 0 | ||||
|     in      x1, USBIN   ;[00] [10] | ||||
|     andi    shift, ~0x80;[01] | ||||
|     andi    x1, USBMASK ;[02] | ||||
|     breq    se0         ;[03] | ||||
|     subi    leap, -1    ;[04] total duration = 11 bits -> subtract 1/3 | ||||
|     nop2                ;[05] | ||||
|     rjmp    didUnstuffE ;[06] | ||||
|  | ||||
| unstuffOdd: | ||||
|     ori     x3, 1<<5    ;[09] will be shifted right 4 times for bit 1 | ||||
|     in      x2, USBIN   ;[00] [10] | ||||
|     andi    shift, ~0x80;[01] | ||||
|     andi    x2, USBMASK ;[02] | ||||
|     breq    se0         ;[03] | ||||
|     subi    leap, -1    ;[04] total duration = 11 bits -> subtract 1/3 | ||||
|     nop2                ;[05] | ||||
|     rjmp    didUnstuffO ;[06] | ||||
|  | ||||
| rxByteLoop: | ||||
|     andi    x1, USBMASK ;[03] | ||||
|     eor     x2, x1      ;[04] | ||||
|     subi    leap, 1     ;[05] | ||||
|     brpl    skipLeap    ;[06] | ||||
|     subi    leap, -3    ;1 one leap cycle every 3rd byte -> 85 + 1/3 cycles per byte | ||||
|     nop                 ;1 | ||||
| skipLeap: | ||||
|     subi    x2, 1       ;[08] | ||||
|     ror     shift       ;[09] | ||||
| didUnstuff6: | ||||
|     cpi     shift, 0xfc ;[10] | ||||
|     in      x2, USBIN   ;[00] [11] <-- sample bit 7 | ||||
|     brcc    unstuff6    ;[01] | ||||
|     andi    x2, USBMASK ;[02] | ||||
|     eor     x1, x2      ;[03] | ||||
|     subi    x1, 1       ;[04] | ||||
|     ror     shift       ;[05] | ||||
| didUnstuff7: | ||||
|     cpi     shift, 0xfc ;[06] | ||||
|     brcc    unstuff7    ;[07] | ||||
|     eor     x3, shift   ;[08] reconstruct: x3 is 1 at bit locations we changed, 0 at others | ||||
|     st      y+, x3      ;[09] store data | ||||
| rxBitLoop: | ||||
|     in      x1, USBIN   ;[00] [11] <-- sample bit 0/2/4 | ||||
|     andi    x1, USBMASK ;[01] | ||||
|     eor     x2, x1      ;[02] | ||||
|     andi    x3, 0x3f    ;[03] topmost two bits reserved for 6 and 7 | ||||
|     subi    x2, 1       ;[04] | ||||
|     ror     shift       ;[05] | ||||
|     cpi     shift, 0xfc ;[06] | ||||
|     brcc    unstuffEven ;[07] | ||||
| didUnstuffE: | ||||
|     lsr     x3          ;[08] | ||||
|     lsr     x3          ;[09] | ||||
| rxbit1: | ||||
|     in      x2, USBIN   ;[00] [10] <-- sample bit 1/3/5 | ||||
|     andi    x2, USBMASK ;[01] | ||||
|     breq    se0         ;[02] | ||||
|     eor     x1, x2      ;[03] | ||||
|     subi    x1, 1       ;[04] | ||||
|     ror     shift       ;[05] | ||||
|     cpi     shift, 0xfc ;[06] | ||||
|     brcc    unstuffOdd  ;[07] | ||||
| didUnstuffO: | ||||
|     subi    bitcnt, 0xab;[08] == addi 0x55, 0x55 = 0x100/3 | ||||
|     brcs    rxBitLoop   ;[09] | ||||
|  | ||||
|     subi    cnt, 1      ;[10] | ||||
|     in      x1, USBIN   ;[00] [11] <-- sample bit 6 | ||||
|     brcc    rxByteLoop  ;[01] | ||||
|     rjmp    overflow | ||||
|  | ||||
| macro POP_STANDARD ; 14 cycles | ||||
|     pop     cnt | ||||
|     pop     x4 | ||||
|     pop     x3 | ||||
|     pop     x2 | ||||
|     pop     x1 | ||||
|     pop     shift | ||||
|     pop     bitcnt | ||||
|     endm | ||||
| macro POP_RETI     ; 7 cycles | ||||
|     pop     YH | ||||
|     pop     YL | ||||
|     out     SREG, YL | ||||
|     pop     YL | ||||
|     endm | ||||
|  | ||||
| #include "asmcommon.inc" | ||||
|  | ||||
| ; USB spec says: | ||||
| ; idle = J | ||||
| ; J = (D+ = 0), (D- = 1) | ||||
| ; K = (D+ = 1), (D- = 0) | ||||
| ; Spec allows 7.5 bit times from EOP to SOP for replies | ||||
|  | ||||
| bitstuffN: | ||||
|     eor     x1, x4          ;[5] | ||||
|     ldi     x2, 0           ;[6] | ||||
|     nop2                    ;[7] | ||||
|     nop                     ;[9] | ||||
|     out     USBOUT, x1      ;[10] <-- out | ||||
|     rjmp    didStuffN       ;[0] | ||||
|      | ||||
| bitstuff6: | ||||
|     eor     x1, x4          ;[5] | ||||
|     ldi     x2, 0           ;[6] Carry is zero due to brcc | ||||
|     rol     shift           ;[7] compensate for ror shift at branch destination | ||||
|     rjmp    didStuff6       ;[8] | ||||
|  | ||||
| bitstuff7: | ||||
|     ldi     x2, 0           ;[2] Carry is zero due to brcc | ||||
|     rjmp    didStuff7       ;[3] | ||||
|  | ||||
|  | ||||
| sendNakAndReti: | ||||
|     ldi     x3, USBPID_NAK  ;[-18] | ||||
|     rjmp    sendX3AndReti   ;[-17] | ||||
| sendAckAndReti: | ||||
|     ldi     cnt, USBPID_ACK ;[-17] | ||||
| sendCntAndReti: | ||||
|     mov     x3, cnt         ;[-16] | ||||
| sendX3AndReti: | ||||
|     ldi     YL, 20          ;[-15] x3==r20 address is 20 | ||||
|     ldi     YH, 0           ;[-14] | ||||
|     ldi     cnt, 2          ;[-13] | ||||
| ;   rjmp    usbSendAndReti      fallthrough | ||||
|  | ||||
| ;usbSend: | ||||
| ;pointer to data in 'Y' | ||||
| ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] | ||||
| ;uses: x1...x4, btcnt, shift, cnt, Y | ||||
| ;Numbers in brackets are time since first bit of sync pattern is sent | ||||
| ;We don't match the transfer rate exactly (don't insert leap cycles every third | ||||
| ;byte) because the spec demands only 1.5% precision anyway. | ||||
| usbSendAndReti:             ; 12 cycles until SOP | ||||
|     in      x2, USBDDR      ;[-12] | ||||
|     ori     x2, USBMASK     ;[-11] | ||||
|     sbi     USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) | ||||
|     in      x1, USBOUT      ;[-8] port mirror for tx loop | ||||
|     out     USBDDR, x2      ;[-7] <- acquire bus | ||||
| ; need not init x2 (bitstuff history) because sync starts with 0 | ||||
|     ldi     x4, USBMASK     ;[-6] exor mask | ||||
|     ldi     shift, 0x80     ;[-5] sync byte is first byte sent | ||||
| txByteLoop: | ||||
|     ldi     bitcnt, 0x35    ;[-4] [6] binary 0011 0101 | ||||
| txBitLoop: | ||||
|     sbrs    shift, 0        ;[-3] [7] | ||||
|     eor     x1, x4          ;[-2] [8] | ||||
|     out     USBOUT, x1      ;[-1] [9] <-- out N | ||||
|     ror     shift           ;[0] [10] | ||||
|     ror     x2              ;[1] | ||||
| didStuffN: | ||||
|     cpi     x2, 0xfc        ;[2] | ||||
|     brcc    bitstuffN       ;[3] | ||||
|     lsr     bitcnt          ;[4] | ||||
|     brcc    txBitLoop       ;[5] | ||||
|     brne    txBitLoop       ;[6] | ||||
|  | ||||
|     sbrs    shift, 0        ;[7] | ||||
|     eor     x1, x4          ;[8] | ||||
| didStuff6: | ||||
|     out     USBOUT, x1      ;[-1] [9] <-- out 6 | ||||
|     ror     shift           ;[0] [10] | ||||
|     ror     x2              ;[1] | ||||
|     cpi     x2, 0xfc        ;[2] | ||||
|     brcc    bitstuff6       ;[3] | ||||
|     ror     shift           ;[4] | ||||
| didStuff7: | ||||
|     ror     x2              ;[5] | ||||
|     sbrs    x2, 7           ;[6] | ||||
|     eor     x1, x4          ;[7] | ||||
|     nop                     ;[8] | ||||
|     cpi     x2, 0xfc        ;[9] | ||||
|     out     USBOUT, x1      ;[-1][10] <-- out 7 | ||||
|     brcc    bitstuff7       ;[0] [11] | ||||
|     ld      shift, y+       ;[1] | ||||
|     dec     cnt             ;[3] | ||||
|     brne    txByteLoop      ;[4] | ||||
| ;make SE0: | ||||
|     cbr     x1, USBMASK     ;[5] prepare SE0 [spec says EOP may be 21 to 25 cycles] | ||||
|     lds     x2, usbNewDeviceAddr;[6] | ||||
|     lsl     x2              ;[8] we compare with left shifted address | ||||
|     subi    YL, 20 + 2      ;[9] Only assign address on data packets, not ACK/NAK in x3 | ||||
|     sbci    YH, 0           ;[10] | ||||
|     out     USBOUT, x1      ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle | ||||
| ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: | ||||
| ;set address only after data packet was sent, not after handshake | ||||
|     breq    skipAddrAssign  ;[0] | ||||
|     sts     usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer | ||||
| skipAddrAssign: | ||||
| ;end of usbDeviceAddress transfer | ||||
|     ldi     x2, 1<<USB_INTR_PENDING_BIT;[2] int0 occurred during TX -- clear pending flag | ||||
|     USB_STORE_PENDING(x2)   ;[3] | ||||
|     ori     x1, USBIDLE     ;[4] | ||||
|     in      x2, USBDDR      ;[5] | ||||
|     cbr     x2, USBMASK     ;[6] set both pins to input | ||||
|     mov     x3, x1          ;[7] | ||||
|     cbr     x3, USBMASK     ;[8] configure no pullup on both pins | ||||
|     ldi     x4, 4           ;[9] | ||||
| se0Delay: | ||||
|     dec     x4              ;[10] [13] [16] [19] | ||||
|     brne    se0Delay        ;[11] [14] [17] [20] | ||||
|     out     USBOUT, x1      ;[21] <-- out J (idle) -- end of SE0 (EOP signal) | ||||
|     out     USBDDR, x2      ;[22] <-- release bus now | ||||
|     out     USBOUT, x3      ;[23] <-- ensure no pull-up resistors are active | ||||
|     rjmp    doReturn | ||||
							
								
								
									
										452
									
								
								usbdrv/usbdrvasm165.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										452
									
								
								usbdrv/usbdrvasm165.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,452 @@ | ||||
| /* Name: usbdrvasm165.inc | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2007-04-22 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* Do not link this file! Link usbdrvasm.S instead, which includes the | ||||
|  * appropriate implementation! | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file is the 16.5 MHz version of the USB driver. It is intended for the | ||||
| ATTiny45 and similar controllers running on 16.5 MHz internal RC oscillator. | ||||
| This version contains a phase locked loop in the receiver routine to cope with | ||||
| slight clock rate deviations of up to +/- 1%. | ||||
|  | ||||
| See usbdrv.h for a description of the entire driver. | ||||
|  | ||||
| Since almost all of this code is timing critical, don't change unless you | ||||
| really know what you are doing! Many parts require not only a maximum number | ||||
| of CPU cycles, but even an exact number of cycles! | ||||
| */ | ||||
|  | ||||
| ;Software-receiver engine. Strict timing! Don't change unless you can preserve timing! | ||||
| ;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled | ||||
| ;max allowable interrupt latency: 59 cycles -> max 52 cycles interrupt disable | ||||
| ;max stack usage: [ret(2), r0, SREG, YL, YH, shift, x1, x2, x3, x4, cnt] = 12 bytes | ||||
| ;nominal frequency: 16.5 MHz -> 11 cycles per bit | ||||
| ; 16.3125 MHz < F_CPU < 16.6875 MHz (+/- 1.1%) | ||||
| ; Numbers in brackets are clocks counted from center of last sync bit | ||||
| ; when instruction starts | ||||
|  | ||||
|  | ||||
| USB_INTR_VECTOR: | ||||
| ;order of registers pushed: YL, SREG [sofError], r0, YH, shift, x1, x2, x3, x4, cnt | ||||
|     push    YL                  ;[-23] push only what is necessary to sync with edge ASAP | ||||
|     in      YL, SREG            ;[-21] | ||||
|     push    YL                  ;[-20] | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Synchronize with sync pattern: | ||||
| ;---------------------------------------------------------------------------- | ||||
| ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] | ||||
| ;sync up with J to K edge during sync pattern -- use fastest possible loops | ||||
| ;The first part waits at most 1 bit long since we must be in sync pattern. | ||||
| ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to | ||||
| ;waitForJ, ensure that this prerequisite is met. | ||||
| waitForJ: | ||||
|     inc     YL | ||||
|     sbis    USBIN, USBMINUS | ||||
|     brne    waitForJ        ; just make sure we have ANY timeout | ||||
| waitForK: | ||||
| ;The following code results in a sampling window of < 1/4 bit which meets the spec. | ||||
|     sbis    USBIN, USBMINUS     ;[-15] | ||||
|     rjmp    foundK              ;[-14] | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
| #if USB_COUNT_SOF | ||||
|     lds     YL, usbSofCount | ||||
|     inc     YL | ||||
|     sts     usbSofCount, YL | ||||
| #endif  /* USB_COUNT_SOF */ | ||||
| #ifdef USB_SOF_HOOK | ||||
|     USB_SOF_HOOK | ||||
| #endif | ||||
|     rjmp    sofError | ||||
| foundK:                         ;[-12] | ||||
| ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling] | ||||
| ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets | ||||
| ;are cycles from center of first sync (double K) bit after the instruction | ||||
|     push    r0                  ;[-12] | ||||
| ;   [---]                       ;[-11] | ||||
|     push    YH                  ;[-10] | ||||
| ;   [---]                       ;[-9] | ||||
|     lds     YL, usbInputBufOffset;[-8] | ||||
| ;   [---]                       ;[-7] | ||||
|     clr     YH                  ;[-6] | ||||
|     subi    YL, lo8(-(usbRxBuf));[-5] [rx loop init] | ||||
|     sbci    YH, hi8(-(usbRxBuf));[-4] [rx loop init] | ||||
|     mov     r0, x2              ;[-3] [rx loop init] | ||||
|     sbis    USBIN, USBMINUS     ;[-2] we want two bits K (sample 2 cycles too early) | ||||
|     rjmp    haveTwoBitsK        ;[-1] | ||||
|     pop     YH                  ;[0] undo the pushes from before | ||||
|     pop     r0                  ;[2] | ||||
|     rjmp    waitForK            ;[4] this was not the end of sync, retry | ||||
| ; The entire loop from waitForK until rjmp waitForK above must not exceed two | ||||
| ; bit times (= 22 cycles). | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; push more registers and initialize values while we sample the first bits: | ||||
| ;---------------------------------------------------------------------------- | ||||
| haveTwoBitsK:               ;[1] | ||||
|     push    shift           ;[1] | ||||
|     push    x1              ;[3] | ||||
|     push    x2              ;[5] | ||||
|     push    x3              ;[7] | ||||
|     ldi     shift, 0xff     ;[9] [rx loop init] | ||||
|     ori     x3, 0xff        ;[10] [rx loop init] == ser x3, clear zero flag | ||||
|  | ||||
|     in      x1, USBIN       ;[11] <-- sample bit 0 | ||||
|     bst     x1, USBMINUS    ;[12] | ||||
|     bld     shift, 0        ;[13] | ||||
|     push    x4              ;[14] == phase | ||||
| ;   [---]                   ;[15] | ||||
|     push    cnt             ;[16] | ||||
| ;   [---]                   ;[17] | ||||
|     ldi     phase, 0        ;[18] [rx loop init] | ||||
|     ldi     cnt, USB_BUFSIZE;[19] [rx loop init] | ||||
|     rjmp    rxbit1          ;[20] | ||||
| ;   [---]                   ;[21] | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Receiver loop (numbers in brackets are cycles within byte after instr) | ||||
| ;---------------------------------------------------------------------------- | ||||
| /* | ||||
| byte oriented operations done during loop: | ||||
| bit 0: store data | ||||
| bit 1: SE0 check | ||||
| bit 2: overflow check | ||||
| bit 3: catch up | ||||
| bit 4: rjmp to achieve conditional jump range | ||||
| bit 5: PLL | ||||
| bit 6: catch up | ||||
| bit 7: jump, fixup bitstuff | ||||
| ; 87 [+ 2] cycles | ||||
| ------------------------------------------------------------------ | ||||
| */ | ||||
| continueWithBit5: | ||||
|     in      x2, USBIN       ;[055] <-- bit 5 | ||||
|     eor     r0, x2          ;[056] | ||||
|     or      phase, r0       ;[057] | ||||
|     sbrc    phase, USBMINUS ;[058] | ||||
|     lpm                     ;[059] optional nop3; modifies r0 | ||||
|     in      phase, USBIN    ;[060] <-- phase | ||||
|     eor     x1, x2          ;[061] | ||||
|     bst     x1, USBMINUS    ;[062] | ||||
|     bld     shift, 5        ;[063] | ||||
|     andi    shift, 0x3f     ;[064] | ||||
|     in      x1, USBIN       ;[065] <-- bit 6 | ||||
|     breq    unstuff5        ;[066] *** unstuff escape | ||||
|     eor     phase, x1       ;[067] | ||||
|     eor     x2, x1          ;[068] | ||||
|     bst     x2, USBMINUS    ;[069] | ||||
|     bld     shift, 6        ;[070] | ||||
| didUnstuff6:                ;[   ] | ||||
|     in      r0, USBIN       ;[071] <-- phase | ||||
|     cpi     shift, 0x02     ;[072] | ||||
|     brlo    unstuff6        ;[073] *** unstuff escape | ||||
| didUnstuff5:                ;[   ] | ||||
|     nop2                    ;[074] | ||||
| ;   [---]                   ;[075] | ||||
|     in      x2, USBIN       ;[076] <-- bit 7 | ||||
|     eor     x1, x2          ;[077] | ||||
|     bst     x1, USBMINUS    ;[078] | ||||
|     bld     shift, 7        ;[079] | ||||
| didUnstuff7:                ;[   ] | ||||
|     eor     r0, x2          ;[080] | ||||
|     or      phase, r0       ;[081] | ||||
|     in      r0, USBIN       ;[082] <-- phase | ||||
|     cpi     shift, 0x04     ;[083] | ||||
|     brsh    rxLoop          ;[084] | ||||
| ;   [---]                   ;[085] | ||||
| unstuff7:                   ;[   ] | ||||
|     andi    x3, ~0x80       ;[085] | ||||
|     ori     shift, 0x80     ;[086] | ||||
|     in      x2, USBIN       ;[087] <-- sample stuffed bit 7 | ||||
|     nop                     ;[088] | ||||
|     rjmp    didUnstuff7     ;[089] | ||||
| ;   [---]                   ;[090] | ||||
|                             ;[080] | ||||
|  | ||||
| unstuff5:                   ;[067] | ||||
|     eor     phase, x1       ;[068] | ||||
|     andi    x3, ~0x20       ;[069] | ||||
|     ori     shift, 0x20     ;[070] | ||||
|     in      r0, USBIN       ;[071] <-- phase | ||||
|     mov     x2, x1          ;[072] | ||||
|     nop                     ;[073] | ||||
|     nop2                    ;[074] | ||||
| ;   [---]                   ;[075] | ||||
|     in      x1, USBIN       ;[076] <-- bit 6 | ||||
|     eor     r0, x1          ;[077] | ||||
|     or      phase, r0       ;[078] | ||||
|     eor     x2, x1          ;[079] | ||||
|     bst     x2, USBMINUS    ;[080] | ||||
|     bld     shift, 6        ;[081] no need to check bitstuffing, we just had one | ||||
|     in      r0, USBIN       ;[082] <-- phase | ||||
|     rjmp    didUnstuff5     ;[083] | ||||
| ;   [---]                   ;[084] | ||||
|                             ;[074] | ||||
|  | ||||
| unstuff6:                   ;[074] | ||||
|     andi    x3, ~0x40       ;[075] | ||||
|     in      x1, USBIN       ;[076] <-- bit 6 again | ||||
|     ori     shift, 0x40     ;[077] | ||||
|     nop2                    ;[078] | ||||
| ;   [---]                   ;[079] | ||||
|     rjmp    didUnstuff6     ;[080] | ||||
| ;   [---]                   ;[081] | ||||
|                             ;[071] | ||||
|  | ||||
| unstuff0:                   ;[013] | ||||
|     eor     r0, x2          ;[014] | ||||
|     or      phase, r0       ;[015] | ||||
|     andi    x2, USBMASK     ;[016] check for SE0 | ||||
|     in      r0, USBIN       ;[017] <-- phase | ||||
|     breq    didUnstuff0     ;[018] direct jump to se0 would be too long | ||||
|     andi    x3, ~0x01       ;[019] | ||||
|     ori     shift, 0x01     ;[020] | ||||
|     mov     x1, x2          ;[021] mov existing sample | ||||
|     in      x2, USBIN       ;[022] <-- bit 1 again | ||||
|     rjmp    didUnstuff0     ;[023] | ||||
| ;   [---]                   ;[024] | ||||
|                             ;[014] | ||||
|  | ||||
| unstuff1:                   ;[024] | ||||
|     eor     r0, x1          ;[025] | ||||
|     or      phase, r0       ;[026] | ||||
|     andi    x3, ~0x02       ;[027] | ||||
|     in      r0, USBIN       ;[028] <-- phase | ||||
|     ori     shift, 0x02     ;[029] | ||||
|     mov     x2, x1          ;[030] | ||||
|     rjmp    didUnstuff1     ;[031] | ||||
| ;   [---]                   ;[032] | ||||
|                             ;[022] | ||||
|  | ||||
| unstuff2:                   ;[035] | ||||
|     eor     r0, x2          ;[036] | ||||
|     or      phase, r0       ;[037] | ||||
|     andi    x3, ~0x04       ;[038] | ||||
|     in      r0, USBIN       ;[039] <-- phase | ||||
|     ori     shift, 0x04     ;[040] | ||||
|     mov     x1, x2          ;[041] | ||||
|     rjmp    didUnstuff2     ;[042] | ||||
| ;   [---]                   ;[043] | ||||
|                             ;[033] | ||||
|  | ||||
| unstuff3:                   ;[043] | ||||
|     in      x2, USBIN       ;[044] <-- bit 3 again | ||||
|     eor     r0, x2          ;[045] | ||||
|     or      phase, r0       ;[046] | ||||
|     andi    x3, ~0x08       ;[047] | ||||
|     ori     shift, 0x08     ;[048] | ||||
|     nop                     ;[049] | ||||
|     in      r0, USBIN       ;[050] <-- phase | ||||
|     rjmp    didUnstuff3     ;[051] | ||||
| ;   [---]                   ;[052] | ||||
|                             ;[042] | ||||
|  | ||||
| unstuff4:                   ;[053] | ||||
|     andi    x3, ~0x10       ;[054] | ||||
|     in      x1, USBIN       ;[055] <-- bit 4 again | ||||
|     ori     shift, 0x10     ;[056] | ||||
|     rjmp    didUnstuff4     ;[057] | ||||
| ;   [---]                   ;[058] | ||||
|                             ;[048] | ||||
|  | ||||
| rxLoop:                     ;[085] | ||||
|     eor     x3, shift       ;[086] reconstruct: x3 is 0 at bit locations we changed, 1 at others | ||||
|     in      x1, USBIN       ;[000] <-- bit 0 | ||||
|     st      y+, x3          ;[001] | ||||
| ;   [---]                   ;[002] | ||||
|     eor     r0, x1          ;[003] | ||||
|     or      phase, r0       ;[004] | ||||
|     eor     x2, x1          ;[005] | ||||
|     in      r0, USBIN       ;[006] <-- phase | ||||
|     ser     x3              ;[007] | ||||
|     bst     x2, USBMINUS    ;[008] | ||||
|     bld     shift, 0        ;[009] | ||||
|     andi    shift, 0xf9     ;[010] | ||||
| rxbit1:                     ;[   ] | ||||
|     in      x2, USBIN       ;[011] <-- bit 1 | ||||
|     breq    unstuff0        ;[012] *** unstuff escape | ||||
|     andi    x2, USBMASK     ;[013] SE0 check for bit 1 | ||||
| didUnstuff0:                ;[   ] Z only set if we detected SE0 in bitstuff | ||||
|     breq    se0             ;[014] | ||||
|     eor     r0, x2          ;[015] | ||||
|     or      phase, r0       ;[016] | ||||
|     in      r0, USBIN       ;[017] <-- phase | ||||
|     eor     x1, x2          ;[018] | ||||
|     bst     x1, USBMINUS    ;[019] | ||||
|     bld     shift, 1        ;[020] | ||||
|     andi    shift, 0xf3     ;[021] | ||||
| didUnstuff1:                ;[   ] | ||||
|     in      x1, USBIN       ;[022] <-- bit 2 | ||||
|     breq    unstuff1        ;[023] *** unstuff escape | ||||
|     eor     r0, x1          ;[024] | ||||
|     or      phase, r0       ;[025] | ||||
|     subi    cnt, 1          ;[026] overflow check | ||||
|     brcs    overflow        ;[027] | ||||
|     in      r0, USBIN       ;[028] <-- phase | ||||
|     eor     x2, x1          ;[029] | ||||
|     bst     x2, USBMINUS    ;[030] | ||||
|     bld     shift, 2        ;[031] | ||||
|     andi    shift, 0xe7     ;[032] | ||||
| didUnstuff2:                ;[   ] | ||||
|     in      x2, USBIN       ;[033] <-- bit 3 | ||||
|     breq    unstuff2        ;[034] *** unstuff escape | ||||
|     eor     r0, x2          ;[035] | ||||
|     or      phase, r0       ;[036] | ||||
|     eor     x1, x2          ;[037] | ||||
|     bst     x1, USBMINUS    ;[038] | ||||
|     in      r0, USBIN       ;[039] <-- phase | ||||
|     bld     shift, 3        ;[040] | ||||
|     andi    shift, 0xcf     ;[041] | ||||
| didUnstuff3:                ;[   ] | ||||
|     breq    unstuff3        ;[042] *** unstuff escape | ||||
|     nop                     ;[043] | ||||
|     in      x1, USBIN       ;[044] <-- bit 4 | ||||
|     eor     x2, x1          ;[045] | ||||
|     bst     x2, USBMINUS    ;[046] | ||||
|     bld     shift, 4        ;[047] | ||||
| didUnstuff4:                ;[   ] | ||||
|     eor     r0, x1          ;[048] | ||||
|     or      phase, r0       ;[049] | ||||
|     in      r0, USBIN       ;[050] <-- phase | ||||
|     andi    shift, 0x9f     ;[051] | ||||
|     breq    unstuff4        ;[052] *** unstuff escape | ||||
|     rjmp    continueWithBit5;[053] | ||||
| ;   [---]                   ;[054] | ||||
|  | ||||
| macro POP_STANDARD ; 16 cycles | ||||
|     pop     cnt | ||||
|     pop     x4 | ||||
|     pop     x3 | ||||
|     pop     x2 | ||||
|     pop     x1 | ||||
|     pop     shift | ||||
|     pop     YH | ||||
|     pop     r0 | ||||
|     endm | ||||
| macro POP_RETI     ; 5 cycles | ||||
|     pop     YL | ||||
|     out     SREG, YL | ||||
|     pop     YL | ||||
|     endm | ||||
|  | ||||
| #include "asmcommon.inc" | ||||
|  | ||||
|  | ||||
| ; USB spec says: | ||||
| ; idle = J | ||||
| ; J = (D+ = 0), (D- = 1) | ||||
| ; K = (D+ = 1), (D- = 0) | ||||
| ; Spec allows 7.5 bit times from EOP to SOP for replies | ||||
|  | ||||
| bitstuff7: | ||||
|     eor     x1, x4          ;[4] | ||||
|     ldi     x2, 0           ;[5] | ||||
|     nop2                    ;[6] C is zero (brcc) | ||||
|     rjmp    didStuff7       ;[8] | ||||
|  | ||||
| bitstuffN: | ||||
|     eor     x1, x4          ;[5] | ||||
|     ldi     x2, 0           ;[6] | ||||
|     lpm                     ;[7] 3 cycle NOP, modifies r0 | ||||
|     out     USBOUT, x1      ;[10] <-- out | ||||
|     rjmp    didStuffN       ;[0] | ||||
|  | ||||
| #define bitStatus   x3 | ||||
|  | ||||
| sendNakAndReti: | ||||
|     ldi     cnt, USBPID_NAK ;[-19] | ||||
|     rjmp    sendCntAndReti  ;[-18] | ||||
| sendAckAndReti: | ||||
|     ldi     cnt, USBPID_ACK ;[-17] | ||||
| sendCntAndReti: | ||||
|     mov     r0, cnt         ;[-16] | ||||
|     ldi     YL, 0           ;[-15] R0 address is 0 | ||||
|     ldi     YH, 0           ;[-14] | ||||
|     ldi     cnt, 2          ;[-13] | ||||
| ;   rjmp    usbSendAndReti      fallthrough | ||||
|  | ||||
| ;usbSend: | ||||
| ;pointer to data in 'Y' | ||||
| ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] | ||||
| ;uses: x1...x4, shift, cnt, Y | ||||
| ;Numbers in brackets are time since first bit of sync pattern is sent | ||||
| usbSendAndReti:             ; 12 cycles until SOP | ||||
|     in      x2, USBDDR      ;[-12] | ||||
|     ori     x2, USBMASK     ;[-11] | ||||
|     sbi     USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) | ||||
|     in      x1, USBOUT      ;[-8] port mirror for tx loop | ||||
|     out     USBDDR, x2      ;[-7] <- acquire bus | ||||
| ; need not init x2 (bitstuff history) because sync starts with 0 | ||||
|     ldi     x4, USBMASK     ;[-6] exor mask | ||||
|     ldi     shift, 0x80     ;[-5] sync byte is first byte sent | ||||
|     ldi     bitStatus, 0xff ;[-4] init bit loop counter, works for up to 12 bytes | ||||
| byteloop: | ||||
| bitloop: | ||||
|     sbrs    shift, 0        ;[8] [-3] | ||||
|     eor     x1, x4          ;[9] [-2] | ||||
|     out     USBOUT, x1      ;[10] [-1] <-- out | ||||
|     ror     shift           ;[0] | ||||
|     ror     x2              ;[1] | ||||
| didStuffN: | ||||
|     cpi     x2, 0xfc        ;[2] | ||||
|     brcc    bitstuffN       ;[3] | ||||
|     nop                     ;[4] | ||||
|     subi    bitStatus, 37   ;[5] 256 / 7 ~=~ 37 | ||||
|     brcc    bitloop         ;[6] when we leave the loop, bitStatus has almost the initial value | ||||
|     sbrs    shift, 0        ;[7] | ||||
|     eor     x1, x4          ;[8] | ||||
|     ror     shift           ;[9] | ||||
| didStuff7: | ||||
|     out     USBOUT, x1      ;[10] <-- out | ||||
|     ror     x2              ;[0] | ||||
|     cpi     x2, 0xfc        ;[1] | ||||
|     brcc    bitstuff7       ;[2] | ||||
|     ld      shift, y+       ;[3] | ||||
|     dec     cnt             ;[5] | ||||
|     brne    byteloop        ;[6] | ||||
| ;make SE0: | ||||
|     cbr     x1, USBMASK     ;[7] prepare SE0 [spec says EOP may be 21 to 25 cycles] | ||||
|     lds     x2, usbNewDeviceAddr;[8] | ||||
|     lsl     x2              ;[10] we compare with left shifted address | ||||
|     out     USBOUT, x1      ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle | ||||
| ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: | ||||
| ;set address only after data packet was sent, not after handshake | ||||
|     subi    YL, 2           ;[0] Only assign address on data packets, not ACK/NAK in r0 | ||||
|     sbci    YH, 0           ;[1] | ||||
|     breq    skipAddrAssign  ;[2] | ||||
|     sts     usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer | ||||
| skipAddrAssign: | ||||
| ;end of usbDeviceAddress transfer | ||||
|     ldi     x2, 1<<USB_INTR_PENDING_BIT;[4] int0 occurred during TX -- clear pending flag | ||||
|     USB_STORE_PENDING(x2)   ;[5] | ||||
|     ori     x1, USBIDLE     ;[6] | ||||
|     in      x2, USBDDR      ;[7] | ||||
|     cbr     x2, USBMASK     ;[8] set both pins to input | ||||
|     mov     x3, x1          ;[9] | ||||
|     cbr     x3, USBMASK     ;[10] configure no pullup on both pins | ||||
|     ldi     x4, 4           ;[11] | ||||
| se0Delay: | ||||
|     dec     x4              ;[12] [15] [18] [21] | ||||
|     brne    se0Delay        ;[13] [16] [19] [22] | ||||
|     out     USBOUT, x1      ;[23] <-- out J (idle) -- end of SE0 (EOP signal) | ||||
|     out     USBDDR, x2      ;[24] <-- release bus now | ||||
|     out     USBOUT, x3      ;[25] <-- ensure no pull-up resistors are active | ||||
|     rjmp    doReturn | ||||
|  | ||||
							
								
								
									
										706
									
								
								usbdrv/usbdrvasm18-crc.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										706
									
								
								usbdrv/usbdrvasm18-crc.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,706 @@ | ||||
| /* Name: usbdrvasm18.inc | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Lukas Schrittwieser (based on 20 MHz usbdrvasm20.inc by Jeroen Benschop) | ||||
|  * Creation Date: 2009-01-20 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2008 by Lukas Schrittwieser and OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* Do not link this file! Link usbdrvasm.S instead, which includes the | ||||
|  * appropriate implementation! | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file is the 18 MHz version of the asssembler part of the USB driver. It | ||||
| requires a 18 MHz crystal (not a ceramic resonator and not a calibrated RC | ||||
| oscillator). | ||||
|  | ||||
| See usbdrv.h for a description of the entire driver. | ||||
|  | ||||
| Since almost all of this code is timing critical, don't change unless you | ||||
| really know what you are doing! Many parts require not only a maximum number | ||||
| of CPU cycles, but even an exact number of cycles! | ||||
| */ | ||||
|  | ||||
|  | ||||
| ;max stack usage: [ret(2), YL, SREG, YH, [sofError], bitcnt(x5), shift, x1, x2, x3, x4, cnt, ZL, ZH] = 14 bytes | ||||
| ;nominal frequency: 18 MHz -> 12 cycles per bit | ||||
| ; Numbers in brackets are clocks counted from center of last sync bit | ||||
| ; when instruction starts | ||||
| ;register use in receive loop to receive the data bytes: | ||||
| ; shift assembles the byte currently being received | ||||
| ; x1 holds the D+ and D- line state | ||||
| ; x2 holds the previous line state | ||||
| ; cnt holds the number of bytes left in the receive buffer | ||||
| ; x3 holds the higher crc byte (see algorithm below) | ||||
| ; x4 is used as temporary register for the crc algorithm | ||||
| ; x5 is used for unstuffing: when unstuffing the last received bit is inverted in shift (to prevent further | ||||
| ;    unstuffing calls. In the same time the corresponding bit in x5 is cleared to mark the bit as beening iverted | ||||
| ; zl lower crc value and crc table index | ||||
| ; zh used for crc table accesses | ||||
|  | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
| ; CRC mods: | ||||
| ;  table driven crc checker, Z points to table in prog space | ||||
| ;   ZL is the lower crc byte, x3 is the higher crc byte | ||||
| ;	x4 is used as temp register to store different results | ||||
| ;	the initialization of the crc register is not 0xFFFF but 0xFE54. This is because during the receipt of the | ||||
| ;	first data byte an virtual zero data byte is added to the crc register, this results in the correct initial | ||||
| ;	value of 0xFFFF at beginning of the second data byte before the first data byte is added to the crc. | ||||
| ;	The magic number 0xFE54 results form the crc table: At tabH[0x54] = 0xFF = crcH (required) and | ||||
| ;	tabL[0x54] = 0x01  ->  crcL = 0x01 xor 0xFE = 0xFF | ||||
| ;  bitcnt is renamed to x5 and is used for unstuffing purposes, the unstuffing works like in the 12MHz version | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
| ; CRC algorithm: | ||||
| ;	The crc register is formed by x3 (higher byte) and ZL (lower byte). The algorithm uses a 'reversed' form | ||||
| ;	i.e. that it takes the least significant bit first and shifts to the right. So in fact the highest order | ||||
| ;	bit seen from the polynomial devision point of view is the lsb of ZL. (If this sounds strange to you i | ||||
| ;	propose a research on CRC :-) ) | ||||
| ;	Each data byte received is xored to ZL, the lower crc byte. This byte now builds the crc | ||||
| ;	table index. Next the new high byte is loaded from the table and stored in x4 until we have space in x3 | ||||
| ;	(its destination). | ||||
| ;	Afterwards the lower table is loaded from the table and stored in ZL (the old index is overwritten as | ||||
| ;	we don't need it anymore. In fact this is a right shift by 8 bits.) Now the old crc high value is xored | ||||
| ;	to ZL, this is the second shift of the old crc value. Now x4 (the temp reg) is moved to x3 and the crc | ||||
| ; 	calculation is done. | ||||
| ;	Prior to the first byte the two CRC register have to be initialized to 0xFFFF (as defined in usb spec) | ||||
| ;	however the crc engine also runs during the receipt of the first byte, therefore x3 and zl are initialized | ||||
| ;	to a magic number which results in a crc value of 0xFFFF after the first complete byte. | ||||
| ; | ||||
| ;	This algorithm is split into the extra cycles of the different bits: | ||||
| ;	bit7:	XOR the received byte to ZL | ||||
| ;	bit5:	load the new high byte to x4 | ||||
| ;	bit6:	load the lower xor byte from the table, xor zl and x3, store result in zl (=the new crc low value) | ||||
| ;			move x4 (the new high byte) to x3, the crc value is ready | ||||
| ; | ||||
|  | ||||
|  | ||||
| macro POP_STANDARD ; 18 cycles | ||||
|     pop		ZH | ||||
|     pop		ZL | ||||
| 	pop     cnt | ||||
|     pop     x5 | ||||
|     pop     x3 | ||||
|     pop     x2 | ||||
|     pop     x1 | ||||
|     pop     shift | ||||
|     pop     x4 | ||||
|     endm | ||||
| macro POP_RETI     ; 7 cycles | ||||
|     pop     YH | ||||
|     pop     YL | ||||
|     out     SREG, YL | ||||
|     pop     YL | ||||
|     endm | ||||
|  | ||||
| macro CRC_CLEANUP_AND_CHECK | ||||
| 	; the last byte has already been xored with the lower crc byte, we have to do the table lookup and xor | ||||
| 	; x3 is the higher crc byte, zl the lower one | ||||
| 	ldi		ZH, hi8(usbCrcTableHigh);[+1] get the new high byte from the table | ||||
| 	lpm		x2, Z				;[+2][+3][+4] | ||||
| 	ldi		ZH, hi8(usbCrcTableLow);[+5] get the new low xor byte from the table | ||||
| 	lpm		ZL, Z				;[+6][+7][+8] | ||||
| 	eor		ZL, x3				;[+7] xor the old high byte with the value from the table, x2:ZL now holds the crc value | ||||
| 	cpi		ZL, 0x01			;[+8] if the crc is ok we have a fixed remainder value of 0xb001 in x2:ZL (see usb spec) | ||||
| 	brne	ignorePacket		;[+9] detected a crc fault -> paket is ignored and retransmitted by the host | ||||
| 	cpi		x2, 0xb0			;[+10] | ||||
| 	brne	ignorePacket		;[+11] detected a crc fault -> paket is ignored and retransmitted by the host | ||||
|     endm | ||||
|  | ||||
|  | ||||
| USB_INTR_VECTOR: | ||||
| ;order of registers pushed: YL, SREG, YH, [sofError], x4, shift, x1, x2, x3, x5, cnt, ZL, ZH | ||||
|     push    YL                  ;[-28] push only what is necessary to sync with edge ASAP | ||||
|     in      YL, SREG            ;[-26] | ||||
|     push    YL                  ;[-25] | ||||
|     push    YH                  ;[-23] | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Synchronize with sync pattern: | ||||
| ;---------------------------------------------------------------------------- | ||||
| ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] | ||||
| ;sync up with J to K edge during sync pattern -- use fastest possible loops | ||||
| ;The first part waits at most 1 bit long since we must be in sync pattern. | ||||
| ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to | ||||
| ;waitForJ, ensure that this prerequisite is met. | ||||
| waitForJ: | ||||
|     inc     YL | ||||
|     sbis    USBIN, USBMINUS | ||||
|     brne    waitForJ        ; just make sure we have ANY timeout | ||||
| waitForK: | ||||
| ;The following code results in a sampling window of < 1/4 bit which meets the spec. | ||||
|     sbis    USBIN, USBMINUS     ;[-17] | ||||
|     rjmp    foundK              ;[-16] | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
| #if USB_COUNT_SOF | ||||
|     lds     YL, usbSofCount | ||||
|     inc     YL | ||||
|     sts     usbSofCount, YL | ||||
| #endif  /* USB_COUNT_SOF */ | ||||
| #ifdef USB_SOF_HOOK | ||||
|     USB_SOF_HOOK | ||||
| #endif | ||||
|     rjmp    sofError | ||||
| foundK:                         ;[-15] | ||||
| ;{3, 5} after falling D- edge, average delay: 4 cycles | ||||
| ;bit0 should be at 30  (2.5 bits) for center sampling. Currently at 4 so 26 cylces till bit 0 sample | ||||
| ;use 1 bit time for setup purposes, then sample again. Numbers in brackets | ||||
| ;are cycles from center of first sync (double K) bit after the instruction | ||||
|     push    x4                  ;[-14] | ||||
| ;   [---]                       ;[-13] | ||||
|     lds     YL, usbInputBufOffset;[-12] used to toggle the two usb receive buffers | ||||
| ;   [---]                       ;[-11] | ||||
|     clr     YH                  ;[-10] | ||||
|     subi    YL, lo8(-(usbRxBuf));[-9] [rx loop init] | ||||
|     sbci    YH, hi8(-(usbRxBuf));[-8] [rx loop init] | ||||
|     push    shift               ;[-7] | ||||
| ;   [---]                       ;[-6] | ||||
|     ldi		shift, 0x80			;[-5] the last bit is the end of byte marker for the pid receiver loop | ||||
|     clc			      	      	;[-4] the carry has to be clear for receipt of pid bit 0 | ||||
|     sbis    USBIN, USBMINUS     ;[-3] we want two bits K (sample 3 cycles too early) | ||||
|     rjmp    haveTwoBitsK        ;[-2] | ||||
|     pop     shift               ;[-1] undo the push from before | ||||
|     pop     x4                  ;[1] | ||||
|     rjmp    waitForK            ;[3] this was not the end of sync, retry | ||||
| ; The entire loop from waitForK until rjmp waitForK above must not exceed two | ||||
| ; bit times (= 24 cycles). | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; push more registers and initialize values while we sample the first bits: | ||||
| ;---------------------------------------------------------------------------- | ||||
| haveTwoBitsK: | ||||
|     push    x1                  ;[0] | ||||
|     push    x2                  ;[2] | ||||
|     push    x3                  ;[4] crc high byte | ||||
|     ldi     x2, 1<<USBPLUS      ;[6] [rx loop init] current line state is K state. D+=="1", D-=="0" | ||||
|     push    x5                  ;[7] | ||||
|     push    cnt                 ;[9] | ||||
|     ldi     cnt, USB_BUFSIZE    ;[11] | ||||
|  | ||||
|  | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
| ; receives the pid byte | ||||
| ; there is no real unstuffing algorithm implemented here as a stuffing bit is impossible in the pid byte. | ||||
| ; That's because the last four bits of the byte are the inverted of the first four bits. If we detect a | ||||
| ; unstuffing condition something went wrong and abort | ||||
| ; shift has to be initialized to 0x80 | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
|  | ||||
| ; pid bit 0 - used for even more register saving (we need the z pointer) | ||||
| 	in      x1, USBIN           ;[0] sample line state | ||||
|     andi    x1, USBMASK         ;[1] filter only D+ and D- bits | ||||
|     eor		x2, x1				;[2] generate inverted of actual bit | ||||
| 	sbrc	x2, USBMINUS		;[3] if the bit is set we received a zero | ||||
| 	sec							;[4] | ||||
| 	ror		shift				;[5] we perform no unstuffing check here as this is the first bit | ||||
| 	mov		x2, x1				;[6] | ||||
| 	push	ZL					;[7] | ||||
| 								;[8] | ||||
| 	push	ZH					;[9] | ||||
| 								;[10] | ||||
| 	ldi		x3, 0xFE			;[11] x3 is the high order crc value | ||||
|  | ||||
|  | ||||
| bitloopPid:						 | ||||
| 	in      x1, USBIN           ;[0] sample line state | ||||
|    	andi    x1, USBMASK         ;[1] filter only D+ and D- bits | ||||
|     breq    nse0                ;[2] both lines are low so handle se0	 | ||||
| 	eor		x2, x1				;[3] generate inverted of actual bit | ||||
| 	sbrc	x2, USBMINUS		;[4] set the carry if we received a zero | ||||
| 	sec							;[5] | ||||
| 	ror		shift				;[6] | ||||
| 	ldi		ZL, 0x54			;[7] ZL is the low order crc value | ||||
| 	ser		x4					;[8] the is no bit stuffing check here as the pid bit can't be stuffed. if so | ||||
| 								; some error occured. In this case the paket is discarded later on anyway. | ||||
| 	mov		x2, x1				;[9] prepare for the next cycle | ||||
| 	brcc	bitloopPid			;[10] while 0s drop out of shift we get the next bit | ||||
| 	eor		x4, shift			;[11] invert all bits in shift and store result in x4 | ||||
|  | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
| ; receives data bytes and calculates the crc | ||||
| ; the last USBIN state has to be in x2 | ||||
| ; this is only the first half, due to branch distanc limitations the second half of the loop is near the end | ||||
| ; of this asm file | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
|  | ||||
| rxDataStart: | ||||
|     in      x1, USBIN           ;[0] sample line state (note: a se0 check is not useful due to bit dribbling) | ||||
|     ser		x5					;[1] prepare the unstuff marker register | ||||
|     eor		x2, x1             	;[2] generates the inverted of the actual bit | ||||
|     bst		x2, USBMINUS       	;[3] copy the bit from x2 | ||||
|     bld		shift, 0	        ;[4] and store it in shift | ||||
|     mov		x2, shift	     	;[5] make a copy of shift for unstuffing check | ||||
|     andi	x2, 0xF9	      	;[6] mask the last six bits, if we got six zeros (which are six ones in fact) | ||||
|     breq	unstuff0	      	;[7] then Z is set now and we branch to the unstuffing handler | ||||
| didunstuff0: | ||||
| 	subi    cnt, 1         		;[8] cannot use dec because it doesn't affect the carry flag | ||||
|     brcs    nOverflow    		;[9] Too many bytes received. Ignore packet							 | ||||
|     st		Y+, x4				;[10] store the last received byte | ||||
| 								;[11] st needs two cycles | ||||
|  | ||||
| ; bit1							 | ||||
| 	in		x2, USBIN			;[0] sample line state | ||||
|     andi	x1, USBMASK			;[1] check for se0 during bit 0 | ||||
|     breq	nse0				;[2] | ||||
|     andi	x2, USBMASK			;[3] check se0 during bit 1 | ||||
|     breq	nse0				;[4] | ||||
| 	eor		x1, x2				;[5] | ||||
|     bst		x1, USBMINUS		;[6] | ||||
|     bld 	shift, 1	 		;[7] | ||||
|     mov		x1, shift			;[8] | ||||
|     andi	x1, 0xF3			;[9] | ||||
|     breq	unstuff1			;[10] | ||||
| didunstuff1: | ||||
| 	nop							;[11]	 | ||||
|  | ||||
| ; bit2 | ||||
| 	in      x1, USBIN           ;[0] sample line state | ||||
|     andi	x1, USBMASK			;[1] check for se0 (as there is nothing else to do here | ||||
| 	breq	nOverflow	 		;[2] | ||||
|     eor		x2, x1              ;[3] generates the inverted of the actual bit | ||||
|     bst		x2, USBMINUS		;[4] | ||||
|     bld		shift, 2			;[5] store the bit | ||||
|     mov		x2, shift			;[6] | ||||
|     andi	x2, 0xE7			;[7] if we have six zeros here (which means six 1 in the stream) | ||||
|     breq	unstuff2			;[8] the next bit is a stuffing bit | ||||
| didunstuff2: | ||||
| 	nop2						;[9] | ||||
| 								;[10] | ||||
| 	nop							;[11]					 | ||||
| 					 | ||||
| ; bit3							 | ||||
| 	in		x2, USBIN			;[0] sample line state | ||||
|     andi	x2, USBMASK			;[1] check for se0 | ||||
|     breq	nOverflow           ;[2] | ||||
|     eor		x1, x2				;[3] | ||||
|     bst		x1, USBMINUS		;[4] | ||||
|     bld 	shift, 3	 		;[5] | ||||
|     mov		x1, shift			;[6] | ||||
|     andi	x1, 0xCF			;[7] | ||||
|     breq	unstuff3			;[8] | ||||
| didunstuff3: | ||||
| 	nop							;[9] | ||||
| 	rjmp 	rxDataBit4			;[10] | ||||
| 								;[11]				 | ||||
|  | ||||
| ; the avr branch instructions allow an offset of +63 insturction only, so we need this | ||||
| ; 'local copy' of se0 | ||||
| nse0:		 | ||||
| 	rjmp	se0					;[4] | ||||
| 								;[5] | ||||
| ; the same same as for se0 is needed for overflow and StuffErr | ||||
| nOverflow: | ||||
| stuffErr: | ||||
| 	rjmp	overflow | ||||
|  | ||||
|  | ||||
| unstuff0:						;[8] this is the branch delay of breq unstuffX | ||||
| 	andi	x1, USBMASK			;[9] do an se0 check here (if the last crc byte ends with 5 one's we might end up here | ||||
| 	breq	didunstuff0			;[10] event tough the message is complete -> jump back and store the byte | ||||
| 	ori		shift, 0x01			;[11] invert the last received bit to prevent furhter unstuffing | ||||
| 	in		x2, USBIN			;[0] we have some free cycles so we could check for bit stuffing errors | ||||
| 	andi	x5, 0xFE			;[1] mark this bit as inverted (will be corrected before storing shift) | ||||
| 	eor		x1, x2				;[2] x1 and x2 have to be different because the stuff bit is always a zero | ||||
| 	andi	x1, USBMASK			;[3] mask the interesting bits | ||||
| 	breq	stuffErr			;[4] if the stuff bit is a 1-bit something went wrong | ||||
| 	mov 	x1, x2				;[5] the next bit expects the last state to be in x1 | ||||
| 	rjmp 	didunstuff0			;[6] | ||||
| 								;[7] jump delay of rjmp didunstuffX	 | ||||
|  | ||||
| unstuff1:						;[11] this is the jump delay of breq unstuffX | ||||
| 	in		x1, USBIN			;[0] we have some free cycles so we could check for bit stuffing errors | ||||
| 	ori		shift, 0x02			;[1] invert the last received bit to prevent furhter unstuffing | ||||
| 	andi	x5, 0xFD			;[2] mark this bit as inverted (will be corrected before storing shift) | ||||
| 	eor		x2, x1				;[3] x1 and x2 have to be different because the stuff bit is always a zero | ||||
| 	andi	x2, USBMASK			;[4] mask the interesting bits | ||||
| 	breq	stuffErr			;[5] if the stuff bit is a 1-bit something went wrong | ||||
| 	mov 	x2, x1				;[6] the next bit expects the last state to be in x2 | ||||
| 	nop2						;[7] | ||||
| 								;[8] | ||||
| 	rjmp 	didunstuff1			;[9] | ||||
| 								;[10] jump delay of rjmp didunstuffX		 | ||||
|  | ||||
| unstuff2:						;[9] this is the jump delay of breq unstuffX | ||||
| 	ori		shift, 0x04			;[10] invert the last received bit to prevent furhter unstuffing | ||||
| 	andi	x5, 0xFB			;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
| 	in		x2, USBIN			;[0] we have some free cycles so we could check for bit stuffing errors | ||||
| 	eor		x1, x2				;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
| 	andi	x1, USBMASK			;[2] mask the interesting bits | ||||
| 	breq	stuffErr			;[3] if the stuff bit is a 1-bit something went wrong | ||||
| 	mov 	x1, x2				;[4] the next bit expects the last state to be in x1 | ||||
| 	nop2						;[5] | ||||
| 								;[6] | ||||
| 	rjmp 	didunstuff2			;[7] | ||||
| 								;[8] jump delay of rjmp didunstuffX	 | ||||
|  | ||||
| unstuff3:						;[9] this is the jump delay of breq unstuffX | ||||
| 	ori		shift, 0x08			;[10] invert the last received bit to prevent furhter unstuffing | ||||
| 	andi	x5, 0xF7			;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
| 	in		x1, USBIN			;[0] we have some free cycles so we could check for bit stuffing errors | ||||
| 	eor		x2, x1				;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
| 	andi	x2, USBMASK			;[2] mask the interesting bits | ||||
| 	breq	stuffErr			;[3] if the stuff bit is a 1-bit something went wrong | ||||
| 	mov 	x2, x1				;[4] the next bit expects the last state to be in x2 | ||||
| 	nop2						;[5] | ||||
| 								;[6] | ||||
| 	rjmp 	didunstuff3			;[7] | ||||
| 								;[8] jump delay of rjmp didunstuffX			 | ||||
|  | ||||
|  | ||||
|  | ||||
| ; the include has to be here due to branch distance restirctions | ||||
| #define __USE_CRC__ | ||||
| #include "asmcommon.inc" | ||||
|  | ||||
| 	 | ||||
|  | ||||
| ; USB spec says: | ||||
| ; idle = J | ||||
| ; J = (D+ = 0), (D- = 1) | ||||
| ; K = (D+ = 1), (D- = 0) | ||||
| ; Spec allows 7.5 bit times from EOP to SOP for replies | ||||
| ; 7.5 bit times is 90 cycles. ...there is plenty of time | ||||
|  | ||||
|  | ||||
| sendNakAndReti: | ||||
|     ldi     x3, USBPID_NAK  ;[-18] | ||||
|     rjmp    sendX3AndReti   ;[-17] | ||||
| sendAckAndReti: | ||||
|     ldi     cnt, USBPID_ACK ;[-17] | ||||
| sendCntAndReti: | ||||
|     mov     x3, cnt         ;[-16] | ||||
| sendX3AndReti: | ||||
|     ldi     YL, 20          ;[-15] x3==r20 address is 20 | ||||
|     ldi     YH, 0           ;[-14] | ||||
|     ldi     cnt, 2          ;[-13] | ||||
| ;   rjmp    usbSendAndReti      fallthrough | ||||
|  | ||||
| ;usbSend: | ||||
| ;pointer to data in 'Y' | ||||
| ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] | ||||
| ;uses: x1...x4, btcnt, shift, cnt, Y | ||||
| ;Numbers in brackets are time since first bit of sync pattern is sent | ||||
|  | ||||
| usbSendAndReti:             ; 12 cycles until SOP | ||||
|     in      x2, USBDDR      ;[-12] | ||||
|     ori     x2, USBMASK     ;[-11] | ||||
|     sbi     USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) | ||||
|     in      x1, USBOUT      ;[-8] port mirror for tx loop | ||||
|     out     USBDDR, x2      ;[-6] <- acquire bus | ||||
| 	ldi		x2, 0			;[-6] init x2 (bitstuff history) because sync starts with 0 | ||||
|     ldi     x4, USBMASK     ;[-5] exor mask | ||||
|     ldi     shift, 0x80     ;[-4] sync byte is first byte sent | ||||
| txByteLoop: | ||||
|     ldi     bitcnt, 0x40    ;[-3]=[9]     binary 01000000 | ||||
| txBitLoop:					; the loop sends the first 7 bits of the byte | ||||
|     sbrs    shift, 0        ;[-2]=[10] if we have to send a 1 don't change the line state | ||||
|     eor     x1, x4          ;[-1]=[11] | ||||
|     out     USBOUT, x1      ;[0] | ||||
|     ror     shift           ;[1] | ||||
|     ror     x2              ;[2] transfers the last sent bit to the stuffing history | ||||
| didStuffN: | ||||
|     nop	                    ;[3] | ||||
|     nop                     ;[4] | ||||
|     cpi     x2, 0xfc        ;[5] if we sent six consecutive ones | ||||
|     brcc    bitstuffN       ;[6] | ||||
|     lsr     bitcnt          ;[7] | ||||
|     brne    txBitLoop       ;[8] restart the loop while the 1 is still in the bitcount | ||||
|  | ||||
| ; transmit bit 7 | ||||
|     sbrs    shift, 0        ;[9] | ||||
|     eor     x1, x4          ;[10] | ||||
| didStuff7: | ||||
|     ror     shift           ;[11] | ||||
| 	out     USBOUT, x1      ;[0] transfer bit 7 to the pins | ||||
|     ror     x2              ;[1] move the bit into the stuffing history	 | ||||
|     cpi     x2, 0xfc        ;[2] | ||||
|     brcc    bitstuff7       ;[3] | ||||
|     ld      shift, y+       ;[4] get next byte to transmit | ||||
|     dec     cnt             ;[5] decrement byte counter | ||||
|     brne    txByteLoop      ;[7] if we have more bytes start next one | ||||
|     						;[8] branch delay | ||||
|     						 | ||||
| ;make SE0: | ||||
|     cbr     x1, USBMASK     ;[8] 		prepare SE0 [spec says EOP may be 25 to 30 cycles] | ||||
|     lds     x2, usbNewDeviceAddr;[9] | ||||
|     lsl     x2              ;[11] 		we compare with left shifted address | ||||
|     out     USBOUT, x1      ;[0] 		<-- out SE0 -- from now 2 bits = 24 cycles until bus idle | ||||
|     subi    YL, 20 + 2      ;[1] 		Only assign address on data packets, not ACK/NAK in x3 | ||||
|     sbci    YH, 0           ;[2] | ||||
| ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: | ||||
| ;set address only after data packet was sent, not after handshake | ||||
|     breq    skipAddrAssign  ;[3] | ||||
|     sts     usbDeviceAddr, x2		; if not skipped: SE0 is one cycle longer | ||||
| skipAddrAssign: | ||||
| ;end of usbDeviceAddress transfer | ||||
|     ldi     x2, 1<<USB_INTR_PENDING_BIT;[5] int0 occurred during TX -- clear pending flag | ||||
|     USB_STORE_PENDING(x2)   ;[6] | ||||
|     ori     x1, USBIDLE     ;[7] | ||||
|     in      x2, USBDDR      ;[8] | ||||
|     cbr     x2, USBMASK     ;[9] set both pins to input | ||||
|     mov     x3, x1          ;[10] | ||||
|     cbr     x3, USBMASK     ;[11] configure no pullup on both pins | ||||
|     ldi     x4, 4           ;[12] | ||||
| se0Delay: | ||||
|     dec     x4              ;[13] [16] [19] [22] | ||||
|     brne    se0Delay        ;[14] [17] [20] [23] | ||||
|     out     USBOUT, x1      ;[24] <-- out J (idle) -- end of SE0 (EOP signal) | ||||
|     out     USBDDR, x2      ;[25] <-- release bus now | ||||
|     out     USBOUT, x3      ;[26] <-- ensure no pull-up resistors are active | ||||
|     rjmp    doReturn | ||||
|  | ||||
| bitstuffN: | ||||
|     eor     x1, x4          ;[8] generate a zero | ||||
|     ldi     x2, 0           ;[9] reset the bit stuffing history | ||||
|     nop2                    ;[10] | ||||
|     out     USBOUT, x1      ;[0] <-- send the stuffing bit | ||||
|     rjmp    didStuffN       ;[1] | ||||
|  | ||||
| bitstuff7: | ||||
|     eor     x1, x4          ;[5] | ||||
|     ldi     x2, 0           ;[6] reset bit stuffing history | ||||
|     clc						;[7] fill a zero into the shift register | ||||
|     rol     shift           ;[8] compensate for ror shift at branch destination | ||||
|     rjmp    didStuff7       ;[9] | ||||
|     						;[10] jump delay | ||||
|  | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
| ; receives data bytes and calculates the crc | ||||
| ; second half of the data byte receiver loop | ||||
| ; most parts of the crc algorithm are here | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
|  | ||||
| nOverflow2: | ||||
| 	rjmp overflow | ||||
|  | ||||
| rxDataBit4: | ||||
| 	in      x1, USBIN           ;[0] sample line state | ||||
|     andi	x1, USBMASK			;[1] check for se0 | ||||
|     breq	nOverflow2			;[2] | ||||
|     eor		x2, x1              ;[3] | ||||
|     bst		x2, USBMINUS		;[4] | ||||
|     bld		shift, 4			;[5] | ||||
|     mov		x2, shift			;[6] | ||||
|     andi	x2, 0x9F			;[7] | ||||
|     breq	unstuff4			;[8] | ||||
| didunstuff4: | ||||
| 	nop2						;[9][10] | ||||
| 	nop							;[11] | ||||
|  | ||||
| ; bit5							 | ||||
| 	in		x2, USBIN			;[0] sample line state | ||||
|     ldi		ZH, hi8(usbCrcTableHigh);[1] use the table for the higher byte | ||||
|     eor		x1, x2				;[2] | ||||
|     bst		x1, USBMINUS		;[3] | ||||
|     bld 	shift, 5	 		;[4] | ||||
|     mov		x1, shift			;[5] | ||||
|     andi	x1, 0x3F			;[6] | ||||
|     breq	unstuff5			;[7] | ||||
| didunstuff5: | ||||
| 	lpm		x4, Z				;[8] load the higher crc xor-byte and store it for later use | ||||
| 								;[9] lpm needs 3 cycles | ||||
| 								;[10]			 | ||||
| 	ldi		ZH, hi8(usbCrcTableLow);[11] load the lower crc xor byte adress | ||||
|  | ||||
| ; bit6	    					 | ||||
| 	in      x1, USBIN           ;[0] sample line state | ||||
|     eor		x2, x1              ;[1] | ||||
|     bst		x2, USBMINUS		;[2] | ||||
|     bld		shift, 6			;[3] | ||||
|     mov		x2, shift			;[4] | ||||
|     andi	x2, 0x7E			;[5] | ||||
|     breq	unstuff6			;[6] | ||||
| didunstuff6: | ||||
| 	lpm		ZL, Z				;[7] load the lower xor crc byte | ||||
| 								;[8] lpm needs 3 cycles | ||||
| 	    						;[9] | ||||
| 	eor		ZL, x3				;[10] xor the old high crc byte with the low xor-byte | ||||
| 	mov		x3, x4				;[11] move the new high order crc value from temp to its destination | ||||
| 			 | ||||
| ; bit7							 | ||||
| 	in		x2, USBIN			;[0] sample line state | ||||
|     eor		x1, x2				;[1] | ||||
|     bst		x1, USBMINUS		;[2] | ||||
|     bld 	shift, 7	 		;[3] now shift holds the complete but inverted data byte | ||||
|     mov		x1, shift			;[4] | ||||
|     andi	x1, 0xFC			;[5] | ||||
|     breq	unstuff7			;[6] | ||||
| didunstuff7: | ||||
| 	eor		x5, shift			;[7] x5 marks all bits which have not been inverted by the unstuffing subs | ||||
| 	mov		x4, x5				;[8] keep a copy of the data byte it will be stored during next bit0 | ||||
| 	eor		ZL, x4				;[9] feed the actual byte into the crc algorithm | ||||
| 	rjmp	rxDataStart			;[10] next byte | ||||
| 								;[11] during the reception of the next byte this one will be fed int the crc algorithm | ||||
|  | ||||
| unstuff4:						;[9] this is the jump delay of rjmp unstuffX | ||||
| 	ori		shift, 0x10			;[10] invert the last received bit to prevent furhter unstuffing | ||||
| 	andi	x5, 0xEF			;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
| 	in		x2, USBIN			;[0] we have some free cycles so we could check for bit stuffing errors | ||||
| 	eor		x1, x2				;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
| 	andi	x1, USBMASK			;[2] mask the interesting bits | ||||
| 	breq	stuffErr2			;[3] if the stuff bit is a 1-bit something went wrong | ||||
| 	mov 	x1, x2				;[4] the next bit expects the last state to be in x1 | ||||
| 	nop2						;[5] | ||||
| 								;[6] | ||||
| 	rjmp 	didunstuff4			;[7] | ||||
| 								;[8] jump delay of rjmp didunstuffX	 | ||||
|  | ||||
| unstuff5:						;[8] this is the jump delay of rjmp unstuffX | ||||
| 	nop							;[9] | ||||
| 	ori		shift, 0x20			;[10] invert the last received bit to prevent furhter unstuffing | ||||
| 	andi	x5, 0xDF			;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
| 	in		x1, USBIN			;[0] we have some free cycles so we could check for bit stuffing errors | ||||
| 	eor		x2, x1				;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
| 	andi	x2, USBMASK			;[2] mask the interesting bits | ||||
| 	breq	stuffErr2			;[3] if the stuff bit is a 1-bit something went wrong | ||||
| 	mov 	x2, x1				;[4] the next bit expects the last state to be in x2 | ||||
| 	nop							;[5] | ||||
| 	rjmp 	didunstuff5			;[6] | ||||
| 								;[7] jump delay of rjmp didunstuffX													 | ||||
|  | ||||
| unstuff6:						;[7] this is the jump delay of rjmp unstuffX | ||||
| 	nop2						;[8] | ||||
| 								;[9] | ||||
| 	ori		shift, 0x40			;[10] invert the last received bit to prevent furhter unstuffing | ||||
| 	andi	x5, 0xBF			;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
| 	in		x2, USBIN			;[0] we have some free cycles so we could check for bit stuffing errors | ||||
| 	eor		x1, x2				;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
| 	andi	x1, USBMASK			;[2] mask the interesting bits | ||||
| 	breq	stuffErr2			;[3] if the stuff bit is a 1-bit something went wrong | ||||
| 	mov 	x1, x2				;[4] the next bit expects the last state to be in x1 | ||||
| 	rjmp 	didunstuff6			;[5] | ||||
| 								;[6] jump delay of rjmp didunstuffX	 | ||||
|  | ||||
| unstuff7:						;[7] this is the jump delay of rjmp unstuffX | ||||
| 	nop							;[8] | ||||
| 	nop							;[9] | ||||
| 	ori		shift, 0x80			;[10] invert the last received bit to prevent furhter unstuffing | ||||
| 	andi	x5, 0x7F			;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
| 	in		x1, USBIN			;[0] we have some free cycles so we could check for bit stuffing errors | ||||
| 	eor		x2, x1				;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
| 	andi	x2, USBMASK			;[2] mask the interesting bits | ||||
| 	breq	stuffErr2			;[3] if the stuff bit is a 1-bit something went wrong | ||||
| 	mov 	x2, x1				;[4] the next bit expects the last state to be in x2 | ||||
| 	rjmp 	didunstuff7			;[5] | ||||
| 								;[6] jump delay of rjmp didunstuff7 | ||||
|  | ||||
| ; local copy of the stuffErr desitnation for the second half of the receiver loop | ||||
| stuffErr2: | ||||
| 	rjmp	stuffErr | ||||
|  | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
| ; The crc table follows. It has to be aligned to enable a fast loading of the needed bytes. | ||||
| ; There are two tables of 256 entries each, the low and the high byte table. | ||||
| ; Table values were generated with the following C code: | ||||
| /* | ||||
| #include <stdio.h> | ||||
| int main (int argc, char **argv) | ||||
| { | ||||
| 	int i, j; | ||||
| 	for (i=0; i<512; i++){ | ||||
| 		unsigned short crc = i & 0xff; | ||||
| 		for(j=0; j<8; j++) crc = (crc >> 1) ^ ((crc & 1) ? 0xa001 : 0); | ||||
| 		if((i & 7) == 0) printf("\n.byte "); | ||||
| 		printf("0x%02x, ", (i > 0xff ? (crc >> 8) : crc) & 0xff); | ||||
| 		if(i == 255) printf("\n"); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| // Use the following algorithm to compute CRC values: | ||||
| ushort computeCrc(uchar *msg, uchar msgLen) | ||||
| { | ||||
|     uchar i; | ||||
| 	ushort crc = 0xffff; | ||||
| 	for(i = 0; i < msgLen; i++) | ||||
| 		crc = usbCrcTable16[lo8(crc) ^ msg[i]] ^ hi8(crc); | ||||
|     return crc; | ||||
| } | ||||
| */ | ||||
|  | ||||
| .balign 256 | ||||
| usbCrcTableLow:	 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 | ||||
| .byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 | ||||
|  | ||||
| ; .balign 256 | ||||
| usbCrcTableHigh: | ||||
| .byte 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2 | ||||
| .byte 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04 | ||||
| .byte 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E | ||||
| .byte 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8 | ||||
| .byte 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A | ||||
| .byte 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC | ||||
| .byte 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6 | ||||
| .byte 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10 | ||||
| .byte 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32 | ||||
| .byte 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4 | ||||
| .byte 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE | ||||
| .byte 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38 | ||||
| .byte 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA | ||||
| .byte 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C | ||||
| .byte 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26 | ||||
| .byte 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0 | ||||
| .byte 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62 | ||||
| .byte 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4 | ||||
| .byte 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE | ||||
| .byte 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68 | ||||
| .byte 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA | ||||
| .byte 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C | ||||
| .byte 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76 | ||||
| .byte 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0 | ||||
| .byte 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92 | ||||
| .byte 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54 | ||||
| .byte 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E | ||||
| .byte 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98 | ||||
| .byte 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A | ||||
| .byte 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C | ||||
| .byte 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86 | ||||
| .byte 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40	 | ||||
|  | ||||
							
								
								
									
										557
									
								
								usbdrv/usbdrvasm18.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										557
									
								
								usbdrv/usbdrvasm18.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,557 @@ | ||||
| /* Name: usbdrvasm18.inc | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Lukas Schrittwieser (based on 20 MHz usbdrvasm20.inc by Jeroen Benschop) | ||||
|  * Creation Date: 2009-01-20 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2008 by Lukas Schrittwieser and OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* Do not link this file! Link usbdrvasm.S instead, which includes the | ||||
|  * appropriate implementation! | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file is the 18 MHz version of the asssembler part of the USB driver. It | ||||
| requires a 18 MHz crystal (not a ceramic resonator and not a calibrated RC | ||||
| oscillator). | ||||
|  | ||||
| See usbdrv.h for a description of the entire driver. | ||||
|  | ||||
| Since almost all of this code is timing critical, don't change unless you | ||||
| really know what you are doing! Many parts require not only a maximum number | ||||
| of CPU cycles, but even an exact number of cycles! | ||||
|  | ||||
| Note: This version is smaller than usbdrvasm18-crc.inc because it saves the CRC | ||||
| table. It's therefore suitable for boot loaders on boards @ 18 MHz. However, it | ||||
| is not as small as it could be, because loops are unrolled in the same way as in | ||||
| usbdrvasm18-crc.inc. There is room for optimization. | ||||
| */ | ||||
|  | ||||
|  | ||||
| ;max stack usage: [ret(2), YL, SREG, YH, [sofError], bitcnt(x5), shift, x1, x2, x3, x4, cnt, ZL, ZH] = 14 bytes | ||||
| ;nominal frequency: 18 MHz -> 12 cycles per bit | ||||
| ; Numbers in brackets are clocks counted from center of last sync bit | ||||
| ; when instruction starts | ||||
| ;register use in receive loop to receive the data bytes: | ||||
| ; shift assembles the byte currently being received | ||||
| ; x1 holds the D+ and D- line state | ||||
| ; x2 holds the previous line state | ||||
| ; cnt holds the number of bytes left in the receive buffer | ||||
| ; x4 is used as temporary register | ||||
| ; x3 is used for unstuffing: when unstuffing the last received bit is inverted in shift (to prevent further | ||||
| ;    unstuffing calls. In the same time the corresponding bit in x3 is cleared to mark the bit as beening iverted | ||||
| ; zl lower crc value and crc table index | ||||
| ; zh used for crc table accesses | ||||
|  | ||||
|  | ||||
|  | ||||
| macro POP_STANDARD ; 18 cycles | ||||
|     pop     cnt | ||||
|     pop     x5 | ||||
|     pop     x3 | ||||
|     pop     x2 | ||||
|     pop     x1 | ||||
|     pop     shift | ||||
|     pop     x4 | ||||
|     endm | ||||
| macro POP_RETI     ; 7 cycles | ||||
|     pop     YH | ||||
|     pop     YL | ||||
|     out     SREG, YL | ||||
|     pop     YL | ||||
|     endm | ||||
|  | ||||
| ;macro CRC_CLEANUP_AND_CHECK | ||||
| ;   ; the last byte has already been xored with the lower crc byte, we have to do the table lookup and xor | ||||
| ;   ; x3 is the higher crc byte, zl the lower one | ||||
| ;   ldi     ZH, hi8(usbCrcTableHigh);[+1] get the new high byte from the table | ||||
| ;   lpm     x2, Z               ;[+2][+3][+4] | ||||
| ;   ldi     ZH, hi8(usbCrcTableLow);[+5] get the new low xor byte from the table | ||||
| ;   lpm     ZL, Z               ;[+6][+7][+8] | ||||
| ;   eor     ZL, x3              ;[+7] xor the old high byte with the value from the table, x2:ZL now holds the crc value | ||||
| ;   cpi     ZL, 0x01            ;[+8] if the crc is ok we have a fixed remainder value of 0xb001 in x2:ZL (see usb spec) | ||||
| ;   brne    ignorePacket        ;[+9] detected a crc fault -> paket is ignored and retransmitted by the host | ||||
| ;   cpi     x2, 0xb0            ;[+10] | ||||
| ;   brne    ignorePacket        ;[+11] detected a crc fault -> paket is ignored and retransmitted by the host | ||||
| ;    endm | ||||
|          | ||||
|  | ||||
| USB_INTR_VECTOR: | ||||
| ;order of registers pushed: YL, SREG, YH, [sofError], x4, shift, x1, x2, x3, x5, cnt, ZL, ZH | ||||
|     push    YL                  ;[-28] push only what is necessary to sync with edge ASAP | ||||
|     in      YL, SREG            ;[-26] | ||||
|     push    YL                  ;[-25] | ||||
|     push    YH                  ;[-23] | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Synchronize with sync pattern: | ||||
| ;---------------------------------------------------------------------------- | ||||
| ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] | ||||
| ;sync up with J to K edge during sync pattern -- use fastest possible loops | ||||
| ;The first part waits at most 1 bit long since we must be in sync pattern. | ||||
| ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to | ||||
| ;waitForJ, ensure that this prerequisite is met. | ||||
| waitForJ: | ||||
|     inc     YL | ||||
|     sbis    USBIN, USBMINUS | ||||
|     brne    waitForJ        ; just make sure we have ANY timeout | ||||
| waitForK: | ||||
| ;The following code results in a sampling window of < 1/4 bit which meets the spec. | ||||
|     sbis    USBIN, USBMINUS     ;[-17] | ||||
|     rjmp    foundK              ;[-16] | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
| #if USB_COUNT_SOF | ||||
|     lds     YL, usbSofCount | ||||
|     inc     YL | ||||
|     sts     usbSofCount, YL | ||||
| #endif  /* USB_COUNT_SOF */ | ||||
| #ifdef USB_SOF_HOOK | ||||
|     USB_SOF_HOOK | ||||
| #endif | ||||
|     rjmp    sofError | ||||
| foundK:                         ;[-15] | ||||
| ;{3, 5} after falling D- edge, average delay: 4 cycles | ||||
| ;bit0 should be at 30  (2.5 bits) for center sampling. Currently at 4 so 26 cylces till bit 0 sample | ||||
| ;use 1 bit time for setup purposes, then sample again. Numbers in brackets | ||||
| ;are cycles from center of first sync (double K) bit after the instruction | ||||
|     push    x4                  ;[-14] | ||||
| ;   [---]                       ;[-13] | ||||
|     lds     YL, usbInputBufOffset;[-12] used to toggle the two usb receive buffers | ||||
| ;   [---]                       ;[-11] | ||||
|     clr     YH                  ;[-10] | ||||
|     subi    YL, lo8(-(usbRxBuf));[-9] [rx loop init] | ||||
|     sbci    YH, hi8(-(usbRxBuf));[-8] [rx loop init] | ||||
|     push    shift               ;[-7] | ||||
| ;   [---]                       ;[-6] | ||||
|     ldi     shift, 0x80         ;[-5] the last bit is the end of byte marker for the pid receiver loop | ||||
|     clc                         ;[-4] the carry has to be clear for receipt of pid bit 0 | ||||
|     sbis    USBIN, USBMINUS     ;[-3] we want two bits K (sample 3 cycles too early) | ||||
|     rjmp    haveTwoBitsK        ;[-2] | ||||
|     pop     shift               ;[-1] undo the push from before | ||||
|     pop     x4                  ;[1] | ||||
|     rjmp    waitForK            ;[3] this was not the end of sync, retry | ||||
| ; The entire loop from waitForK until rjmp waitForK above must not exceed two | ||||
| ; bit times (= 24 cycles). | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; push more registers and initialize values while we sample the first bits: | ||||
| ;---------------------------------------------------------------------------- | ||||
| haveTwoBitsK: | ||||
|     push    x1                  ;[0] | ||||
|     push    x2                  ;[2] | ||||
|     push    x3                  ;[4]  | ||||
|     ldi     x2, 1<<USBPLUS      ;[6] [rx loop init] current line state is K state. D+=="1", D-=="0" | ||||
|     push    x5                  ;[7] used by tx loop for bitcnt | ||||
|     push    cnt                 ;[9] | ||||
|     ldi     cnt, USB_BUFSIZE    ;[11] | ||||
|  | ||||
|  | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
| ; receives the pid byte | ||||
| ; there is no real unstuffing algorithm implemented here as a stuffing bit is impossible in the pid byte. | ||||
| ; That's because the last four bits of the byte are the inverted of the first four bits. If we detect a | ||||
| ; unstuffing condition something went wrong and abort | ||||
| ; shift has to be initialized to 0x80 | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
|  | ||||
| bitloopPid:                      | ||||
|     in      x1, USBIN           ;[0] sample line state | ||||
|     andi    x1, USBMASK         ;[1] filter only D+ and D- bits | ||||
|     breq    nse0                ;[2] both lines are low so handle se0    | ||||
|     eor     x2, x1              ;[3] generate inverted of actual bit | ||||
|     sbrc    x2, USBMINUS        ;[4] set the carry if we received a zero | ||||
|     sec                         ;[5] | ||||
|     ror     shift               ;[6] | ||||
|     nop                         ;[7] ZL is the low order crc value | ||||
|     ser     x4                  ;[8] the is no bit stuffing check here as the pid bit can't be stuffed. if so | ||||
|                                 ; some error occured. In this case the paket is discarded later on anyway. | ||||
|     mov     x2, x1              ;[9] prepare for the next cycle | ||||
|     brcc    bitloopPid          ;[10] while 0s drop out of shift we get the next bit | ||||
|     eor     x4, shift           ;[11] invert all bits in shift and store result in x4 | ||||
|  | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
| ; receives data bytes and calculates the crc | ||||
| ; the last USBIN state has to be in x2 | ||||
| ; this is only the first half, due to branch distanc limitations the second half of the loop is near the end | ||||
| ; of this asm file | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
|  | ||||
| rxDataStart: | ||||
|     in      x1, USBIN           ;[0] sample line state (note: a se0 check is not useful due to bit dribbling) | ||||
|     ser     x3                  ;[1] prepare the unstuff marker register | ||||
|     eor     x2, x1              ;[2] generates the inverted of the actual bit | ||||
|     bst     x2, USBMINUS        ;[3] copy the bit from x2 | ||||
|     bld     shift, 0            ;[4] and store it in shift | ||||
|     mov     x2, shift           ;[5] make a copy of shift for unstuffing check | ||||
|     andi    x2, 0xF9            ;[6] mask the last six bits, if we got six zeros (which are six ones in fact) | ||||
|     breq    unstuff0            ;[7] then Z is set now and we branch to the unstuffing handler | ||||
| didunstuff0: | ||||
|     subi    cnt, 1              ;[8] cannot use dec because it doesn't affect the carry flag | ||||
|     brcs    nOverflow           ;[9] Too many bytes received. Ignore packet                          | ||||
|     st      Y+, x4              ;[10] store the last received byte | ||||
|                                 ;[11] st needs two cycles | ||||
|  | ||||
| ; bit1                           | ||||
|     in      x2, USBIN           ;[0] sample line state | ||||
|     andi    x1, USBMASK         ;[1] check for se0 during bit 0 | ||||
|     breq    nse0                ;[2] | ||||
|     andi    x2, USBMASK         ;[3] check se0 during bit 1 | ||||
|     breq    nse0                ;[4] | ||||
|     eor     x1, x2              ;[5] | ||||
|     bst     x1, USBMINUS        ;[6] | ||||
|     bld     shift, 1            ;[7] | ||||
|     mov     x1, shift           ;[8] | ||||
|     andi    x1, 0xF3            ;[9] | ||||
|     breq    unstuff1            ;[10] | ||||
| didunstuff1: | ||||
|     nop                         ;[11]    | ||||
|  | ||||
| ; bit2 | ||||
|     in      x1, USBIN           ;[0] sample line state | ||||
|     andi    x1, USBMASK         ;[1] check for se0 (as there is nothing else to do here | ||||
|     breq    nOverflow           ;[2] | ||||
|     eor     x2, x1              ;[3] generates the inverted of the actual bit | ||||
|     bst     x2, USBMINUS        ;[4] | ||||
|     bld     shift, 2            ;[5] store the bit | ||||
|     mov     x2, shift           ;[6] | ||||
|     andi    x2, 0xE7            ;[7] if we have six zeros here (which means six 1 in the stream) | ||||
|     breq    unstuff2            ;[8] the next bit is a stuffing bit | ||||
| didunstuff2: | ||||
|     nop2                        ;[9] | ||||
|                                 ;[10] | ||||
|     nop                         ;[11]                    | ||||
|                      | ||||
| ; bit3                           | ||||
|     in      x2, USBIN           ;[0] sample line state | ||||
|     andi    x2, USBMASK         ;[1] check for se0 | ||||
|     breq    nOverflow           ;[2] | ||||
|     eor     x1, x2              ;[3] | ||||
|     bst     x1, USBMINUS        ;[4] | ||||
|     bld     shift, 3            ;[5] | ||||
|     mov     x1, shift           ;[6] | ||||
|     andi    x1, 0xCF            ;[7] | ||||
|     breq    unstuff3            ;[8] | ||||
| didunstuff3: | ||||
|     nop                         ;[9] | ||||
|     rjmp    rxDataBit4          ;[10] | ||||
|                                 ;[11]                | ||||
|  | ||||
| ; the avr branch instructions allow an offset of +63 insturction only, so we need this | ||||
| ; 'local copy' of se0 | ||||
| nse0:        | ||||
|     rjmp    se0                 ;[4] | ||||
|                                 ;[5] | ||||
| ; the same same as for se0 is needed for overflow and StuffErr | ||||
| nOverflow: | ||||
| stuffErr: | ||||
|     rjmp    overflow | ||||
|  | ||||
|  | ||||
| unstuff0:                       ;[8] this is the branch delay of breq unstuffX | ||||
|     andi    x1, USBMASK         ;[9] do an se0 check here (if the last crc byte ends with 5 one's we might end up here | ||||
|     breq    didunstuff0         ;[10] event tough the message is complete -> jump back and store the byte | ||||
|     ori     shift, 0x01         ;[11] invert the last received bit to prevent furhter unstuffing | ||||
|     in      x2, USBIN           ;[0] we have some free cycles so we could check for bit stuffing errors | ||||
|     andi    x3, 0xFE            ;[1] mark this bit as inverted (will be corrected before storing shift) | ||||
|     eor     x1, x2              ;[2] x1 and x2 have to be different because the stuff bit is always a zero | ||||
|     andi    x1, USBMASK         ;[3] mask the interesting bits | ||||
|     breq    stuffErr            ;[4] if the stuff bit is a 1-bit something went wrong | ||||
|     mov     x1, x2              ;[5] the next bit expects the last state to be in x1 | ||||
|     rjmp    didunstuff0         ;[6] | ||||
|                                 ;[7] jump delay of rjmp didunstuffX  | ||||
|  | ||||
| unstuff1:                       ;[11] this is the jump delay of breq unstuffX | ||||
|     in      x1, USBIN           ;[0] we have some free cycles so we could check for bit stuffing errors | ||||
|     ori     shift, 0x02         ;[1] invert the last received bit to prevent furhter unstuffing | ||||
|     andi    x3, 0xFD            ;[2] mark this bit as inverted (will be corrected before storing shift) | ||||
|     eor     x2, x1              ;[3] x1 and x2 have to be different because the stuff bit is always a zero | ||||
|     andi    x2, USBMASK         ;[4] mask the interesting bits | ||||
|     breq    stuffErr            ;[5] if the stuff bit is a 1-bit something went wrong | ||||
|     mov     x2, x1              ;[6] the next bit expects the last state to be in x2 | ||||
|     nop2                        ;[7] | ||||
|                                 ;[8] | ||||
|     rjmp    didunstuff1         ;[9] | ||||
|                                 ;[10] jump delay of rjmp didunstuffX         | ||||
|  | ||||
| unstuff2:                       ;[9] this is the jump delay of breq unstuffX | ||||
|     ori     shift, 0x04         ;[10] invert the last received bit to prevent furhter unstuffing | ||||
|     andi    x3, 0xFB            ;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
|     in      x2, USBIN           ;[0] we have some free cycles so we could check for bit stuffing errors | ||||
|     eor     x1, x2              ;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
|     andi    x1, USBMASK         ;[2] mask the interesting bits | ||||
|     breq    stuffErr            ;[3] if the stuff bit is a 1-bit something went wrong | ||||
|     mov     x1, x2              ;[4] the next bit expects the last state to be in x1 | ||||
|     nop2                        ;[5] | ||||
|                                 ;[6] | ||||
|     rjmp    didunstuff2         ;[7] | ||||
|                                 ;[8] jump delay of rjmp didunstuffX  | ||||
|  | ||||
| unstuff3:                       ;[9] this is the jump delay of breq unstuffX | ||||
|     ori     shift, 0x08         ;[10] invert the last received bit to prevent furhter unstuffing | ||||
|     andi    x3, 0xF7            ;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
|     in      x1, USBIN           ;[0] we have some free cycles so we could check for bit stuffing errors | ||||
|     eor     x2, x1              ;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
|     andi    x2, USBMASK         ;[2] mask the interesting bits | ||||
|     breq    stuffErr            ;[3] if the stuff bit is a 1-bit something went wrong | ||||
|     mov     x2, x1              ;[4] the next bit expects the last state to be in x2 | ||||
|     nop2                        ;[5] | ||||
|                                 ;[6] | ||||
|     rjmp    didunstuff3         ;[7] | ||||
|                                 ;[8] jump delay of rjmp didunstuffX          | ||||
|  | ||||
|  | ||||
|  | ||||
| ; the include has to be here due to branch distance restirctions | ||||
| #include "asmcommon.inc" | ||||
|  | ||||
|      | ||||
|  | ||||
| ; USB spec says: | ||||
| ; idle = J | ||||
| ; J = (D+ = 0), (D- = 1) | ||||
| ; K = (D+ = 1), (D- = 0) | ||||
| ; Spec allows 7.5 bit times from EOP to SOP for replies | ||||
| ; 7.5 bit times is 90 cycles. ...there is plenty of time | ||||
|  | ||||
|  | ||||
| sendNakAndReti: | ||||
|     ldi     x3, USBPID_NAK  ;[-18] | ||||
|     rjmp    sendX3AndReti   ;[-17] | ||||
| sendAckAndReti: | ||||
|     ldi     cnt, USBPID_ACK ;[-17] | ||||
| sendCntAndReti: | ||||
|     mov     x3, cnt         ;[-16] | ||||
| sendX3AndReti: | ||||
|     ldi     YL, 20          ;[-15] x3==r20 address is 20 | ||||
|     ldi     YH, 0           ;[-14] | ||||
|     ldi     cnt, 2          ;[-13] | ||||
| ;   rjmp    usbSendAndReti      fallthrough | ||||
|  | ||||
| ;usbSend: | ||||
| ;pointer to data in 'Y' | ||||
| ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] | ||||
| ;uses: x1...x4, btcnt, shift, cnt, Y | ||||
| ;Numbers in brackets are time since first bit of sync pattern is sent | ||||
|  | ||||
| usbSendAndReti:             ; 12 cycles until SOP | ||||
|     in      x2, USBDDR      ;[-12] | ||||
|     ori     x2, USBMASK     ;[-11] | ||||
|     sbi     USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) | ||||
|     in      x1, USBOUT      ;[-8] port mirror for tx loop | ||||
|     out     USBDDR, x2      ;[-6] <- acquire bus | ||||
|     ldi     x2, 0           ;[-6] init x2 (bitstuff history) because sync starts with 0 | ||||
|     ldi     x4, USBMASK     ;[-5] exor mask | ||||
|     ldi     shift, 0x80     ;[-4] sync byte is first byte sent | ||||
| txByteLoop: | ||||
|     ldi     bitcnt, 0x40    ;[-3]=[9]     binary 01000000 | ||||
| txBitLoop:                  ; the loop sends the first 7 bits of the byte | ||||
|     sbrs    shift, 0        ;[-2]=[10] if we have to send a 1 don't change the line state | ||||
|     eor     x1, x4          ;[-1]=[11] | ||||
|     out     USBOUT, x1      ;[0] | ||||
|     ror     shift           ;[1] | ||||
|     ror     x2              ;[2] transfers the last sent bit to the stuffing history | ||||
| didStuffN: | ||||
|     nop                     ;[3] | ||||
|     nop                     ;[4] | ||||
|     cpi     x2, 0xfc        ;[5] if we sent six consecutive ones | ||||
|     brcc    bitstuffN       ;[6] | ||||
|     lsr     bitcnt          ;[7] | ||||
|     brne    txBitLoop       ;[8] restart the loop while the 1 is still in the bitcount | ||||
|  | ||||
| ; transmit bit 7 | ||||
|     sbrs    shift, 0        ;[9] | ||||
|     eor     x1, x4          ;[10] | ||||
| didStuff7: | ||||
|     ror     shift           ;[11] | ||||
|     out     USBOUT, x1      ;[0] transfer bit 7 to the pins | ||||
|     ror     x2              ;[1] move the bit into the stuffing history  | ||||
|     cpi     x2, 0xfc        ;[2] | ||||
|     brcc    bitstuff7       ;[3] | ||||
|     ld      shift, y+       ;[4] get next byte to transmit | ||||
|     dec     cnt             ;[5] decrement byte counter | ||||
|     brne    txByteLoop      ;[7] if we have more bytes start next one | ||||
|                             ;[8] branch delay | ||||
|                              | ||||
| ;make SE0: | ||||
|     cbr     x1, USBMASK     ;[8]        prepare SE0 [spec says EOP may be 25 to 30 cycles] | ||||
|     lds     x2, usbNewDeviceAddr;[9] | ||||
|     lsl     x2              ;[11]       we compare with left shifted address | ||||
|     out     USBOUT, x1      ;[0]        <-- out SE0 -- from now 2 bits = 24 cycles until bus idle | ||||
|     subi    YL, 20 + 2      ;[1]        Only assign address on data packets, not ACK/NAK in x3 | ||||
|     sbci    YH, 0           ;[2] | ||||
| ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: | ||||
| ;set address only after data packet was sent, not after handshake | ||||
|     breq    skipAddrAssign  ;[3] | ||||
|     sts     usbDeviceAddr, x2       ; if not skipped: SE0 is one cycle longer | ||||
| skipAddrAssign: | ||||
| ;end of usbDeviceAddress transfer | ||||
|     ldi     x2, 1<<USB_INTR_PENDING_BIT;[5] int0 occurred during TX -- clear pending flag | ||||
|     USB_STORE_PENDING(x2)   ;[6] | ||||
|     ori     x1, USBIDLE     ;[7] | ||||
|     in      x2, USBDDR      ;[8] | ||||
|     cbr     x2, USBMASK     ;[9] set both pins to input | ||||
|     mov     x3, x1          ;[10] | ||||
|     cbr     x3, USBMASK     ;[11] configure no pullup on both pins | ||||
|     ldi     x4, 4           ;[12] | ||||
| se0Delay: | ||||
|     dec     x4              ;[13] [16] [19] [22] | ||||
|     brne    se0Delay        ;[14] [17] [20] [23] | ||||
|     out     USBOUT, x1      ;[24] <-- out J (idle) -- end of SE0 (EOP signal) | ||||
|     out     USBDDR, x2      ;[25] <-- release bus now | ||||
|     out     USBOUT, x3      ;[26] <-- ensure no pull-up resistors are active | ||||
|     rjmp    doReturn | ||||
|  | ||||
| bitstuffN: | ||||
|     eor     x1, x4          ;[8] generate a zero | ||||
|     ldi     x2, 0           ;[9] reset the bit stuffing history | ||||
|     nop2                    ;[10] | ||||
|     out     USBOUT, x1      ;[0] <-- send the stuffing bit | ||||
|     rjmp    didStuffN       ;[1] | ||||
|  | ||||
| bitstuff7: | ||||
|     eor     x1, x4          ;[5] | ||||
|     ldi     x2, 0           ;[6] reset bit stuffing history | ||||
|     clc                     ;[7] fill a zero into the shift register | ||||
|     rol     shift           ;[8] compensate for ror shift at branch destination | ||||
|     rjmp    didStuff7       ;[9] | ||||
|                             ;[10] jump delay | ||||
|  | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
| ; receives data bytes and calculates the crc | ||||
| ; second half of the data byte receiver loop | ||||
| ; most parts of the crc algorithm are here | ||||
| ;-------------------------------------------------------------------------------------------------------------- | ||||
|  | ||||
| nOverflow2: | ||||
|     rjmp overflow | ||||
|  | ||||
| rxDataBit4: | ||||
|     in      x1, USBIN           ;[0] sample line state | ||||
|     andi    x1, USBMASK         ;[1] check for se0 | ||||
|     breq    nOverflow2          ;[2] | ||||
|     eor     x2, x1              ;[3] | ||||
|     bst     x2, USBMINUS        ;[4] | ||||
|     bld     shift, 4            ;[5] | ||||
|     mov     x2, shift           ;[6] | ||||
|     andi    x2, 0x9F            ;[7] | ||||
|     breq    unstuff4            ;[8] | ||||
| didunstuff4: | ||||
|     nop2                        ;[9][10] | ||||
|     nop                         ;[11] | ||||
|  | ||||
| ; bit5                           | ||||
|     in      x2, USBIN           ;[0] sample line state | ||||
|     nop                         ;[1] use the table for the higher byte | ||||
|     eor     x1, x2              ;[2] | ||||
|     bst     x1, USBMINUS        ;[3] | ||||
|     bld     shift, 5            ;[4] | ||||
|     mov     x1, shift           ;[5] | ||||
|     andi    x1, 0x3F            ;[6] | ||||
|     breq    unstuff5            ;[7] | ||||
| didunstuff5: | ||||
|     nop2                        ;[8] load the higher crc xor-byte and store it for later use | ||||
|                                 ;[9] lpm needs 3 cycles | ||||
|     nop                         ;[10]            | ||||
|     nop                         ;[11] load the lower crc xor byte adress | ||||
|  | ||||
| ; bit6                           | ||||
|     in      x1, USBIN           ;[0] sample line state | ||||
|     eor     x2, x1              ;[1] | ||||
|     bst     x2, USBMINUS        ;[2] | ||||
|     bld     shift, 6            ;[3] | ||||
|     mov     x2, shift           ;[4] | ||||
|     andi    x2, 0x7E            ;[5] | ||||
|     breq    unstuff6            ;[6] | ||||
| didunstuff6: | ||||
|     nop2                        ;[7] load the lower xor crc byte | ||||
|                                 ;[8] lpm needs 3 cycles | ||||
|     nop                         ;[9] | ||||
|     nop                         ;[10] xor the old high crc byte with the low xor-byte | ||||
|     nop                         ;[11] move the new high order crc value from temp to its destination | ||||
|              | ||||
| ; bit7                           | ||||
|     in      x2, USBIN           ;[0] sample line state | ||||
|     eor     x1, x2              ;[1] | ||||
|     bst     x1, USBMINUS        ;[2] | ||||
|     bld     shift, 7            ;[3] now shift holds the complete but inverted data byte | ||||
|     mov     x1, shift           ;[4] | ||||
|     andi    x1, 0xFC            ;[5] | ||||
|     breq    unstuff7            ;[6] | ||||
| didunstuff7: | ||||
|     eor     x3, shift           ;[7] x3 marks all bits which have not been inverted by the unstuffing subs | ||||
|     mov     x4, x3              ;[8] keep a copy of the data byte it will be stored during next bit0 | ||||
|     nop                         ;[9] feed the actual byte into the crc algorithm | ||||
|     rjmp    rxDataStart         ;[10] next byte | ||||
|                                 ;[11] during the reception of the next byte this one will be fed int the crc algorithm | ||||
|  | ||||
| unstuff4:                       ;[9] this is the jump delay of rjmp unstuffX | ||||
|     ori     shift, 0x10         ;[10] invert the last received bit to prevent furhter unstuffing | ||||
|     andi    x3, 0xEF            ;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
|     in      x2, USBIN           ;[0] we have some free cycles so we could check for bit stuffing errors | ||||
|     eor     x1, x2              ;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
|     andi    x1, USBMASK         ;[2] mask the interesting bits | ||||
|     breq    stuffErr2           ;[3] if the stuff bit is a 1-bit something went wrong | ||||
|     mov     x1, x2              ;[4] the next bit expects the last state to be in x1 | ||||
|     nop2                        ;[5] | ||||
|                                 ;[6] | ||||
|     rjmp    didunstuff4         ;[7] | ||||
|                                 ;[8] jump delay of rjmp didunstuffX  | ||||
|  | ||||
| unstuff5:                       ;[8] this is the jump delay of rjmp unstuffX | ||||
|     nop                         ;[9] | ||||
|     ori     shift, 0x20         ;[10] invert the last received bit to prevent furhter unstuffing | ||||
|     andi    x3, 0xDF            ;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
|     in      x1, USBIN           ;[0] we have some free cycles so we could check for bit stuffing errors | ||||
|     eor     x2, x1              ;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
|     andi    x2, USBMASK         ;[2] mask the interesting bits | ||||
|     breq    stuffErr2           ;[3] if the stuff bit is a 1-bit something went wrong | ||||
|     mov     x2, x1              ;[4] the next bit expects the last state to be in x2 | ||||
|     nop                         ;[5] | ||||
|     rjmp    didunstuff5         ;[6] | ||||
|                                 ;[7] jump delay of rjmp didunstuffX                                                  | ||||
|  | ||||
| unstuff6:                       ;[7] this is the jump delay of rjmp unstuffX | ||||
|     nop2                        ;[8] | ||||
|                                 ;[9] | ||||
|     ori     shift, 0x40         ;[10] invert the last received bit to prevent furhter unstuffing | ||||
|     andi    x3, 0xBF            ;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
|     in      x2, USBIN           ;[0] we have some free cycles so we could check for bit stuffing errors | ||||
|     eor     x1, x2              ;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
|     andi    x1, USBMASK         ;[2] mask the interesting bits | ||||
|     breq    stuffErr2           ;[3] if the stuff bit is a 1-bit something went wrong | ||||
|     mov     x1, x2              ;[4] the next bit expects the last state to be in x1 | ||||
|     rjmp    didunstuff6         ;[5] | ||||
|                                 ;[6] jump delay of rjmp didunstuffX  | ||||
|  | ||||
| unstuff7:                       ;[7] this is the jump delay of rjmp unstuffX | ||||
|     nop                         ;[8] | ||||
|     nop                         ;[9] | ||||
|     ori     shift, 0x80         ;[10] invert the last received bit to prevent furhter unstuffing | ||||
|     andi    x3, 0x7F            ;[11] mark this bit as inverted (will be corrected before storing shift) | ||||
|     in      x1, USBIN           ;[0] we have some free cycles so we could check for bit stuffing errors | ||||
|     eor     x2, x1              ;[1] x1 and x2 have to be different because the stuff bit is always a zero | ||||
|     andi    x2, USBMASK         ;[2] mask the interesting bits | ||||
|     breq    stuffErr2           ;[3] if the stuff bit is a 1-bit something went wrong | ||||
|     mov     x2, x1              ;[4] the next bit expects the last state to be in x2 | ||||
|     rjmp    didunstuff7         ;[5] | ||||
|                                 ;[6] jump delay of rjmp didunstuff7 | ||||
|  | ||||
| ; local copy of the stuffErr desitnation for the second half of the receiver loop | ||||
| stuffErr2: | ||||
|     rjmp    stuffErr | ||||
							
								
								
									
										359
									
								
								usbdrv/usbdrvasm20.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										359
									
								
								usbdrv/usbdrvasm20.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,359 @@ | ||||
| /* Name: usbdrvasm20.inc | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Jeroen Benschop | ||||
|  * Based on usbdrvasm16.inc from Christian Starkjohann | ||||
|  * Creation Date: 2008-03-05 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* Do not link this file! Link usbdrvasm.S instead, which includes the | ||||
|  * appropriate implementation! | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This file is the 20 MHz version of the asssembler part of the USB driver. It | ||||
| requires a 20 MHz crystal (not a ceramic resonator and not a calibrated RC | ||||
| oscillator). | ||||
|  | ||||
| See usbdrv.h for a description of the entire driver. | ||||
|  | ||||
| Since almost all of this code is timing critical, don't change unless you | ||||
| really know what you are doing! Many parts require not only a maximum number | ||||
| of CPU cycles, but even an exact number of cycles! | ||||
| */ | ||||
|  | ||||
| #define leap2   x3 | ||||
| #ifdef __IAR_SYSTEMS_ASM__ | ||||
| #define nextInst    $+2 | ||||
| #else | ||||
| #define nextInst    .+0 | ||||
| #endif | ||||
|  | ||||
| ;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes | ||||
| ;nominal frequency: 20 MHz -> 13.333333 cycles per bit, 106.666667 cycles per byte | ||||
| ; Numbers in brackets are clocks counted from center of last sync bit | ||||
| ; when instruction starts | ||||
| ;register use in receive loop: | ||||
| ; shift assembles the byte currently being received | ||||
| ; x1 holds the D+ and D- line state | ||||
| ; x2 holds the previous line state | ||||
| ; x4 (leap)  is used to add a leap cycle once every three bytes received | ||||
| ; X3 (leap2) is used to add a leap cycle once every three stuff bits received | ||||
| ; bitcnt is used to determine when a stuff bit is due | ||||
| ; cnt holds the number of bytes left in the receive buffer | ||||
|  | ||||
| USB_INTR_VECTOR: | ||||
| ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt | ||||
|     push    YL                  ;[-28] push only what is necessary to sync with edge ASAP | ||||
|     in      YL, SREG            ;[-26] | ||||
|     push    YL                  ;[-25] | ||||
|     push    YH                  ;[-23] | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Synchronize with sync pattern: | ||||
| ;---------------------------------------------------------------------------- | ||||
| ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] | ||||
| ;sync up with J to K edge during sync pattern -- use fastest possible loops | ||||
| ;The first part waits at most 1 bit long since we must be in sync pattern. | ||||
| ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to | ||||
| ;waitForJ, ensure that this prerequisite is met. | ||||
| waitForJ: | ||||
|     inc     YL | ||||
|     sbis    USBIN, USBMINUS | ||||
|     brne    waitForJ        ; just make sure we have ANY timeout | ||||
| waitForK: | ||||
| ;The following code results in a sampling window of < 1/4 bit which meets the spec. | ||||
|     sbis    USBIN, USBMINUS     ;[-19] | ||||
|     rjmp    foundK              ;[-18] | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
|     sbis    USBIN, USBMINUS | ||||
|     rjmp    foundK | ||||
| #if USB_COUNT_SOF | ||||
|     lds     YL, usbSofCount | ||||
|     inc     YL | ||||
|     sts     usbSofCount, YL | ||||
| #endif  /* USB_COUNT_SOF */ | ||||
| #ifdef USB_SOF_HOOK | ||||
|     USB_SOF_HOOK | ||||
| #endif | ||||
|     rjmp    sofError | ||||
| foundK:                         ;[-16] | ||||
| ;{3, 5} after falling D- edge, average delay: 4 cycles | ||||
| ;bit0 should be at 34 for center sampling. Currently at 4 so 30 cylces till bit 0 sample | ||||
| ;use 1 bit time for setup purposes, then sample again. Numbers in brackets | ||||
| ;are cycles from center of first sync (double K) bit after the instruction | ||||
|     push    bitcnt              ;[-16] | ||||
| ;   [---]                       ;[-15] | ||||
|     lds     YL, usbInputBufOffset;[-14] | ||||
| ;   [---]                       ;[-13] | ||||
|     clr     YH                  ;[-12] | ||||
|     subi    YL, lo8(-(usbRxBuf));[-11] [rx loop init] | ||||
|     sbci    YH, hi8(-(usbRxBuf));[-10] [rx loop init] | ||||
|     push    shift               ;[-9] | ||||
| ;   [---]                       ;[-8] | ||||
|     ldi     shift,0x40          ;[-7] set msb to "1" so processing bit7 can be detected | ||||
|     nop2                        ;[-6] | ||||
| ;   [---]                       ;[-5] | ||||
|     ldi     bitcnt, 5           ;[-4] [rx loop init] | ||||
|     sbis    USBIN, USBMINUS     ;[-3] we want two bits K (sample 3 cycles too early) | ||||
|     rjmp    haveTwoBitsK        ;[-2] | ||||
|     pop     shift               ;[-1] undo the push from before | ||||
|     pop     bitcnt              ;[1]  | ||||
|     rjmp    waitForK            ;[3] this was not the end of sync, retry | ||||
| ; The entire loop from waitForK until rjmp waitForK above must not exceed two | ||||
| ; bit times (= 27 cycles). | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; push more registers and initialize values while we sample the first bits: | ||||
| ;---------------------------------------------------------------------------- | ||||
| haveTwoBitsK: | ||||
|     push    x1                  ;[0] | ||||
|     push    x2                  ;[2] | ||||
|     push    x3                  ;[4] (leap2) | ||||
|     ldi     leap2, 0x55         ;[6] add leap cycle on 2nd,5th,8th,... stuff bit | ||||
|     push    x4                  ;[7] == leap | ||||
|     ldi     leap, 0x55          ;[9] skip leap cycle on 2nd,5th,8th,... byte received | ||||
|     push    cnt                 ;[10] | ||||
|     ldi     cnt, USB_BUFSIZE    ;[12] [rx loop init] | ||||
|     ldi     x2, 1<<USBPLUS      ;[13] current line state is K state. D+=="1", D-=="0" | ||||
| bit0:        | ||||
|     in      x1, USBIN           ;[0] sample line state | ||||
|     andi    x1, USBMASK         ;[1] filter only D+ and D- bits | ||||
|     rjmp    handleBit           ;[2] make bit0 14 cycles long | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Process bit7. However, bit 6 still may need unstuffing. | ||||
| ;---------------------------------------------------------------------------- | ||||
|  | ||||
| b6checkUnstuff: | ||||
|     dec     bitcnt              ;[9] | ||||
|     breq    unstuff6            ;[10] | ||||
| bit7: | ||||
|     subi    cnt, 1              ;[11] cannot use dec becaus it does not affect the carry flag | ||||
|     brcs    overflow            ;[12] Too many bytes received. Ignore packet | ||||
|     in      x1, USBIN           ;[0] sample line state | ||||
|     andi    x1, USBMASK         ;[1] filter only D+ and D- bits | ||||
|     cpse    x1, x2              ;[2] when previous line state equals current line state, handle "1" | ||||
|     rjmp    b7handle0           ;[3] when line state differs, handle "0" | ||||
|     sec                         ;[4] | ||||
|     ror     shift               ;[5] shift "1" into the data | ||||
|     st      y+, shift           ;[6] store the data into the buffer | ||||
|     ldi     shift, 0x40         ;[7] reset data for receiving the next byte | ||||
|     subi    leap, 0x55          ;[9] trick to introduce a leap cycle every 3 bytes | ||||
|     brcc    nextInst            ;[10 or 11] it will fail after 85 bytes. However low speed can only receive 11 | ||||
|     dec     bitcnt              ;[11 or 12] | ||||
|     brne    bit0                ;[12 or 13] | ||||
|     ldi     x1, 1               ;[13 or 14] unstuffing bit 7 | ||||
|     in      bitcnt, USBIN       ;[0] sample stuff bit | ||||
|     rjmp    unstuff             ;[1] | ||||
|  | ||||
| b7handle0: | ||||
|     mov     x2,x1               ;[5] Set x2 to current line state | ||||
|     ldi     bitcnt, 6           ;[6] | ||||
|     lsr     shift               ;[7] shift "0" into the data | ||||
|     st      y+, shift           ;[8] store data into the buffer | ||||
|     ldi     shift, 0x40         ;[10] reset data for receiving the next byte | ||||
|     subi    leap, 0x55          ;[11] trick to introduce a leap cycle every 3 bytes | ||||
|     brcs    bit0                ;[12] it will fail after 85 bytes. However low speed can only receive 11 | ||||
|     rjmp    bit0                ;[13] | ||||
|  | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Handle unstuff | ||||
| ; x1==0xFF indicate unstuffing bit6 | ||||
| ;---------------------------------------------------------------------------- | ||||
|  | ||||
| unstuff6: | ||||
|     ldi     x1,0xFF             ;[12] indicate unstuffing bit 6 | ||||
|     in      bitcnt, USBIN       ;[0]  sample stuff bit | ||||
|     nop                         ;[1]  fix timing | ||||
| unstuff:                        ;b0-5  b6   b7 | ||||
|     mov     x2,bitcnt           ;[3]  [2]  [3]  Set x2 to match line state | ||||
|     subi    leap2, 0x55         ;[4]  [3]  [4]  delay loop | ||||
|     brcs    nextInst            ;[5]  [4]  [5]  add one cycle every three stuff bits | ||||
|     sbci    leap2,0             ;[6]  [5]  [6] | ||||
|     ldi     bitcnt,6            ;[7]  [6]  [7]  reset bit stuff counter | ||||
|     andi    x2, USBMASK         ;[8]  [7]  [8] only keep D+ and D- | ||||
|     cpi     x1,0                ;[9]  [8]  [9] | ||||
|     brmi    bit7                ;[10] [9]  [10] finished unstuffing bit6 When x1<0 | ||||
|     breq    bitloop             ;[11] ---  [11] finished unstuffing bit0-5 when x1=0 | ||||
|     nop                         ;---  ---  [12] | ||||
|     in      x1, USBIN           ;---  ---  [0] sample line state for bit0 | ||||
|     andi    x1, USBMASK         ;---  ---  [1] filter only D+ and D- bits | ||||
|     rjmp    handleBit           ;---  ---  [2] make bit0 14 cycles long | ||||
|  | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; Receiver loop (numbers in brackets are cycles within byte after instr) | ||||
| ;---------------------------------------------------------------------------- | ||||
| bitloop: | ||||
|     in      x1, USBIN           ;[0] sample line state | ||||
|     andi    x1, USBMASK         ;[1] filter only D+ and D- bits | ||||
|     breq    se0                 ;[2] both lines are low so handle se0 | ||||
| handleBit: | ||||
|     cpse    x1, x2              ;[3] when previous line state equals current line state, handle "1" | ||||
|     rjmp    handle0             ;[4] when line state differs, handle "0" | ||||
|     sec                         ;[5] | ||||
|     ror     shift               ;[6] shift "1" into the data | ||||
|     brcs    b6checkUnstuff      ;[7] When after shift C is set, next bit is bit7 | ||||
|     nop2                        ;[8] | ||||
|     dec     bitcnt              ;[10] | ||||
|     brne    bitloop             ;[11] | ||||
|     ldi     x1,0                ;[12] indicate unstuff for bit other than bit6 or bit7 | ||||
|     in      bitcnt, USBIN       ;[0] sample stuff bit | ||||
|     rjmp    unstuff             ;[1] | ||||
|  | ||||
| handle0: | ||||
|     mov     x2, x1              ;[6] Set x2 to current line state | ||||
|     ldi     bitcnt, 6           ;[7] reset unstuff counter.  | ||||
|     lsr     shift               ;[8] shift "0" into the data | ||||
|     brcs    bit7                ;[9] When after shift C is set, next bit is bit7 | ||||
|     nop                         ;[10] | ||||
|     rjmp    bitloop             ;[11]  | ||||
|      | ||||
| ;---------------------------------------------------------------------------- | ||||
| ; End of receive loop. Now start handling EOP | ||||
| ;---------------------------------------------------------------------------- | ||||
|  | ||||
| macro POP_STANDARD ; 14 cycles | ||||
|     pop     cnt | ||||
|     pop     x4 | ||||
|     pop     x3 | ||||
|     pop     x2 | ||||
|     pop     x1 | ||||
|     pop     shift | ||||
|     pop     bitcnt | ||||
|     endm | ||||
| macro POP_RETI     ; 7 cycles | ||||
|     pop     YH | ||||
|     pop     YL | ||||
|     out     SREG, YL | ||||
|     pop     YL | ||||
|     endm | ||||
|  | ||||
|  | ||||
|  | ||||
| #include "asmcommon.inc" | ||||
|  | ||||
| ; USB spec says: | ||||
| ; idle = J | ||||
| ; J = (D+ = 0), (D- = 1) | ||||
| ; K = (D+ = 1), (D- = 0) | ||||
| ; Spec allows 7.5 bit times from EOP to SOP for replies | ||||
| ; 7.5 bit times is 100 cycles. This implementation arrives a bit later at se0 | ||||
| ; then specified in the include file but there is plenty of time | ||||
|  | ||||
| bitstuffN: | ||||
|     eor     x1, x4          ;[8] | ||||
|     ldi     x2, 0           ;[9] | ||||
|     nop2                    ;[10] | ||||
|     out     USBOUT, x1      ;[12] <-- out | ||||
|     rjmp    didStuffN       ;[0] | ||||
|      | ||||
| bitstuff7: | ||||
|     eor     x1, x4          ;[6] | ||||
|     ldi     x2, 0           ;[7] Carry is zero due to brcc | ||||
|     rol     shift           ;[8] compensate for ror shift at branch destination | ||||
|     nop2                    ;[9] | ||||
|     rjmp    didStuff7       ;[11] | ||||
|  | ||||
| sendNakAndReti: | ||||
|     ldi     x3, USBPID_NAK  ;[-18] | ||||
|     rjmp    sendX3AndReti   ;[-17] | ||||
| sendAckAndReti: | ||||
|     ldi     cnt, USBPID_ACK ;[-17] | ||||
| sendCntAndReti: | ||||
|     mov     x3, cnt         ;[-16] | ||||
| sendX3AndReti: | ||||
|     ldi     YL, 20          ;[-15] x3==r20 address is 20 | ||||
|     ldi     YH, 0           ;[-14] | ||||
|     ldi     cnt, 2          ;[-13] | ||||
| ;   rjmp    usbSendAndReti      fallthrough | ||||
|  | ||||
| ;usbSend: | ||||
| ;pointer to data in 'Y' | ||||
| ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] | ||||
| ;uses: x1...x4, btcnt, shift, cnt, Y | ||||
| ;Numbers in brackets are time since first bit of sync pattern is sent | ||||
| ;We don't match the transfer rate exactly (don't insert leap cycles every third | ||||
| ;byte) because the spec demands only 1.5% precision anyway. | ||||
| usbSendAndReti:             ; 12 cycles until SOP | ||||
|     in      x2, USBDDR      ;[-12] | ||||
|     ori     x2, USBMASK     ;[-11] | ||||
|     sbi     USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) | ||||
|     in      x1, USBOUT      ;[-8] port mirror for tx loop | ||||
|     out     USBDDR, x2      ;[-7] <- acquire bus | ||||
| ; need not init x2 (bitstuff history) because sync starts with 0 | ||||
|     ldi     x4, USBMASK     ;[-6] exor mask | ||||
|     ldi     shift, 0x80     ;[-5] sync byte is first byte sent | ||||
| txByteLoop: | ||||
|     ldi     bitcnt, 0x49    ;[-4]        [10] binary 01001001 | ||||
| txBitLoop: | ||||
|     sbrs    shift, 0        ;[-3] [10]   [11] | ||||
|     eor     x1, x4          ;[-2] [11]   [12] | ||||
|     out     USBOUT, x1      ;[-1] [12]   [13]   <-- out N | ||||
|     ror     shift           ;[0]  [13]   [14] | ||||
|     ror     x2              ;[1] | ||||
| didStuffN: | ||||
|     nop2                    ;[2] | ||||
|     nop                     ;[4] | ||||
|     cpi     x2, 0xfc        ;[5] | ||||
|     brcc    bitstuffN       ;[6] | ||||
|     lsr     bitcnt          ;[7] | ||||
|     brcc    txBitLoop       ;[8] | ||||
|     brne    txBitLoop       ;[9] | ||||
|  | ||||
|     sbrs    shift, 0        ;[10] | ||||
|     eor     x1, x4          ;[11] | ||||
| didStuff7: | ||||
|     out     USBOUT, x1      ;[-1] [13] <-- out 7 | ||||
|     ror     shift           ;[0] [14] | ||||
|     ror     x2              ;[1] | ||||
|     nop                     ;[2] | ||||
|     cpi     x2, 0xfc        ;[3] | ||||
|     brcc    bitstuff7       ;[4] | ||||
|     ld      shift, y+       ;[5] | ||||
|     dec     cnt             ;[7] | ||||
|     brne    txByteLoop      ;[8] | ||||
| ;make SE0: | ||||
|     cbr     x1, USBMASK     ;[9] prepare SE0 [spec says EOP may be 25 to 30 cycles] | ||||
|     lds     x2, usbNewDeviceAddr;[10] | ||||
|     lsl     x2              ;[12] we compare with left shifted address | ||||
|     out     USBOUT, x1      ;[13] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle | ||||
|     subi    YL, 20 + 2      ;[0] Only assign address on data packets, not ACK/NAK in x3 | ||||
|     sbci    YH, 0           ;[1] | ||||
| ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: | ||||
| ;set address only after data packet was sent, not after handshake | ||||
|     breq    skipAddrAssign  ;[2] | ||||
|     sts     usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer | ||||
| skipAddrAssign: | ||||
| ;end of usbDeviceAddress transfer | ||||
|     ldi     x2, 1<<USB_INTR_PENDING_BIT;[4] int0 occurred during TX -- clear pending flag | ||||
|     USB_STORE_PENDING(x2)   ;[5] | ||||
|     ori     x1, USBIDLE     ;[6] | ||||
|     in      x2, USBDDR      ;[7] | ||||
|     cbr     x2, USBMASK     ;[8] set both pins to input | ||||
|     mov     x3, x1          ;[9] | ||||
|     cbr     x3, USBMASK     ;[10] configure no pullup on both pins | ||||
|     ldi     x4, 5           ;[11] | ||||
| se0Delay: | ||||
|     dec     x4              ;[12] [15] [18] [21] [24] | ||||
|     brne    se0Delay        ;[13] [16] [19] [22] [25] | ||||
|     out     USBOUT, x1      ;[26] <-- out J (idle) -- end of SE0 (EOP signal) | ||||
|     out     USBDDR, x2      ;[27] <-- release bus now | ||||
|     out     USBOUT, x3      ;[28] <-- ensure no pull-up resistors are active | ||||
|     rjmp    doReturn | ||||
							
								
								
									
										143
									
								
								usbdrv/usbportability.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								usbdrv/usbportability.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| /* Name: usbportability.h | ||||
|  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | ||||
|  * Author: Christian Starkjohann | ||||
|  * Creation Date: 2008-06-17 | ||||
|  * Tabsize: 4 | ||||
|  * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH | ||||
|  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| General Description: | ||||
| This header is intended to contain all (or at least most of) the compiler | ||||
| and library dependent stuff. The C code is written for avr-gcc and avr-libc. | ||||
| The API of other development environments is converted to gcc's and avr-libc's | ||||
| API by means of defines. | ||||
|  | ||||
| This header also contains all system includes since they depend on the | ||||
| development environment. | ||||
|  | ||||
| Thanks to Oleg Semyonov for his help with the IAR tools port! | ||||
| */ | ||||
|  | ||||
| #ifndef __usbportability_h_INCLUDED__ | ||||
| #define __usbportability_h_INCLUDED__ | ||||
|  | ||||
| /* We check explicitly for IAR and CodeVision. Default is avr-gcc/avr-libc. */ | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #if defined __IAR_SYSTEMS_ICC__ || defined __IAR_SYSTEMS_ASM__  /* check for IAR */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| #ifndef ENABLE_BIT_DEFINITIONS | ||||
| #   define ENABLE_BIT_DEFINITIONS	1   /* Enable bit definitions */ | ||||
| #endif | ||||
|  | ||||
| /* Include IAR headers */ | ||||
| #include <ioavr.h> | ||||
| #ifndef __IAR_SYSTEMS_ASM__ | ||||
| #   include <inavr.h> | ||||
| #endif | ||||
|  | ||||
| #define __attribute__(arg)  /* not supported on IAR */ | ||||
|  | ||||
| #ifdef __IAR_SYSTEMS_ASM__ | ||||
| #   define __ASSEMBLER__    /* IAR does not define standard macro for asm */ | ||||
| #endif | ||||
|  | ||||
| #ifdef __HAS_ELPM__ | ||||
| #   define PROGMEM __farflash | ||||
| #else | ||||
| #   define PROGMEM __flash | ||||
| #endif | ||||
|  | ||||
| #define USB_READ_FLASH(addr)    (*(PROGMEM char *)(addr)) | ||||
|  | ||||
| /* The following definitions are not needed by the driver, but may be of some | ||||
|  * help if you port a gcc based project to IAR. | ||||
|  */ | ||||
| #define cli()       __disable_interrupt() | ||||
| #define sei()       __enable_interrupt() | ||||
| #define wdt_reset() __watchdog_reset() | ||||
| #define _BV(x)      (1 << (x)) | ||||
|  | ||||
| /* assembler compatibility macros */ | ||||
| #define nop2    rjmp    $+2 /* jump to next instruction */ | ||||
| #define XL      r26 | ||||
| #define XH      r27 | ||||
| #define YL      r28 | ||||
| #define YH      r29 | ||||
| #define ZL      r30 | ||||
| #define ZH      r31 | ||||
| #define lo8(x)  LOW(x) | ||||
| #define hi8(x)  (((x)>>8) & 0xff)   /* not HIGH to allow XLINK to make a proper range check */ | ||||
|  | ||||
| /* Depending on the device you use, you may get problems with the way usbdrv.h | ||||
|  * handles the differences between devices. Since IAR does not use #defines | ||||
|  * for MCU registers, we can't check for the existence of a particular | ||||
|  * register with an #ifdef. If the autodetection mechanism fails, include | ||||
|  * definitions for the required USB_INTR_* macros in your usbconfig.h. See | ||||
|  * usbconfig-prototype.h and usbdrv.h for details. | ||||
|  */ | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #elif __CODEVISIONAVR__ /* check for CodeVision AVR */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| /* This port is not working (yet) */ | ||||
|  | ||||
| /* #define F_CPU   _MCU_CLOCK_FREQUENCY_    seems to be defined automatically */ | ||||
|  | ||||
| #include <io.h> | ||||
| #include <delay.h> | ||||
|  | ||||
| #define __attribute__(arg)  /* not supported on IAR */ | ||||
|  | ||||
| #define PROGMEM                 __flash | ||||
| #define USB_READ_FLASH(addr)    (*(PROGMEM char *)(addr)) | ||||
|  | ||||
| #ifndef __ASSEMBLER__ | ||||
| static inline void  cli(void) | ||||
| { | ||||
|     #asm("cli"); | ||||
| } | ||||
| static inline void  sei(void) | ||||
| { | ||||
|     #asm("sei"); | ||||
| } | ||||
| #endif | ||||
| #define _delay_ms(t)    delay_ms(t) | ||||
| #define _BV(x)          (1 << (x)) | ||||
| #define USB_CFG_USE_SWITCH_STATEMENT 1  /* macro for if() cascase fails for unknown reason */ | ||||
|  | ||||
| #define macro   .macro | ||||
| #define endm    .endmacro | ||||
| #define nop2    rjmp    .+0 /* jump to next instruction */ | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #else   /* default development environment is avr-gcc/avr-libc */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
| #include <avr/io.h> | ||||
| #ifdef __ASSEMBLER__ | ||||
| #   define _VECTOR(N)   __vector_ ## N   /* io.h does not define this for asm */ | ||||
| #else | ||||
| #   include <avr/pgmspace.h> | ||||
| #endif | ||||
|  | ||||
| #if USB_CFG_DRIVER_FLASH_PAGE | ||||
| #   define USB_READ_FLASH(addr)    pgm_read_byte_far(((long)USB_CFG_DRIVER_FLASH_PAGE << 16) | (long)(addr)) | ||||
| #else | ||||
| #   define USB_READ_FLASH(addr)    pgm_read_byte(addr) | ||||
| #endif | ||||
|  | ||||
| #define macro   .macro | ||||
| #define endm    .endm | ||||
| #define nop2    rjmp    .+0 /* jump to next instruction */ | ||||
|  | ||||
| #endif  /* development environment */ | ||||
|  | ||||
| /* for conveniecne, ensure that PRG_RDB exists */ | ||||
| #ifndef PRG_RDB | ||||
| #   define PRG_RDB(addr)    USB_READ_FLASH(addr) | ||||
| #endif | ||||
| #endif  /* __usbportability_h_INCLUDED__ */ | ||||
		Reference in New Issue
	
	Block a user