I am trying to use the following method:
response,err:=http.Get("https://support.microsoft.com")
It is working as expected. But when I call it with "https://samsung.com", it is throwing fatal exception that I can not handle.
A code sample:
package main
import (
"fmt"
"net/http"
)
func main() {
_, err := http.Get("http://support.microsoft.com")
if err != nil {
fmt.Println(err)
}
}
and here is the error:
panic: cipher.NewCBCEncrypter: IV length must equal block size
goroutine 55 [running]:
crypto/cipher.NewCBCEncrypter(0x7c7680, 0xc0001cd0b0, 0xc0000c03c8, 0x10, 0x20, 0x0, 0x0)
C:/Go/src/crypto/cipher/cbc.go:47 +0x139
crypto/tls.cipherAES(0xc0000c0388, 0x20, 0x60, 0xc0000c03c8, 0x10, 0x20, 0x0, 0x20, 0xc00008c156)
C:/Go/src/crypto/tls/cipher_suites.go:139 +0xe2
crypto/tls.(*clientHandshakeState).establishKeys(0xc0001dfdc8, 0x0, 0x0)
C:/Go/src/crypto/tls/handshake_client.go:625 +0x20c
crypto/tls.(*clientHandshakeState).handshake(0xc0001dfdc8, 0xc0000b7200, 0x0)
C:/Go/src/crypto/tls/handshake_client.go:402 +0x426
crypto/tls.(*Conn).clientHandshake(0xc00003dc00, 0x0, 0x0)
C:/Go/src/crypto/tls/handshake_client.go:208 +0x2d4
crypto/tls.(*Conn).Handshake(0xc00003dc00, 0x0, 0x0)
C:/Go/src/crypto/tls/conn.go:1343 +0xf6
net/http.(*persistConn).addTLS.func2(0x0, 0xc00003dc00, 0xc0000cc7d0, 0xc000093da0)
C:/Go/src/net/http/transport.go:1190 +0x49
created by net/http.(*persistConn).addTLS
C:/Go/src/net/http/transport.go:1186 +0x1b2
i just fixed my problem by updating go from 1.12.4 to 1.12.5.
thanks to #Markus-W-Mahlberg
As visible in the official documentation as well as almost everywhere else online, the common pattern for handling http client errors is the following:
req, err := http.NewRequest("GET", "http://example.com", nil)
req.Header.Add("If-None-Match", `W/"wyzzy"`)
resp, err := client.Do(req)
if err != nil {
// handle error
}
defer resp.Body.Close()
Reading the docs about the methods on the http client, I'm not able to understand if it is possible to receive both resp and err not nil, it seems like it's possible if we consider what is written in the Do method documentation:
The request Body, if non-nil, will be closed by the underlying
Transport, even on errors.
On error, any Response can be ignored. A non-nil Response with a
non-nil error only occurs when CheckRedirect fails, and even then the
returned Response.Body is already closed.
Therefore my questions are the following:
Is it possible to receive non-nil resp and err at the same time?
If it is possible, and in my program I end up receiving a lot of errors, and I return or panic in the //handle error piece of the code shown above, thus never reaching the defer right after, is it possible that on the long run I end up having too many open bodies that the transport hasn't been able to close?
Context Addendum :
The problem I encounter is that, after a while, the program crashes with the following big print of goroutines on the stdErr, and following the trace I end up to a piece of code that seems normal, unless something bad happens if an error is encountered and there's a responseBody upon which no defer close will be made, but since the official docs say not to worry about it, the problem must be elsewhere...
Stderr logs
Display timestamps
net/http.(*persistConn).readLoop(0xc4244e0240)
/usr/local/go/src/net/http/transport.go:1474 +0x196
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1117 +0xa35
goroutine 194055 [select, 2 minutes]:
net/http.(*persistConn).readLoop(0xc42421ec60)
/usr/local/go/src/net/http/transport.go:1599 +0x9ec
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1117 +0xa35
goroutine 215944 [IO wait]:
net.runtime_pollWait(0x7f63736f0628, 0x72, 0x21b)
/usr/local/go/src/runtime/netpoll.go:164 +0x59
net.(*pollDesc).wait(0xc420963568, 0x72, 0xa85c40, 0xa81350)
/usr/local/go/src/net/fd_poll_runtime.go:75 +0x38
net.(*pollDesc).waitRead(0xc420963568, 0xc422289000, 0x1000)
/usr/local/go/src/net/fd_poll_runtime.go:80 +0x34
net.(*netFD).Read(0xc420963500, 0xc422289000, 0x1000, 0x1000, 0x0, 0xa85c40, 0xa81350)
/usr/local/go/src/net/fd_unix.go:250 +0x1b7
net.(*conn).Read(0xc42025bbb8, 0xc422289000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
/usr/local/go/src/net/net.go:181 +0x70
net/http.(*persistConn).Read(0xc4217af8c0, 0xc422289000, 0x1000, 0x1000, 0xc420b33400, 0x8b61a3, 0xc423dd6b80)
/usr/local/go/src/net/http/transport.go:1316 +0x14b
bufio.(*Reader).fill(0xc421af0060)
/usr/local/go/src/bufio/bufio.go:97 +0x117
bufio.(*Reader).Peek(0xc421af0060, 0x1, 0xc421af01e0, 0xc420536c80, 0xc420b17e00, 0x60, 0xc420536c60)
/usr/local/go/src/bufio/bufio.go:129 +0x67
net/http.(*persistConn).readLoop(0xc4217af8c0)
/usr/local/go/src/net/http/transport.go:1474 +0x196
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1117 +0xa35
goroutine 199855 [select, 1 minutes]:
net/http.(*persistConn).writeLoop(0xc421db1320)
/usr/local/go/src/net/http/transport.go:1704 +0x43a
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1118 +0xa5a
goroutine 198707 [select, 1 minutes]:
net/http.(*persistConn).readLoop(0xc4236ea000)
/usr/local/go/src/net/http/transport.go:1599 +0x9ec
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1117 +0xa35
goroutine 192577 [select, 2 minutes]:
net/http.(*persistConn).readLoop(0xc424a8fc20)
/usr/local/go/src/net/http/transport.go:1599 +0x9ec
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1117 +0xa35
goroutine 213681 [select]:
net/http.(*persistConn).writeLoop(0xc42455e6c0)
/usr/local/go/src/net/http/transport.go:1704 +0x43a
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1118 +0xa5a
goroutine 190222 [select, 2 minutes]:
net/http.(*persistConn).writeLoop(0xc4238617a0)
/usr/local/go/src/net/http/transport.go:1704 +0x43a
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1118 +0xa5a
goroutine 208970 [select, 1 minutes]:
net/http.(*persistConn).writeLoop(0xc4234530e0)
/usr/local/go/src/net/http/transport.go:1704 +0x43a
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1118 +0xa5a
goroutine 219699 [select]:
net/http.(*persistConn).writeLoop(0xc42155cb40)
/usr/local/go/src/net/http/transport.go:1704 +0x43a
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1118 +0xa5a
goroutine 221664 [select]:
net/http.setRequestCancel.func3(0x0, 0xc4231af680, 0xc423657000, 0xc4214aeecc, 0xc422f926c0)
/usr/local/go/src/net/http/client.go:320 +0x17c
created by net/http.setRequestCancel
/usr/local/go/src/net/http/client.go:330 +0x287
goroutine 220550 [select]:
net/http.(*persistConn).readLoop(0xc4218f0c60)
/usr/local/go/src/net/http/transport.go:1599 +0x9ec
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1117 +0xa35
goroutine 216169 [IO wait]:
net.runtime_pollWait(0x7f6373700fb0, 0x72, 0x221)
/usr/local/go/src/runtime/netpoll.go:164 +0x59
net.(*pollDesc).wait(0xc4212fdb18, 0x72, 0xa85c40, 0xa81350)
/usr/local/go/src/net/fd_poll_runtime.go:75 +0x38
net.(*pollDesc).waitRead(0xc4212fdb18, 0xc42393c000, 0x1000)
/usr/local/go/src/net/fd_poll_runtime.go:80 +0x34
net.(*netFD).Read(0xc4212fdab0, 0xc42393c000, 0x1000, 0x1000, 0x0, 0xa85c40, 0xa81350)
/usr/local/go/src/net/fd_unix.go:250 +0x1b7
net.(*conn).Read(0xc42300aa38, 0xc42393c000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
/usr/local/go/src/net/net.go:181 +0x70
net/http.(*persistConn).Read(0xc422102c60, 0xc42393c000, 0x1000, 0x1000, 0xc423d30820, 0xc42002a800, 0xc424422b80)
/usr/local/go/src/net/http/transport.go:1316 +0x14b
bufio.(*Reader).fill(0xc4220598c0)
/usr/local/go/src/bufio/bufio.go:97 +0x117
bufio.(*Reader).Peek(0xc4220598c0, 0x1, 0xc422059a40, 0xc420535c80, 0xc422059700, 0x60, 0xc420535c60)
/usr/local/go/src/bufio/bufio.go:129 +0x67
net/http.(*persistConn).readLoop(0xc422102c60)
/usr/local/go/src/net/http/transport.go:1474 +0x196
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1117 +0xa35
goroutine 213706 [select]:
net/http.(*persistConn).writeLoop(0xc42321d200)
/usr/local/go/src/net/http/transport.go:1704 +0x43a
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1118 +0xa5a
goroutine 214335 [select]:
net/http.(*persistConn).writeLoop(0xc4230d7560)
/usr/local/go/src/net/http/transport.go:1704 +0x43a
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1118 +0xa5a
goroutine 221651 [IO wait]:
net.runtime_pollWait(0x7f63736eff38, 0x72, 0x254)
/usr/local/go/src/runtime/netpoll.go:164 +0x59
net.(*pollDesc).wait(0xc422449b18, 0x72, 0xa85c40, 0xa81350)
/usr/local/go/src/net/fd_poll_runtime.go:75 +0x38
net.(*pollDesc).waitRead(0xc422449b18, 0xc423d93000, 0x1000)
/usr/local/go/src/net/fd_poll_runtime.go:80 +0x34
net.(*netFD).Read(0xc422449ab0, 0xc423d93000, 0x1000, 0x1000, 0x0, 0xa85c40, 0xa81350)
/usr/local/go/src/net/fd_unix.go:250 +0x1b7
net.(*conn).Read(0xc421eb21b8, 0xc423d93000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
/usr/local/go/src/net/net.go:181 +0x70
net/http.(*persistConn).Read(0xc422e5b440, 0xc423d93000, 0x1000, 0x1000, 0x8cc888, 0x0, 0xc42347bb80)
/usr/local/go/src/net/http/transport.go:1316 +0x14b
bufio.(*Reader).fill(0xc422f2c960)
/usr/local/go/src/bufio/bufio.go:97 +0x117
bufio.(*Reader).Peek(0xc422f2c960, 0x1, 0xc422f2d6e0, 0xc420b8ec80, 0xc42180ff00, 0x60, 0xc420b8ec60)
/usr/local/go/src/bufio/bufio.go:129 +0x67
net/http.(*persistConn).readLoop(0xc422e5b440)
/usr/local/go/src/net/http/transport.go:1474 +0x196
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1117 +0xa35
goroutine 221670 [IO wait]:
net.runtime_pollWait(0x7f63736ff7b0, 0x72, 0x259)
/usr/local/go/src/runtime/netpoll.go:164 +0x59
net.(*pollDesc).wait(0xc422449b88, 0x72, 0xa85c40, 0xa81350)
/usr/local/go/src/net/fd_poll_runtime.go:75 +0x38
net.(*pollDesc).waitRead(0xc422449b88, 0xc423f28000, 0x1000)
/usr/local/go/src/net/fd_poll_runtime.go:80 +0x34
net.(*netFD).Read(0xc422449b20, 0xc423f28000, 0x1000, 0x1000, 0x0, 0xa85c40, 0xa81350)
/usr/local/go/src/net/fd_unix.go:250 +0x1b7
net.(*conn).Read(0xc423eac3c8, 0xc423f28000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
/usr/local/go/src/net/net.go:181 +0x70
net/http.(*persistConn).Read(0xc4235930e0, 0xc423f28000, 0x1000, 0x1000, 0xa82dc0, 0xc42000e0b0, 0xc423be7b80)
/usr/local/go/src/net/http/transport.go:1316 +0x14b
bufio.(*Reader).fill(0xc422bb70e0)
/usr/local/go/src/bufio/bufio.go:97 +0x117
bufio.(*Reader).Peek(0xc422bb70e0, 0x1, 0xc422bb7320, 0xc424191480, 0xc4237a4820, 0x0, 0xc422ac9138)
/usr/local/go/src/bufio/bufio.go:129 +0x67
net/http.(*persistConn).readLoop(0xc4235930e0)
/usr/local/go/src/net/http/transport.go:1474 +0x196
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1117 +0xa35
goroutine 213543 [select]:
net/http.(*persistConn).readLoop(0xc424795c20)
/usr/local/go/src/net/http/transport.go:1599 +0x9ec
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:1117 +0xa35
goroutine 220529 [select]:
net/http.(*persistConn).roundTrip(0xc4215fd680, 0xc4212c5c80, 0x0, 0x0, 0x0)
/usr/local/go/src/net/http/transport.go:1898 +0x974
net/http.(*Transport).RoundTrip(0xc420847b30, 0xc421248800, 0xc420847b30, 0xed15b2cf4, 0x16cd81f7)
/usr/local/go/src/net/http/transport.go:391 +0x74c
net/http.send(0xc421248700, 0xa84080, 0xc420847b30, 0xed15b2cf4, 0x16cd81f7, 0xab7060, 0x0, 0x8, 0xc4213a2a80, 0x40f258)
/usr/local/go/src/net/http/client.go:249 +0x162
net/http.(*Client).send(0xc42075ed20, 0xc421248700, 0xed15b2cf4, 0x16cd81f7, 0xab7060, 0xc4213a2a80, 0x0, 0x1, 0x4084fe)
/usr/local/go/src/net/http/client.go:173 +0x108
net/http.(*Client).Do(0xc42075ed20, 0xc421248700, 0xa, 0x8b359b, 0x5)
/usr/local/go/src/net/http/client.go:595 +0x254
github.com/myCompanyName/gojsonrpc.(*Client).sendJsonRequest(0xc42078c6e0, 0xc4215fd320, 0xbb, 0x11a, 0x0, 0x0, 0x0, 0x0, 0x0)
/home/ubuntu/go/src/github.com/myCompanyName/gojsonrpc/client.go:45 +0x2f2
github.com/myCompanyName/gojsonrpc.(*Client).Run(0xc42078c6e0, 0x8be6b2, 0x1d, 0x838780, 0xc420789ce0, 0x7fb2e0, 0xc4212c5b40, 0x1, 0xe)
/home/ubuntu/go/src/github.com/myCompanyName/gojsonrpc/client.go:72 +0x219
github.com/myCompanyName/app/connectors/vendor.(*Connector).ReadStatus(0xc42078aa30, 0xc4212c5a60, 0xd, 0xc4212c5a6e, 0x7, 0xc4212c59c0, 0x1d, 0x0, 0x0, 0x0, ...)
/home/ubuntu/go/src/github.com/myCompanyName/app/connectors/vendor/tickets.go:52 +0x386
github.com/myCompanyName/app/obscuredPkgName/connabslayer.(*ConnAbsLayer).ReadMetrics(0xc42075ac40, 0xc4212c5a60, 0x15, 0xc4212c59c0, 0x1d, 0xc42121eb30, 0xf)
/home/ubuntu/go/src/github.com/myCompanyName/app/obscuredPkgName/connabslayer/connector_abstraction_layer.go:145 +0xdc
github.com/myCompanyName/app/obscuredPkgName/updater/plugins.(*UpdaterPlugin).SyncPluggedData(0xc42078c820, 0xc4208b9ef0, 0x28, 0xf)
/home/ubuntu/go/src/github.com/myCompanyName/app/obscuredPkgName/updater/plugins/vendor_plugin.go:69 +0x1e1
github.com/myCompanyName/app/obscuredPkgName/updater.(*Updater).syncData.func1(0xc420763a00, 0xc4208b9ef0, 0x28, 0xc4201824f0, 0xf)
/home/ubuntu/go/src/github.com/myCompanyName/app/obscuredPkgName/updater/updater.go:127 +0xf6
created by github.com/myCompanyName/app/obscuredPkgName/updater.(*Updater).syncData
/home/ubuntu/go/src/github.com/myCompanyName/app/obscuredPkgName/updater/updater.go:131 +0x17b
// AND SO ON
Solution:
The problem was elsewhere, as visible in the comments below, but the question might be useful for somebody else asking the same.
Yes, they can both be non-nil in one situation, apparently. From the source, we see:
if err != nil {
// Special case for Go 1 compatibility: return both the response
// and an error if the CheckRedirect function failed.
// See https://golang.org/issue/3795
// The resp.Body has already been closed.
ue := uerr(err)
ue.(*url.Error).URL = loc
return resp, ue
}
Every other return is returning either a response and nil err, or a nil response and non-nil error.
So for the questions above:
Yes
Can't happen, for the only case in which both a body and an error are non-nil, the body has already been closed
I have an AES encryption program that has been loaded into the MSP430 Launchpad. Is there any way I am able to view the output on the terminal to check whether the encryption works? I am using Ubuntu 16.04. This is what the terminal shows as I run the load and continue command in the terminal.
(gdb) load
Loading section .rodata, size 0x20e lma 0x4400
Loading section .rodata2, size 0xc lma 0x4610
Loading section .data, size 0x9e lma 0x461c
Loading section .upper.data, size 0x2 lma 0x46ba
Loading section .text, size 0x694 lma 0x46bc
Loading section __reset_vector, size 0x2 lma 0xfffe
Starting address 0x46bc, load size 2384
Transfer rate: 5KB/sec, 340 bytes/write.
(gdb) continue
Continuing.
The MSP430 is connected through USB FET at ttyACM0. I have a .out file for encryption, but I have no idea how to show its output to check whether the encryption is working.
This is the .c file that I used.
#include "msp430x26x.h"
#include "TI_aes.h"
int main( void )
{
unsigned char state[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
//unsigned char ciphertext[] = {0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a};
unsigned char key[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
aes_encrypt(state, key);
//aes_decrypt(state, key);
return 0;
}
I'm facing an odd situation. I need to analyze and clean some text found on the internet. One of such documents is like this (Italian):
"L'Antitrust: sull'acquisto dei vaccini a uso umano opportuna una ... - ІL Cоrrіеrе dеllа Cіttà L'Antitrust chiede maggiore trasparenza sulla definizione dei costi e dei prezzi dei vaccini, che in Italia costano ogni anno almeno 300 milioni di euro al servizio sanitario nazionale, e propone di inserirli nelle classi di rimborso dei farmaci per ..."
The part "ІL Cоrrіеrе dеllа Cіttà" seems made by normal character but instead it's not (try to use your browser search function with those words).
I need to clean the text from stopwords ("il" and "della" in this case), but I cannot match the words in that part with my list of stopwords.
Is there a way to sanitize such strange characters to normal UTF-8 characters?
Thanks
UPDATE:
as asked in the comments I run dput(charToRaw("ІL Cоrrіеrе dеllа Cіttà")) copying and pasting the strange text:
as.raw(c(0xd0, 0x86, 0x4c, 0x20, 0x43, 0xd0, 0xbe, 0x72, 0x72,
0xd1, 0x96, 0xd0, 0xb5, 0x72, 0xd0, 0xb5, 0x20, 0x64, 0xd0, 0xb5,
0x6c, 0x6c, 0xd0, 0xb0, 0x20, 0x43, 0xd1, 0x96, 0x74, 0x74, 0xc3,
0xa0))
And this is the output of dput(charToRaw("IL Corriere della Città")), this time written by hand:
as.raw(c(0x49, 0x4c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x69, 0x65,
0x72, 0x65, 0x20, 0x64, 0x65, 0x6c, 0x6c, 0x61, 0x20, 0x43, 0x69,
0x74, 0x74, 0xc3, 0xa0))
I am trying to use an Arduino Leonardo for keyboard emulation since that is one of its advertised features. I have been playing with the Leonardo and wrote a very simple sketch based off the Blink example.
// Pin 13 has an LED connected on most Arduino boards.
int led = 13;
// The setup routine runs once when you press reset:
void setup()
{
// Initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// The loop routine runs over and over again forever:
void loop()
{
delay(5000); // Wait for five seconds
digitalWrite(led, HIGH); // Turn the LED on (HIGH is the voltage level)
delay(100); // Wait for a secondA
digitalWrite(led, LOW); // Turn the LED off by making the voltage LOW
Keyboard.write('A'); // Write an A using keyboard emulator
}
Now this example works great on my Windows XP machine. It is recognized as a generic HID keyboard and will type an 'A' every five seconds.
The targeted environment is running DOS so to my knowledge I need to get the Arduino Leonardo recognized by the BIOS on this machine, which it is not and it does not type the 'A' in DOS.
I have been making modifications to the USB device descriptor of the Leonardo, trying to make it match a Dell L100 as much as possible. The modifications I've made haven't helped, and I suspect it is because the Leonardo is a composite device which exposes the serial communication, keyboard emulation, and mouse emulation on the same USB port. The source code for the USB descriptors/configuration is available to be edited and is located at:
Arduino_Installation\hardware\arduino\cores\arduino\HID.cpp
Arduino_Installation\hardware\arduino\cores\arduino\USBDesc.h
Arduino_Installation\hardware\arduino\cores\arduino\USBCore.h
Arduino_Installation\hardware\arduino\cores\arduino\USBCore.cpp
The following is a dump from USB Device Viewer for the Leonardo:
[Port3] : USB Composite Device
---===>Device Information<===---
English product name: "Arduino Leonardo"
ConnectionStatus:
Current Config Value: 0x01 -> Device Bus Speed: Full
Device Address: 0x03
Open Pipes: 4
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x81 -> Direction: IN - EndpointID: 1
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize: 0x0010 = 0x10 bytes
bInterval: 0x40
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x02 -> Direction: OUT - EndpointID: 2
bmAttributes: 0x02 -> Bulk Transfer Type
wMaxPacketSize: 0x0040 = 0x40 bytes
bInterval: 0x00
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3
bmAttributes: 0x02 -> Bulk Transfer Type
wMaxPacketSize: 0x0040 = 0x40 bytes
bInterval: 0x00
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x84 -> Direction: IN - EndpointID: 4
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize: 0x0040 = 0x40 bytes
bInterval: 0x01
===>Device Descriptor<===
bLength: 0x12
bDescriptorType: 0x01
bcdUSB: 0x0110
bDeviceClass: 0x00
*!*ERROR: device class should be Multi-interface Function 0xEF
When IAD descriptor is used
bDeviceSubClass: 0x00
*!*ERROR: device SubClass should be USB Common Sub Class 2
When IAD descriptor is used
bDeviceProtocol: 0x00
*!*ERROR: device Protocol should be USB IAD Protocol 1
When IAD descriptor is used
bMaxPacketSize0: 0x40 = (64) Bytes
idVendor: 0x2341 = Vendor ID not listed with USB.org as of 03-19-2008
idProduct: 0x8036
bcdDevice: 0x0100
iManufacturer: 0x01
English (United States) "Arduino LLC"
iProduct: 0x02
English (United States) "Arduino Leonardo"
iSerialNumber: 0x00
bNumConfigurations: 0x01
===>Configuration Descriptor<===
bLength: 0x09
bDescriptorType: 0x02
wTotalLength: 0x0064 -> Validated
bNumInterfaces: 0x03
bConfigurationValue: 0x01
iConfiguration: 0x00
bmAttributes: 0x80 -> Bus Powered
MaxPower: 0xFA = 500 mA
===>IAD Descriptor<===
bLength: 0x08
bDescriptorType: 0x0B
bFirstInterface: 0x00
bInterfaceCount: 0x02
bFunctionClass: 0x02 -> This is Communications (CDC Control) USB Device Interface Class
bFunctionSubClass: 0x01
bFunctionProtocol: 0x01
iFunction: 0x00
===>Interface Descriptor<===
bLength: 0x09
bDescriptorType: 0x04
bInterfaceNumber: 0x00
bAlternateSetting: 0x00
bNumEndpoints: 0x01
bInterfaceClass: 0x02 -> This is Communications (CDC Control) USB Device Interface Class
bInterfaceSubClass: 0x01
bInterfaceProtocol: 0x00
CAUTION: This may be an invalid bInterfaceProtocol
iInterface: 0x00
-> This is a Communications (CDC Control) USB Device Interface Class
===>Descriptor Hex Dump<===
bLength: 0x05
bDescriptorType: 0x24
05 24 00 10 01
-> This is a Communications (CDC Control) USB Device Interface Class
===>Descriptor Hex Dump<===
bLength: 0x05
bDescriptorType: 0x24
05 24 01 01 01
-> This is a Communications (CDC Control) USB Device Interface Class
===>Descriptor Hex Dump<===
bLength: 0x04
bDescriptorType: 0x24
04 24 02 06
-> This is a Communications (CDC Control) USB Device Interface Class
===>Descriptor Hex Dump<===
bLength: 0x05
bDescriptorType: 0x24
05 24 06 00 01
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x81 -> Direction: IN - EndpointID: 1
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize: 0x0010 = 0x10 bytes
bInterval: 0x40
===>Interface Descriptor<===
bLength: 0x09
bDescriptorType: 0x04
bInterfaceNumber: 0x01
bAlternateSetting: 0x00
bNumEndpoints: 0x02
bInterfaceClass: 0x0A -> This is a CDC Data USB Device Interface Class
bInterfaceSubClass: 0x01
bInterfaceProtocol: 0x00
CAUTION: This may be an invalid bInterfaceProtocol
iInterface: 0x00
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x02 -> Direction: OUT - EndpointID: 2
bmAttributes: 0x02 -> Bulk Transfer Type
wMaxPacketSize: 0x0040 = 0x40 bytes
bInterval: 0x00
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3
bmAttributes: 0x02 -> Bulk Transfer Type
wMaxPacketSize: 0x0040 = 0x40 bytes
bInterval: 0x00
===>Interface Descriptor<===
bLength: 0x09
bDescriptorType: 0x04
bInterfaceNumber: 0x02
bAlternateSetting: 0x00
bNumEndpoints: 0x01
bInterfaceClass: 0x03 -> HID Interface Class
bInterfaceSubClass: 0x01
bInterfaceProtocol: 0x00
CAUTION: This may be an invalid bInterfaceProtocol
iInterface: 0x00
===>HID Descriptor<===
bLength: 0x09
bDescriptorType: 0x21
bcdHID: 0x0101
bCountryCode: 0x00
bNumDescriptors: 0x01
bDescriptorType: 0x22
wDescriptorLength: 0x0065
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x84 -> Direction: IN - EndpointID: 4
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize: 0x0040 = 0x40 bytes
bInterval: 0x01
How could I get this Leonardo recognized by a BIOS as a generic keyboard?
Arduino does not support the boot protocol. I have started using Teensy (which is Arduino compatible), and it works pretty well.
I might be mistaken, but if you want your device to be recognized during boot, its bInterfaceSubClass should be 0x01 (boot device subclass).
In source files, as you have pointed out, sub class is set to 0x00 everywhere.
You may try to set the subclass in all usages of the D_INTERFACE macro from file USBCore.h to 0x01.
I'm not an Arduino user. I was only once playing with HID keyboard emulation on AVR using V-USB. You can try to find detailed information about usb descriptors at USB.org in documentation. But it's quite a pile of pages to read.
Here is part od HID descriptor dump of my keyboard, notice values in Interface Descriptor:
Bus 005 Device 002: ID 046d:c30e Logitech, Inc. UltraX Keyboard (Y-BL49)
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x046d Logitech, Inc.
idProduct 0xc30e UltraX Keyboard (Y-BL49)
bcdDevice 1.80
iManufacturer 1 Logitech
iProduct 2 HID compliant keyboard
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 59
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 1 Keyboard
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 62
The dump was made using "lsusb -v" as root under Linux.