hillcraft
Joined: 22 Sep 2003 Posts: 101 Location: Cape Town (South africa)
|
USB Compound device |
Posted: Wed Apr 05, 2006 4:09 am |
|
|
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] |
|