CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

USB Compound device

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hillcraft



Joined: 22 Sep 2003
Posts: 101
Location: Cape Town (South africa)

View user's profile Send private message Send e-mail Visit poster's website

USB Compound device
PostPosted: Wed Apr 05, 2006 4:09 am     Reply with quote

I have taken a working USB joystick application, and the working HID demo and spliced them together. I have checked the code many times, but I cannot see why the descriptors are not correct. The device shows up as composite and it enumerates partially, but then fails.

I am stumped. It would be great if you guys could give it a looksee!

Here is the main code

Code:
 
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
////                        hc_comp.c                                ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////

#include <18F4550.h>
////SLOW SPEED
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV3,VREGEN
#use delay(clock=24000000)
#define USB_USE_FULL_SPEED  FALSE

#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)


/////////////////////////////////////////////////////////////////////////////
//
// CCS Library dynamic defines.  For dynamic configuration of the CCS Library
// for your application several defines need to be made.  See the comments
// at usb.h for more information
//
/////////////////////////////////////////////////////////////////////////////

//Tells the CCS PIC USB firmware to include HID handling code.
#DEFINE USB_HID_DEVICE  TRUE

//the following defines needed for the CCS USB PIC driver to enable the TX endpoint 1
// and allocate buffer space on the peripheral
#define USB_EP1_TX_ENABLE  USB_ENABLE_INTERRUPT   //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP1_TX_SIZE    8  //allocate 8 bytes in the hardware for transmission

//the following defines needed for the CCS USB PIC driver to enable the RX endpoint 1
// and allocate buffer space on the peripheral
#define USB_EP1_RX_ENABLE  USB_ENABLE_INTERRUPT   //turn on EP1 for OUT bulk/interrupt transfers
#define USB_EP1_RX_SIZE    8  //allocate 8 bytes in the hardware for reception

//turn on EP1 for IN interrupt transfers.  (IN = PIC -> PC)
#define USB_EP2_TX_ENABLE  USB_ENABLE_INTERRUPT
#define USB_EP2_TX_SIZE 8     //max packet size of this endpoint


/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries.  See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#include <pic18_usb.h>   //Microchip 18Fxx5x hardware layer for usb.c
#include "hc_comp_desc.h"   //USB Configuration and Device descriptors for this UBS device
#include <usb.c>        //handles usb setup tokens and get descriptor reports


/////////////////////////////////////////////////////////////////////////////
//
// Configure the demonstration I/O
//
/////////////////////////////////////////////////////////////////////////////
#define LED1 PIN_D0
#define LED2 PIN_D1
#define LED3 PIN_D2
#DEFINE BUTTON PIN_B4
#define LED_ON output_low
#define LED_OFF output_high


/////////////////////////////////////////////////////////////////////////////
//
// usb_debug_task()
//
// When called periodically, displays debugging information over serial
// to display enumeration and connection states.  Also lights LED1 based upon
// enumeration and status.
//
/////////////////////////////////////////////////////////////////////////////
void usb_debug_task(void) {
   static int8 last_connected;
   static int8 last_enumerated;
   int8 new_connected;
   int8 new_enumerated;

   new_connected=usb_attached();
   new_enumerated=usb_enumerated();

   if (new_enumerated)
      LED_ON(LED1);
   else
      LED_OFF(LED1);

   if (new_connected && !last_connected)
      printf("\r\n\nUSB connected, waiting for enumaration...");
   if (!new_connected && last_connected)
      printf("\r\n\nUSB disconnected, waiting for connection...");
   if (new_enumerated && !last_enumerated)
      printf("\r\n\nUSB enumerated by PC/HOST");
   if (!new_enumerated && last_enumerated)
      printf("\r\n\nUSB unenumerated by PC/HOST, waiting for enumeration...");

   last_connected=new_connected;
   last_enumerated=new_enumerated;
}

