USB HID y dispositivo de juegos

si te das cuenta, si es un eje de 10bits, entonces tienes que pasar el valor con 2 bytes para no perder nada.
Report Size (16) = 2 x 8 bits = 2 bytes
Report Count (1) = 1 x 16 bits = 2 bytes
Saludos, Willy
Yo lo interpretaba de otra manera:
Report Size (16)=2 bytes
Report Count (1)=1 byte (1 byte para enviar 16 bits?)

Recuerda que debes modificar en alguna parte de tu programa el tamaño del descriptor e indicar la cantidad de bytes que pasaras por el endpoint. Puede ser por eso que no te ande.

Saludos, Willy

Seguro que es por eso, nunca modifique nada mas que el report descriptor.

Ahora en la PC nisiquiera hace el "Dee Doo" de cuando conectamos un dispositivo USB.:unsure:

Nos vemos.
 
Última edición:
claro es eso, tiene que coincidir todo, el largo del descriptor, la cantidad de bytes que envias o recibes y el descriptor en si mismo. Cualquiera que no coincida hara que tu dispositivo quede mal enumerado y no se acorrectamente identificado o el funcionamiento incorrecto.

Creo ya lo he puesto antes, pero es bueno que le des una leida a la documentación del HID http://www.usb.org/developers/devclass_docs/HID1_11.pdf
 
Si, el problema es a veces la enumeracion y por que no puede reconocer el dispositivo. El descriptor completo que tengo es este:

Código:
#define	EP0_BUFF_SIZE		64	; 8, 16, 32, or 64
#define	MAX_NUM_INT		1	; For tracking Alternate Setting
#define	MAX_EP_NUMBER		1	; UEP1
#define	NUM_CONFIGURATIONS	1
#define	NUM_INTERFACES		1

#define	MODE_PP			    _PPBM0
#define	UCFG_VAL		    _PUEN|_TRINT|_FS|MODE_PP	; Full-speed

; DEVICE CLASS USAGE
#define USB_USE_HID

; HID
; Endpoints Allocation
#define	HID_INTF_ID		  0x00
#define	HID_UEP			  UEP1
#define	HID_BD_OUT		  ep1Bo
#define	HID_INT_OUT_EP_SIZE	  64
#define	HID_BD_IN		  ep1Bi
#define	HID_INT_IN_EP_SIZE	  64
#define	HID_NUM_OF_DSC		  1

; ******************************************************************
; This table is polled by the host immediately after USB Reset has been released.
; This table defines the maximum packet size EP0 can take.
; See section 9.6.1 of the Rev 1.0 USB specification.
; These fields are application DEPENDENT. Modify these to meet
; your specifications.
; ******************************************************************
DeviceDescriptor
	retlw	(EndDeviceDescriptor-DeviceDescriptor)/2	; bLength Length of this descriptor
	retlw	DSC_DEV		; bDescType This is a DEVICE descriptor
	retlw	0x10		; bcdUSBUSB Revision 1.10 (low byte)
	retlw	0x01		; high byte
	retlw	0x00		; bDeviceClass zero means each interface operates independently
	retlw	0x00		; bDeviceSubClass
	retlw	0x00		; bDeviceProtocol
	retlw	EP0_BUFF_SIZE	; bMaxPacketSize for EP0

        ; idVendor (low byte, high byte)
	retlw	0x81
	retlw	0x17

        ; idProduct (low byte, high byte)
	retlw	0xD0
	retlw	0x07

        retlw	0x00		; bcdDevice (low byte)
	retlw	0x00		; (high byte)
	retlw	0x01		; iManufacturer (string index)
	retlw	0x02		; iProduct      (string index)

        ; iSerialNumber (string index)
	retlw	0x03
	retlw	NUM_CONFIGURATIONS ; bNumConfigurations
EndDeviceDescriptor

; ******************************************************************
; This table is retrieved by the host after the address has been set.
; This table defines the configurations available for the device.
; See section 9.6.2 of the Rev 1.0 USB specification (page 184).
; These fields are application DEPENDENT. 
; Modify these to meet your specifications.
; ******************************************************************
; Configuration pointer table
USB_CD_Ptr
Configs
	db	low Config1, high Config1
	db	low Config1, high Config1

; Configuration Descriptor
Config1
	retlw	(Interface1-Config1)/2	; bLength Length of this descriptor
	retlw	DSC_CFG		; bDescType 2=CONFIGURATION
