i wanna USB HID mikroC Open source code

Thread Starter

buffon2009

Joined Dec 7, 2011
28
hi guys

hi everyone,


i wanna a USB HID Open source library for mikroC for PIC in order to use it in my project as i use PIC18f4550 with built-in usb module

i don't want to use the default library with mikroC because i wanna more customization one.

Thanks in Advance,
 

Thread Starter

buffon2009

Joined Dec 7, 2011
28
i use this code
this is the main.c file

Rich (BB code):
#include "usb.h"
#include "callbacks.h"
#include "usb.c"
// Lcd pinout settings
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D4 at RB0_bit;

// Pin direction
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D7_Direction at TRISB3_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB0_bit;

// HID feature buffer
volatile unsigned char HIDFeatureBuffer[HID_FEATURE_REPORT_BYTES];

void interrupt_low(void)
{
}

// Allocate buffers in RAM for storage of bytes that have either just
// come in from the SIE or are waiting to go out to the SIE.
char txBuffer[HID_INPUT_REPORT_BYTES];
char rxBuffer[HID_OUTPUT_REPORT_BYTES];
unsigned int timestamp=0;
extern byte transferType;

// Entry point for user initialization
void UserInit(void)
{
        TRISA=0b11111001;
        PORTA=0;
        TRISB=0;
        PORTB=0;
        T0CON=0x80;                        // Timer0 period = T*2^16:2 = 5.46ms:2 = 10.93ms (PS=2)
        //display("USER INIT");
}

#define LOBYTE(x) (*((char *)&x))
#define HIBYTE(x) (*(((char *)&x)+1))

// If we got some bytes from the host, then echo them back.
byte rxCnt;
static void USBEcho(void)
{
    byte i;

    // Find out if an Output report has been received from the host.
    rxCnt = HIDRxReport(rxBuffer, HID_OUTPUT_REPORT_BYTES);

        // If no bytes in, then nothing to do
        if (rxCnt == 0)
                return;

        // put first byte in PORTB
        LATB=rxBuffer[0];
        // x01 to signal interrupt transfer
        LATB.LATB1=0;
        LATB.LATB0=1;

        //read PORTA levels and store in first byte of report
        txBuffer[0]=PORTA;
        txBuffer[1]=0xF0;        //this is to differentiate between different transfer types
        txBuffer[2]=HIBYTE(timestamp);
        txBuffer[3]=LOBYTE(timestamp);
    // Copy input bytes to the output buffer
        for (i=4;i<HID_OUTPUT_REPORT_BYTES;i++)
        txBuffer = rxBuffer;

    // As long as the SIE is owned by the processor, we let USB tasks continue.
        while (ep1Bi.Stat & UOWN)
        ProcessUSBTransactions();

    // The report will be sent in the next interrupt IN transfer.
    HIDTxReport(txBuffer, HID_INPUT_REPORT_BYTES);
}

// Central processing loop.  Whenever the firmware isn't busy servicing
// the USB, we will get control here to do other processing.
void ProcessIO(void)
{
    // User Application USB tasks
     if ((deviceState < CONFIGURED) || (UCON.SUSPND==1))
                return;

        // Process USB: Echo back any bytes that have come in.
    USBEcho();
}

// Initialization for a SET_FEATURE request.  This routine will be
// invoked during the setup stage and is used to set up the buffer
// for receiving data from the host
void SetupFeatureReport(byte reportID)
{
    if (reportID == 0)
    {
        // When the report arrives in the data stage, the data will be
        // stored in HIDFeatureBuffer.
        inPtr = (byte*)&HIDFeatureBuffer;
    }
}

// Post processing for a SET_FEATURE request.  After all the data has
// been delivered from host to device, this will be invoked to perform
// application specific processing.
void SetFeatureReport(byte reportID)
{
    // Currently only handling report 0, ignore any others.
    if (reportID == 0)
    {
        // Set the state of PORTB based on the first byte
        // of the feature report.
        LATB = HIDFeatureBuffer[0];
                // x10 to signal feature transfer
                LATB.LATB1=1;
                LATB.LATB0=0;
    }
}

