<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb">
	<link rel="self" type="application/atom+xml" href="https://forums.obdev.at/app.php/feed/topic/10780" />

	<title>Objective Development Forums</title>
	
	<link href="https://forums.obdev.at/index.php" />
	<updated>2017-03-27T15:39:01+02:00</updated>

	<author><name><![CDATA[Objective Development Forums]]></name></author>
	<id>https://forums.obdev.at/app.php/feed/topic/10780</id>

		<entry>
		<author><name><![CDATA[noperator]]></name></author>
		<updated>2017-03-27T15:39:01+02:00</updated>

		<published>2017-03-27T15:39:01+02:00</published>
		<id>https://forums.obdev.at/viewtopic.php?t=10780&amp;p=32107#p32107</id>
		<link href="https://forums.obdev.at/viewtopic.php?t=10780&amp;p=32107#p32107"/>
		<title type="html"><![CDATA[Re: HID keyboard/mouse combo report ID]]></title>

		
		<content type="html" xml:base="https://forums.obdev.at/viewtopic.php?t=10780&amp;p=32107#p32107"><![CDATA[
Ok the problem was that usbSetInterrupt can only send 8 bytes at a time and my keyboard descriptor took up 9 bytes (report ID + modifier + reserved + 6 keycodes). I reduced the number of keycodes to 5 and can now send mouse and keyboard data at the same time!<br />I discovered that endpoint 3 can also be used to implement a separate HID device. I tried that briefly without success before stumbling upon the 8 byte limit. I may revisit that path at a later time...<br /><br />The full HID Descriptor for reference<br /><div class="codebox"><p>Code: </p><pre><code>PROGMEM const char usbHidReportDescriptor&#91;USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH&#93; = {<br />   //45 47<br />   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)<br />   0x09, 0x06,                    // USAGE (Keyboard)<br />   0xa1, 0x01,                    // COLLECTION (Application)<br />   0x85, (uint8_t)ID_KEYBOARD,    //   REPORT_ID (2)<br />   0x05, 0x07,                    //   USAGE_PAGE (Keyboard)<br />   0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)<br />   0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)<br />   0x15, 0x00,                    //   LOGICAL_MINIMUM (0)<br />   0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)<br />   0x95, 0x08,                    //   REPORT_COUNT (8)<br />   0x75, 0x01,                    //   REPORT_SIZE (1)<br />   0x81, 0x02,                    //   INPUT (Data,Var,Abs)<br />   0x95, 0x01,                    //   REPORT_COUNT (1)<br />   0x75, 0x08,                    //   REPORT_SIZE (8)<br />   0x81, 0x01,                    //   INPUT (Cnst,Ary,Abs)<br />   0x95, 0x05,                    //   REPORT_COUNT (6)<br />   0x75, 0x08,                    //   REPORT_SIZE (8)<br />   0x15, 0x00,                    //   LOGICAL_MINIMUM (0)<br />   0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)<br />   0x05, 0x07,                    //   USAGE_PAGE (Keyboard)<br />   0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))<br />   0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)<br />   0x81, 0x00,                    //   INPUT (Data,Ary,Abs)<br />   0xc0,                           // END_COLLECTION<br />   <br />   //52 54<br />   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)<br />   0x09, 0x02,                    // USAGE (Mouse)<br />   0xa1, 0x01,                    // COLLECTION (Application)<br />   0x85, (uint8_t)ID_MOUSE,       //   REPORT_ID (1)<br />   0x09, 0x01,                    //   USAGE (Pointer)<br />   0xA1, 0x00,                    //   COLLECTION (Physical)<br />   0x05, 0x09,                    //     USAGE_PAGE (Button)<br />   0x19, 0x01,                    //     USAGE_MINIMUM<br />   0x29, 0x03,                    //     USAGE_MAXIMUM<br />   0x15, 0x00,                    //     LOGICAL_MINIMUM (0)<br />   0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)<br />   0x95, 0x03,                    //     REPORT_COUNT (3)<br />   0x75, 0x01,                    //     REPORT_SIZE (1)<br />   0x81, 0x02,                    //     INPUT (Data,Var,Abs)<br />   0x95, 0x01,                    //     REPORT_COUNT (1)<br />   0x75, 0x05,                    //     REPORT_SIZE (5)<br />   0x81, 0x03,                    //     INPUT (Const,Var,Abs)<br />   0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)<br />   0x09, 0x30,                    //     USAGE (X)<br />   0x09, 0x31,                    //     USAGE (Y)<br />   0x09, 0x38,                    //     USAGE (Wheel)<br />   0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)<br />   0x25, 0x7F,                    //     LOGICAL_MAXIMUM (127)<br />   0x75, 0x08,                    //     REPORT_SIZE (8)<br />   0x95, 0x03,                    //     REPORT_COUNT (3)<br />   0x81, 0x06,                    //     INPUT (Data,Var,Rel)<br />   0xC0,                          //   END_COLLECTION<br />   0xC0,                     // END COLLECTION   <br />};</code></pre></div><br /><br />and structures<br /><div class="codebox"><p>Code: </p><pre><code>typedef struct{<br />   uint8_t   reportID;<br />    uint8_t   buttonMask;<br />    int8_t   dx;<br />    int8_t   dy;<br />    int8_t   dWheel;<br />}mouse_report_t;<br /><br />typedef struct{<br />   uint8_t   reportID;<br />   uint8_t   modifier;<br />   uint8_t   reserved;<br />   uint8_t   keycode&#91;5&#93;;<br />}keyboard_report_t;</code></pre></div><p>Statistics: Posted by <a href="https://forums.obdev.at/memberlist.php?mode=viewprofile&amp;u=22538">noperator</a> — Mon Mar 27, 2017 3:39 pm</p><hr />
]]></content>
	</entry>
		<entry>
		<author><name><![CDATA[noperator]]></name></author>
		<updated>2017-03-27T13:53:29+02:00</updated>

		<published>2017-03-27T13:53:29+02:00</published>
		<id>https://forums.obdev.at/viewtopic.php?t=10780&amp;p=32106#p32106</id>
		<link href="https://forums.obdev.at/viewtopic.php?t=10780&amp;p=32106#p32106"/>
		<title type="html"><![CDATA[HID keyboard/mouse combo report ID]]></title>

		
		<content type="html" xml:base="https://forums.obdev.at/viewtopic.php?t=10780&amp;p=32106#p32106"><![CDATA[
I am trying to create a device which acts as a keyboard and mouse at the same time. After some research I've concluded that it should be possible to combine both the mouse and keyboard HID descriptors, and separate them with Report IDs. I've successfully implemented the keyboard and mouse separately, but when I try to assign a report ID to the keyboard, no output is produced.<br /><br />Here is the offending keyboard descriptor:<br /><div class="codebox"><p>Code: </p><pre><code>PROGMEM const char usbHidReportDescriptor&#91;USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH&#93; = {   <br />   //45 without report ID<br />   //47 with report ID<br />   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)<br />   0x09, 0x06,                    // USAGE (Keyboard)<br />   0xa1, 0x01,                    // COLLECTION (Application)<br />   //0x85, (uint8_t)ID_KEYBOARD,    //   REPORT_ID (2)<br />   0x05, 0x07,                    //   USAGE_PAGE (Keyboard)<br />   0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)<br />   0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)<br />   0x15, 0x00,                    //   LOGICAL_MINIMUM (0)<br />   0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)<br />   0x95, 0x08,                    //   REPORT_COUNT (8)<br />   0x75, 0x01,                    //   REPORT_SIZE (1)<br />   0x81, 0x02,                    //   INPUT (Data,Var,Abs)<br />   0x95, 0x01,                    //   REPORT_COUNT (1)<br />   0x75, 0x08,                    //   REPORT_SIZE (8)<br />   0x81, 0x01,                    //   INPUT (Cnst,Ary,Abs)<br />   0x95, 0x06,                    //   REPORT_COUNT (6)<br />   0x75, 0x08,                    //   REPORT_SIZE (8)<br />   0x15, 0x00,                    //   LOGICAL_MINIMUM (0)<br />   0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)<br />   0x05, 0x07,                    //   USAGE_PAGE (Keyboard)<br />   0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))<br />   0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)<br />   0x81, 0x00,                    //   INPUT (Data,Ary,Abs)<br />   0xc0,                           // END_COLLECTION<br />}</code></pre></div><br /><br />and the code I'm testing it with<br /><div class="codebox"><p>Code: </p><pre><code>typedef struct{<br />   //uint8_t   reportID;<br />   uint8_t   modifier;<br />   uint8_t   reserved;<br />   uint8_t   keycode&#91;6&#93;;<br />}keyboard_report_t;<br /><br />//static keyboard_report_t keyboardReportBuffer = {(uint8_t)ID_KEYBOARD, 0, 0, {0, 0, 0, 0, 0, 0}};<br />static keyboard_report_t keyboardReportBuffer = {0, 0, {0, 0, 0, 0, 0, 0}};<br />static uchar    idleRate;   /* repeat rate for keyboards, never used for mice */<br /><br />usbMsgLen_t usbFunctionSetup(uchar data&#91;8&#93;)<br />{<br />usbRequest_t    *rq = (void *)data;<br /><br />    /* The following requests are never used. But since they are required by<br />     * the specification, we implement them in this example.<br />     */<br />   <br />   if((rq-&gt;bmRequestType &amp; USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {<br />      switch(rq-&gt;bRequest) {<br />      case USBRQ_HID_GET_REPORT: // send &quot;no keys pressed&quot; if asked here<br />         <br />         usbMsgPtr = (usbMsgPtr_t)(void *)&amp;keyboardReportBuffer; // we only have this one<br />         keyboardReportBuffer.modifier = 0;<br />         keyboardReportBuffer.keycode&#91;0&#93; = 0;<br />         return sizeof(keyboardReportBuffer);      <br />         <br />      case USBRQ_HID_SET_REPORT: // if wLength == 1, should be LED state<br />         return (rq-&gt;wLength.word == 1) ? USB_NO_MSG : 0;<br />         <br />      case USBRQ_HID_GET_IDLE: // send idle rate to PC as required by spec<br />         usbMsgPtr = (usbMsgPtr_t)&amp;idleRate;<br />         return 1;<br />         <br />      case USBRQ_HID_SET_IDLE: // save idle rate as required by spec<br />         idleRate = rq-&gt;wValue.bytes&#91;1&#93;;<br />         return 0;<br />      }<br />   }<br />   return 0;<br />}<br /><br />usbMsgLen_t usbFunctionWrite(uint8_t * data, uchar len) {<br />   return 1; // Data read, not expecting more<br />}<br /><br />int __attribute__((noreturn)) main(void)<br />{<br />    usbInit();<br />    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */<br />    _delay_ms(255);<br />    usbDeviceConnect();<br />    sei();<br />   <br />    for(;;){                /* main event loop */<br /><br />        usbPoll();<br />        if(usbInterruptIsReady()){<br /><br />         keyboardReportBuffer.keycode&#91;0&#93; = 5;<br />         usbSetInterrupt((void *)&amp;keyboardReportBuffer, sizeof(keyboardReportBuffer));<br />         while(!usbInterruptIsReady())usbPoll();<br />         <br />         keyboardReportBuffer.keycode&#91;0&#93; = 0;<br />         usbSetInterrupt((void *)&amp;keyboardReportBuffer, sizeof(keyboardReportBuffer));<br />        }<br />    }<br />}</code></pre></div><br /><br />The code simply sends the letter 'b' over and over. With the report ID lines commented out in the descriptor and the code, it works fine, but when not commented the device not produce any output, but is still recognized by Windows. I also tried adding a report ID to the mouse HID descriptor and it worked without problems.<br /><br />Does anyone know why this might be happening?<p>Statistics: Posted by <a href="https://forums.obdev.at/memberlist.php?mode=viewprofile&amp;u=22538">noperator</a> — Mon Mar 27, 2017 1:53 pm</p><hr />
]]></content>
	</entry>
	</feed>
