mirror of
https://git.code.sf.net/p/newrpl/sources
synced 2024-11-16 19:51:25 +01:00
More progress on USB driver
This commit is contained in:
parent
37839199f8
commit
db7c861446
4 changed files with 843 additions and 1007 deletions
840
firmware/sys/target_50g/usbdriver.c
Normal file
840
firmware/sys/target_50g/usbdriver.c
Normal file
|
@ -0,0 +1,840 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015, Claudio Lapilli and the newRPL Team
|
||||
* All rights reserved.
|
||||
* This file is released under the 3-clause BSD license.
|
||||
* See the file LICENSE.txt that shipped with this distribution.
|
||||
*/
|
||||
|
||||
#include <newrpl.h>
|
||||
#include <ui.h>
|
||||
|
||||
// HARDWARE PORTS FOR S3C2410 - USB DEVICE
|
||||
|
||||
|
||||
#define CLKCON HWREG(CLK_REGS,0xc)
|
||||
|
||||
#define FUNC_ADDR_REG HWREG(USBD_REGS,0x140)
|
||||
#define PWR_REG HWREG(USBD_REGS,0x144)
|
||||
#define EP_INT_REG HWREG(USBD_REGS,0x148)
|
||||
#define USB_INT_REG HWREG(USBD_REGS,0x158)
|
||||
#define EP_INT_EN_REG HWREG(USBD_REGS,0x15c)
|
||||
#define USB_INT_EN_REG HWREG(USBD_REGS,0x16c)
|
||||
#define INDEX_REG HWREG(USBD_REGS,0x178)
|
||||
#define EP0_FIFO HWREG(USBD_REGS,0x1c0)
|
||||
#define EP1_FIFO HWREG(USBD_REGS,0x1c4)
|
||||
#define EP2_FIFO HWREG(USBD_REGS,0x1c8)
|
||||
#define EP3_FIFO HWREG(USBD_REGS,0x1cc)
|
||||
#define EP4_FIFO HWREG(USBD_REGS,0x1d0)
|
||||
|
||||
// INDEXED REGISTERS
|
||||
#define EP0_CSR HWREG(USBD_REGS,0x184)
|
||||
#define IN_CSR1_REG HWREG(USBD_REGS,0x184)
|
||||
#define IN_CSR2_REG HWREG(USBD_REGS,0x188)
|
||||
#define MAXP_REG HWREG(USBD_REGS,0x18c)
|
||||
#define OUT_CSR1_REG HWREG(USBD_REGS,0x190)
|
||||
#define OUT_CSR2_REG HWREG(USBD_REGS,0x194)
|
||||
#define OUT_FIFO_CNT1_REG HWREG(USBD_REGS,0x198)
|
||||
#define OUT_FIFO_CNT2_REG HWREG(USBD_REGS,0x19c)
|
||||
|
||||
|
||||
|
||||
// MISCELLANEOUS REGISTERS
|
||||
#define MISCCR HWREG(IO_REGS,0x80)
|
||||
#define UPLLCON HWREG(CLK_REGS,0x8)
|
||||
#define CLKCON HWREG(CLK_REGS,0xc)
|
||||
#define CLKSLOW HWREG(CLK_REGS,0x10)
|
||||
|
||||
|
||||
|
||||
// VARIOUS STATES AND PIN CONSTANTS
|
||||
#define USBSUSPND1 (1<<13)
|
||||
#define USBSUSPND0 (1<<13)
|
||||
#define USBPAD (1<<3)
|
||||
|
||||
|
||||
// CONTROL ENDPOINT CSR
|
||||
#define EP0_OUT_PKT_RDY 1
|
||||
#define EP0_IN_PKT_RDY 2
|
||||
#define EP0_SENT_STALL 4
|
||||
#define EP0_DATA_END 8
|
||||
#define EP0_SETUP_END 16
|
||||
#define EP0_SEND_STALL 32
|
||||
#define EP0_SERVICED_OUT_PKT_RDY 64
|
||||
#define EP0_SERVICED_SETUP_END 128
|
||||
|
||||
// OTHER ENDPOINTS CSR
|
||||
#define EPn_IN_SEND_STALL 0x10
|
||||
#define EPn_OUT_SEND_STALL 0x20
|
||||
|
||||
#define EP0_FIFO_SIZE 8
|
||||
|
||||
//********************************************************************
|
||||
// THE DESCRIPTOR DATA BELOW WAS COPIED AND PORTED FROM THE Teensy rawHID
|
||||
// EXAMPLE IN AGREEMENT WITH THE LICENSE BELOW:
|
||||
|
||||
/* Teensy RawHID example
|
||||
* http://www.pjrc.com/teensy/rawhid.html
|
||||
* Copyright (c) 2009 PJRC.COM, LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above description, website URL and copyright notice and this permission
|
||||
* notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Configurable Options
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// You can change these to give your code its own name.
|
||||
#define STR_MANUFACTURER L"newRPL Team"
|
||||
#define STR_PRODUCT L"Calculator with newRPL"
|
||||
|
||||
// These 4 numbers identify your device. Set these to
|
||||
// something that is (hopefully) not used by any others!
|
||||
#define VENDOR_ID 0x3f0
|
||||
#define PRODUCT_ID 0x121 // ORIGINAL VID/PID OF THE 50g/39gs/40g TARGET HARDWARE
|
||||
//#define PRODUCT_ID 0x441 // ORIGINAL VID/PID OF THE Prime TARGET HARDWARE
|
||||
#define RAWHID_USAGE_PAGE 0xFFAB // recommended: 0xFF00 to 0xFFFF
|
||||
#define RAWHID_USAGE 0x0200 // recommended: 0x0100 to 0xFFFF
|
||||
|
||||
// These determine the bandwidth that will be allocated
|
||||
// for your communication. You do not need to use it
|
||||
// all, but allocating more than necessary means reserved
|
||||
// bandwidth is no longer available to other USB devices.
|
||||
#define RAWHID_TX_SIZE 64 // transmit packet size
|
||||
#define RAWHID_TX_INTERVAL 2 // max # of ms between transmit packets
|
||||
#define RAWHID_RX_SIZE 64 // receive packet size
|
||||
#define RAWHID_RX_INTERVAL 8 // max # of ms between receive packets
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Endpoint Buffer Configuration
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#define ENDPOINT0_SIZE 8
|
||||
#define RAWHID_INTERFACE 0
|
||||
#define RAWHID_TX_ENDPOINT 1
|
||||
#define RAWHID_RX_ENDPOINT 2
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Descriptor Data
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// standard control endpoint request types
|
||||
#define GET_STATUS 0
|
||||
#define CLEAR_FEATURE 1
|
||||
#define SET_FEATURE 3
|
||||
#define SET_ADDRESS 5
|
||||
#define GET_DESCRIPTOR 6
|
||||
#define GET_CONFIGURATION 8
|
||||
#define SET_CONFIGURATION 9
|
||||
#define GET_INTERFACE 10
|
||||
#define SET_INTERFACE 11
|
||||
// HID (human interface device)
|
||||
#define HID_GET_REPORT 1
|
||||
#define HID_GET_IDLE 2
|
||||
#define HID_GET_PROTOCOL 3
|
||||
#define HID_SET_REPORT 9
|
||||
#define HID_SET_IDLE 10
|
||||
#define HID_SET_PROTOCOL 11
|
||||
|
||||
// other control definitions
|
||||
#define EP_TYPE_CONTROL 0x00
|
||||
#define EP_TYPE_BULK_IN 0x81
|
||||
#define EP_TYPE_BULK_OUT 0x80
|
||||
#define EP_TYPE_INTERRUPT_IN 0xC1
|
||||
#define EP_TYPE_INTERRUPT_OUT 0xC0
|
||||
#define EP_TYPE_ISOCHRONOUS_IN 0x41
|
||||
#define EP_TYPE_ISOCHRONOUS_OUT 0x40
|
||||
|
||||
#define EP_SINGLE_BUFFER 0x02
|
||||
#define EP_DOUBLE_BUFFER 0x06
|
||||
|
||||
#define EP_SIZE(s) ((s) > 32 ? 0x30 : \
|
||||
((s) > 16 ? 0x20 : \
|
||||
((s) > 8 ? 0x10 : \
|
||||
0x00)))
|
||||
|
||||
#define MAX_ENDPOINT 4
|
||||
|
||||
#define LSB(n) (n & 255)
|
||||
#define MSB(n) ((n >> 8) & 255)
|
||||
|
||||
|
||||
// Descriptors are the data that your computer reads when it auto-detects
|
||||
// this USB device (called "enumeration" in USB lingo). The most commonly
|
||||
// changed items are editable at the top of this file. Changing things
|
||||
// in here should only be done by those who've read chapter 9 of the USB
|
||||
// spec and relevant portions of any USB class specifications!
|
||||
|
||||
|
||||
const BYTE const device_descriptor[] = {
|
||||
18, // bLength
|
||||
1, // bDescriptorType
|
||||
0x00, 0x02, // bcdUSB
|
||||
0, // bDeviceClass
|
||||
0, // bDeviceSubClass
|
||||
0, // bDeviceProtocol
|
||||
ENDPOINT0_SIZE, // bMaxPacketSize0
|
||||
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
|
||||
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
|
||||
0x00, 0x01, // bcdDevice
|
||||
1, // iManufacturer
|
||||
2, // iProduct
|
||||
0, // iSerialNumber
|
||||
1 // bNumConfigurations
|
||||
};
|
||||
|
||||
const BYTE const rawhid_hid_report_desc[] = {
|
||||
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE),
|
||||
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
|
||||
0xA1, 0x01, // Collection 0x01
|
||||
0x75, 0x08, // report size = 8 bits
|
||||
0x15, 0x00, // logical minimum = 0
|
||||
0x26, 0xFF, 0x00, // logical maximum = 255
|
||||
0x95, RAWHID_TX_SIZE, // report count
|
||||
0x09, 0x01, // usage
|
||||
0x81, 0x02, // Input (array)
|
||||
0x95, RAWHID_RX_SIZE, // report count
|
||||
0x09, 0x02, // usage
|
||||
0x91, 0x02, // Output (array)
|
||||
0xC0 // end collection
|
||||
};
|
||||
|
||||
|
||||
#define CONFIG1_DESC_SIZE (9+9+9+7+7)
|
||||
#define RAWHID_HID_DESC_OFFSET (9+9)
|
||||
const BYTE const config1_descriptor[CONFIG1_DESC_SIZE] = {
|
||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
|
||||
9, // bLength;
|
||||
2, // bDescriptorType;
|
||||
LSB(CONFIG1_DESC_SIZE), // wTotalLength
|
||||
MSB(CONFIG1_DESC_SIZE),
|
||||
1, // bNumInterfaces
|
||||
1, // bConfigurationValue
|
||||
0, // iConfiguration
|
||||
0xC0, // bmAttributes
|
||||
50, // bMaxPower
|
||||
|
||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||
9, // bLength
|
||||
4, // bDescriptorType
|
||||
RAWHID_INTERFACE, // bInterfaceNumber
|
||||
0, // bAlternateSetting
|
||||
2, // bNumEndpoints
|
||||
0x03, // bInterfaceClass (0x03 = HID)
|
||||
0x00, // bInterfaceSubClass (0x01 = Boot)
|
||||
0x00, // bInterfaceProtocol (0x01 = Keyboard)
|
||||
0, // iInterface
|
||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1
|
||||
9, // bLength
|
||||
0x21, // bDescriptorType
|
||||
0x11, 0x01, // bcdHID
|
||||
0, // bCountryCode
|
||||
1, // bNumDescriptors
|
||||
0x22, // bDescriptorType
|
||||
sizeof(rawhid_hid_report_desc), // wDescriptorLength
|
||||
0,
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
7, // bLength
|
||||
5, // bDescriptorType
|
||||
RAWHID_TX_ENDPOINT | 0x80, // bEndpointAddress
|
||||
0x03, // bmAttributes (0x03=intr)
|
||||
RAWHID_TX_SIZE, 0, // wMaxPacketSize
|
||||
RAWHID_TX_INTERVAL, // bInterval
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
7, // bLength
|
||||
5, // bDescriptorType
|
||||
RAWHID_RX_ENDPOINT, // bEndpointAddress
|
||||
0x03, // bmAttributes (0x03=intr)
|
||||
RAWHID_RX_SIZE, 0, // wMaxPacketSize
|
||||
RAWHID_RX_INTERVAL // bInterval
|
||||
};
|
||||
|
||||
// If you're desperate for a little extra code memory, these strings
|
||||
// can be completely removed if iManufacturer, iProduct, iSerialNumber
|
||||
// in the device desciptor are changed to zeros.
|
||||
|
||||
typedef const uint16_t wchar_t;
|
||||
|
||||
struct usb_string_descriptor_struct {
|
||||
BYTE bLength;
|
||||
BYTE bDescriptorType;
|
||||
wchar_t const wString[];
|
||||
};
|
||||
const struct usb_string_descriptor_struct const _usb_string0 = {
|
||||
4,
|
||||
3,
|
||||
{0x0409}
|
||||
};
|
||||
const struct usb_string_descriptor_struct const _usb_string1 = {
|
||||
sizeof(STR_MANUFACTURER),
|
||||
3,
|
||||
STR_MANUFACTURER
|
||||
};
|
||||
const struct usb_string_descriptor_struct const _usb_string2 = {
|
||||
sizeof(STR_PRODUCT),
|
||||
3,
|
||||
STR_PRODUCT
|
||||
};
|
||||
|
||||
// This table defines which descriptor data is sent for each specific
|
||||
// request from the host (in wValue and wIndex).
|
||||
const struct descriptor_list_struct {
|
||||
HALFWORD wValue;
|
||||
HALFWORD wIndex;
|
||||
const BYTE *addr;
|
||||
BYTE length;
|
||||
} const descriptor_list[] = {
|
||||
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
|
||||
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
|
||||
{0x2200, RAWHID_INTERFACE, rawhid_hid_report_desc, sizeof(rawhid_hid_report_desc)},
|
||||
{0x2100, RAWHID_INTERFACE, config1_descriptor+RAWHID_HID_DESC_OFFSET, 9},
|
||||
{0x0300, 0x0000, (const BYTEPTR )&_usb_string0, 4},
|
||||
{0x0301, 0x0409, (const BYTEPTR )&_usb_string1, sizeof(STR_MANUFACTURER)},
|
||||
{0x0302, 0x0409, (const BYTEPTR )&_usb_string2, sizeof(STR_PRODUCT)}
|
||||
};
|
||||
|
||||
#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
|
||||
|
||||
|
||||
|
||||
|
||||
//********************************************************************
|
||||
// END OF DEFINITIONS BORROWED FROM Teensy rawHID project.
|
||||
// EVERYTHING BELOW WAS WRITTEN FROM SCRATCH BY THE newRPL Team
|
||||
|
||||
// INITIALIZE USB SUBSYSTEM, POWER, PINS
|
||||
#define USB_STATUS_INIT 1
|
||||
#define USB_STATUS_EP0TX 2
|
||||
#define USB_STATUS_EP0RX 4
|
||||
#define USB_STATUS_EP1TX 8
|
||||
#define USB_STATUS_EP1RX 16
|
||||
#define USB_STATUS_EP2TX 32
|
||||
#define USB_STATUS_EP2RX 64
|
||||
#define USB_STATUS_CONNECTED 128
|
||||
#define USB_STATUS_CONFIGURED 256
|
||||
#define USB_STATUS_SUSPEND 512
|
||||
#define USB_STATUS_WAKEUPENABLED 1024
|
||||
#define USB_STATUS_TESTMODE 2048
|
||||
|
||||
|
||||
// GLOBAL VARIABLES OF THE USB SUBSYSTEM
|
||||
BINT __usb_drvstatus __SYSTEM_GLOBAL__; // FLAGS TO INDICATE IF INITIALIZED, CONNECTED, SENDING/RECEIVING, ETC.
|
||||
BYTE *__usb_bufptr[3]; __SYSTEM_GLOBAL__; // POINTERS TO BUFFERS FOR EACH ENDPOINT (0/1/2)
|
||||
BINT __usb_count[3]; __SYSTEM_GLOBAL__; // REMAINING BYTES TO TRANSFER ON EACH ENDPOINT (0/1/2)
|
||||
BYTE __usb_tmpbuffer[RAWHID_TX_SIZE] __SYSTEM_GLOBAL__; // TEMPORARY BUFFER FOR NON-BLOCKING CONTROL TRANSFERS
|
||||
|
||||
|
||||
void usb_hwsetup()
|
||||
{
|
||||
*CLKCON&=~0xc0; // POWER DOWN BOTH USB DEVICE AND HOST TO MAKE SURE HOST AND DEVICE AREN'T WORKING AT ONCE
|
||||
*CLKCON|=0x80; // POWER UP USB DEVICE
|
||||
|
||||
*UPLLCON=0x78023; // 48 MHZ CLOCK
|
||||
*CLKSLOW&=~0x80; // MAKE SURE UPLL IS ON
|
||||
|
||||
*MISCCR&=~(USBSUSPND0|USBSUSPND1|USBPAD); // SET DEVICE MODE, CHANGE TO NORMAL MODE
|
||||
|
||||
*PWR_REG=1; // ALLOW THE DEVICE TO ENTER SUSPEND MODE
|
||||
|
||||
// SET WHICH INTERRUPTS WE WANT
|
||||
*USB_INT_EN_REG=0x7; // ENABLE RESET, RESUME AND SUSPEND INTERRUPTS
|
||||
*EP_INT_EN_REG=0x7; // ENABLE ONLY EP0, EP1 AND EP2 INTERRUPTS
|
||||
*USB_INT_REG=0x7; // CLEAR ALL PENDING INTERRUPTS
|
||||
*EP_INT_REG=0x1f; // CLEAR ALL PENDING INTERRUPTS
|
||||
|
||||
*INDEX_REG=0; // SETUP ENDPOINT0
|
||||
*MAXP_REG=1; // USE 8-BYTE PACKETS
|
||||
|
||||
*INDEX_REG=1;
|
||||
*MAXP_REG=8; // USE 64-BYTE PACKETS ON EP1
|
||||
*INDEX_REG=2;
|
||||
*MAXP_REG=8; // USE 64-BYTE PACKETS ON EP2
|
||||
|
||||
}
|
||||
|
||||
void usb_hwsuspend()
|
||||
{
|
||||
|
||||
*MISCCR|=(USBSUSPND0|USBSUSPND1); // CHANGE TO SUSPEND MODE
|
||||
|
||||
*CLKSLOW|=~0x80; // TURN OFF UPLL
|
||||
|
||||
|
||||
}
|
||||
|
||||
void usb_hwresume()
|
||||
{
|
||||
*UPLLCON=0x78023; // 48 MHZ CLOCK
|
||||
*CLKSLOW&=~0x80; // MAKE SURE UPLL IS ON
|
||||
|
||||
*MISCCR&=~(USBSUSPND0|USBSUSPND1); // CHANGE TO NORMAL MODE
|
||||
|
||||
}
|
||||
|
||||
void usb_init()
|
||||
{
|
||||
|
||||
if(__usb_drvstatus&USB_STATUS_INIT) return;
|
||||
|
||||
__usb_drvstatus=USB_STATUS_INIT;
|
||||
|
||||
usb_hwsetup();
|
||||
|
||||
// SET INTERRUPT HANDLER
|
||||
__irq_mask(25);
|
||||
|
||||
__irq_addhook(25,&usb_irqservice);
|
||||
|
||||
__irq_unmask(25);
|
||||
|
||||
// TODO: SETUP COMMUNICATIONS BUFFERS
|
||||
|
||||
}
|
||||
|
||||
void usb_shutdown()
|
||||
{
|
||||
|
||||
if(!__usb_drvstatus&USB_STATUS_INIT) return;
|
||||
// MASK INTERRUPT AND REMOVE HANDLER
|
||||
__irq_mask(25);
|
||||
__irq_releasehook(25);
|
||||
|
||||
// CLEANUP INTERRUPT SYSTEM
|
||||
*USB_INT_EN_REG=0x0; // DISABLE INTERRUPTS
|
||||
*EP_INT_EN_REG=0x0; // DISABLE INTERRUPTS
|
||||
*USB_INT_REG=0x7; // CLEAR ALL PENDING INTERRUPTS
|
||||
*EP_INT_REG=0x1f; // CLEAR ALL PENDING INTERRUPTS
|
||||
|
||||
// STOP THE CLOCK
|
||||
*CLKSLOW|=0x80; // SHUT DOWN UPLL
|
||||
|
||||
*CLKCON&=~0xc0; // POWER DOWN BOTH USB DEVICE AND HOST
|
||||
|
||||
__usb_drvstatus=0; // MARK UNCONFIGURED
|
||||
|
||||
// TODO: RELEASE COMMUNICATIONS BUFFERS
|
||||
|
||||
}
|
||||
|
||||
|
||||
// TRANSMIT BYTES TO THE HOST IN EP0 ENDPOINT
|
||||
// STARTS A NEW TRANSMISSION IF newtransmission IS TRUE, EVEN IF
|
||||
// THERE ARE ZERO BYTES IN THE BUFFER
|
||||
// FOR USE WITHIN ISR
|
||||
|
||||
void usb_ep0_transmit(int newtransmission)
|
||||
{
|
||||
|
||||
if(!__usb_drvstatus&USB_STATUS_CONNECTED) return;
|
||||
|
||||
if(newtransmission || (__usb_drvstatus&USB_STATUS_EP0TX)) {
|
||||
|
||||
*INDEX_REG=0;
|
||||
|
||||
if(*EP0_CSR&EP0_IN_PKT_RDY) {
|
||||
// PREVIOUS PACKET IS STILL BEING SENT, DON'T PUSH IT
|
||||
__usb_drvstatus|=USB_STATUS_EP0TX; // AND KEEP TRANSMITTING
|
||||
return;
|
||||
}
|
||||
|
||||
int cnt=0;
|
||||
while(__usb_count[0] && (cnt<EP0_FIFO_SIZE)) {
|
||||
*EP0_FIFO=(WORD) *__usb_bufptr[0];
|
||||
++__usb_bufptr[0];
|
||||
++cnt;
|
||||
--__usb_count[0];
|
||||
}
|
||||
|
||||
if(__usb_count[0]==0) {
|
||||
*EP0_CSR|=EP0_IN_PKT_RDY|EP0_DATA_END; // SEND THE LAST PACKET
|
||||
__usb_drvstatus&=~USB_STATUS_EP0TX;
|
||||
}
|
||||
else {
|
||||
*EP0_CSR|=EP0_IN_PKT_RDY; // SEND PART OF THE BUFFER
|
||||
__usb_drvstatus|=USB_STATUS_EP0TX; // AND KEEP TRANSMITTING
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TRANSMIT BYTES TO THE HOST IN EP0 ENDPOINT
|
||||
// STARTS A NEW TRANSMISSION IF newtransmission IS TRUE, EVEN IF
|
||||
// THERE ARE ZERO BYTES IN THE BUFFER
|
||||
// FOR USE WITHIN ISR
|
||||
|
||||
void usb_ep0_receive(int newtransmission)
|
||||
{
|
||||
|
||||
if(!__usb_drvstatus&USB_STATUS_CONNECTED) return;
|
||||
|
||||
if(newtransmission || (__usb_drvstatus&USB_STATUS_EP0RX)) {
|
||||
|
||||
*INDEX_REG=0;
|
||||
|
||||
if(*EP0_CSR&EP0_IN_PKT_RDY) {
|
||||
// PREVIOUS PACKET IS STILL BEING SENT, DON'T PUSH IT
|
||||
__usb_drvstatus|=USB_STATUS_EP0TX; // AND KEEP TRANSMITTING
|
||||
return;
|
||||
}
|
||||
|
||||
int cnt=0;
|
||||
while(__usb_count[0] && (cnt<EP0_FIFO_SIZE)) {
|
||||
*__usb_bufptr[0]=(BYTE)*EP0_FIFO;
|
||||
++__usb_bufptr[0];
|
||||
--__usb_count[0];
|
||||
++cnt;
|
||||
}
|
||||
|
||||
if(__usb_count[0]==0) {
|
||||
*EP0_CSR|=EP0_OUT_PKT_RDY|EP0_DATA_END; // RECEIVED THE LAST PACKET
|
||||
__usb_drvstatus&=~USB_STATUS_EP0RX;
|
||||
}
|
||||
else {
|
||||
*EP0_CSR|=EP0_OUT_PKT_RDY; // RECIEVED PART OF THE BUFFER
|
||||
__usb_drvstatus|=USB_STATUS_EP0RX; // AND KEEP RECEIVING MORE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ep0_irqservice()
|
||||
{
|
||||
*INDEX_REG=0; // SELECT ENDPOINT 0
|
||||
|
||||
if( (*EP0_CSR) & EP0_OUT_PKT_RDY) {
|
||||
|
||||
// PROCESS FIRST ANY ONGOING TRANSMISSIONS
|
||||
if(__usb_drvstatus&USB_STATUS_EP0RX) {
|
||||
usb_ep0_receive(0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// WE HAVE A PACKET
|
||||
BINT reqtype;
|
||||
BINT request;
|
||||
BINT value;
|
||||
BINT index;
|
||||
BINT length;
|
||||
|
||||
// READ ALL 8 BYTES FROM THE FIFO
|
||||
|
||||
reqtype=*EP0_FIFO;
|
||||
request=*EP0_FIFO;
|
||||
value=*EP0_FIFO;
|
||||
value|=(*EP0_FIFO)<<8;
|
||||
index=*EP0_FIFO;
|
||||
index|=(*EP0_FIFO)<<8;
|
||||
length=*EP0_FIFO;
|
||||
length|=(*EP0_FIFO)<<8;
|
||||
|
||||
|
||||
if(reqtype&0x60==0) { // STANDARD REQUESTS
|
||||
// PROCESS THE REQUEST
|
||||
switch(request) {
|
||||
case GET_DESCRIPTOR:
|
||||
{
|
||||
// SEND THE REQUESTED RESPONSE
|
||||
int k;
|
||||
for(k=0;k<NUM_DESC_LIST;++k)
|
||||
{
|
||||
if((descriptor_list[k].wValue==value)&&(descriptor_list[k].wIndex==index))
|
||||
{
|
||||
// FOUND THE REQUESTED DESCRIPTOR
|
||||
__usb_bufptr[0]=descriptor_list[k].addr;
|
||||
if(length<descriptor_list[k].length) __usb_count[0]=length;
|
||||
else __usb_count[0]=descriptor_list[k].length;
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY;
|
||||
usb_ep0_transmit(1); // SEND 0-DATA STATUS STAGE
|
||||
return;
|
||||
}
|
||||
}
|
||||
// DON'T KNOW THE ANSWER TO THIS
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY|EP0_SEND_STALL;
|
||||
return;
|
||||
}
|
||||
case SET_ADDRESS:
|
||||
{
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY;
|
||||
__usb_count[0]=0;
|
||||
*FUNC_ADDR_REG=value|0x80;
|
||||
usb_ep0_transmit(1); // SEND 0-DATA STATUS STAGE
|
||||
return;
|
||||
}
|
||||
case SET_CONFIGURATION:
|
||||
{
|
||||
// OUR DEVICE HAS ONE SINGLE CONFIGURATION AND IS SETUP
|
||||
// ON WAKEUP, SO NOTHING TO DO HERE BUT ACKNOWLEDGE
|
||||
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY;
|
||||
__usb_count[0]=0;
|
||||
if(value) __usb_drvstatus|=USB_STATUS_CONFIGURED;
|
||||
else __usb_drvstatus&=~USB_STATUS_CONFIGURED;
|
||||
usb_ep0_transmit(1); // SEND 0-DATA STATUS STAGE
|
||||
return;
|
||||
}
|
||||
case GET_CONFIGURATION:
|
||||
{
|
||||
BINT configvalue=(__usb_drvstatus&USB_STATUS_CONFIGURED)? 1:0;
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY;
|
||||
__usb_count[0]=1;
|
||||
__usb_bufptr[0]=__usb_tmpbuffer;
|
||||
__usb_tmpbuffer[0]=configvalue;
|
||||
usb_ep0_transmit(1); // SEND DATA STATUS STAGE
|
||||
return;
|
||||
}
|
||||
case GET_STATUS:
|
||||
{
|
||||
__usb_tmpbuffer[0]=__usb_tmpbuffer[1]=0;
|
||||
switch(reqtype) {
|
||||
case 0x80: // DEVICE GET STATUS
|
||||
__usb_bufptr[0]=(__usb_drvstatus&USB_STATUS_WAKEUPENABLED)? 2:0;
|
||||
break;
|
||||
case 0x82: // ENDPONT GET STATUS
|
||||
*INDEX_REG=index&0x7;
|
||||
if((index&7)==0) {
|
||||
__usb_bufptr[0]=((*EP0_CSR)&EP0_SEND_STALL)? 1:0;
|
||||
}
|
||||
else {
|
||||
__usb_bufptr[0]|=((*OUT_CSR1_REG)&EPn_OUT_SEND_STALL)? 1:0;
|
||||
__usb_bufptr[0]|=((*IN_CSR1_REG)&EPn_IN_SEND_STALL)? 1:0;
|
||||
}
|
||||
break;
|
||||
default: // NOTHING TO DO FOR INTERFACE REQUESTS
|
||||
|
||||
}
|
||||
|
||||
// FOR NOW SEND THE DATA
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY;
|
||||
__usb_count[0]=2;
|
||||
__usb_bufptr[0]=__usb_tmpbuffer;
|
||||
|
||||
usb_ep0_transmit(1); // SEND DATA STATUS STAGE
|
||||
return;
|
||||
}
|
||||
case SET_FEATURE:
|
||||
{
|
||||
switch(reqtype)
|
||||
{
|
||||
case 0: // DEVICE FEATURES
|
||||
if(value==1) __usb_drvstatus|=USB_STATUS_WAKEUPENABLED;
|
||||
if(value==2) __usb_drvstatus|=USB_STATUS_TESTMODE;
|
||||
break;
|
||||
case 1: // INTERFACE FEATURES
|
||||
// NO INTERFACE FEATURES
|
||||
break;
|
||||
case 2: // ENDPOINT FEATURES
|
||||
if(value==0) {
|
||||
// ENDPOINT_HALT FEATURE REQUEST
|
||||
|
||||
int endp=index&7;
|
||||
*INDEX_REG=endp;
|
||||
if(endp!=0) { // DO NOT STALL THE CONTROL ENDPOINT
|
||||
*OUT_CSR1_REG|=EPn_OUT_SEND_STALL;
|
||||
*IN_CSR1_REG|=EPn_IN_SEND_STALL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY;
|
||||
__usb_count[0]=0;
|
||||
usb_ep0_transmit(1); // SEND 0-DATA STATUS STAGE
|
||||
return;
|
||||
}
|
||||
case CLEAR_FEATURE:
|
||||
{
|
||||
switch(reqtype)
|
||||
{
|
||||
case 0: // DEVICE FEATURES
|
||||
if(value==1) __usb_drvstatus&=~USB_STATUS_WAKEUPENABLED;
|
||||
if(value==2) __usb_drvstatus&=~USB_STATUS_TESTMODE;
|
||||
break;
|
||||
case 1: // INTERFACE FEATURES
|
||||
// NO INTERFACE FEATURES
|
||||
break;
|
||||
case 2: // ENDPOINT FEATURES
|
||||
if(value==0) {
|
||||
// ENDPOINT_HALT FEATURE REQUEST
|
||||
|
||||
int endp=index&3;
|
||||
*INDEX_REG=endp;
|
||||
if(endp!=0) { // DO NOT STALL THE CONTROL ENDPOINT
|
||||
*OUT_CSR1_REG&=~EPn_OUT_SEND_STALL;
|
||||
*IN_CSR1_REG&=~EPn_IN_SEND_STALL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY;
|
||||
__usb_count[0]=0;
|
||||
usb_ep0_transmit(1); // SEND 0-DATA STATUS STAGE
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// UNKNOWN STANDARD REQUEST??
|
||||
// DON'T KNOW THE ANSWER TO THIS
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY|EP0_SEND_STALL;
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if((reqtype&0x60)==0x20) { // CLASS REQUESTS
|
||||
|
||||
if(index==RAWHID_INTERFACE) {
|
||||
switch(request)
|
||||
{
|
||||
case HID_SET_REPORT:
|
||||
// GET DATA FROM HOST
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY;
|
||||
__usb_count[0]=RAWHID_TX_SIZE;
|
||||
__usb_bufptr[0]=__usb_tmpbuffer; // FOR NOW, LET'S SEE WHAT TO DO WITH THIS LATER
|
||||
usb_ep0_receive();
|
||||
return;
|
||||
case HID_GET_REPORT:
|
||||
// SEND DATA TO HOST
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY;
|
||||
__usb_count[0]=RAWHID_TX_SIZE;
|
||||
__usb_bufptr[0]=__usb_tmpbuffer; // FOR NOW SEND WHATEVER WAS STORED THERE
|
||||
usb_ep0_transmit(1);
|
||||
return;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// UNKNOWN CLASS REQUEST??
|
||||
// DON'T KNOW THE ANSWER TO THIS
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY|EP0_SEND_STALL;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// ADD OTHER REQUESTS HERE
|
||||
|
||||
// ENOUGH REQUESTS FOR NOW
|
||||
*EP0_CSR|=EP0_SERVICED_OUT_PKT_RDY|EP0_SEND_STALL;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if( !((*EP0_CSR) & EP0_IN_PKT_RDY)) {
|
||||
// SEND PACKAGES IF WE HAVE ANY ONGOING TRANSMISSION
|
||||
|
||||
if(__usb_drvstatus&USB_STATUS_EP0TX) {
|
||||
usb_ep0_transmit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// THERE'S NO TRANSMISSIONS, DON'T SENT ANYTHING
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ep1_irqservice()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ep2_irqservice()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// GENERAL INTERRUPT SERVICE ROUTINE - DISPATCH TO INDIVIDUAL ENDPOINT ROUTINES
|
||||
void usb_irqservice()
|
||||
{
|
||||
|
||||
if(!__usb_drvstatus&USB_STATUS_INIT) return;
|
||||
|
||||
if(*EP_INT_REG&1) {
|
||||
ep0_irqservice();
|
||||
*EP_INT_REG=1;
|
||||
return;
|
||||
}
|
||||
if(*EP_INT_REG&2) {
|
||||
ep1_irqservice();
|
||||
*EP_INT_REG=2;
|
||||
return;
|
||||
}
|
||||
if(*EP_INT_REG&4) {
|
||||
ep2_irqservice();
|
||||
*EP_INT_REG=4;
|
||||
return;
|
||||
}
|
||||
|
||||
if(*USB_INT_REG&1) {
|
||||
// ENTER SUSPEND MODE
|
||||
usb_hwsuspend();
|
||||
*USB_INT_REG=1;
|
||||
__usb_drvstatus|=USB_STATUS_SUSPEND;
|
||||
return;
|
||||
}
|
||||
|
||||
if(*USB_INT_REG&2) {
|
||||
// RESUME FROM SUSPEND MODE
|
||||
usb_hwresume();
|
||||
*USB_INT_REG=2;
|
||||
__usb_drvstatus&=~USB_STATUS_SUSPEND;
|
||||
return;
|
||||
}
|
||||
|
||||
if(*USB_INT_REG&4) {
|
||||
// RESET RECEIVED
|
||||
__usb_drvstatus=USB_STATUS_INIT|USB_STATUS_CONNECTED; // DECONFIGURE THE DEVICE
|
||||
usb_hwsetup(); // AND MAKE SURE THE HARDWARE IS IN KNOWN STATE
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,954 +0,0 @@
|
|||
/* Teensy RawHID example
|
||||
* http://www.pjrc.com/teensy/rawhid.html
|
||||
* Copyright (c) 2009 PJRC.COM, LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above description, website URL and copyright notice and this permission
|
||||
* notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Modified for newRPL and redistributed in agreement with the license above by
|
||||
* The newRPL Team, 2017
|
||||
*/
|
||||
|
||||
|
||||
// Version 1.0: Initial Release
|
||||
// Version 1.1: fixed bug in analog
|
||||
|
||||
#define USB_PRIVATE_INCLUDE
|
||||
#include "usb_rawhid.h"
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Configurable Options
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// You can change these to give your code its own name.
|
||||
#define STR_MANUFACTURER L"MfgName"
|
||||
#define STR_PRODUCT L"Teensy Raw HID Example"
|
||||
|
||||
// These 4 numbers identify your device. Set these to
|
||||
// something that is (hopefully) not used by any others!
|
||||
#define VENDOR_ID 0x16C0
|
||||
#define PRODUCT_ID 0x0480
|
||||
#define RAWHID_USAGE_PAGE 0xFFAB // recommended: 0xFF00 to 0xFFFF
|
||||
#define RAWHID_USAGE 0x0200 // recommended: 0x0100 to 0xFFFF
|
||||
|
||||
// These determine the bandwidth that will be allocated
|
||||
// for your communication. You do not need to use it
|
||||
// all, but allocating more than necessary means reserved
|
||||
// bandwidth is no longer available to other USB devices.
|
||||
#define RAWHID_TX_SIZE 64 // transmit packet size
|
||||
#define RAWHID_TX_INTERVAL 2 // max # of ms between transmit packets
|
||||
#define RAWHID_RX_SIZE 64 // receive packet size
|
||||
#define RAWHID_RX_INTERVAL 8 // max # of ms between receive packets
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Endpoint Buffer Configuration
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#define ENDPOINT0_SIZE 32
|
||||
#define RAWHID_INTERFACE 0
|
||||
#define RAWHID_TX_ENDPOINT 1
|
||||
#define RAWHID_RX_ENDPOINT 2
|
||||
|
||||
#if defined(__AVR_AT90USB162__)
|
||||
#define RAWHID_TX_BUFFER EP_SINGLE_BUFFER
|
||||
#define RAWHID_RX_BUFFER EP_SINGLE_BUFFER
|
||||
#else
|
||||
#define RAWHID_TX_BUFFER EP_DOUBLE_BUFFER
|
||||
#define RAWHID_RX_BUFFER EP_DOUBLE_BUFFER
|
||||
#endif
|
||||
|
||||
static const BYTE PROGMEM endpoint_config_table[] = {
|
||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(RAWHID_TX_SIZE) | RAWHID_TX_BUFFER,
|
||||
1, EP_TYPE_INTERRUPT_OUT, EP_SIZE(RAWHID_RX_SIZE) | RAWHID_RX_BUFFER,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Descriptor Data
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// Descriptors are the data that your computer reads when it auto-detects
|
||||
// this USB device (called "enumeration" in USB lingo). The most commonly
|
||||
// changed items are editable at the top of this file. Changing things
|
||||
// in here should only be done by those who've read chapter 9 of the USB
|
||||
// spec and relevant portions of any USB class specifications!
|
||||
|
||||
|
||||
static BYTE PROGMEM device_descriptor[] = {
|
||||
18, // bLength
|
||||
1, // bDescriptorType
|
||||
0x00, 0x02, // bcdUSB
|
||||
0, // bDeviceClass
|
||||
0, // bDeviceSubClass
|
||||
0, // bDeviceProtocol
|
||||
ENDPOINT0_SIZE, // bMaxPacketSize0
|
||||
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
|
||||
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
|
||||
0x00, 0x01, // bcdDevice
|
||||
1, // iManufacturer
|
||||
2, // iProduct
|
||||
0, // iSerialNumber
|
||||
1 // bNumConfigurations
|
||||
};
|
||||
|
||||
static BYTE PROGMEM rawhid_hid_report_desc[] = {
|
||||
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE),
|
||||
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
|
||||
0xA1, 0x01, // Collection 0x01
|
||||
0x75, 0x08, // report size = 8 bits
|
||||
0x15, 0x00, // logical minimum = 0
|
||||
0x26, 0xFF, 0x00, // logical maximum = 255
|
||||
0x95, RAWHID_TX_SIZE, // report count
|
||||
0x09, 0x01, // usage
|
||||
0x81, 0x02, // Input (array)
|
||||
0x95, RAWHID_RX_SIZE, // report count
|
||||
0x09, 0x02, // usage
|
||||
0x91, 0x02, // Output (array)
|
||||
0xC0 // end collection
|
||||
};
|
||||
|
||||
|
||||
#define CONFIG1_DESC_SIZE (9+9+9+7+7)
|
||||
#define RAWHID_HID_DESC_OFFSET (9+9)
|
||||
static BYTE PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
|
||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
|
||||
9, // bLength;
|
||||
2, // bDescriptorType;
|
||||
LSB(CONFIG1_DESC_SIZE), // wTotalLength
|
||||
MSB(CONFIG1_DESC_SIZE),
|
||||
1, // bNumInterfaces
|
||||
1, // bConfigurationValue
|
||||
0, // iConfiguration
|
||||
0xC0, // bmAttributes
|
||||
50, // bMaxPower
|
||||
|
||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||
9, // bLength
|
||||
4, // bDescriptorType
|
||||
RAWHID_INTERFACE, // bInterfaceNumber
|
||||
0, // bAlternateSetting
|
||||
2, // bNumEndpoints
|
||||
0x03, // bInterfaceClass (0x03 = HID)
|
||||
0x00, // bInterfaceSubClass (0x01 = Boot)
|
||||
0x00, // bInterfaceProtocol (0x01 = Keyboard)
|
||||
0, // iInterface
|
||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1
|
||||
9, // bLength
|
||||
0x21, // bDescriptorType
|
||||
0x11, 0x01, // bcdHID
|
||||
0, // bCountryCode
|
||||
1, // bNumDescriptors
|
||||
0x22, // bDescriptorType
|
||||
sizeof(rawhid_hid_report_desc), // wDescriptorLength
|
||||
0,
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
7, // bLength
|
||||
5, // bDescriptorType
|
||||
RAWHID_TX_ENDPOINT | 0x80, // bEndpointAddress
|
||||
0x03, // bmAttributes (0x03=intr)
|
||||
RAWHID_TX_SIZE, 0, // wMaxPacketSize
|
||||
RAWHID_TX_INTERVAL, // bInterval
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
7, // bLength
|
||||
5, // bDescriptorType
|
||||
RAWHID_RX_ENDPOINT, // bEndpointAddress
|
||||
0x03, // bmAttributes (0x03=intr)
|
||||
RAWHID_RX_SIZE, 0, // wMaxPacketSize
|
||||
RAWHID_RX_INTERVAL // bInterval
|
||||
};
|
||||
|
||||
// If you're desperate for a little extra code memory, these strings
|
||||
// can be completely removed if iManufacturer, iProduct, iSerialNumber
|
||||
// in the device desciptor are changed to zeros.
|
||||
struct usb_string_descriptor_struct {
|
||||
BYTE bLength;
|
||||
BYTE bDescriptorType;
|
||||
HALFWORD wString[];
|
||||
};
|
||||
static struct usb_string_descriptor_struct PROGMEM string0 = {
|
||||
4,
|
||||
3,
|
||||
{0x0409}
|
||||
};
|
||||
static struct usb_string_descriptor_struct PROGMEM string1 = {
|
||||
sizeof(STR_MANUFACTURER),
|
||||
3,
|
||||
STR_MANUFACTURER
|
||||
};
|
||||
static struct usb_string_descriptor_struct PROGMEM string2 = {
|
||||
sizeof(STR_PRODUCT),
|
||||
3,
|
||||
STR_PRODUCT
|
||||
};
|
||||
|
||||
// This table defines which descriptor data is sent for each specific
|
||||
// request from the host (in wValue and wIndex).
|
||||
static struct descriptor_list_struct {
|
||||
HALFWORD wValue;
|
||||
HALFWORD wIndex;
|
||||
const BYTE *addr;
|
||||
BYTE length;
|
||||
} PROGMEM descriptor_list[] = {
|
||||
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
|
||||
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
|
||||
{0x2200, RAWHID_INTERFACE, rawhid_hid_report_desc, sizeof(rawhid_hid_report_desc)},
|
||||
{0x2100, RAWHID_INTERFACE, config1_descriptor+RAWHID_HID_DESC_OFFSET, 9},
|
||||
{0x0300, 0x0000, (const BYTEPTR )&string0, 4},
|
||||
{0x0301, 0x0409, (const BYTEPTR )&string1, sizeof(STR_MANUFACTURER)},
|
||||
{0x0302, 0x0409, (const BYTEPTR )&string2, sizeof(STR_PRODUCT)}
|
||||
};
|
||||
#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Variables - these are the only non-stack RAM usage
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// zero when we are not configured, non-zero when enumerated
|
||||
static volatile BYTE usb_configuration=0;
|
||||
|
||||
// these are a more reliable timeout than polling the
|
||||
// frame counter (UDFNUML)
|
||||
static volatile BYTE rx_timeout_count=0;
|
||||
static volatile BYTE tx_timeout_count=0;
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Public Functions - these are the API intended for the user
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#define CLKCON HWREGS(CLK_REGS,0xc)
|
||||
#define PWRREG HWREGS(USBD_REGS,0x144)
|
||||
|
||||
// initialize USB
|
||||
void usb_init(void)
|
||||
{
|
||||
|
||||
*CLKCON&=~0xc0; // REMOVE POWER TO BOTH USB DEVICE AND HOST JUST IN CASE
|
||||
*CLKCON|=0x80; // ENABLE CLOCK TO USB DEVICE BLOCK
|
||||
|
||||
|
||||
HW_CONFIG();
|
||||
USB_FREEZE(); // enable USB
|
||||
PLL_CONFIG(); // config PLL
|
||||
while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
|
||||
USB_CONFIG(); // start USB clock
|
||||
UDCON = 0; // enable attach resistor
|
||||
usb_configuration = 0;
|
||||
UDIEN = (1<<EORSTE)|(1<<SOFE);
|
||||
sei();
|
||||
}
|
||||
|
||||
// return 0 if the USB is not configured, or the configuration
|
||||
// number selected by the HOST
|
||||
BYTE usb_configured(void)
|
||||
{
|
||||
return usb_configuration;
|
||||
}
|
||||
|
||||
|
||||
// receive a packet, with timeout
|
||||
int8_t usb_rawhid_recv(BYTEPTR buffer, BYTE timeout)
|
||||
{
|
||||
BYTE intr_state;
|
||||
|
||||
// if we're not online (enumerated and configured), error
|
||||
if (!usb_configuration) return -1;
|
||||
intr_state = SREG;
|
||||
cli();
|
||||
rx_timeout_count = timeout;
|
||||
UENUM = RAWHID_RX_ENDPOINT;
|
||||
// wait for data to be available in the FIFO
|
||||
while (1) {
|
||||
if (UEINTX & (1<<RWAL)) break;
|
||||
SREG = intr_state;
|
||||
if (rx_timeout_count == 0) return 0;
|
||||
if (!usb_configuration) return -1;
|
||||
intr_state = SREG;
|
||||
cli();
|
||||
UENUM = RAWHID_RX_ENDPOINT;
|
||||
}
|
||||
// read bytes from the FIFO
|
||||
#if (RAWHID_RX_SIZE >= 64)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 63)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 62)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 61)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 60)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 59)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 58)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 57)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 56)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 55)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 54)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 53)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 52)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 51)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 50)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 49)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 48)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 47)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 46)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 45)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 44)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 43)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 42)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 41)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 40)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 39)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 38)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 37)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 36)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 35)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 34)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 33)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 32)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 31)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 30)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 29)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 28)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 27)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 26)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 25)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 24)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 23)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 22)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 21)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 20)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 19)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 18)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 17)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 16)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 15)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 14)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 13)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 12)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 11)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 10)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 9)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 8)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 7)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 6)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 5)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 4)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 3)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 2)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
#if (RAWHID_RX_SIZE >= 1)
|
||||
*buffer++ = UEDATX;
|
||||
#endif
|
||||
// release the buffer
|
||||
UEINTX = 0x6B;
|
||||
SREG = intr_state;
|
||||
return RAWHID_RX_SIZE;
|
||||
}
|
||||
|
||||
// send a packet, with timeout
|
||||
int8_t usb_rawhid_send(const BYTEPTR buffer, BYTE timeout)
|
||||
{
|
||||
BYTE intr_state;
|
||||
|
||||
// if we're not online (enumerated and configured), error
|
||||
if (!usb_configuration) return -1;
|
||||
intr_state = SREG;
|
||||
cli();
|
||||
tx_timeout_count = timeout;
|
||||
UENUM = RAWHID_TX_ENDPOINT;
|
||||
// wait for the FIFO to be ready to accept data
|
||||
while (1) {
|
||||
if (UEINTX & (1<<RWAL)) break;
|
||||
SREG = intr_state;
|
||||
if (tx_timeout_count == 0) return 0;
|
||||
if (!usb_configuration) return -1;
|
||||
intr_state = SREG;
|
||||
cli();
|
||||
UENUM = RAWHID_TX_ENDPOINT;
|
||||
}
|
||||
// write bytes from the FIFO
|
||||
#if (RAWHID_TX_SIZE >= 64)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 63)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 62)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 61)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 60)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 59)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 58)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 57)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 56)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 55)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 54)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 53)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 52)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 51)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 50)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 49)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 48)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 47)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 46)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 45)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 44)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 43)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 42)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 41)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 40)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 39)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 38)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 37)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 36)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 35)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 34)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 33)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 32)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 31)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 30)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 29)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 28)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 27)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 26)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 25)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 24)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 23)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 22)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 21)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 20)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 19)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 18)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 17)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 16)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 15)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 14)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 13)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 12)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 11)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 10)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 9)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 8)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 7)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 6)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 5)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 4)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 3)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 2)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
#if (RAWHID_TX_SIZE >= 1)
|
||||
UEDATX = *buffer++;
|
||||
#endif
|
||||
// transmit it now
|
||||
UEINTX = 0x3A;
|
||||
SREG = intr_state;
|
||||
return RAWHID_TX_SIZE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Private Functions - not intended for general user consumption....
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#if (GCC_VERSION >= 40300) && (GCC_VERSION < 40302)
|
||||
#error "Buggy GCC 4.3.0 compiler, please upgrade!"
|
||||
#endif
|
||||
|
||||
|
||||
// USB Device Interrupt - handle all device-level events
|
||||
// the transmit buffer flushing is triggered by the start of frame
|
||||
//
|
||||
ISR(USB_GEN_vect)
|
||||
{
|
||||
BYTE intbits, t;
|
||||
|
||||
intbits = UDINT;
|
||||
UDINT = 0;
|
||||
if (intbits & (1<<EORSTI)) {
|
||||
UENUM = 0;
|
||||
UECONX = 1;
|
||||
UECFG0X = EP_TYPE_CONTROL;
|
||||
UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
|
||||
UEIENX = (1<<RXSTPE);
|
||||
usb_configuration = 0;
|
||||
}
|
||||
if ((intbits & (1<<SOFI)) && usb_configuration) {
|
||||
t = rx_timeout_count;
|
||||
if (t) rx_timeout_count = --t;
|
||||
t = tx_timeout_count;
|
||||
if (t) tx_timeout_count = --t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Misc functions to wait for ready and send/receive packets
|
||||
static inline void usb_wait_in_ready(void)
|
||||
{
|
||||
while (!(UEINTX & (1<<TXINI))) ;
|
||||
}
|
||||
static inline void usb_send_in(void)
|
||||
{
|
||||
UEINTX = ~(1<<TXINI);
|
||||
}
|
||||
static inline void usb_wait_receive_out(void)
|
||||
{
|
||||
while (!(UEINTX & (1<<RXOUTI))) ;
|
||||
}
|
||||
static inline void usb_ack_out(void)
|
||||
{
|
||||
UEINTX = ~(1<<RXOUTI);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// USB Endpoint Interrupt - endpoint 0 is handled here. The
|
||||
// other endpoints are manipulated by the user-callable
|
||||
// functions, and the start-of-frame interrupt.
|
||||
//
|
||||
ISR(USB_COM_vect)
|
||||
{
|
||||
BYTE intbits;
|
||||
const BYTEPTR list;
|
||||
const BYTEPTR cfg;
|
||||
BYTE i, n, len, en;
|
||||
BYTE bmRequestType;
|
||||
BYTE bRequest;
|
||||
HALFWORD wValue;
|
||||
HALFWORD wIndex;
|
||||
HALFWORD wLength;
|
||||
HALFWORD desc_val;
|
||||
const BYTEPTR desc_addr;
|
||||
BYTE desc_length;
|
||||
|
||||
UENUM = 0;
|
||||
intbits = UEINTX;
|
||||
if (intbits & (1<<RXSTPI)) {
|
||||
bmRequestType = UEDATX;
|
||||
bRequest = UEDATX;
|
||||
wValue = UEDATX;
|
||||
wValue |= (UEDATX << 8);
|
||||
wIndex = UEDATX;
|
||||
wIndex |= (UEDATX << 8);
|
||||
wLength = UEDATX;
|
||||
wLength |= (UEDATX << 8);
|
||||
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
|
||||
if (bRequest == GET_DESCRIPTOR) {
|
||||
list = (const BYTEPTR )descriptor_list;
|
||||
for (i=0; ; i++) {
|
||||
if (i >= NUM_DESC_LIST) {
|
||||
UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
|
||||
return;
|
||||
}
|
||||
desc_val = pgm_read_word(list);
|
||||
if (desc_val != wValue) {
|
||||
list += sizeof(struct descriptor_list_struct);
|
||||
continue;
|
||||
}
|
||||
list += 2;
|
||||
desc_val = pgm_read_word(list);
|
||||
if (desc_val != wIndex) {
|
||||
list += sizeof(struct descriptor_list_struct)-2;
|
||||
continue;
|
||||
}
|
||||
list += 2;
|
||||
desc_addr = (const BYTEPTR )pgm_read_word(list);
|
||||
list += 2;
|
||||
desc_length = pgm_read_byte(list);
|
||||
break;
|
||||
}
|
||||
len = (wLength < 256) ? wLength : 255;
|
||||
if (len > desc_length) len = desc_length;
|
||||
do {
|
||||
// wait for host ready for IN packet
|
||||
do {
|
||||
i = UEINTX;
|
||||
} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
|
||||
if (i & (1<<RXOUTI)) return; // abort
|
||||
// send IN packet
|
||||
n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
|
||||
for (i = n; i; i--) {
|
||||
UEDATX = pgm_read_byte(desc_addr++);
|
||||
}
|
||||
len -= n;
|
||||
usb_send_in();
|
||||
} while (len || n == ENDPOINT0_SIZE);
|
||||
return;
|
||||
}
|
||||
if (bRequest == SET_ADDRESS) {
|
||||
usb_send_in();
|
||||
usb_wait_in_ready();
|
||||
UDADDR = wValue | (1<<ADDEN);
|
||||
return;
|
||||
}
|
||||
if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
|
||||
usb_configuration = wValue;
|
||||
usb_send_in();
|
||||
cfg = endpoint_config_table;
|
||||
for (i=1; i<5; i++) {
|
||||
UENUM = i;
|
||||
en = pgm_read_byte(cfg++);
|
||||
UECONX = en;
|
||||
if (en) {
|
||||
UECFG0X = pgm_read_byte(cfg++);
|
||||
UECFG1X = pgm_read_byte(cfg++);
|
||||
}
|
||||
}
|
||||
UERST = 0x1E;
|
||||
UERST = 0;
|
||||
return;
|
||||
}
|
||||
if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
|
||||
usb_wait_in_ready();
|
||||
UEDATX = usb_configuration;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
|
||||
if (bRequest == GET_STATUS) {
|
||||
usb_wait_in_ready();
|
||||
i = 0;
|
||||
if (bmRequestType == 0x82) {
|
||||
UENUM = wIndex;
|
||||
if (UECONX & (1<<STALLRQ)) i = 1;
|
||||
UENUM = 0;
|
||||
}
|
||||
UEDATX = i;
|
||||
UEDATX = 0;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
|
||||
&& bmRequestType == 0x02 && wValue == 0) {
|
||||
i = wIndex & 0x7F;
|
||||
if (i >= 1 && i <= MAX_ENDPOINT) {
|
||||
usb_send_in();
|
||||
UENUM = i;
|
||||
if (bRequest == SET_FEATURE) {
|
||||
UECONX = (1<<STALLRQ)|(1<<EPEN);
|
||||
} else {
|
||||
UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
|
||||
UERST = (1 << i);
|
||||
UERST = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (wIndex == RAWHID_INTERFACE) {
|
||||
if (bmRequestType == 0xA1 && bRequest == HID_GET_REPORT) {
|
||||
len = RAWHID_TX_SIZE;
|
||||
do {
|
||||
// wait for host ready for IN packet
|
||||
do {
|
||||
i = UEINTX;
|
||||
} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
|
||||
if (i & (1<<RXOUTI)) return; // abort
|
||||
// send IN packet
|
||||
n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
|
||||
for (i = n; i; i--) {
|
||||
// just send zeros
|
||||
UEDATX = 0;
|
||||
}
|
||||
len -= n;
|
||||
usb_send_in();
|
||||
} while (len || n == ENDPOINT0_SIZE);
|
||||
return;
|
||||
}
|
||||
if (bmRequestType == 0x21 && bRequest == HID_SET_REPORT) {
|
||||
len = RAWHID_RX_SIZE;
|
||||
do {
|
||||
n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
|
||||
usb_wait_receive_out();
|
||||
// ignore incoming bytes
|
||||
usb_ack_out();
|
||||
len -= n;
|
||||
} while (len);
|
||||
usb_wait_in_ready();
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
|
||||
}
|
||||
|
||||
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
void usb_init(void); // initialize everything
|
||||
BYTE usb_configured(void); // is the USB port configured
|
||||
int8_t usb_rawhid_recv(BYTEPTR buffer, BYTE timeout); // receive a packet, with timeout
|
||||
int8_t usb_rawhid_send(const BYTEPTR buffer, BYTE timeout); // send a packet, with timeout
|
||||
BINT usb_rawhid_recv(BYTEPTR buffer, BYTE timeout); // receive a packet, with timeout
|
||||
BINT usb_rawhid_send(const BYTEPTR buffer, BYTE timeout); // send a packet, with timeout
|
||||
|
||||
// This file does not include the HID debug functions, so these empty
|
||||
// macros replace them with nothing, so users can compile code that
|
||||
|
@ -30,55 +30,6 @@ int8_t usb_rawhid_send(const BYTEPTR buffer, BYTE timeout); // send a packet, wi
|
|||
#define usb_debug_flush_output()
|
||||
|
||||
|
||||
// Everything below this point is only intended for usb_serial.c
|
||||
#ifdef USB_PRIVATE_INCLUDE
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#define EP_TYPE_CONTROL 0x00
|
||||
#define EP_TYPE_BULK_IN 0x81
|
||||
#define EP_TYPE_BULK_OUT 0x80
|
||||
#define EP_TYPE_INTERRUPT_IN 0xC1
|
||||
#define EP_TYPE_INTERRUPT_OUT 0xC0
|
||||
#define EP_TYPE_ISOCHRONOUS_IN 0x41
|
||||
#define EP_TYPE_ISOCHRONOUS_OUT 0x40
|
||||
|
||||
#define EP_SINGLE_BUFFER 0x02
|
||||
#define EP_DOUBLE_BUFFER 0x06
|
||||
|
||||
#define EP_SIZE(s) ((s) > 32 ? 0x30 : \
|
||||
((s) > 16 ? 0x20 : \
|
||||
((s) > 8 ? 0x10 : \
|
||||
0x00)))
|
||||
|
||||
#define MAX_ENDPOINT 4
|
||||
|
||||
#define LSB(n) (n & 255)
|
||||
#define MSB(n) ((n >> 8) & 255)
|
||||
|
||||
#if defined(__AVR_AT90USB162__)
|
||||
#define HW_CONFIG()
|
||||
#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
|
||||
#define USB_CONFIG() (USBCON = (1<<USBE))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
#define HW_CONFIG() (UHWCON = 0x01)
|
||||
#define PLL_CONFIG() (PLLCSR = 0x12)
|
||||
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#elif defined(__AVR_AT90USB646__)
|
||||
#define HW_CONFIG() (UHWCON = 0x81)
|
||||
#define PLL_CONFIG() (PLLCSR = 0x1A)
|
||||
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#elif defined(__AVR_AT90USB1286__)
|
||||
#define HW_CONFIG() (UHWCON = 0x81)
|
||||
#define PLL_CONFIG() (PLLCSR = 0x16)
|
||||
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#endif
|
||||
|
||||
// standard control endpoint request types
|
||||
#define GET_STATUS 0
|
||||
#define CLEAR_FEATURE 1
|
||||
|
@ -97,4 +48,3 @@ int8_t usb_rawhid_send(const BYTEPTR buffer, BYTE timeout); // send a packet, wi
|
|||
#define HID_SET_IDLE 10
|
||||
#define HID_SET_PROTOCOL 11
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -217,7 +217,7 @@ SOURCES +=\
|
|||
newrpl/mul_real_arm.c \
|
||||
newrpl/rng.c \
|
||||
newrpl/solvers.c \
|
||||
firmware/sys/usb/usb_rawhid.c
|
||||
firmware/sys/target_50g/usbdriver.c
|
||||
|
||||
|
||||
HEADERS += \
|
||||
|
|
Loading…
Reference in a new issue