// Handle a feature report request on the control pipe
void GetFeatureReport(byte reportID)
{
        if (reportID == 0)
        {
                // Handle report #0
                outPtr = (byte *)&HIDFeatureBuffer;
                HIDFeatureBuffer[0]=PORTA;
                HIDFeatureBuffer[1]=0xF1;        //this is to differentiate between different transfer types
                HIDFeatureBuffer[2]=HIBYTE(timestamp);
                HIDFeatureBuffer[3]=LOBYTE(timestamp);
                wCount = HID_FEATURE_REPORT_BYTES;
                transferType=0;
        }

}

// Handle control out.  This might be an alternate way of processing
// an output report, so all that's needed is to point the output
// pointer to the output buffer
// Initialization for a SET_REPORT request.  This routine will be
// invoked during the setup stage and is used to set up the buffer
// for receiving data from the host
void SetupOutputReport(byte reportID)
{
        if (reportID == 0)
        {
                // When the report arrives in the data stage, the data will be
                // stored in HIDFeatureBuffer
                inPtr = (byte*)&HIDRxBuffer;
        }
}


// Post processing for a SET_REPORT request.  After all the data has
// been delivered from host to device, this will be invoked to perform
// application specific processing.
void SetOutputReport(byte reportID)
{

        // Currently only handling report 0, ignore any others.
        if (reportID != 0)
                return;

        LATB=HIDRxBuffer[0];
        // x11 to signal SET_REPORT transfer
        LATB.LATB1=1;
        LATB.LATB0=1;
}

// Handle a control input report
void GetInputReport(byte reportID)
{
        if (reportID == 0)
        {
                byte i;
                // Send back the contents of the HID report
                // TBD: provide useful information...
                outPtr = (byte *)&HIDTxBuffer;
                HIDTxBuffer[0]=PORTA;
                HIDTxBuffer[1]=0xF2;        //this is to differentiate between different transfer types
                HIDTxBuffer[2]=HIBYTE(timestamp);
                HIDTxBuffer[3]=LOBYTE(timestamp);
                for(i=4;i<HID_INPUT_REPORT_BYTES;i++) HIDTxBuffer=HIDRxBuffer;
                // The number of bytes in the report (from usb.h).
                wCount = HID_INPUT_REPORT_BYTES;
                transferType=0;
        }
}
void display(unsigned int txt){
     unsigned char ttxt[7];
     Lcd_Cmd(_LCD_CLEAR);
     delay_ms(200);
     intToStr(txt,ttxt);
     lcd_out(1,1,ttxt);
     delay_ms(200);
}
// Entry point of the firmware
void main(void) {
    //byte led_cnt=0;

    ADCON1 |= 0x0F;                             // Set all I/O pins to digital
     // Initialize USB
    lcd_init();
    UCFG = 0x14; // Enable pullup resistors; full speed mode

    
    
    //default configuration of the device..
    deviceState = DETACHED;
    remoteWakeup = 0x00;
    currentConfiguration = 0x00;
    //display("DETACHED");

    
    // Call user initialization function
        UserInit();
        

while(1)
    {
        // Ensure USB module is available
                EnableUSBModule();
                // As long as we aren't in test mode (UTEYE), process
                // USB transactions.
                if(UCFG.UTEYE != 1)
                       ProcessUSBTransactions();

        // Application specific tasks
        ProcessIO();
                 //  display(UIR.UERRIF);
        /*//Blink LED2 @ 1Hz when configured
                 if(INTCON.TMR0IF){
                        INTCON.TMR0IF=0;
                        timestamp++;
                        led_cnt++;
                        if (deviceState<CONFIGURED&&led_cnt>=10){
                                LED2 = !LED2;
                                led_cnt=0;
                        }
                        else if (deviceState == CONFIGURED&&led_cnt>=46){
                                LED2 = !LED2;
                                led_cnt=0;
                        }
                }*/
    }

}
 

Thread Starter

buffon2009

Joined Dec 7, 2011
28
this is the includes file
this is usb.h
Rich (BB code):
#ifndef USB_H
#define USB_H

#define DEBUG_PRINT 0


#define LSB(x) (x & 0xFF)
#define MSB(x) ((x & 0xFF00) >> 8)