void main() {
   int8 out_data[20];
   int8 in_data[2];
   int8 usb_data_out_2[5];
   int8 send_timer=0;

   LED_OFF(LED1);
   LED_OFF(LED2);
   LED_OFF(LED3);

   printf("\r\n\nCCS Vendor Specific HID Example");

  #ifdef __PCH__
   printf("\r\nPCH: v");
   printf(__PCH__);
  #else
   printf("\r\n\PCM: v");
   printf(__PCM__);
  #endif

   usb_init_cs();

   printf("\r\n");

  #if defined(AN0)
   setup_adc_ports(AN0);
  #elif defined(AN0_AN1_AN3)
   setup_adc_ports(AN0_AN1_AN3);
  #else
   #error CONFIGURE ADC PORTS SO WE CAN READ CHANNEL 0
  #endif

   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);

   while (TRUE) {
      usb_task();
      usb_debug_task();
      if (usb_enumerated()) {
         if (!send_timer) {
            send_timer=250;
            out_data[0]=read_adc();
            out_data[1]=!input(BUTTON);
            if (usb_put_packet(1, out_data, 2, USB_DTS_TOGGLE))
               printf("\r\n<-- Sending 2 bytes: 0x%X 0x%X", out_data[0], out_data[1]);
               
            if (usb_put_packet(2, usb_data_out_2, 5, USB_DTS_TOGGLE))
               printf("\r\n<-- Sending joystick 5 bytes: 0x%X 0x%X", out_data[0], out_data[1]);               
         }
         if (usb_kbhit(1)) {
            usb_get_packet(1, in_data, 2);
            printf("\r\n--> Received data: 0x%X 0x%X",in_data[0],in_data[1]);
            if (in_data[0]) {LED_ON(LED2);} else {LED_OFF(LED2);}
            if (in_data[1]) {LED_ON(LED3);} else {LED_OFF(LED3);}
         }
         send_timer--;
         delay_ms(1);
      }
   }
}


Here are the descriptor tables
Code:

///////////////////////////////////////////////////////////////////////////
////                                                                   ////
///                             hc_comp.h                              ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////

