2 Devices with one AVR
2 Devices with one AVR
Is there a way to simulate 2 devices with one avr ?
My Problem:
I want to develop a device wich is a gamepad with a led.But I dont want to develop my own gamepad driver.
I want to send the report to switch led from an extern program.
And the gamepad should be used from the normal gameport driver.
In linux I dont find a way to send the report to switch led without unloading the gameport driver.
Is there a way to do so (I know better ask in a linux usb forum) ?
Or, I have to simulate 2 devices.
My Problem:
I want to develop a device wich is a gamepad with a led.But I dont want to develop my own gamepad driver.
I want to send the report to switch led from an extern program.
And the gamepad should be used from the normal gameport driver.
In linux I dont find a way to send the report to switch led without unloading the gameport driver.
Is there a way to do so (I know better ask in a linux usb forum) ?
Or, I have to simulate 2 devices.
Do someone have an example, how to implement this ?
I was searching the half day, but I cant see where to start.
Is this done with another report descriptor or is there more ?
Until now this is my (not all, borrowed some) code:
Which works.
So, where start make it stop working ?
And make it work again different?
I was searching the half day, but I cant see where to start.
Is this done with another report descriptor or is there more ?
Until now this is my (not all, borrowed some) code:
Code: Select all
... stuff
char usbHidReportDescriptor[73] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x02, // USAGE_PAGE (Simulation Controls)
0x09, 0xbb, // USAGE (Throttle)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x0d, // USAGE_MAXIMUM (Button 13)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x0d, // REPORT_COUNT (13)
0x55, 0x00, // UNIT_EXPONENT (0)
0x65, 0x00, // UNIT (None)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x81, 0x01, // INPUT (Cnst,Ary,Abs)
0xc0, // END_COLLECTION
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x85, 0x01, // REPORT_ID (1)
0x95, 0x01, // REPORT_COUNT (1)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0xc0 // END_COLLECTION
};
... more stuff
uchar usbFunctionWrite(uchar *data, uchar len)
{
if( data[0] == 1 ){ // set led
if( data[1] == 0x00 ){
resetLED();
} else {
setLED();
}
}
return 1;
}
... some stuff
uchar usbFunctionSetup(uchar data[8])
{
rq = (void *)data;
usbMsgPtr = reportBuffer;
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
makeNewReport();
return sizeof(reportBuffer);
}else if(rq->bRequest == USBRQ_HID_SET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
return 0xff;
}else if(rq->bRequest == USBRQ_HID_GET_IDLE){
usbMsgPtr = &idleRate;
return 1;
}else if(rq->bRequest == USBRQ_HID_SET_IDLE){
idleRate = rq->wValue.bytes[1];
}
}else{
/* no vendor specific requests implemented */
}
return 0;
}
... something
Which works.
So, where start make it stop working ?
And make it work again different?
You don't need two HID descriptors, just one with a collection around two functions. I must admit that I never understood the fine details of USB descriptor parsing and always experimented until the operating system accepted the descriptor.
If you can find a composite device (e.g. keyboard with trackball), use that as a starting point.
If you can find a composite device (e.g. keyboard with trackball), use that as a starting point.
christian wrote:You don't need two HID descriptors, just one with a collection around two functions.
I tried to implement a USB device with 4 game controllers. They were identical but I think it does not matter. The key is to use two (or more) Application collections with two (or more) different report IDs. The sample HID Report Descriptor may be like this:
Code: Select all
PROGMEM const char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] =
{
// Controller #1
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x0c, // REPORT_COUNT (12)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x0c, // USAGE_MAXIMUM (Button 12)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x01, // INPUT (Constant) - 4 bit padding
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
// Controller #2
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x85, 0x02, // REPORT_ID (2)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x0c, // REPORT_COUNT (12)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x0c, // USAGE_MAXIMUM (Button 12)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x01, // INPUT (Constant) - 4 bit padding
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
};
os wrote:christian wrote:You don't need two HID descriptors, just one with a collection around two functions.
I tried to implement a USB device with 4 game controllers. They were identical but I think it does not matter. The key is to use two (or more) Application collections with two (or more) different report IDs.
And where shoud I add information, which REPORT_ID is comming (I meen in which byte of buffer).. I want to build a mouse which I want to control by IR remote and by buttons on it.. Buttons part I've already done, it's got standard mouse descriptor:
Code: Select all
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
// I guess here goes the REPORT_ID
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
The second descriptor will be the same..
But how in buildReport function add which REPORT_ID I want use..?
More info about my device:
buttons are checked every 22us, if changed - buildReportButtons() updates reportBufferButtons[] and sends to host..
IR transmition will be detected in interrupts, after receive full IR frame, it will be prepared to send in buildReportIR() and send..
How in this functions add select e.g. REPORT_ID(1) for buttons, 2 - IR?
Did you know that the USB Implementers Forum (http://www.usb.org) offers an application which creates HID descriptors? I can't find it right now, but it must be somewhere in the Downloads area of the Developer section.
Can be found here.
ksz wrote:And where shoud I add information, which REPORT_ID is comming (I meen in which byte of buffer)..
ReportID byte is the first byte of the buffer if you use it in the HID Report Descriptor.
You may see my implementation of RC USB controller (downloadable from ObDev web site). out_joystick_btn.c implements two reports for HID-compatible joystick with buttons. One report is for axes, the second - for buttons.
If host requests a specific ReportID then it is checked in usbFunctionSetup(). If it was an USB Interrupt In transfer then HID reports are sent by turns. In that case the firmware keeps track of which ReportID is to be sent this time (and you may use different repeat intervals for them if you wish, e.g. send the reports as 1, 1, 1, 2, 1, 1, 1, 2, ...). Note that WinXP usually uses Interrupt transfer, and PC application simply reads data from WinXP buffers (a lot of them by default, up to 512 buffers software controllable, 32 (?) by default).
Hope this helps.
christian wrote:Did you know that the USB Implementers Forum (http://www.usb.org) offers an application which creates HID descriptors? I can't find it right now, but it must be somewhere in the Downloads area of the Developer section.
Yes, I've used this to create my first mouse report..
What I didn't know is what wrote os:
[quote="os"]
ReportID byte is the first byte of the buffer if you use it in the HID Report Descriptor. ...........[quote]
Yes, os, this helps, thanks a lot!
This is all outlined in Device Class Definition for HID 1.11 and HID Usage Tables 1.12 found on usb.org's HID Information page.. Very good reads (hint, hint .)
Edit: Whatdoyouknow -- there's a standard controller for magic carpets..
Edit: Whatdoyouknow -- there's a standard controller for magic carpets..
HID Usage Tables 1.12 wrote:5.7 Miscellaneous Simulation Devices
Magic Carpet Simulation Device
CA – Allows a device to be generally classified as one that uses the standard control of a magic carpet. This control is a bar, grasped by both hands, that controls the Yaw, Pitch and Roll of the carpet.
The bar, at which the pilot sits, may be pushed forward or pulled back to cause the carpet to dive or rise, respectively. In the zero position, the carpet is in level flight. Pushing forward on the bar causes the carpet to nose down and generates negative values. Pulling back on the bar causes the carpet to nose up and generates positive values.
Turning the bar turns the carpet. In the zero position, the carpet travels straight ahead. Pulling back on the right side turns the carpet to the right and generates positive values. Pulling back on the left side turns the carpet to the left and generates negative values.
Rotating the bar rolls the carpet. In the zero position, the carpet travels level. Rotating the bar in a clockwise direction rolls the carpet to the right and generates positive values. Rotating the bar in the counterclockwise direction rolls the carpet to the left and generates negative values.