#define PTR16(x) ((unsigned int)(((unsigned long)x) & 0xFFFF))
//
// Standard Request Codes USB 2.0 Spec Ref Table 9-4
//
#define GET_STATUS         0
#define CLEAR_FEATURE      1
#define SET_FEATURE        3
#define SET_ADDRESS        5
#define GET_DESCRIPTOR     6
#define SET_DESCRIPTOR     7
#define GET_CONFIGURATION  8
#define SET_CONFIGURATION  9
#define GET_INTERFACE     10
#define SET_INTERFACE     11
#define SYNCH_FRAME       12

// Descriptor Types
#define DEVICE_DESCRIPTOR        0x01
#define CONFIGURATION_DESCRIPTOR 0x02
#define STRING_DESCRIPTOR        0x03
#define INTERFACE_DESCRIPTOR     0x04
#define ENDPOINT_DESCRIPTOR      0x05

// Buffer Descriptor bit masks (from PIC datasheet)
#define UOWN   0x80 // USB Own Bit
#define DTS    0x40 // Data Toggle Synchronization Bit
#define KEN    0x20 // BD Keep Enable Bit
#define INCDIS 0x10 // Address Increment Disable Bit
#define DTSEN  0x08 // Data Toggle Synchronization Enable Bit
#define BSTALL 0x04 // Buffer Stall Enable Bit
#define BC9    0x02 // Byte count bit 9
#define BC8    0x01 // Byte count bit 8

// visible Device states (Chap 9.1.1)
#define DETACHED     0
#define ATTACHED     1
#define POWERED      2
#define DEFAULT      3
#define ADDRESS      4
#define CONFIGURED   5

// Definitions from "Device Class Definition for Human Interface Devices (HID)",
// version 1.11
//

// Class Descriptor Types
#define HID_DESCRIPTOR      0x21
#define REPORT_DESCRIPTOR   0x22
#define PHYSICAL_DESCRIPTOR 0x23

// HID Class specific requests
#define GET_REPORT      0x01
#define GET_IDLE        0x02
#define GET_PROTOCOL    0x03
#define SET_REPORT      0x09
#define SET_IDLE        0x0A
#define SET_PROTOCOL    0x0B

// Size of the feature, input, and output reports
#define HID_INPUT_REPORT_BYTES   64
#define HID_OUTPUT_REPORT_BYTES  64
#define HID_FEATURE_REPORT_BYTES 64

// Standard Feature Selectors
#define DEVICE_REMOTE_WAKEUP    0x01
#define ENDPOINT_HALT           0x00

typedef unsigned char byte;
typedef unsigned int  word;

// Global variables
extern byte deviceState;    // Visible device states (from USB 2.0, chap 9.1.1)
extern byte selfPowered;
extern byte remoteWakeup;
extern byte currentConfiguration;

typedef struct _BDT
{
    byte Stat;
    byte Cnt;
    unsigned int ADDR;
} BDT; //Buffer Descriptor Table

extern volatile BDT  ep0Bo; //Endpoint #0 BD Out
extern volatile BDT  ep0Bi; //Endpoint #0 BD In
extern volatile BDT  ep1Bo; //Endpoint #1 BD Out
extern volatile BDT  ep1Bi; //Endpoint #1 BD In

// Every device request starts with an 8 byte setup packet (USB 2.0, chap 9.3)
// with a standard layout.  The meaning of wValue and wIndex will
// vary depending on the request type and specific request.
typedef struct _setupPacketStruct
{
    byte bmRequestType; // D7: Direction, D6..5: Type, D4..0: Recipient
    byte bRequest;      // Specific request
    byte wValue0;       // LSB of wValue
    byte wValue1;       // MSB of wValue
    byte wIndex0;       // LSB of wIndex
    byte wIndex1;       // MSB of wIndex
    word wLength;       // Number of bytes to transfer if there's a data stage
    byte extra[1];      // Fill out to same size as Endpoint 0 max buffer (E0SZ-7)
} setupPacketStruct;

extern volatile setupPacketStruct SetupPacket;

// Size of the buffer for endpoint 0
#define E0SZ 8

extern volatile byte HIDRxBuffer[HID_OUTPUT_REPORT_BYTES]; // Data received OUT from the host
extern volatile byte HIDTxBuffer[HID_INPUT_REPORT_BYTES]; // Data sent IN to host

// inPtr/OutPtr are used to move data from user memory (RAM/ROM/EEPROM) buffers
// from/to USB dual port buffers.
extern byte *outPtr;        // Address of buffer to send to host
extern byte *inPtr;         // Address of buffer to receive data from host
extern unsigned int wCount; // Total # of bytes to move