Config1Len
	retlw	low ((EndConfig1 - Config1)/2)	; Length of this configuration
	retlw	high ((EndConfig1 - Config1)/2)
	retlw	0x01		; bNumInterfaces Number of interfaces
	retlw	0x01		; bConfigValue Configuration Value
	retlw	0x00		; iConfig (string index)
	retlw	0xA0		; bmAttributes attributes - bus powered

        ; Max power consumption (2X mA)
	retlw	0x32
Interface1
	retlw	(HIDDescriptor1-Interface1)/2	; length of descriptor
	retlw	DSC_INTF
	retlw	0x00		; number of interface, 0 based array
	retlw	0x00		; alternate setting
	retlw	0x02		; number of endpoints used in this interface
	retlw	0x03		; interface class - assigned by the USB
	retlw	0x00		; boot device
	retlw	0x00		; interface protocol - mouse
	retlw 	0x00		; index to string descriptor that describes this interface
HIDDescriptor1
	retlw	(Endpoint1In-HIDDescriptor1)/2	; descriptor size (9 bytes)
        retlw	0x21		; descriptor type (HID)
	retlw	0x00		; HID class release number (1.00)
	retlw	0x01
        retlw	0x00		; Localized country code (none)
        retlw	0x01		; # of HID class descriptor to follow (1)
        retlw	0x22		; Report descriptor type (HID)
[COLOR="Red"][SIZE="4"][B]ReportDescriptor1Len
	retlw	low ((EndReportDescriptor1-ReportDescriptor1)/2)
	retlw	high ((EndReportDescriptor1-ReportDescriptor1)/2)
Endpoint1In
	retlw	(EndPoint1Out-Endpoint1In)/2	; length of descriptor[/B][/SIZE][/COLOR]
	retlw	DSC_EP
	retlw	0x81		; EP1, In
	retlw	0x03		; Interrupt
	[SIZE="4"][COLOR="Red"][B]retlw	0x40		; This should be the size of the endpoint buffer[/B][/COLOR][/SIZE]
	retlw	0x00
	retlw	0x0A                        ; Polling interval
EndPoint1Out
	retlw	(EndConfig1-EndPoint1Out)/2	; Length of this Endpoint Descriptor
	retlw	DSC_EP		; bDescriptorType = 5 for Endpoint Descriptor
	retlw	0x01		; Endpoint number & direction
	retlw	0x03		; Transfer type supported by this Endpoint
	retlw	0x40		; This should be the size of the endpoint buffer
	retlw	0x00
	retlw	0x0A                        ; Polling interval
EndConfig1

ReportDescriptor1
    ; vendor defined usage page
    retlw	0x06		
    retlw	0x00
    retlw	0xFF

    ; vendor defined usage
    retlw	0x09
    retlw	0x00

    ; collection(application)
    retlw	0xA1
    retlw	0x01

    ; *** INPUT REPORT ***

    ; vendor defined usage
    retlw	0x09
    retlw	0x01

    retlw	0x15 	; logical minimum (-128)
    retlw	0x80    ;
    retlw	0x25 	; logical maximum (127)
    retlw	0x7F    ;
    retlw	0x35 	; Physical Minimum (0)
    retlw	0x00    ;
    retlw	0x45 	; Physical Maximum (255)
    retlw	0xFF    ;

    ; report size in bits
    retlw	0x75
    retlw	0x08

    ; report count (number of fields)
    retlw	0x95
    retlw	0x08

    ; Input (Data, Variable, Absolute)
    retlw	0x81
    retlw	0x02

    ; *** OUTPUT REPORT ***

    ; vendor defined usage
    retlw	0x09	    ; usage (Vendor Defined)
    retlw	0x02        ;

    retlw	0x15	    ; logical minimum (-128)
    retlw	0x80        ;
    retlw	0x25	    ; logical maximum (127)
    retlw	0x7F        ;
    retlw	0x35	    ; Physical Minimum (0)
    retlw	0x00        ;
    retlw	0x45	    ; Physical Maximum (255)
    retlw	0xFF        ;

    ; report size in bits
    retlw	0x75
    retlw	0x08

    ; report count (number of fields)
    retlw	0x95
    retlw	0x08

    ; Output (Data, Variable, Absolute)
    retlw	0x91
    retlw	0x02

    retlw   0xC0       	   ; end collection

EndReportDescriptor1

; String pointer table
USB_SD_Ptr
Strings
	db	low String0, high String0
	db	low String1, high String1
	db	low String2, high String2
	db	low String3, high String3