#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>

   //////////////////////////////////////////////////////////////////
   ///
   ///  HID Report.  Tells HID driver how to handle and deal with
   ///  received data.  HID Reports can be extremely complex,
   ///  see HID specifcation for help on writing your own.
   ///
   ///  CCS example uses a vendor specified usage, that sends and
   ///  receives 2 absolute bytes ranging from 0 to 0xFF.
   ///
   //////////////////////////////////////////////////////////////////

   const char USB_CLASS_SPECIFIC_DESC[] = {
    6, 0, 255,  /* Usage Page = Vendor Defined               2 */
    9, 1,       /* Usage = IO device                         4 */
    0xa1, 1,    /* Collection = Application                  6 */
    0x19, 1,    /* Usage minimum                             8 */
    0x29, 8,    /* Usage maximum                            10 */
    0x15, 0x80, /* Logical minimum (-128)                   12 */
    0x25, 0x7F, /* Logical maximum (127)                    14 */
    0x75, 8,    /* Report size = 8 (bits)                   16 */
    0x95, 2,    /* Report count = 16 bits (2 bytes)         18 */
    0x81, 2,    /* Input (Data, Var, Abs)                   20 */
    0x19, 1,    /* Usage minimum                            22 */
    0x29, 8,    /* Usage maximum                            24 */
    0x75, 8,    /* Report size = 8 (bits)                   26 */
    0x95, 2,    /* Report count = 16 bits (2 bytes)         28 */
    0x91, 2,    /* Output (Data, Var, Abs)                  30 */
    0xc0        /* End Collection                           31 */
    0x05, 0x01, /* .Usage Page (Generic Desktop)            33  2 */
    0x09, 0x04, /* .Usage (Joystick)                        35  4 */
    0xA1, 0x01, /* .Collection (Application)                37  6 */
    0x05, 0x01, /* .Usage Page (Generic Desktop)            39  8 */
    0x09, 0x01, /* .Usage (Pointer)                         41 10 */
    0xA1, 0x00, /* .Collection (Physical)                   43 12 */
    0x09, 0x30, /* .Usage(Usage_X)                          45 14 */
    0x09, 0x31, /* .Usage(Usage_Y)                          47 16 */
    0x15, 0x00, /* .Logical Minimum (0)                     49 18 */
    0x26, 0xFF, 0x00, /* .Logical Maximum (FF)              52 21 */
    0x75, 0x08, /* .Report Size (8)                         54 23 */
    0x95, 0x02, /* .Report Count (2)                        56 25 */
    0x81, 0x02, /* .Input (Data, Variable, Absolute)        58 27 */
    0xC0,       /* .End Collection                          59 28 */
    0x05, 0x02, /* .Usage Page (Simulation Controls)        61 30 */
    0x09, 0xBB, /* .Usage(Usage_Throttle)                   63 32 */
    0x15, 0x00, /* .Logical Minimum (0)                     65 34 */
    0x26, 0xFF, 0x00, /* .Logical Maximum (FF)              68 37 */
    0x75, 0x08, /* .Report Size (8)                         70 39 */
    0x95, 0x01, /* .Report Count (1)                        72 41 */
    0x81, 0x02, /* .Input (Data, Variable, Absolute)        74 43 */
    0x05, 0x02, /* .Usage Page (Simulation Controls)        76 45 */
    0x09, 0xBA, /* .Usage(Usage_Rudder)                     78 47 */
    0x15, 0x00, /* .Logical Minimum (0)                     80 49 */
    0x26, 0xFF, 0x00, /* .Logical Maximum (FF)              83 52 */
    0x75, 0x08, /* .Report Size (1)                         85 54 */
    0x95, 0x01, /* .Report Count (1)                        87 56 */
    0x81, 0x02, /* .Input (Data, Variable, Absolute)        89 58 */
    0x05, 0x09, /* .Usage Page (Button)                     91 60 */
    0x19, 0x01, /* .Usage Minimum (01)                      93 62 */
    0x29, 0x04, /* .Usage Maximum (04)                      95 64 */
    0x15, 0x00, /* .Logical Minimum (0)                     97 66 */
    0x25, 0x01, /* .Logical Maximum (Toggle)                99 68 */
    0x75, 0x01, /* .Report Size (1)                        101 70 */
    0x95, 0x04, /* .Report Count (4)                       103 72 */
    0x81, 0x02, /* .Input (Data, Variable, Absolute)       105 74 */
    0x75, 0x01, /* .Report Size (1)                        107 76 */
    0x95, 0x04, /* .Report Count (4)                       109 78 */
    0x81, 0x03, /* .Hid Input constant                     111 80 */   
    0xC0        /* End Collection                          112 81 */
   };

   //if a class has an extra descriptor not part of the config descriptor,
   // this lookup table defines where to look for it in the const
   // USB_CLASS_SPECIFIC_DESC[] array.
   //first element is the config number (if your device has more than one config)
   //second element is which interface number
   //set element to 0xFFFF if this config/interface combo doesn't exist
   const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP[USB_NUM_CONFIGURATIONS][2] =
   {
   //config 1
      //interface 0
         0,
         32
   };

   //if a class has an extra descriptor not part of the config descriptor,
   // this lookup table defines the size of that descriptor.
   //first element is the config number (if your device has more than one config)
   //second element is which interface number
   //set element to 0xFFFF if this config/interface combo doesn't exist
   const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[USB_NUM_CONFIGURATIONS][2] =
   {
   //config 1
      //interface 0
         32,
         81
   };