// USB Functions
void EnableUSBModule(void);
void ProcessUSBTransactions(void);

// # of bytes from last HID transaction
extern byte hidRxLen;

// Functions for reading/writing the HID interrupt endpoint
byte HIDTxReport(byte *buffer, byte len);
byte HIDRxReport(byte *buffer, byte len);

#endif //USB_H
 

Thread Starter

buffon2009

Joined Dec 7, 2011
28
this is usb.c
Rich (BB code):
#include "usb.h"
#include "callbacks.h"

#define ALLOW_SUSPEND 0
// It appears that you need at least 6 loops that are replaced by memcpy()
// before it is an advantage.
#define USE_MEMCPY 0

// Device and configuration descriptors.  These are used as the
// host enumerates the device and discovers what class of device
// it is and what interfaces it supports.
#define DEVICE_DESCRIPTOR_SIZE 0x12
#define CONFIG_HEADER_SIZE  0x09
#define HID_DESCRIPTOR_SIZE 0x20
#define HID_HEADER_SIZE 0x09

typedef struct _configStruct
{
    byte configHeader[CONFIG_HEADER_SIZE];
    byte HIDDescriptor[HID_DESCRIPTOR_SIZE];
} ConfigStruct;

// Global variables
byte deviceState;
byte remoteWakeup;
byte deviceAddress;
byte selfPowered;
byte currentConfiguration;

// Control Transfer Stages - see USB spec chapter 5
#define SETUP_STAGE    0 // Start of a control transfer (followed by 0 or more data stages)
#define DATA_OUT_STAGE 1 // Data from host to device
#define DATA_IN_STAGE  2 // Data from device to host
#define STATUS_STAGE   3 // Unused - if data I/O went ok, then back to Setup

byte ctrlTransferStage; // Holds the current stage in a control transfer

byte HIDPostProcess;    // Set to 1 if HID needs to process after the data stage
byte requestHandled;    // Set to 1 if request was understood and processed.

byte *outPtr;           // Data to send to the host
const byte *ROMoutPtr;    // Data to send to the host   //rom
byte *inPtr;            // Data from the host
word wCount;            // Number of bytes of data
byte transferType;                // 0=ram 1=rom

// HID Class variables
byte hidIdleRate;
byte hidProtocol; // [0] Boot Protocol [1] Report Protocol
byte hidRxLen;    // # of bytes put into buffer

volatile BDT  ep0Bo; //Endpoint #0 BD Out
volatile BDT  ep0Bi; //Endpoint #0 BD In
volatile BDT  ep1Bo; //Endpoint #1 BD Out
volatile BDT  ep1Bi; //Endpoint #1 BD In

// TBD: add definitions for additional endpoints (2-16).

// Put endpoint 0 buffers into dual port RAM
volatile setupPacketStruct SetupPacket;
volatile byte controlTransferBuffer[E0SZ];

// HID specific buffers
volatile byte HIDRxBuffer[HID_OUTPUT_REPORT_BYTES];
volatile byte HIDTxBuffer[HID_INPUT_REPORT_BYTES];

const byte deviceDescriptor[] =
{
    0x12, 0x01, // bLength, bDescriptorType
    0x00, 0x02, // bcdUSB (low byte), bcdUSB (high byte)
    0x00, 0x00, // bDeviceClass, bDeviceSubClass
    0x00, E0SZ, // bDeviceProtocl, bMaxPacketSize
    0xD8, 0x04, // idVendor (low byte), idVendor (high byte)
    0xFF, 0x01, // idProduct (low byte), idProduct (high byte)
    0x01, 0x00, // bcdDevice (low byte), bcdDevice (high byte)
    0x01, 0x02, // iManufacturer, iProduct
    0x00, 0x01  // iSerialNumber (none), bNumConfigurations
};

// Total config size is 0x09 + 0x09 + 0x09 + 0x07 + 0x07 = 0x29
#define CFSZ 0x29
#define HISZ HID_INPUT_REPORT_BYTES
#define HOSZ HID_OUTPUT_REPORT_BYTES