String0
	retlw	(String1-String0)/2	; Length of string
	retlw	DSC_STR		        ; Descriptor type 3
	retlw	0x09		        ; Language ID (as defined by MS 0x0409)
	retlw	0x04

; company name
String1
	retlw	(String2-String1)/2
	retlw	DSC_STR
	
        retlw   'Y'
        retlw   0x00
        retlw   'e'
        retlw   0x00
        retlw   'y'
        retlw   0x00
        retlw   'o'
        retlw   0x00
        retlw   '''
        retlw   0x00
        retlw   's'
        retlw   0x00
        retlw   ' '
        retlw   0x00
        retlw   'I'
        retlw   0x00
        retlw   'n'
        retlw   0x00
        retlw   'c'
        retlw   0x00
        retlw   '.'
        retlw   0x00
        retlw   ' '
        retlw   0x00
        retlw   'U'
        retlw   0x00
        retlw   'S'
        retlw   0x00
        retlw   'B'
        retlw   0x00
        retlw   '!'
        retlw   0x00

	
; product name	
String2
	retlw	(String3-String2)/2
	retlw	DSC_STR
	
        retlw   '1'
        retlw   0x00
        retlw   '2'
        retlw   0x00
        retlw   '3'
        retlw   0x00
        retlw   '4'
        retlw   0x00
        retlw   '5'
        retlw   0x00
        retlw   '6'
        retlw   0x00
        retlw   '7'
        retlw   0x00
        retlw   '8'
        retlw   0x00

; serial number
String3
	retlw	(String4-String3)/2
	retlw	DSC_STR
	
        retlw   '1'
        retlw   0x00
        retlw   '2'
        retlw   0x00
        retlw   '0'
        retlw   0x00
        retlw   '8'
        retlw   0x00
        retlw   '1'
        retlw   0x00
        retlw   '0'
        retlw   0x00
        retlw   '1'
        retlw   0x00
        retlw   '4'
        retlw   0x00
        retlw   '2'
        retlw   0x00
        retlw   '2'
        retlw   0x00

String4

Resalte con rojo lo que yo creo es el tamaño del report descriptor, que calcula con esa rutina el tamaño siempre que lo coloquemos entre las etiquetas ReportDescriptor1 y EndReportDescriptor1, dicho sea de paso asi modifico yo el report.

Estoy en lo cierto?

Cualquiera sea el tamaño que yo coloque entre ReportDescriptor1 y EndReportDescriptor1 la rutina "ReportDescriptor1Len" va a calcular el tamaño.

Nos vemos.:D
 
aja, lo del calculo de las longitudes automatico si es posible de esa forma, aunque yo prefiero hacerlo manualmente.
Este descriptor lo has copiado de algún ejemplo, no?
Lo has modificado en algo?

Yo le haria estos cambios al descriptor:
Código:
ReportDescriptor1
    ; vendor defined usage page
    retlw	0x06		
    retlw	[COLOR="Red"]0xA0[/COLOR]
    retlw	0xFF

    ; vendor defined usage
    retlw	0x09
    retlw	0x00

    ; collection(application)
    retlw	0xA1
    retlw	0x01

    ; *** INPUT REPORT ***

    ; vendor defined usage
    retlw	0x09
    retlw	[COLOR="Red"]0x03[/COLOR]

    retlw	0x15 	; logical minimum (0)
    retlw	[COLOR="Red"]0x00[/COLOR]    ;
[COLOR="Red"]    retlw	0x26 	; logical maximum (255)
    retlw	0xFF    ;
    retlw	0x00    ;[/COLOR]
    retlw	0x35 	; Physical Minimum (0)
    retlw	0x00    ;
[COLOR="Red"]    retlw	0x46 	; Physical Maximum (255)
    retlw	0xFF    ;
    retlw	0x00    ;[/COLOR]

    ; report size in bits
    retlw	0x75
    retlw	0x08

    ; report count (number of fields)
    retlw	0x95
    retlw	0x08

    ; Input (Data, Variable, Absolute)
    retlw	0x81
    retlw	0x02

    ; *** OUTPUT REPORT ***

    ; vendor defined usage
    retlw	0x09	    ; usage (Vendor Defined)
    retlw	[COLOR="Red"]0x04[/COLOR]

    retlw	0x15 	; logical minimum (0)
    retlw	[COLOR="Red"]0x00[/COLOR]    ;
[COLOR="Red"]    retlw	0x26 	; logical maximum (255)
    retlw	0xFF    ;
    retlw	0x00    ;[/COLOR]
    retlw	0x35 	; Physical Minimum (0)
    retlw	0x00    ;
[COLOR="Red"]    retlw	0x46 	; Physical Maximum (255)
    retlw	0xFF    ;
    retlw	0x00    ;[/COLOR]

    ; report size in bits
    retlw	0x75
    retlw	0x08

    ; report count (number of fields)
    retlw	0x95
    retlw	0x08

    ; Output (Data, Variable, Absolute)
    retlw	0x91
    retlw	0x02

    retlw   0xC0       	   ; end collection

EndReportDescriptor1

Como te contaba antes, no trabajo con la versión en Assembler, si no con la de C18.

Lo que está indicado como
#define HID_INT_OUT_EP_SIZE 64
#define HID_INT_IN_EP_SIZE 64

corresponden a los Máximos tamaños de los paquetes de los endpoint, pero no a los actuales que usas tu, si bien por lo que vi en tu aplicación quieres usar 8 bytes de entrada y 8 de salida, en ninguna parte lo estas especificando, tampoco deberias indicarlo en el descriptor, sino que debes tener algun otro archivo del tipo cabecera, es decir, un .inc en el cual debes definir la cantidad de bytes que vas a estar pasando por cada endpoint.

Por ejemplo yo tengo estas definiciones
#define HID_INPUT_REPORT_BYTES 2
#define HID_OUTPUT_REPORT_BYTES 2


Búscalas en los archivos que tienes y pon en cada una esto
#define HID_INPUT_REPORT_BYTES 8
#define HID_OUTPUT_REPORT_BYTES 8


Quizas estas definiciones no las tengas y esten puestos los valores directamente en el código, si es así luego en casa te busco donde se usan.

Si quieres puedes pasarme el proyecto completo y lo analizo en el MPLAB con todos los archivos.

Saludos, Willy
 
Hola willy, este report es el original que genera EasyHID para enviar y recibir 8 bytes. Es generico y no tiene un descriptor de dispositivo especifico. Igualmente algun problema debe haber porque cuando uso un descriptor propio nunca le llega ningun dato a la pc. Voy a poner un ejemplo completo en cuanto llegue a casa.

Saludos.
 
Hola a todos, les comento que estoy probando varios analizadores USB por software y este me parecio muy completo es el Uzblyzer 1.6

http://www.usblyzer.com/explore-usb-device-tree-view-usb-device-properties.htm

El link de descarga es este:

http://turbobit.net/download/free/k4ryduvr13d2#

Estoy comprando unos volantes con vibración para poder ver como declaran el dispositivo.

Buscar en Mercadolibre: MLA-92607615-volante-ps2-y-pc-con-usb-pedalera-vibracion-oferta-limitada-_JM

Saludos.
Claudio J. Pérez
Jujuy-Argentina
 
Excelente tema, he probado todos los proyectos que han subido y funcionan perfectamente. Actualmente me encuentro desarrollando un proyecto en el cual necesito que el PIC sea reconocido como dos dispositivos al mismo tiempo: Como un Joystic y como un PIC (microchip). Esto porque el joystick es reconocido por un juego a diferencia del pic, y el pic es reconocido por una aplicación en java con la ayuda de la librería JPICUSB.

Lo que quería saber es si es posible introducir dos descriptores en un mismo pic para que este sea reconocido por la pc como dos dispositivos distintos al mismo tiempo??? y como hacerlo claro esta...
 
Hola gracias por toda la informacion, pero temgo un problema con el descriptor haber si me pueden ayudar, lo que pasa es que compilo el codigo del descriptor y me sale el siguiente error "A #DEVICE required before this line", peor no se que hacer, de antemano gracias.
 
Buenas expertos

he estado leyendo su hilo y me parace bien pero tengo una duda con respecto al HID descriptor.

Veran he tratado de hacer un PIC HID generico, digamos que le envie un comando X y este encienda un LED y otro para que lo apague, el pic es reconocido por el PC y el programa pero no enciende el led y tampoco parece responder al comando usb_kbhit(1) ya que tambien le digo que cuando reciba un caracter en el puerto enciando un led #2 pero no enciende cuando con el programa en el PC le doy enviar el caracter, asi que despues de estar leyendo sus post y otras cosas creo que mi problema esta en el descriptor solo que ya he leido como 7 veces las primeras paginas donde explican eso y no lo entiendo todavia, seria mucha molestia que alguien me explique como se configura?

les agredesco mucho!
 
Excelente tema, he probado todos los proyectos que han subido y funcionan perfectamente. Actualmente me encuentro desarrollando un proyecto en el cual necesito que el PIC sea reconocido como dos dispositivos al mismo tiempo: Como un Joystic y como un PIC (microchip). Esto porque el joystick es reconocido por un juego a diferencia del pic, y el pic es reconocido por una aplicación en java con la ayuda de la librería JPICUSB.

Lo que quería saber es si es posible introducir dos descriptores en un mismo pic para que este sea reconocido por la pc como dos dispositivos distintos al mismo tiempo??? y como hacerlo claro esta...


Josel99:

También quería hacer lo mismo que vos, y otra aplicación para los dos descriptores sería tener por ejemplo dos joystick "en uno"
Encontraste información sobre el tema?

vamos por partes, ante todo aviso que trabajo con C18 y puede que algunas cosillas alla que adaptarlas al compilador CCS.

Con respecto al descriptor, no lo he probado en W7 porque no lo tengo asi que estoy en las mismas que tu oscar.

Este es el descriptor que uso y en base a ese hago las modificaciones para adaptarlo a otras soluciones.
Código:
	0x05, 0x01, 		//	Usage Page (Generic Desktop)
	0x09, 0x04, 		//	Usage (Joy)
	0xA1, 0x00, 		//	Collection (Physical)
	0x09, 0x30, 		//	  Usage (X)
	0x09, 0x31, 		//	  Usage (Y)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0x03,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x02, 		//	  Report Count (2)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)
	0x09, 0x32, 		//	  Usage (Z)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0x03,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x01, 		//	  Report Count (1)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)
	0x09, 0x33, 		//	  Usage (Rx)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0x03,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x01, 		//	  Report Count (1)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)
	0x09, 0x34, 		//	  Usage (Ry)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0x03,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x01, 		//	  Report Count (1)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)
	0x09, 0x35, 		//	  Usage (Rz)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0x03,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x01, 		//	  Report Count (1)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)

	0x09, 0x39,			//    Usage (Hat Sw)
	0x15, 0x00, 		//	  Log Min (0)
	0x25, 0x07,			//	  Log Max (7)
	0x35, 0x00,			//    Phy Min (0)
	0x46, 0x3B, 0x01,	//    Phy Max (315)
	0x65, 0x12,			//    Unit (SI Rot : Ang Pos)
	0x75, 0x08, 		//	  Report Size (8)
	0x95, 0x01, 		//	  Report Count (1)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)

	0x05, 0x09,			//    Usage Page (Button)
	0x19, 0x01,			//    Usage Min (1)
	0x29, 0x20,			//    Usage Max (32)
	0x15, 0x00, 		//	  Log Min (0)
	0x25, 0x01,			//	  Log Max (1)
	0x75, 0x01, 		//	  Report Size (1)
	0x95, 0x20, 		//	  Report Count (32)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)
	0xC0};				//	End Collection

La parte de los ejes es muy repetitiva, y puede simplificarse segun he leido en algunas documentaciones aunque no lo he probado, es decir, las cosas que son comunes a los 6 ejes con ponerlas una sola ves bastaria.

Un punto importante es el tema de indicar la longitud o tamaño del descriptor y la cantidad de bytes que se estan transmitiendo. Eso deberan ver en parte del código, pero si esos valores no coindicen tendran problemas al comunicarse con el host.

Con respecto a asignarle un nombre al dispositivo, para el que trabaje con el C18 puede buscar parte del codigo que sea similar a esto.
Código:
rom struct{byte bLength;byte bDscType;word string[22];}sd001={
sizeof(sd001),DSC_STR,
'W','i','l','l','y','N','o','v','i',' ',
'R','a','c','i','n','g',' ','T','e','a','m','.'};

rom struct{byte bLength;byte bDscType;word string[12];}sd002={
sizeof(sd002),DSC_STR,
'J','o','y','s','t','i','c','k',' ','0','.','1'};

El decriptor para trabjar con salidas es este:
Código:
	0x05, 0x01, 		//	Usage Page (Generic Desktop)
	0x09, 0x04, 		//	Usage (Joy)
	0xA1, 0x00, 		//	Collection (Physical)
	0x09, 0x30, 		//	  Usage (X)
	0x09, 0x31, 		//	  Usage (Y)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0xFF,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x02, 		//	  Report Count (2)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)

    0x06, 0x00, 0xFF,       // Usage Page = 0xFF00 (Vendor Defined Page 1)
	// The Output report
    0x09, 0x04,     	// Usage ID - vendor defined
    0x15, 0x00,     	// Logical Minimum (0)
    0x26, 0xFF, 0x00,   // Logical Maximum (255)
    0x75, 0x08,     	// Report Size (8 bits)
    0x95, 0x04,     	// Report Count (4 fields)
    0x91, 0x02,      	// Output (Data, Variable, Absolute)  
	0xC0

Por lo de la comunicacion con el host luego preparo un programita simple en C para que lo tengan de guia, es que la aplicacion que tnego hecha es un quilombete y por ahi se marean:D

Willynovi:

Una pregunta, al utilizar 10 bits de resolución, tenés que usar variables de int16 vos los truncas en dos bytes antes de "transmitirlos " por el usb?
Yo uso CCS y envio de la siguiente forma

usb_put_packet(1,envia,10,USB_DTS_TOGGLE);

envia es un array int envia[10] ( mando los ejes mas los botones pero todo int8 en total son 10 bytes) como hago para enviar los ejes en int16 y los botones int8 ?

Se entiende? :)

tenés algún ejemplo aunque sea en c18?

Gracias.

vamos por partes, ante todo aviso que trabajo con C18 y puede que algunas cosillas alla que adaptarlas al compilador CCS.

Con respecto al descriptor, no lo he probado en W7 porque no lo tengo asi que estoy en las mismas que tu oscar.

Este es el descriptor que uso y en base a ese hago las modificaciones para adaptarlo a otras soluciones.
Código:
	0x05, 0x01, 		//	Usage Page (Generic Desktop)
	0x09, 0x04, 		//	Usage (Joy)
	0xA1, 0x00, 		//	Collection (Physical)
	0x09, 0x30, 		//	  Usage (X)
	0x09, 0x31, 		//	  Usage (Y)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0x03,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x02, 		//	  Report Count (2)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)
	0x09, 0x32, 		//	  Usage (Z)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0x03,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x01, 		//	  Report Count (1)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)
	0x09, 0x33, 		//	  Usage (Rx)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0x03,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x01, 		//	  Report Count (1)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)
	0x09, 0x34, 		//	  Usage (Ry)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0x03,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x01, 		//	  Report Count (1)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)
	0x09, 0x35, 		//	  Usage (Rz)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0x03,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x01, 		//	  Report Count (1)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)

	0x09, 0x39,			//    Usage (Hat Sw)
	0x15, 0x00, 		//	  Log Min (0)
	0x25, 0x07,			//	  Log Max (7)
	0x35, 0x00,			//    Phy Min (0)
	0x46, 0x3B, 0x01,	//    Phy Max (315)
	0x65, 0x12,			//    Unit (SI Rot : Ang Pos)
	0x75, 0x08, 		//	  Report Size (8)
	0x95, 0x01, 		//	  Report Count (1)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)

	0x05, 0x09,			//    Usage Page (Button)
	0x19, 0x01,			//    Usage Min (1)
	0x29, 0x20,			//    Usage Max (32)
	0x15, 0x00, 		//	  Log Min (0)
	0x25, 0x01,			//	  Log Max (1)
	0x75, 0x01, 		//	  Report Size (1)
	0x95, 0x20, 		//	  Report Count (32)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)
	0xC0};				//	End Collection

La parte de los ejes es muy repetitiva, y puede simplificarse segun he leido en algunas documentaciones aunque no lo he probado, es decir, las cosas que son comunes a los 6 ejes con ponerlas una sola ves bastaria.

Un punto importante es el tema de indicar la longitud o tamaño del descriptor y la cantidad de bytes que se estan transmitiendo. Eso deberan ver en parte del código, pero si esos valores no coindicen tendran problemas al comunicarse con el host.

Con respecto a asignarle un nombre al dispositivo, para el que trabaje con el C18 puede buscar parte del codigo que sea similar a esto.
Código:
rom struct{byte bLength;byte bDscType;word string[22];}sd001={
sizeof(sd001),DSC_STR,
'W','i','l','l','y','N','o','v','i',' ',
'R','a','c','i','n','g',' ','T','e','a','m','.'};

rom struct{byte bLength;byte bDscType;word string[12];}sd002={
sizeof(sd002),DSC_STR,
'J','o','y','s','t','i','c','k',' ','0','.','1'};

El decriptor para trabjar con salidas es este:
Código:
	0x05, 0x01, 		//	Usage Page (Generic Desktop)
	0x09, 0x04, 		//	Usage (Joy)
	0xA1, 0x00, 		//	Collection (Physical)
	0x09, 0x30, 		//	  Usage (X)
	0x09, 0x31, 		//	  Usage (Y)
	0x15, 0x00, 		//	  Log Min (0)
	0x26, 0xFF, 0xFF,	//	  Log Max (1023)
	0x75, 0x10, 		//	  Report Size (16)
	0x95, 0x02, 		//	  Report Count (2)
	0x81, 0x02, 		//	  Input (Data, Variable, Absolute)

    0x06, 0x00, 0xFF,       // Usage Page = 0xFF00 (Vendor Defined Page 1)
	// The Output report
    0x09, 0x04,     	// Usage ID - vendor defined
    0x15, 0x00,     	// Logical Minimum (0)
    0x26, 0xFF, 0x00,   // Logical Maximum (255)
    0x75, 0x08,     	// Report Size (8 bits)
    0x95, 0x04,     	// Report Count (4 fields)
    0x91, 0x02,      	// Output (Data, Variable, Absolute)  
	0xC0

Por lo de la comunicacion con el host luego preparo un programita simple en C para que lo tengan de guia, es que la aplicacion que tnego hecha es un quilombete y por ahi se marean:D

Willynovi:

Una pregunta, al utilizar 10 bits de resolución, tenés que usar variables de int16 vos los truncas en dos bytes antes de "transmitirlos " por el usb?
Yo uso CCS y envio de la siguiente forma

usb_put_packet(1,envia,10,USB_DTS_TOGGLE);

envia es un array int envia[10] ( mando los ejes mas los botones pero todo int8 en total son 10 bytes) como hago para enviar los ejes en int16 y los botones int8 ?

Se entiende?

tenés algún ejemplo aunque sea en c18?

Gracias.
 
Última edición:
hola dashtronic, hace tiempo no me pasaba por aca, perdon por la demora en la respuesta.

En el PIC la conversion digital analógica al ser de 10 bits vas a tener el valor en dos bytes, el alto y el bajo.

Como la transmisión hacia la PC por el USB en el modo HID es tambien por bytes, y en el descriptor le indicas que vas a pasar un valor de 10 bits, tambien tendras que pasar esos dos mismo bytes, el alto y el bajo tal cual como estan. No es necesario hacer ningun tipo de arreglo o truncado.

Luego en casa te paso parte del código así te queda mas claro, pero creo que con esta idea puedes ir trabajando.

Saludos,
Willy
 
Que parte habría que añadir al descriptor para poder controlar unos motores como si fueran force feedback?

En realidad lo unico que quiero hacer es encender un led, pero no se me ocurre otra forma si configuro el pic para que sea reconocido como un gamepad.
 
hola soy novato en esto del protocolo usb queria pedirte un favor si me podrias indicar q tengo q hacer para cambiar de pic en tu proyecto de joystic usb q hiciste "del pic 18f4550 al 18f2550 " puesto q en mi pais no venden ese pic, quiero el joystick de 2 ejes x y ,"no el analogico" o desearia q me expliques como se hace para saber en q puertos habilitamos tanto las botoneras como las palancas.
por ultimo me gustaria saber si podemos poner 2 joystick en un mismo pic por ejemplo en el q tu hiciste "18f4550" aprobechando los puertos libres q quedan.
Espero q me puedas colaborar con toda la informacion posible.

P.D: Espero q me colabores porfa sin mas q decirte me despido agradeciendote de antemano.
 
necesito de su ayuda resulta que el pc no me reconoce el montaje. ya he probado el mismo pero con controladores genericos y con un programa en matlab y todo perfecto pero cuando lo conecto asi como se a colocado aqui sin controlador no me reconoce el pic

les coloco a continuación el rograma de ccs estoy utilizando en puerto analogo AN0 y AN1 y los botones los coloco en el puerto E del 18f4550 (reloj 20Mhz)


#include <18F4550.h>
#device ADC=8
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)

#DEFINE USB_HID_DEVICE TRUE

#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP1_TX_SIZE 8

#include <pic18_usb.h>
#include <usb_gamepad_HID.h> //USB Configuration and Device descriptors for this USB device
#include <usb.c> //handles usb setup tokens and get descriptor reports
#include <ctype.h>
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#USE fast_IO (E)

void main(void) {

SET_TRIS_E(0xFF);


int8 out_data[2];
int8 eje_x=0;
int8 botones=0;
int8 eje_y=0;


usb_init_cs();
usb_task();
usb_wait_for_enumeration();


setup_adc_ports(AN0_TO_AN1|VSS_VDD);//Canal 0 y 1 analógico
setup_adc(ADC_CLOCK_INTERNAL); //Fuente de reloj RC




while (TRUE) {
if(usb_enumerated()) // PicWinUSB is enumerated?
{
if (usb_kbhit(1)) // EP has data?
{

botones=INPUT_E();

set_adc_channel(0); //Habilitación canal 0
delay_us(20);
eje_x = read_adc();
delay_us(20);
set_adc_channel(1); //Habilitación canal 1
delay_us(20);
eje_y = read_adc();


out_data[0]=eje_x;
out_data[1]=eje_y;
out_data[2]=botones;


usb_put_packet(1,out_data,2,USB_DTS_TOGGLE);
}
}
}
}


y el HID

es el que colocaron anteriormente

///////////////////////////////////////////////////////////////////////////
/// usb_gamepad_HID.h ////
//// ////
//// An example set of device / configuration descriptors. ////
//// ////
///////////////////////////////////////////////////////////////////////////

#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.
///
/// This examples configures HID driver to take received data
/// as mouse x, y and button data.
///
//////////////////////////////////////////////////////////////////

const char USB_CLASS_SPECIFIC_DESC[] = {

0x05, 0x01, // usage page (generic desktop Choose the usage page "mouse" is on
0x09, 0x05, // usage Device is a gamepad
0xA1, 0x01, // collection (application) This collection encompasses the report format
0x09, 0x01, // usage (pointer) Choose the key code usage page
0xA1, 0x00, // collection (physical) Physical collection
0x09, 0x30, // usage (X) X direction of pointer
0x09, 0x31, // usage (Y) Y direction of pointer
0x15, 0x00, // logical minimum (0)
0x26, 0xFF, 0x00, // logical maximum (255)
0x35, 0x00, // PHYSICAL minimum (0)
0x46, 0xFF, 0x00, // PHYSICAL maximum (255)
0x75, 0x08, // report size (8)
0x95, 0x02, // report count (2) Two reports, eight bit each
0x81, 0x02, // input (data, variable, absolute)
0xC0, // end collection
0x05, 0x09, // usage page (buttons) Choose the “button” usage page
0x19, 0x01, // usage minimum (1) There are three buttons
0x29, 0x08, // usage maximum (8)
0x15, 0x00, // logical minimum (0) Each button is represented by one bit
0x25, 0x01, // logical maximum (1)
0x95, 0x08, // report count (8) Three reports, one bit each
0x75, 0x01, // report size (1)
0x81, 0x02, // input (data, variable, absolute)
0xC0, // end collection

};

//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][1] =
{
//config 1
//interface 0
0
};

//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][1] =
{
//config 1
//interface 0
sizeof(USB_CLASS_SPECIFIC_DESC)
};



//////////////////////////////////////////////////////////////////
///
/// 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 34 //config+interface+class+endpoint

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

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

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

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


//****** 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 1

//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 1

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

//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][USB_NUM_HID_INTERFACES][1]=
{
//config 1
//interface 0
//class 1
18
};


#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[] = {
//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 ??)
0x22,0x00, //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
};

#if (sizeof(USB_DEVICE_DESC) != USB_DESC_DEVICE_LEN)
#error USB_DESC_DEVICE_LEN not defined correctly
#endif


//////////////////////////////////////////////////////////////////
///
/// start string descriptors
/// String 0 is a special language string, and must be defined. People in U.S.A. can leave this alone.
///
//////////////////////////////////////////////////////////////////

//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)
':',0,
' ',0,
')',0,
//string 2
28, //length of string index
USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
'b',0,
'y',0,
' ',0,
'J',0,
'O',0,
'S',0,
'E',0,

};
 
Última edición:
Buenas, alguien sabe como hacer un descriptor para que el dispositivo me aparezca como dos o mas gamepads para saltear la limitacion de 8 analogicos y 32 botones enviando datos desde un mismo pic?
Mi idea es hacer un controlador midi, pero 8 canales analogicos son insuficientes...
 
Gracias por la sugerencia, la verdad que dije de hacerlo como gamepad hid porque no habia encontrado mucho sobre midi y usb... en cambio con el tema del gamepad en 2 dias ya lo tenia funcionando y lo habia entendido.
Ahora me bajè el framework usb de microchip... pero estoy acostumbrado a programar en proton, pic simulator y esos, me falta tiempo para el ccs y demas ;)
 
Atrás
Arriba