//////////////////////////////////////////////////////////////////
///
///   start config descriptor
///   right now we only support one configuration descriptor.
///   the config, interface, class, and endpoint goes into this array.
///
//////////////////////////////////////////////////////////////////

   #DEFINE USB_TOTAL_CONFIG_LEN      66 //config+interface+class+endpoint+endpoint (2 endpoints)

   const char USB_CONFIG_DESC[] = {
   //IN ORDER TO COMPLY WITH WINDOWS HOSTS, THE ORDER OF THIS ARRAY MUST BE:
      //    config(s)
      //    interface(s)
      //    class(es)
      //    endpoint(s)

   //config_descriptor for config index 1
         USB_DESC_CONFIG_LEN, //length of descriptor size          ==0
         USB_DESC_CONFIG_TYPE, //constant CONFIGURATION (CONFIGURATION 0x02)     ==1
         USB_TOTAL_CONFIG_LEN,0, //size of all data returned for this config      ==2,3
         2, //number of interfaces this device supports       ==4
         0x01, //identifier for this configuration.  (IF we had more than one configurations)      ==5
         0x00, //index of string descriptor for this configuration      ==6
         0xC0, //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 unused and bit7=1         ==7
         0x32, //maximum bus power required (maximum milliamperes/2)  (0x32 = 100mA) ==8

   //interface descriptor 1
         USB_DESC_INTERFACE_LEN, //length of descriptor      = 9
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =10
         0x00, //number defining this interface (IF we had more than one interface)    ==11
         0x00, //alternate setting     ==12
         2, //number of endpoins, except 0 (pic167xx has 3, but we dont have to use all).       ==13
         0x03, //class code, 03 = HID     ==14
         0x00, //subclass code //boot     ==15
         0x00, //protocol code      ==16
         0x00, //index of string descriptor for interface      ==17

   //class descriptor 1  (HID)
         USB_DESC_CLASS_LEN, //length of descriptor    ==18
         USB_DESC_CLASS_TYPE, //dscriptor type (0x21 == HID)      ==19
         0x00,0x01, //hid class release number (1.0) (try 1.10)      ==20,21
         0x00, //localized country code (0 = none)       ==22
         0x01, //number of hid class descrptors that follow (1)      ==23
         0x22, //report descriptor type (0x22 == HID)                ==24
         USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[0][0], 0x00, //length of report descriptor            ==25,26

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==27
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==28
         0x81, //endpoint number and direction (0x81 = EP1 IN)       ==29
         0x03, //transfer type supported (0x03 is interrupt)         ==30
         USB_EP1_TX_SIZE,0x00, //maximum packet size supported                  ==31,32
         250,  //polling interval, in ms.  (cant be smaller than 10)      ==33

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==34
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==35
         0x01, //endpoint number and direction (0x01 = EP1 OUT)      ==36
         0x03, //transfer type supported (0x03 is interrupt)         ==37
         USB_EP1_RX_SIZE,0x00, //maximum packet size supported                  ==38,39
         10, //polling interval, in ms.  (cant be smaller than 10)    ==40
         
  //interface descriptor 2
         USB_DESC_INTERFACE_LEN, //length of descriptor      =41
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =42
         0x00, //number defining this interface (IF we had more than one interface)    ==43
         0x00, //alternate setting     ==44
         1, //number of endpoins, except 0 (pic167xx has 3, but we dont have to use all).       ==45
         0x03, //class code, 03 = HID     ==46
         0x00, //subclass code //boot     ==47
         0x00, //protocol code      ==48
         0x00, //index of string descriptor for interface      ==49

   //class descriptor 2  (HID)
         USB_DESC_CLASS_LEN, //length of descriptor    ==50
         USB_DESC_CLASS_TYPE, //dscriptor type (0x21 == HID)      ==51
         0x00,0x01, //hid class release number (1.0) (try 1.10)      ==52,53
         0x00, //localized country code (0 = none)       ==54
         0x01, //number of hid class descrptors that follow (1)      ==55
         0x22, //report descriptor type (0x22 == HID)                ==56
         USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[0][0], 0x00, //length of report descriptor            ==57,58

   //endpoint descriptor 2
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==59
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==60
         0x81, //endpoint number and direction (0x81 = EP1 IN)       ==61
         USB_ENDPOINT_TYPE_INTERRUPT, //transfer type supported (0x03 is interrupt)         ==62
         USB_EP2_TX_SIZE,0x00, //maximum packet size supported                  ==63,64
         10  //polling interval, in ms.  (cant be smaller than 10 for slow speed devices)     ==65
   };
   

   //****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ********
   //since we can't make pointers to constants in certain pic16s, this is an offset table to find
   //  a specific descriptor in the above table.

   //NOTE: DO TO A LIMITATION OF THE CCS CODE, ALL HID INTERFACES MUST START AT 0 AND BE SEQUENTIAL
   //      FOR EXAMPLE, IF YOU HAVE 2 HID INTERFACES THEY MUST BE INTERFACE 0 AND INTERFACE 1
   #define USB_NUM_HID_INTERFACES   2

   //the maximum number of interfaces seen on any config
   //for example, if config 1 has 1 interface and config 2 has 2 interfaces you must define this as 2
   #define USB_MAX_NUM_INTERFACES   2

   //define how many interfaces there are per config.  [0] is the first config, etc.
   const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={2};

   //define where to find class descriptors
   //first dimension is the config number
   //second dimension specifies which interface
   //last dimension specifies which class in this interface to get, but most will only have 1 class per interface
   //if a class descriptor is not valid, set the value to 0xFFFF
   const int16 USB_CLASS_DESCRIPTORS[USB_NUM_CONFIGURATIONS][2][1]=
   {
   //config 1
      //interface 0
         //class 1
          18,
      //interface 1
         //class 1
         50
   };

   #if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)
      #error USB_TOTAL_CONFIG_LEN not defined correctly
   #endif