const ConfigStruct configDescriptor =
{
    {
    // Configuration descriptor
    0x09, 0x02, // bLength, bDescriptorType (Configuration)
    CFSZ, 0x00, // wTotalLength (low), wTotalLength (high)
    0x01, 0x01, // bNumInterfaces, bConfigurationValue
    0x00, 0xA0, // iConfiguration, bmAttributes ()
    0x32,       // bMaxPower
    },
    {
    // HID Interface descriptor
    0x09, 0x04, // bLength, bDescriptorType (Interface)
    0x00, 0x00, // bInterfaceNumber, bAlternateSetting
    0x02, 0x03, // bNumEndpoints, bInterfaceClass (HID)
    0x00, 0x00, // bInterfaceSubclass, bInterfaceProtocol,
    0x00,       // iInterface
    // Hid descriptor
    0x09, 0x21, // bLength, bDescriptorType (HID)
    0x01, 0x01, // bcdHID (low), bcdHID (high)
    0x00, 0x01, // bCountryCode, bNumDescriptors
    0x22, 47  , // bDescriptorType, wDescriptorLength (low)
    0x00,       // wDescriptorLength (high)
    // HID Endpoint 1 In
    0x07, 0x05, // bLength, bDescriptorType (Endpoint)
    0x81, 0x03, // bEndpointAddress, bmAttributes (Interrupt)
    HISZ, 0x00, // wMaxPacketSize (low), wMaxPacketSize (high)
    0x01,       // bInterval (1 millisecond)
    // HID Endpoint 1 Out
    0x07, 0x05, // bLength, bDescriptorType (Endpoint)
    0x01, 0x03, // bEndpointAddress, bmAttributes (Interrupt)
    HOSZ, 0x00, // wMaxPacketSize (low), wMaxPacketSize (high)
    0x01,       // bInterval (1 millisecond)
    }
};

#define HIRB HID_INPUT_REPORT_BYTES
#define HORB HID_OUTPUT_REPORT_BYTES
#define HFRB HID_FEATURE_REPORT_BYTES

#define HID_REPORT_SIZE 47 // Size is from HID Descriptor tool
const byte HIDReport[HID_REPORT_SIZE] = {
    0x06, 0xa0, 0xff,  // USAGE_PAGE (Vendor Defined Page 1)
    0x09, 0x01,        // USAGE (Vendor Usage 1)
    0xa1, 0x01,        // COLLECTION (Application)

        // The Input report
        0x09, 0x01,             // Usage ID - vendor defined
        0x15, 0x00,             // Logical Minimum (0)
        0x26, 0xFF, 0x00,   // Logical Maximum (255)
        0x75, 0x08,             // Report Size (8 bits)
        0x95, 0x40,             // Report Count (64 fields)
        0x81, 0x02,             // Input (Data, Variable, Absolute)

        // The Output report
        0x09, 0x01,             // Usage ID - vendor defined
        0x15, 0x00,             // Logical Minimum (0)
        0x26, 0xFF, 0x00,   // Logical Maximum (255)
        0x75, 0x08,             // Report Size (8 bits)
        0x95, 0x40,             // Report Count (64 fields)
        0x91, 0x02,              // Output (Data, Variable, Absolute)

        // The Feature report
        0x09, 0x02,             // Usage ID - vendor defined
        0x15, 0x00,             // Logical Minimum (0)
        0x26, 0xFF, 0x00,   // Logical Maximum (255)
        0x75, 0x08,             // Report Size (8 bits)
        0x95, 0x40,             // Report Count (64 fields)
        0xB1, 0x02,              // Feature (Data, Variable, Absolute)

    0xc0               // END_COLLECTION
};

const byte stringDescriptor0[] =
{
    0x04, STRING_DESCRIPTOR,
    0x09, 0x04,
};
const byte stringDescriptor1[] =
{
    32, STRING_DESCRIPTOR, // bLength, bDscType
    'G',0,'e',0,'n',0,'e',0,'r',0,'i',0,'c',0,' ',0,'H',0,'I',0,'D',0,' ',0,'I',0,'/',0,'O',0,
};
const byte stringDescriptor2[] =
{
    48, STRING_DESCRIPTOR,
    'E',0,'x',0,'a',0,'m',0,'p',0,'l',0,'e',0,' ',0,'o',0,'f',0,' ',0,'H',0,'I',0,'D',0,' ',0,
    'f',0,'i',0,'r',0,'m',0,'w',0,'a',0,'r',0,'e',0,
};
 
Top