//////////////////////////////////////////////////////////////////
///
///   start device descriptors
///
//////////////////////////////////////////////////////////////////

   const char USB_DEVICE_DESC[USB_DESC_DEVICE_LEN] ={
      //starts of with device configuration. only one possible
         USB_DESC_DEVICE_LEN, //the length of this report   ==1
         0x01, //the constant DEVICE (DEVICE 0x01)  ==2
         0x10,0x01, //usb version in bcd (pic167xx is 1.1) ==3,4
         0x00, //class code ==5
         0x00, //subclass code ==6
         0x00, //protocol code ==7
         USB_MAX_EP0_PACKET_LENGTH, //max packet size for endpoint 0. (SLOW SPEED SPECIFIES 8) ==8
         0x61,0x04, //vendor id (0x04D8 is Microchip, or is it 0x0461 ??)
         0x20,0x0A, //product id   ==11,12  //don't use ffff says usb-by-example guy.  oops
         0x00,0x01, //device release number  ==13,14
         0x01, //index of string description of manufacturer. therefore we point to string_1 array (see below)  ==15
         0x02, //index of string descriptor of the product  ==16
         0x00, //index of string descriptor of serial number  ==17
         USB_NUM_CONFIGURATIONS  //number of possible configurations  ==18
   };


//the offset of the starting location of each string.  offset[0] is the start of string 0, offset[1] is the start of string 1, etc.
const char USB_STRING_DESC_OFFSET[]={0,4,12};

//number of strings you have, including string 0.
#define USB_STRING_DESC_COUNT sizeof(USB_STRING_DESC_OFFSET)

char const USB_STRING_DESC[]={
   //string 0
         4, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         0x09,0x04,   //Microsoft Defined for US-English
   //string 1
         8, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'C',0,
         'C',0,
         'S',0,
   //string 2
         28, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'C',0,
         'C',0,
         'S',0,
         ' ',0,
         'C',0,
         'o',0,
         'm',0,
         'p',0,
         'o',0,
         's',0,
         'i',0,
         't',0,
         'e',0
};
[/code]
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group